Procházet zdrojové kódy

started on debuggeable hybrid simulator

Simon Van Mierlo před 9 roky
rodič
revize
324db3f1f3
30 změnil soubory, kde provedl 359995 přidání a 7004 odebrání
  1. 0 14
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBD.py
  2. 63 66
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml
  3. 347856 0
      debugging_fsa_cbd_composition/cbdsimulator/log.txt
  4. 3 3
      debugging_fsa_cbd_composition/cbdsimulator/plot.html
  5. 122 141
      debugging_fsa_cbd_composition/cbdsimulator/target.py
  6. 885 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBD.py
  7. 54 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBDDraw.py
  8. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/__init__.py
  9. 129 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/naivelog.py
  10. 49 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/plot.py
  11. 48 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/CounterTest.py
  12. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/__init__.py
  13. 551 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/basicCBDTest.py
  14. 201 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/flattenCBDTest.py
  15. 201 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/hierarchyCBDTest.py
  16. 172 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/sortedGraphCBDTest.py
  17. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/__init__.py
  18. 80 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/EvenNumbersCBD.py
  19. 21 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/HarmonicOscilator.py
  20. 300 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/TrainControlCBD.py
  21. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/__init__.py
  22. 262 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBD_Controller.py
  23. 56 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/Options.py
  24. 129 129
      debugging_fsa_cbd_composition/fsa_cbd_simulator/events.csv
  25. 222 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/fsaclasses.py
  26. 149 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/run_debug.py
  27. 6494 6494
      debugging_fsa_cbd_composition/fsa_cbd_simulator/signals.csv
  28. 1079 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/target.py
  29. 158 157
      debugging_fsa_cbd_composition/fsa_cbd_simulator/weaved_cbd_fsa_lib.py
  30. 711 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/woven_fsa_cbd_simulator_hierarchical_debugging.xml

+ 0 - 14
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBD.py

@@ -76,13 +76,6 @@ class BaseBlock:
         name_output = "OUT1" if name_output == None else name_output
         name_output = "OUT1" if name_output == None else name_output
         assert name_output in self.__signals.keys()
         assert name_output in self.__signals.keys()
         return self.__signals[name_output] if name_output != None else self.__signals["OUT1"]
         return self.__signals[name_output] if name_output != None else self.__signals["OUT1"]
-    
-    # TODO: probably remove this feature
-    def setSignal(self, value, name_output = None):    
-        name_output = "OUT1" if name_output == None else name_output
-        assert name_output in self.__signals.keys()
-        if self.__signals[name_output]:
-            self.__signals[name_output][-1] = Signal(self.__signals[name_output][-1].time, value)
 
 
     def getDependencies(self, curIteration):
     def getDependencies(self, curIteration):
         return list(set([ tup.block for tup in self._linksIn.values() ]))
         return list(set([ tup.block for tup in self._linksIn.values() ]))
@@ -538,13 +531,6 @@ class CBD(BaseBlock):
         assert portBlock != None
         assert portBlock != None
         return portBlock.getSignal("OUT1")
         return portBlock.getSignal("OUT1")
     
     
-    # TODO: probably remove this feature
-    def setSignal(self, value, name_output = None):    
-        name_output = "OUT1" if name_output == None else name_output
-        portBlock = self.getBlockByName(name_output)
-        assert portBlock != None
-        portBlock.setSignal(value, "OUT1")
-    
     
     
 class AddOneBlock(CBD):
 class AddOneBlock(CBD):
     """
     """

+ 63 - 66
debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml

@@ -53,7 +53,27 @@
         <method name="hasNextStrongComponent">
         <method name="hasNextStrongComponent">
             <body>
             <body>
             <![CDATA[
             <![CDATA[
-                return (self.currentCompIdx + 1) < len(self.strongComponentList)
+                return self.currentCompIdx < len(self.strongComponentList)
+            ]]>
+            </body>
+        </method>
+        <method name="computeBlock">
+            <body>
+            <![CDATA[
+                if self.currentComponentIsCycle():
+                    self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+                else:
+                    self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+            ]]>
+            </body>
+        </method>
+        <method name="advanceTime">
+            <body>
+            <![CDATA[
+                self.iteration = self.iteration + 1
+                self.clock = self.time_next
+                self.cbdController.advanceTimeStep()
+                self.time_next = self.clock + self.delta
             ]]>
             ]]>
             </body>
             </body>
         </method>
         </method>
@@ -85,16 +105,6 @@
             ]]>
             ]]>
             </body>
             </body>
         </method>
         </method>
-        <method name="advanceTime">
-            <body>
-            <![CDATA[
-                self.iteration = self.iteration + 1
-                self.clock = self.time_next
-                self.cbdController.advanceTimeStep()
-                self.time_next = self.clock + self.delta
-            ]]>
-            </body>
-        </method>
         <method name="finalize">
         <method name="finalize">
             <body>
             <body>
             <![CDATA[
             <![CDATA[
@@ -234,9 +244,7 @@
                         </transition>
                         </transition>
                     </state>
                     </state>
                     <state id="Running" initial="Continuous">
                     <state id="Running" initial="Continuous">
-                        <transition target="../PreStopped" cond="self.endCondition()">
-                            <raise event="termination_condition" />
-                        </transition>
+                        <transition target="../PreStopped" cond="self.endCondition()" />
                         <transition target="../PrePaused" event="pause" port="user_input" />
                         <transition target="../PrePaused" event="pause" port="user_input" />
                         <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
                         <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
                         <state id="Continuous" />
                         <state id="Continuous" />
@@ -273,7 +281,13 @@
                             <raise event="termination_condition" />
                             <raise event="termination_condition" />
                         </transition>
                         </transition>
                     </state>
                     </state>
-                    <state id="Stopped" />
+                    <state id="Stopped">
+                        <onentry>
+                            <script>
+                                print 'arriving in SimulationState/Stopped'
+                            </script>
+                        </onentry>
+                    </state>
                 </state>
                 </state>
                 <state id="SimulationFlow" initial="Initialize">
                 <state id="SimulationFlow" initial="Initialize">
                     <state id="Initialize">
                     <state id="Initialize">
@@ -297,9 +311,17 @@
                         <transition target="../CheckTerminationCondition" />
                         <transition target="../CheckTerminationCondition" />
                     </state>
                     </state>
                     <state id="CheckTerminationCondition">
                     <state id="CheckTerminationCondition">
-                        <transition target="../CreateDependencyGraph" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')" />
-                        <transition target="../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
-                        <transition target="../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()" />
+                        <state id="MacroStepProcessed">
+                            <transition target="../../DoSimulation" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')">
+                                <script>
+                                    self.currentCompIdx = 0
+                                    self.depGraph = self.cbdController.createDepGraph(self.iteration)
+                                    self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+                                </script>
+                            </transition>
+                            <transition target="../../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
+                            <transition target="../../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" />
+                        </state>
                     </state>
                     </state>
                     <state id="Waiting">
                     <state id="Waiting">
                         <!-- We schedule to go back to the check_termination state after the smallest possible delay (to accomodate for pauses). -->
                         <!-- We schedule to go back to the check_termination state after the smallest possible delay (to accomodate for pauses). -->
@@ -311,78 +333,53 @@
                             </script>
                             </script>
                         </transition>
                         </transition>
                         <!-- We execute a step when the wait time is smaller than the smallest possible delay. -->
                         <!-- We execute a step when the wait time is smaller than the smallest possible delay. -->
-                        <transition target="../CreateDependencyGraph" cond="self.waitTime() / 1000.0 &lt;= self.sccd_yield()" />
-                    </state>
-                    <state id="CreateDependencyGraph">
-                        <onentry>
+                        <transition target="../DoSimulation" cond="self.waitTime() / 1000.0 &lt;= self.sccd_yield()">
                             <script>
                             <script>
-                            <![CDATA[
+                                self.currentCompIdx = 0
                                 self.depGraph = self.cbdController.createDepGraph(self.iteration)
                                 self.depGraph = self.cbdController.createDepGraph(self.iteration)
-                            ]]>
-                            </script>
-                        </onentry>
-                        <transition target="../IsolateStrongComponents" />
-                    </state>
-                    <state id="IsolateStrongComponents">
-                        <onentry>
-                            <script>
-                            <![CDATA[
                                 self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
                                 self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
-                            ]]>
-                            </script>
-                        </onentry>
-                        <transition target="../ExecuteSimulationStep">
-                            <script>
-                                <![CDATA[
-                                    self.currentCompIdx = -1
-                                ]]>
-                            </script>
+                            </script>                        
                         </transition>
                         </transition>
                     </state>
                     </state>
-                    <state id="ExecuteSimulationStep" initial="CheckNextComponent">
-                        <state id="CheckNextComponent">
-                            <!-- Here, we wait long enough for the simulation state to settle to 'Paused' if we are small stepping. -->
-                            <transition target="../PreCheckCycle" cond="self.hasNextStrongComponent()" after="self.sccd_yield() * 2">
-                                <script>
-                                    <![CDATA[
-                                        self.currentCompIdx = self.currentCompIdx + 1
-                                    ]]>
-                                </script>
-                            </transition>
+                    <state id="DoSimulation" initial="MacroStepPrepared">
+                        <state id="MacroStepPrepared">
+                            <transition target="../MicroStepProcessed" />
+                        </state>
+                        <state id="MicroStepProcessed">
                             <!-- We wait a minimum amount of time to allow pause requests to be processed. -->
                             <!-- We wait a minimum amount of time to allow pause requests to be processed. -->
                             <transition target="../../CheckTerminationCondition" cond="not self.hasNextStrongComponent()" after="self.sccd_yield()">
                             <transition target="../../CheckTerminationCondition" cond="not self.hasNextStrongComponent()" after="self.sccd_yield()">
                                 <script>
                                 <script>
                                     <![CDATA[
                                     <![CDATA[
                                         self.advanceTime()
                                         self.advanceTime()
-                                        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
                                     ]]>
                                     ]]>
                                 </script>
                                 </script>
                                 <raise event="big_step_done" />
                                 <raise event="big_step_done" />
                             </transition>
                             </transition>
+                            <!-- Here, we wait long enough for the simulation state to settle to 'Paused' if we are small stepping. -->
+                            <transition target="../PreMicroStepPrepared" cond="self.hasNextStrongComponent()" after="self.sccd_yield() * 3" />
                         </state>
                         </state>
-                        <state id="PreCheckCycle">
-                            <transition target="../CheckCycle" cond="INSTATE('/Main/SimulationState/Running')" />
+                        <state id="PreMicroStepPrepared">
+                            <transition target="../MicroStepPrepared" cond="INSTATE('/Main/SimulationState/Running')" />
                         </state>
                         </state>
-                        <state id="CheckCycle">
-                            <transition target="../CheckNextComponent" cond="not self.currentComponentIsCycle()">
-                                <script>
-                                    <![CDATA[
-                                        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
-                                    ]]>
-                                </script>
-                                <raise event="small_step_done" />
-                            </transition>
-                            <transition target="../CheckNextComponent" cond="self.currentComponentIsCycle()">
+                        <state id="MicroStepPrepared">
+                            <transition target="../MicroStepProcessed">
                                 <script>
                                 <script>
                                     <![CDATA[
                                     <![CDATA[
-                                        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+                                        self.computeBlock()
+                                        self.currentCompIdx = self.currentCompIdx + 1
                                     ]]>
                                     ]]>
                                 </script>
                                 </script>
                                 <raise event="small_step_done" />
                                 <raise event="small_step_done" />
                             </transition>
                             </transition>
                         </state>
                         </state>
                     </state>
                     </state>
-                    <state id="Stopped" />
+                    <state id="Stopped">
+                        <onentry>
+                            <script>
+                                print 'arriving in SimulationFlow/Stopped'
+                            </script>
+                        </onentry>
+                    </state>
                 </state>
                 </state>
                 <state id="BreakpointManager" initial="Listening">
                 <state id="BreakpointManager" initial="Listening">
                     <state id="Listening">
                     <state id="Listening">

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 347856 - 0
debugging_fsa_cbd_composition/cbdsimulator/log.txt


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 3
debugging_fsa_cbd_composition/cbdsimulator/plot.html


+ 122 - 141
debugging_fsa_cbd_composition/cbdsimulator/target.py

@@ -1,7 +1,7 @@
 """
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
 
-Date:   Wed Oct 12 17:10:43 2016
+Date:   Fri Oct 21 13:30:15 2016
 
 
 Model author: Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo
 Model author: Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo
 Model name:   CBDSimulator
 Model name:   CBDSimulator
@@ -68,7 +68,23 @@ class CBDSimulator(RuntimeClassBase):
     
     
     # user defined method
     # user defined method
     def hasNextStrongComponent(self):
     def hasNextStrongComponent(self):
-        return (self.currentCompIdx + 1) < len(self.strongComponentList)
+        return self.currentCompIdx < len(self.strongComponentList)
+    
+    
+    # user defined method
+    def computeBlock(self):
+        if self.currentComponentIsCycle():
+            self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+        else:
+            self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    
+    # user defined method
+    def advanceTime(self):
+        self.iteration = self.iteration + 1
+        self.clock = self.time_next
+        self.cbdController.advanceTimeStep()
+        self.time_next = self.clock + self.delta
     
     
     
     
     # user defined method
     # user defined method
@@ -93,14 +109,6 @@ class CBDSimulator(RuntimeClassBase):
         return self.initialized and self.iteration >= self.options.getMaxIterations()
         return self.initialized and self.iteration >= self.options.getMaxIterations()
     
     
     
     
-    # user defined method
-    def advanceTime(self):
-        self.iteration = self.iteration + 1
-        self.clock = self.time_next
-        self.cbdController.advanceTimeStep()
-        self.time_next = self.clock + self.delta
-    
-    
     # user defined method
     # user defined method
     def finalize(self):
     def finalize(self):
         from bokeh.plotting import figure, output_file, show    
         from bokeh.plotting import figure, output_file, show    
@@ -248,6 +256,7 @@ class CBDSimulator(RuntimeClassBase):
         
         
         # state /Main/SimulationState/Stopped
         # state /Main/SimulationState/Stopped
         self.states["/Main/SimulationState/Stopped"] = State(14, self)
         self.states["/Main/SimulationState/Stopped"] = State(14, self)
+        self.states["/Main/SimulationState/Stopped"].setEnter(self._Main_SimulationState_Stopped_enter)
         
         
         # state /Main/SimulationFlow
         # state /Main/SimulationFlow
         self.states["/Main/SimulationFlow"] = State(15, self)
         self.states["/Main/SimulationFlow"] = State(15, self)
@@ -262,38 +271,35 @@ class CBDSimulator(RuntimeClassBase):
         
         
         # state /Main/SimulationFlow/CheckTerminationCondition
         # state /Main/SimulationFlow/CheckTerminationCondition
         self.states["/Main/SimulationFlow/CheckTerminationCondition"] = State(18, self)
         self.states["/Main/SimulationFlow/CheckTerminationCondition"] = State(18, self)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].setEnter(self._Main_SimulationFlow_CheckTerminationCondition_enter)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].setExit(self._Main_SimulationFlow_CheckTerminationCondition_exit)
+        
+        # state /Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"] = State(19, self)
         
         
         # state /Main/SimulationFlow/Waiting
         # state /Main/SimulationFlow/Waiting
-        self.states["/Main/SimulationFlow/Waiting"] = State(19, self)
+        self.states["/Main/SimulationFlow/Waiting"] = State(20, self)
         self.states["/Main/SimulationFlow/Waiting"].setEnter(self._Main_SimulationFlow_Waiting_enter)
         self.states["/Main/SimulationFlow/Waiting"].setEnter(self._Main_SimulationFlow_Waiting_enter)
         self.states["/Main/SimulationFlow/Waiting"].setExit(self._Main_SimulationFlow_Waiting_exit)
         self.states["/Main/SimulationFlow/Waiting"].setExit(self._Main_SimulationFlow_Waiting_exit)
         
         
-        # state /Main/SimulationFlow/CreateDependencyGraph
-        self.states["/Main/SimulationFlow/CreateDependencyGraph"] = State(20, self)
-        self.states["/Main/SimulationFlow/CreateDependencyGraph"].setEnter(self._Main_SimulationFlow_CreateDependencyGraph_enter)
+        # state /Main/SimulationFlow/DoSimulation
+        self.states["/Main/SimulationFlow/DoSimulation"] = State(21, self)
         
         
-        # state /Main/SimulationFlow/IsolateStrongComponents
-        self.states["/Main/SimulationFlow/IsolateStrongComponents"] = State(21, self)
-        self.states["/Main/SimulationFlow/IsolateStrongComponents"].setEnter(self._Main_SimulationFlow_IsolateStrongComponents_enter)
+        # state /Main/SimulationFlow/DoSimulation/MacroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"] = State(22, self)
         
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"] = State(22, self)
+        # state /Main/SimulationFlow/DoSimulation/MicroStepProcessed
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"] = State(23, self)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].setEnter(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_enter)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].setExit(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_exit)
         
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"] = State(23, self)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].setEnter(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_enter)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].setExit(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_exit)
+        # state /Main/SimulationFlow/DoSimulation/PreMicroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"] = State(24, self)
         
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"] = State(24, self)
-        
-        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"] = State(25, self)
+        # state /Main/SimulationFlow/DoSimulation/MicroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"] = State(25, self)
         
         
         # state /Main/SimulationFlow/Stopped
         # state /Main/SimulationFlow/Stopped
         self.states["/Main/SimulationFlow/Stopped"] = State(26, self)
         self.states["/Main/SimulationFlow/Stopped"] = State(26, self)
+        self.states["/Main/SimulationFlow/Stopped"].setEnter(self._Main_SimulationFlow_Stopped_enter)
         
         
         # state /Main/BreakpointManager
         # state /Main/BreakpointManager
         self.states["/Main/BreakpointManager"] = State(27, self)
         self.states["/Main/BreakpointManager"] = State(27, self)
@@ -340,13 +346,13 @@ class CBDSimulator(RuntimeClassBase):
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/InitializeDebugger"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/InitializeDebugger"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Waiting"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Waiting"])
-        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CreateDependencyGraph"])
-        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/IsolateStrongComponents"])
-        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/DoSimulation"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Stopped"])
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Stopped"])
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"])
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"])
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"])
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"])
         self.states["/Main/BreakpointManager"].addChild(self.states["/Main/BreakpointManager/Listening"])
         self.states["/Main/BreakpointManager"].addChild(self.states["/Main/BreakpointManager/Listening"])
         self.states["/Main/GodEventManager"].addChild(self.states["/Main/GodEventManager/Listening"])
         self.states["/Main/GodEventManager"].addChild(self.states["/Main/GodEventManager/Listening"])
         self.states["/Main/UserOutput"].addChild(self.states["/Main/UserOutput/Waiting"])
         self.states["/Main/UserOutput"].addChild(self.states["/Main/UserOutput/Waiting"])
@@ -355,7 +361,8 @@ class CBDSimulator(RuntimeClassBase):
         self.states["/Main/SimulationState"].default_state = self.states["/Main/SimulationState/Paused"]
         self.states["/Main/SimulationState"].default_state = self.states["/Main/SimulationState/Paused"]
         self.states["/Main/SimulationState/Running"].default_state = self.states["/Main/SimulationState/Running/Continuous"]
         self.states["/Main/SimulationState/Running"].default_state = self.states["/Main/SimulationState/Running/Continuous"]
         self.states["/Main/SimulationFlow"].default_state = self.states["/Main/SimulationFlow/Initialize"]
         self.states["/Main/SimulationFlow"].default_state = self.states["/Main/SimulationFlow/Initialize"]
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].default_state = self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].default_state = self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"]
+        self.states["/Main/SimulationFlow/DoSimulation"].default_state = self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"]
         self.states["/Main/BreakpointManager"].default_state = self.states["/Main/BreakpointManager/Listening"]
         self.states["/Main/BreakpointManager"].default_state = self.states["/Main/BreakpointManager/Listening"]
         self.states["/Main/GodEventManager"].default_state = self.states["/Main/GodEventManager/Listening"]
         self.states["/Main/GodEventManager"].default_state = self.states["/Main/GodEventManager/Listening"]
         self.states["/Main/UserOutput"].default_state = self.states["/Main/UserOutput/Waiting"]
         self.states["/Main/UserOutput"].default_state = self.states["/Main/UserOutput/Waiting"]
@@ -427,70 +434,59 @@ class CBDSimulator(RuntimeClassBase):
         _Main_SimulationFlow_InitializeDebugger_0.setTrigger(None)
         _Main_SimulationFlow_InitializeDebugger_0.setTrigger(None)
         self.states["/Main/SimulationFlow/InitializeDebugger"].addTransition(_Main_SimulationFlow_InitializeDebugger_0)
         self.states["/Main/SimulationFlow/InitializeDebugger"].addTransition(_Main_SimulationFlow_InitializeDebugger_0)
         
         
-        # transition /Main/SimulationFlow/CheckTerminationCondition
-        _Main_SimulationFlow_CheckTerminationCondition_0 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/CreateDependencyGraph"]])
-        _Main_SimulationFlow_CheckTerminationCondition_0.setTrigger(None)
-        _Main_SimulationFlow_CheckTerminationCondition_0.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_0_guard)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_0)
-        _Main_SimulationFlow_CheckTerminationCondition_1 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/Waiting"]])
-        _Main_SimulationFlow_CheckTerminationCondition_1.setTrigger(None)
-        _Main_SimulationFlow_CheckTerminationCondition_1.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_1_guard)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_1)
-        _Main_SimulationFlow_CheckTerminationCondition_2 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/Stopped"]])
-        _Main_SimulationFlow_CheckTerminationCondition_2.setTrigger(Event("_5after"))
-        _Main_SimulationFlow_CheckTerminationCondition_2.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_2_guard)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_2)
+        # transition /Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/DoSimulation"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setAction(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_exec)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/Waiting"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/Stopped"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2)
         
         
         # transition /Main/SimulationFlow/Waiting
         # transition /Main/SimulationFlow/Waiting
         _Main_SimulationFlow_Waiting_0 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
         _Main_SimulationFlow_Waiting_0 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
         _Main_SimulationFlow_Waiting_0.setAction(self._Main_SimulationFlow_Waiting_0_exec)
         _Main_SimulationFlow_Waiting_0.setAction(self._Main_SimulationFlow_Waiting_0_exec)
-        _Main_SimulationFlow_Waiting_0.setTrigger(Event("_6after"))
+        _Main_SimulationFlow_Waiting_0.setTrigger(Event("_5after"))
         self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_0)
         self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_0)
-        _Main_SimulationFlow_Waiting_1 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/CreateDependencyGraph"]])
+        _Main_SimulationFlow_Waiting_1 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/DoSimulation"]])
+        _Main_SimulationFlow_Waiting_1.setAction(self._Main_SimulationFlow_Waiting_1_exec)
         _Main_SimulationFlow_Waiting_1.setTrigger(None)
         _Main_SimulationFlow_Waiting_1.setTrigger(None)
         _Main_SimulationFlow_Waiting_1.setGuard(self._Main_SimulationFlow_Waiting_1_guard)
         _Main_SimulationFlow_Waiting_1.setGuard(self._Main_SimulationFlow_Waiting_1_guard)
         self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_1)
         self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_1)
         
         
-        # transition /Main/SimulationFlow/CreateDependencyGraph
-        _Main_SimulationFlow_CreateDependencyGraph_0 = Transition(self, self.states["/Main/SimulationFlow/CreateDependencyGraph"], [self.states["/Main/SimulationFlow/IsolateStrongComponents"]])
-        _Main_SimulationFlow_CreateDependencyGraph_0.setTrigger(None)
-        self.states["/Main/SimulationFlow/CreateDependencyGraph"].addTransition(_Main_SimulationFlow_CreateDependencyGraph_0)
-        
-        # transition /Main/SimulationFlow/IsolateStrongComponents
-        _Main_SimulationFlow_IsolateStrongComponents_0 = Transition(self, self.states["/Main/SimulationFlow/IsolateStrongComponents"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep"]])
-        _Main_SimulationFlow_IsolateStrongComponents_0.setAction(self._Main_SimulationFlow_IsolateStrongComponents_0_exec)
-        _Main_SimulationFlow_IsolateStrongComponents_0.setTrigger(None)
-        self.states["/Main/SimulationFlow/IsolateStrongComponents"].addTransition(_Main_SimulationFlow_IsolateStrongComponents_0)
-        
-        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setTrigger(Event("_7after"))
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setTrigger(Event("_8after"))
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1)
-        
-        # transition /Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0.setTrigger(None)
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0)
-        
-        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setTrigger(None)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setTrigger(None)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1)
+        # transition /Main/SimulationFlow/DoSimulation/MacroStepPrepared
+        _Main_SimulationFlow_DoSimulation_MacroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"]])
+        _Main_SimulationFlow_DoSimulation_MacroStepPrepared_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_MacroStepPrepared_0)
+        
+        # transition /Main/SimulationFlow/DoSimulation/MicroStepProcessed
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setAction(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_exec)
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setTrigger(Event("_6after"))
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setGuard(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepProcessed_0)
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"], [self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1.setTrigger(Event("_7after"))
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1.setGuard(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_1_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepProcessed_1)
+        
+        # transition /Main/SimulationFlow/DoSimulation/PreMicroStepPrepared
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"]])
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0.setTrigger(None)
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0.setGuard(self._Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0)
+        
+        # transition /Main/SimulationFlow/DoSimulation/MicroStepPrepared
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0.setAction(self._Main_SimulationFlow_DoSimulation_MicroStepPrepared_0_exec)
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepPrepared_0)
         
         
         # transition /Main/BreakpointManager/Listening
         # transition /Main/BreakpointManager/Listening
         _Main_BreakpointManager_Listening_0 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
         _Main_BreakpointManager_Listening_0 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
@@ -550,7 +546,6 @@ class CBDSimulator(RuntimeClassBase):
         
         
         # transition /Main/SimulationState/Running
         # transition /Main/SimulationState/Running
         _Main_SimulationState_Running_0 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/PreStopped"]])
         _Main_SimulationState_Running_0 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/PreStopped"]])
-        _Main_SimulationState_Running_0.setAction(self._Main_SimulationState_Running_0_exec)
         _Main_SimulationState_Running_0.setTrigger(None)
         _Main_SimulationState_Running_0.setTrigger(None)
         _Main_SimulationState_Running_0.setGuard(self._Main_SimulationState_Running_0_guard)
         _Main_SimulationState_Running_0.setGuard(self._Main_SimulationState_Running_0_guard)
         self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_0)
         self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_0)
@@ -599,47 +594,39 @@ class CBDSimulator(RuntimeClassBase):
     def _Main_SimulationState_PreStopped_exit(self):
     def _Main_SimulationState_PreStopped_exit(self):
         self.removeTimer(4)
         self.removeTimer(4)
     
     
+    def _Main_SimulationState_Stopped_enter(self):
+        print 'arriving in SimulationState/Stopped'
+    
     def _Main_SimulationFlow_Initialize_enter(self):
     def _Main_SimulationFlow_Initialize_enter(self):
         self.initialize()
         self.initialize()
     
     
     def _Main_SimulationFlow_InitializeDebugger_enter(self):
     def _Main_SimulationFlow_InitializeDebugger_enter(self):
         self.initializeDebugger()
         self.initializeDebugger()
     
     
-    def _Main_SimulationFlow_CheckTerminationCondition_enter(self):
+    def _Main_SimulationFlow_Waiting_enter(self):
         self.addTimer(5, self.sccd_yield())
         self.addTimer(5, self.sccd_yield())
     
     
-    def _Main_SimulationFlow_CheckTerminationCondition_exit(self):
+    def _Main_SimulationFlow_Waiting_exit(self):
         self.removeTimer(5)
         self.removeTimer(5)
     
     
-    def _Main_SimulationFlow_Waiting_enter(self):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_enter(self):
         self.addTimer(6, self.sccd_yield())
         self.addTimer(6, self.sccd_yield())
+        self.addTimer(7, self.sccd_yield() * 3)
     
     
-    def _Main_SimulationFlow_Waiting_exit(self):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_exit(self):
         self.removeTimer(6)
         self.removeTimer(6)
-    
-    def _Main_SimulationFlow_CreateDependencyGraph_enter(self):
-        self.depGraph = self.cbdController.createDepGraph(self.iteration)
-    
-    def _Main_SimulationFlow_IsolateStrongComponents_enter(self):
-        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_enter(self):
-        self.addTimer(7, self.sccd_yield() * 2)
-        self.addTimer(8, self.sccd_yield())
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_exit(self):
         self.removeTimer(7)
         self.removeTimer(7)
-        self.removeTimer(8)
+    
+    def _Main_SimulationFlow_Stopped_enter(self):
+        print 'arriving in SimulationFlow/Stopped'
     
     
     def _Main_0_exec(self, parameters):
     def _Main_0_exec(self, parameters):
+        print 'finalizing'
         self.finalize()
         self.finalize()
     
     
     def _Main_0_guard(self, parameters):
     def _Main_0_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Stopped"]) and self.inState(["/Main/SimulationFlow/Stopped"])
         return self.inState(["/Main/SimulationState/Stopped"]) and self.inState(["/Main/SimulationFlow/Stopped"])
     
     
-    def _Main_SimulationState_Running_0_exec(self, parameters):
-        self.raiseInternalEvent(Event("termination_condition", None, []))
-    
     def _Main_SimulationState_Running_0_guard(self, parameters):
     def _Main_SimulationState_Running_0_guard(self, parameters):
         return self.endCondition()
         return self.endCondition()
     
     
@@ -662,56 +649,50 @@ class CBDSimulator(RuntimeClassBase):
     def _Main_SimulationState_PreStopped_0_exec(self, parameters):
     def _Main_SimulationState_PreStopped_0_exec(self, parameters):
         self.raiseInternalEvent(Event("termination_condition", None, []))
         self.raiseInternalEvent(Event("termination_condition", None, []))
     
     
-    def _Main_SimulationFlow_CheckTerminationCondition_0_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_exec(self, parameters):
+        self.currentCompIdx = 0
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Running/Continuous"]) or self.inState(["/Main/SimulationState/Running/BigStep"]) or self.inState(["/Main/SimulationState/Running/SmallStep"])
         return self.inState(["/Main/SimulationState/Running/Continuous"]) or self.inState(["/Main/SimulationState/Running/BigStep"]) or self.inState(["/Main/SimulationState/Running/SmallStep"])
     
     
-    def _Main_SimulationFlow_CheckTerminationCondition_1_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Running/Realtime"])
         return self.inState(["/Main/SimulationState/Running/Realtime"])
     
     
-    def _Main_SimulationFlow_CheckTerminationCondition_2_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Stopped"])
         return self.inState(["/Main/SimulationState/Stopped"])
     
     
     def _Main_SimulationFlow_Waiting_0_exec(self, parameters):
     def _Main_SimulationFlow_Waiting_0_exec(self, parameters):
         diff = accurate_time.time() - self.realtime_start_time
         diff = accurate_time.time() - self.realtime_start_time
         self.clock = diff * self.realtime_scale
         self.clock = diff * self.realtime_scale
     
     
+    def _Main_SimulationFlow_Waiting_1_exec(self, parameters):
+        self.currentCompIdx = 0
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
     def _Main_SimulationFlow_Waiting_1_guard(self, parameters):
     def _Main_SimulationFlow_Waiting_1_guard(self, parameters):
         return self.waitTime() / 1000.0 <= self.sccd_yield()
         return self.waitTime() / 1000.0 <= self.sccd_yield()
     
     
-    def _Main_SimulationFlow_IsolateStrongComponents_0_exec(self, parameters):
-        self.currentCompIdx = -1
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec(self, parameters):
-        self.currentCompIdx = self.currentCompIdx + 1
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard(self, parameters):
-        return self.hasNextStrongComponent()
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec(self, parameters):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_exec(self, parameters):
         self.advanceTime()
         self.advanceTime()
-        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
         self.raiseInternalEvent(Event("big_step_done", None, []))
         self.raiseInternalEvent(Event("big_step_done", None, []))
     
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard(self, parameters):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_guard(self, parameters):
         return not self.hasNextStrongComponent()
         return not self.hasNextStrongComponent()
     
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0_guard(self, parameters):
-        return self.inState(["/Main/SimulationState/Running"])
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec(self, parameters):
-        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
-        self.raiseInternalEvent(Event("small_step_done", None, []))
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1_guard(self, parameters):
+        return self.hasNextStrongComponent()
     
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard(self, parameters):
-        return not self.currentComponentIsCycle()
+    def _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running"])
     
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec(self, parameters):
-        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+    def _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0_exec(self, parameters):
+        self.computeBlock()
+        self.currentCompIdx = self.currentCompIdx + 1
         self.raiseInternalEvent(Event("small_step_done", None, []))
         self.raiseInternalEvent(Event("small_step_done", None, []))
     
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard(self, parameters):
-        return self.currentComponentIsCycle()
-    
     def _Main_BreakpointManager_Listening_0_exec(self, parameters):
     def _Main_BreakpointManager_Listening_0_exec(self, parameters):
         name = parameters[0]
         name = parameters[0]
         function = parameters[1]
         function = parameters[1]

+ 885 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBD.py

@@ -0,0 +1,885 @@
+import math
+import naivelog
+from collections import namedtuple
+
+InputLink = namedtuple("InputLink", ["block", "output_port"])
+Signal = namedtuple("Signal", ["time", "value"])
+def enum(**enums):
+            return type('Enum', (), enums)
+level = enum(WARNING=1, ERROR=2, FATAL=3)	
+epsilon = 0.001		
+
+class BaseBlock:
+    """
+    A base class for all types of basic blocks
+    """
+    def __init__(self, name, input_ports, output_ports):
+        self.setBlockName(name)
+
+        #The output signals produced by this block is encoded as a dictionary.
+        #The key of this dictionary is the name of the output port.
+        #Each element of the dictionary contains an ordered list of values.
+        self.__signals = dict()
+        for output_port in output_ports:
+            self.__signals[output_port] = []
+        
+        self._output_ports = output_ports
+        
+        #The input links produced by this block is encoded as a dictionary.
+        #The key of this dictionary is the name of the input port.
+        #Each element of the dictionary contains
+        #an tuple of the block and the output name of the other block.
+        self._linksIn = dict()
+
+        #The list of possible input ports
+        self.__nameLinks = input_ports
+        #In wich CBD the baseblock is situated
+        self._parent = None
+    
+    def getOutputPorts(self):
+        return self._output_ports
+    
+    def resetSignals(self):
+        for output_port in self.__signals:
+            self.__signals[output_port] = []
+    
+    def getBlockName(self):
+        return self.__block_name
+
+    def setBlockName(self, block_name):
+        self.__block_name = block_name
+
+    def setParent(self, parent):
+        self._parent = parent
+
+    def getBlockType(self):
+        return self.__class__.__name__
+
+    def getLinksIn(self):
+        return self._linksIn
+
+    def getOutputNameOfInput(self, inputBlock):
+        return [ y for (x,y) in self._linksIn.iteritems() if y.block == inputBlock ][0].output_port
+
+    def getInputName(self, inputBlock):
+        return [ x for (x,y) in self._linksIn.iteritems() if y.block == inputBlock ]
+
+    def getClock(self):
+        return self._parent.getClock()
+
+    def appendToSignal(self, value, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        assert name_output in self.__signals.keys()
+        self.__signals[name_output].append(Signal(self.getClock().getTime(), value))
+
+    def getSignal(self, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        assert name_output in self.__signals.keys()
+        return self.__signals[name_output] if name_output != None else self.__signals["OUT1"]
+
+    def getDependencies(self, curIteration):
+        return list(set([ tup.block for tup in self._linksIn.values() ]))
+
+    def getBlockConnectedToInput(self, input_port):
+        return self._linksIn[input_port]
+
+    def getInputSignal(self, curIteration, input_port = None):
+        """
+        Returns the signal sent out by the input block (IN1 if none given,
+        at the last time if no curIteration is given).
+        """
+        input_port = "IN1" if input_port == None else input_port
+        curIteration = -1 if curIteration == None else curIteration
+
+        (incoming_block, out_port_name) = self._linksIn[input_port]
+        return incoming_block.getSignal(out_port_name)[curIteration]
+
+    def compute(self, curIteration):
+        exit("BaseBlock has nothing to compute")
+
+    def linkInput(self, in_block, name_input, name_output):
+        """
+        linkInput will link the output of the from_block to the input of the to_block
+        -if no name_input was given for the to_block, we will derive the right input,
+        by checking which input IN has nothing connected to it yet
+        -if no name_output was given we use the first OUT output
+        """
+        name_output = "OUT1" if name_output == None else name_output
+        if name_input != None:
+            assert name_input in self.__nameLinks
+            self._linksIn[name_input] = InputLink(in_block, name_output)
+        else:
+            i = 1
+            while True:
+                nextIn = "IN" + str(i)
+                if nextIn in self.__nameLinks:
+                    if not nextIn in self._linksIn:
+                        self._linksIn[nextIn] = InputLink(in_block, name_output)
+                        return
+                else:
+                    exit("There are no open IN inputs left in block %s" % self.getBlockName())
+                i += 1
+
+    def __repr__(self):
+        repr = self.getBlockName() + ":" + self.getBlockType() + "\n"
+        if len(self._linksIn) == 0:
+            repr+= "  No incoming connections to IN ports\n"
+        else:
+            for (key, (in_block, out_port)) in self._linksIn.iteritems():
+                repr += "In input " + key + ":  IN <- " + in_block.getBlockName() + ":" + in_block.getBlockType() + "\n"
+        return repr
+
+class ConstantBlock(BaseBlock):
+    """
+    The constant block will always output its constant value
+    """
+    def __init__(self, block_name, value=0.0):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.__value = value
+
+    def getValue(self):
+        return self.__value
+
+    def setValue(self, value):
+        self.__value = value
+
+    def compute(self, curIteration):
+        self.appendToSignal(self.getValue())
+
+    def __repr__(self):
+        return BaseBlock.__repr__(self) + "  Value = " + str(self.getValue()) + "\n"
+
+class NegatorBlock(BaseBlock):
+    """
+    The negator block will output the value of the input multiplied with -1
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(-self.getInputSignal(curIteration).value)
+
+class InverterBlock(BaseBlock):
+    """
+    The invertblock will output 1/IN
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(1.0/self.getInputSignal(curIteration).value)
+
+class AdderBlock(BaseBlock):
+    """
+    The adderblock will add the 2 inputs
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value + self.getInputSignal(curIteration, "IN2").value)
+
+class ProductBlock(BaseBlock):
+    """
+    The product block will multiply the two inputs
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value * self.getInputSignal(curIteration, "IN2").value)
+
+class GenericBlock(BaseBlock):
+    """
+    The generic block will evaluate the operator on the input
+    operator is the name (a string) of a Python function from the math library
+    which will be called when the block is evaluated
+    by default, initialized to None
+    """
+    def __init__(self, block_name, block_operator=None):
+        # operator is the name (a string) of a Python function from the math library
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.__block_operator = block_operator
+
+    def getBlockOperator(self):
+        return self.__block_operator
+
+    def compute(self, curIteration):
+        operator = getattr(math, self.getBlockOperator())
+        self.appendToSignal(operator(self.getInputSignal(curIteration).value))
+
+    def __repr__(self):
+        repr = BaseBlock.__repr__(self)
+        if self.__block_operator == None:
+            repr += "  No operator given\n"
+        else:
+            repr += "  Operator :: " + self.__block_operator + "\n"
+        return repr
+
+class RootBlock(BaseBlock):
+    """
+    A basic block that computes the IN2-th root from IN1
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(pow(self.getInputSignal(curIteration, "IN1").value, 1.0/self.getInputSignal(curIteration, "IN2").value))
+
+class ModuloBlock(BaseBlock):
+    """
+    A basic block that computes the IN1 modulo IN3
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(math.fmod(self.getInputSignal(curIteration, "IN1").value, self.getInputSignal(curIteration, "IN2").value))
+
+class DelayBlock(BaseBlock):
+    """
+    A delay block that takes the last value from the list
+    IC: Initial Condition
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IC"], ["OUT1"])
+        self.__values = []
+
+    def getDependencies(self, curIteration):
+        if curIteration == 0:
+            return [self._linksIn["IC"].block]
+        return []
+    
+    def resetSignals(self):
+        BaseBlock.resetSignals(self)
+        self.__values = []
+    
+    def compute(self, curIteration):
+        if curIteration == 0:
+            outputValue = self.getInputSignal(curIteration, "IC")
+            self.appendToSignal(outputValue.value)
+        else:
+            assert curIteration == len(self.__values)+1
+            (incoming_block, out_port_name) = self._linksIn["IN1"]
+            self.__values.append(incoming_block.getSignal(out_port_name)[curIteration-1])
+            self.appendToSignal(self.__values[curIteration-1].value)
+    
+class InputPortBlock(BaseBlock):
+    """
+    The input port of a CBD
+    """
+    def __init__(self, block_name, parent):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.parent = parent
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.parent.getInputSignal(curIteration, self.getBlockName()).value)
+
+class OutputPortBlock(BaseBlock):
+    """
+    The output port of a CBD
+    """
+    def __init__(self, block_name, parent):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.parent = parent
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
+
+class WireBlock(BaseBlock):
+    """
+    When a CBD gets flattened, the port blocks will be replaced by a wire block
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
+
+class TimeBlock(BaseBlock):
+    """
+    Outputs the current time of the simulation
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getClock().getTime())
+
+class LessThanBlock(BaseBlock):
+    """
+    A simple block that will test if the IN1 is smaller than IC (output == 1 if true else 0)
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IC", "IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        gisv = lambda s: self.getInputSignal(curIteration, s).value
+        self.appendToSignal(1 if gisv("IN1") < gisv("IC") else 0)
+
+class EqualsBlock(BaseBlock):
+    """
+    A simple block that will test if the IN1 is equal to IC (output == 1 if true else 0)
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IC", "IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        gisv = lambda s: self.getInputSignal(curIteration, s).value
+        self.appendToSignal(1 if gisv("IN1") == gisv("IC") else 0)
+
+class NotBlock(BaseBlock):
+    """
+    A simple Not block that will set a 0 to 1 and vice versa
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        result = 0 if self.getInputSignal(curIteration, "IN1").value else 1
+        self.appendToSignal(result)    
+
+class OrBlock(BaseBlock):
+    """
+    A simple Or block with possibly multiple inputlines
+    """
+    def __init__(self, block_name, numberOfInputs=2):
+        BaseBlock.__init__(self, block_name, ["IN{0}".format(i) for i in xrange(1,numberOfInputs+1)], ["OUT1"])
+        self.__numberOfInputs = numberOfInputs
+
+    def	compute(self, curIteration):
+        result = 0
+        for i in xrange(1, self.__numberOfInputs+1):
+            result = result or self.getInputSignal(curIteration, "IN"+str(i)).value
+        self.appendToSignal(result)    
+
+class AndBlock(BaseBlock):
+    """
+    A simple And block with possibly multiple inputlines
+    """
+    def __init__(self, block_name, numberOfInputs=2):
+        BaseBlock.__init__(self, block_name, ["IN{0}".format(i) for i in xrange(1,numberOfInputs+1)], ["OUT1"])
+        self.__numberOfInputs = numberOfInputs
+
+    def	compute(self, curIteration):
+        result = 1
+        for i in xrange(1, self.__numberOfInputs+1):
+            result = result and self.getInputSignal(curIteration, "IN"+str(i)).value
+        self.appendToSignal(result)
+
+class SequenceBlock(BaseBlock):
+    """
+    A simple Sequence block: block initializes signal input with given sequence
+    Use only for the tests please
+    """
+    def __init__(self, block_name, sequence):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.__sequence = sequence
+
+    def	compute(self, curIteration):
+        if len(self.__sequence) < curIteration:
+            self.__logger.fatal("Sequence is not long enough")
+        self.appendToSignal(self.__sequence[curIteration])
+
+class LoggingBlock(BaseBlock):
+    """
+    A simple Logging block
+    """
+    def __init__(self, block_name, string, lev = level.WARNING):
+        BaseBlock.__init__(self, block_name, ["IN1"], [])
+        self.__string = string
+        self.__logger = naivelog.getLogger("WarningLog")
+        self.__lev = lev
+
+    def	compute(self, curIteration):
+        if self.getInputSignal(curIteration, "IN1").value == 1:
+            if self.__lev == level.WARNING:
+                self.__logger.warning("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+            elif self.__lev == level.ERROR:
+                self.__logger.error("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+            elif self.__lev == level.FATAL:
+                self.__logger.fatal("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+
+class Clock:
+    """
+    The clock of the simulation
+    delta_t is the timestep of the simulation
+    """
+    def __init__(self, delta_t):
+        self.__delta_t = delta_t
+        self.__time = 0.0
+
+    def getTime(self):
+        return self.__time
+
+    def step(self):
+        self.__time = self.__time + self.__delta_t
+
+    def setDeltaT(self, new_delta_t):
+        self.__delta_t = new_delta_t
+
+    def getDeltaT(self):
+        return self.__delta_t
+
+class CBD(BaseBlock):
+    """
+    The CBD class, contains an entire Causal Block Diagram
+    Call the run function to simulate the model.
+    """
+    def __init__(self, block_name, input_ports = None, output_ports = None):
+        input_ports = input_ports if input_ports != None else []
+        output_ports = output_ports if output_ports != None else []
+        BaseBlock.__init__(self, block_name, input_ports, output_ports)
+        #The blocks in the CBD will be stored both
+        #-as an ordered list __blocks and
+        #-as a dictionary __blocksDict with the blocknames as keys
+        #for fast name-based retrieval and to ensure block names are unique within a single CBD
+        self.__blocks = []
+        self.__blocksDict = {}
+        self.__clock = None
+        self.__deltaT = None
+        self.__logger = naivelog.getLogger("CBD")
+
+        for input_port in input_ports:
+            self.addBlock(InputPortBlock(input_port, self))
+
+        for output_port in output_ports:
+            self.addBlock(OutputPortBlock(output_port, self))
+
+    def getTopCBD(self):
+        return self if self._parent == None else self._parent.getTopCBD()
+
+    def setBlocks(self, blocks):
+        # blocks must be a list of BaseBlock (subclass) instances
+        assert type(blocks) == list, ("CBD.setBlocks() takes a list as argument, not a %s" % type(blocks))
+        for block in blocks:
+            assert isinstance(block, BaseBlock), "CBD.setBlocks() takes a list of BaseBlock (subclass) instances"
+
+    def getBlocks(self):
+        return self.__blocks
+
+    def getBlockByName(self, name):
+        return self.__blocksDict[name]
+    
+    def setClock(self, clock):
+        self.__clock = clock;
+    
+    def getClock(self):
+        return self.__clock if self._parent == None else self._parent.getClock()
+
+    def setDeltaT(self, deltaT):
+        self.__deltaT = deltaT
+
+    def addBlock(self, block):
+        """
+        Add a block to the CBD model
+        """
+        assert isinstance(block, BaseBlock), "Can only add BaseBlock (subclass) instances to a CBD"
+        block.setParent(self)
+
+        if not self.__blocksDict.has_key(block.getBlockName()):
+            self.__blocks.append(block)
+            self.__blocksDict[block.getBlockName()] = block
+        else:
+            print("Warning: did not add this block as it has the same name %s as an existing block" % block.getBlockName())
+
+    def removeBlock(self, block):
+        assert isinstance(block, BaseBlock), "Can only delete BaseBlock (subclass) instances to a CBD"
+
+        if self.__blocksDict.has_key(block.getBlockName()):
+            self.__blocks.remove(block)
+            del self.__blocksDict[block.getBlockName()]
+        else:
+            exit("Warning: did not remove this block %s as it was not found" % block.getBlockName())
+
+    def addConnection(self, from_block, to_block, input_port_name = None, output_port_name = None):
+        """
+        Add a connection between from_block with input_port_name to to_block with outport_port_name
+        """
+        if type(from_block) == str:
+            from_block = self.getBlockByName(from_block)
+        if type(to_block) == str:
+            to_block = self.getBlockByName(to_block)
+        to_block.linkInput(from_block, input_port_name, output_port_name)
+
+    def __repr__(self):
+        repr = BaseBlock.__repr__(self)
+        repr += "\n"
+        for block in self.getBlocks():
+            repr+= block.__repr__()
+        return repr
+
+    def dump(self):
+        print("=========== Start of Model Dump ===========")
+        print(self)
+        print("=========== End of Model Dump =============\n")
+
+    def dumpSignals(self):
+        print("=========== Start of Signals Dump ===========")
+        for block in self.getBlocks():
+            print("%s:%s" % (block.getBlockName(), block.getBlockType()))
+            print(str(block.getSignal()) + "\n")
+        print("=========== End of Signals Dump =============\n")
+    
+    def resetSignals(self):
+        for block in self.getBlocks():
+            block.resetSignals()
+    
+    def getSignal(self, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        portBlock = self.getBlockByName(name_output)
+        assert portBlock != None
+        return portBlock.getSignal("OUT1")
+    
+    
+class AddOneBlock(CBD):
+    """
+    Block adds a one to the input (used a lot for mux)
+    """
+    def __init__(self, block_name, faultOrder=3):
+        CBD.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.addBlock(ConstantBlock(block_name="OneConstant", value=1))
+        self.addBlock(AdderBlock("PlusOne"))
+        self.addConnection("IN1", "PlusOne")
+        self.addConnection("OneConstant", "PlusOne")
+        self.addConnection("PlusOne", "OUT1")
+
+class DerivatorBlock(CBD):
+    """
+    The derivator block is a CBD that calculates the derivative
+    """
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["IN1", "delta_t", "IC"], ["OUT1"])
+        self.addBlock(ProductBlock(block_name="multIc"))
+        self.addBlock(NegatorBlock(block_name="neg1"))
+        self.addBlock(AdderBlock(block_name="sum1"))
+        self.addBlock(DelayBlock(block_name="delay"))
+        self.addBlock(NegatorBlock(block_name="neg2"))
+        self.addBlock(AdderBlock(block_name="sum2"))
+        self.addBlock(ProductBlock(block_name="mult"))
+        self.addBlock(InverterBlock(block_name="inv"))
+        
+        self.addConnection("IC", "multIc")
+        self.addConnection("delta_t", "multIc")
+        self.addConnection("multIc", "neg1")
+        self.addConnection("neg1", "sum1")
+        self.addConnection("IN1", "sum1")
+        self.addConnection("sum1", "delay", input_port_name="IC")
+        self.addConnection("IN1", "delay", input_port_name="IN1")
+        self.addConnection("delay", "neg2")
+        self.addConnection("neg2", "sum2")
+        self.addConnection("IN1", "sum2")
+        self.addConnection("sum2", "mult")
+        self.addConnection("delta_t", "inv")
+        self.addConnection("inv", "mult")
+        self.addConnection("mult", "OUT1")
+        
+
+class IntegratorBlock(CBD):
+    """
+    The integrator block is a CBD that calculates the integration
+    """
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["IN1", "delta_t", "IC"], ["OUT1"])
+        self.addBlock(ConstantBlock(block_name="zero", value=0))
+        self.addBlock(DelayBlock(block_name="delayIn"))
+        self.addBlock(ProductBlock(block_name="multDelta"))
+        self.addBlock(DelayBlock(block_name="delayState"))
+        self.addBlock(AdderBlock(block_name="sumState"))
+        
+        self.addConnection("zero", "delayIn", input_port_name="IC")
+        self.addConnection("IN1", "delayIn", input_port_name="IN1")
+        self.addConnection("delayIn", "multDelta")
+        self.addConnection("delta_t", "multDelta")
+        self.addConnection("multDelta", "sumState")
+        self.addConnection("IC", "delayState", input_port_name="IC")
+        self.addConnection("delayState", "sumState")
+        self.addConnection("sumState", "delayState", input_port_name="IN1")
+        self.addConnection("sumState", "OUT1")
+        
+        
+
+""" This module implements a dependency graph
+    @author: Marc Provost
+    @organization: McGill University
+    @license: GNU General Public License
+    @contact: marc.provost@mail.mcgill.ca
+"""
+
+import copy
+class DepNode:
+    """ Class implementing a node in the dependency graph.
+    """
+
+    def __init__(self, object):
+        """ DepNode's constructor.
+                @param object: Reference to a semantic object identifying the node
+                @type object: Object
+        """
+        self.__object = object
+        self.__isMarked	 = False
+
+    def mark(self):
+        self.__isMarked = True
+
+    def unMark(self):
+        self.__isMarked = False
+
+    def isMarked(self):
+        return self.__isMarked
+
+    def getMappedObj(self):
+        return self.__object
+
+    def __repr__(self):
+        return "DepNode :: "+str(self.__object)
+
+class DepGraph:
+    """ Class implementing dependency graph.
+    """
+
+    def __init__(self):
+        """ DepGraph's constructor.
+        """
+        #Dict holding a mapping "Object -> DepNode"
+        self.__semanticMapping = {}
+
+        #map object->list of objects depending on object
+        self.__dependents = {}
+        #map object->list of objects that influences object
+        self.__influencers = {}
+
+    def __repr__(self):
+        repr = "Dependents: \n"
+        for dep in self.__dependents:
+            repr += dep.getBlockName() + ":" + str(self.__dependents[dep]) + "\n"
+        repr += "Influencers: \n"
+        for infl in self.__influencers:
+            repr += infl.getBlockName() + ":" + str(self.__influencers[infl]) + "\n"
+        return repr
+
+    def addMember(self, object):
+        """ Add an object mapped to this graph.
+                @param object: the object to be added
+                @type object: Object
+                @raise ValueError: If object is already in the graph
+        """
+        if not self.hasMember(object):
+            if not isinstance(object, CBD):
+                node = DepNode(object)
+                self.__dependents[object] = []
+                self.__influencers[object] = []
+                self.__semanticMapping[object] = node
+            else:
+                for block in object.getBlocks():
+                    self.addMember(block)
+        else:
+            raise ValueError("Specified object is already member of this graph")
+
+    def hasMember(self, object):
+        return self.__semanticMapping.has_key(object)
+
+    def removeMember(self, object):
+        """ Remove a object from this graph.
+                @param object: the object to be removed
+                @type object: Object
+                @raise ValueError: If object is not in the graph
+        """
+        if self.hasMember(object):
+            for dependent in self.getDependents(object):
+                self.__influencers[dependent].remove(object)
+            for influencer in self.getInfluencers(object):
+                self.__dependents[influencer].remove(object)
+
+            del self.__dependents[object]
+            del self.__influencers[object]
+            del self.__semanticMapping[object]
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def setDependency(self, dependent, influencer, curIt):
+        """
+            Creates a dependency between two objects.
+                @param dependent: The object which depends on the other
+                @param influcencer: The object which influences the other
+                @type dependent: Object
+                @type dependent: Object
+                @raise ValueError: if depedent or influencer is not member of this graph
+                @raise ValueError: if the dependency already exists
+        """
+
+        # Link CBD outputs
+        if isinstance(influencer, CBD):
+            # When there is more than one connection from a CBD to one and the same block,
+            # more than one dependency should be set, as there is more than one underlying
+            # output block
+            for output_port in [ y.output_port for (x,y) in dependent.getLinksIn().iteritems() if y.block == influencer ]:
+                self.setDependency(dependent, influencer.getBlockByName(output_port), curIt)
+            return
+
+        # Link CBD inputs
+        if isinstance(dependent, CBD):
+            cbd = dependent
+            directlyConnected = influencer.parent if isinstance(influencer, OutputPortBlock) else influencer
+            inputnames = dependent.getInputName(directlyConnected)
+
+            # When one influencer has multiple connections to this CBD, call this function once fo
+            for inputname in inputnames:
+                inputtingBlock = dependent.getBlockByName(inputname)
+                thisdep = inputtingBlock
+                self.setDependency(thisdep, influencer, curIt)
+            return
+
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            if not influencer in self.__influencers[dependent] and\
+                 not dependent in self.__dependents[influencer]:
+                self.__influencers[dependent].append(influencer)
+                self.__dependents[influencer].append(dependent)
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                print(influencer)
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def hasDependency(self, dependent, influencer):
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            return influencer in self.__influencers[dependent] and\
+                         dependent in self.__dependents[influencer]
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def unsetDependency(self, dependent, influencer):
+        """ Removes a dependency between two objects.
+                @param dependent: The object which depends on the other
+                @param influcencer: The object which influences the other
+                @type dependent: Object
+                @type dependent: Object
+                @raise ValueError: if depedent or influencer is not member of this graph
+                @raise ValueError: if the dependency does not exists
+        """
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            if influencer in self.__influencers[dependent] and\
+                 dependent in self.__dependents[influencer]:
+                self.__influencers[dependent].remove(influencer)
+                self.__dependents[influencer].remove(dependent)
+            else:
+                raise ValueError("Specified dependency does not exists")
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def getDependents(self, object):
+        if self.hasMember(object):
+            return copy.copy(self.__dependents[object])
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def getInfluencers(self, object):
+        if self.hasMember(object):
+            return copy.copy(self.__influencers[object])
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def getStrongComponents(self, curIt = 1):
+        return self.__strongComponents(curIt)
+
+    def __getDepNode(self, object):
+        if self.hasMember(object):
+            return self.__semanticMapping[object]
+        else:
+            raise ValueError("Specified object is not a member of this graph")
+
+    def __mark(self, object):
+        self.__getDepNode(object).mark()
+
+    def __unMark(self, object):
+        self.__getDepNode(object).unMark()
+
+    def __isMarked(self, object):
+        return self.__getDepNode(object).isMarked()
+
+    def __topoSort(self):
+        """ Performs a topological sort on the graph.
+        """
+        for object in self.__semanticMapping.keys():
+            self.__unMark(object)
+
+        sortedList = []
+
+        for object in self.__semanticMapping.keys():
+            if not self.__isMarked(object):
+                self.__dfsSort(object, sortedList)
+
+        return sortedList
+
+    def __dfsSort(self, object, sortedList):
+        """ Performs a depth first search collecting
+                the objects in topological order.
+                @param object: the currently visited object.
+                @param sortedList: partial sorted list of objects
+                @type object: Object
+                @type sortedList: list Of Object
+        """
+
+        if not self.__isMarked(object):
+            self.__mark(object)
+
+            for influencer in self.getInfluencers(object):
+                self.__dfsSort(influencer, sortedList)
+
+            sortedList.append(object)
+
+    def __strongComponents(self, curIt):
+        """ Determine the strong components of the graph
+                @rtype: list of list of Object
+        """
+        strongComponents = []
+        sortedList = self.__topoSort()
+
+        for object in self.__semanticMapping.keys():
+            self.__unMark(object)
+
+        sortedList.reverse()
+
+        for object in sortedList:
+            if not self.__isMarked(object):
+                component = []
+                self.__dfsCollect(object, component, curIt)
+                strongComponents.append(component)
+
+        strongComponents.reverse()
+        return strongComponents
+
+    def __dfsCollect(self, object, component, curIt):
+        """ Collects objects member of a strong component.
+                @param object: Node currently visited
+                @param component: current component
+                @type object: Object
+                @type component: List of Object
+        """
+        if not self.__isMarked(object):
+            self.__mark(object)
+
+            for dependent in self.getDependents(object):
+                self.__dfsCollect(dependent, component, curIt)
+
+            component.append(object)
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 54 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBDDraw.py

@@ -0,0 +1,54 @@
+from CBD import *
+
+def draw(cbd, filename, colors=None):
+	""" Output cbd as a dot script to filename.
+
+	colors is a dictionary of blockname => color
+	"""
+	f = open(filename, "w")
+	write = lambda s: f.write(s)
+
+	write("""
+digraph graphname {
+ """)
+
+	if colors == None:
+		colors = {}
+
+	def writeBlock(block):
+		if isinstance(block, ConstantBlock):
+			label = block.getBlockType() + " (" + block.getBlockName() + ")\\n" + str(block.getValue())
+		else:
+			label = block.getBlockType() + " (" + block.getBlockName() + ")"
+
+		shape = ""
+		if isinstance(block, CBD):
+			shape=",shape=Msquare"
+
+		col = ""
+		if block.getBlockName() in colors:
+			col = ", color=\"{0}\", fontcolor=\"{0}\"".format(colors[block.getBlockName()])
+
+		write("{b} [label=\"{lbl}\"{shape}{col}];\n".format(b=block.getBlockName(),
+			lbl=label,
+			shape=shape,
+			col=col))
+
+
+	for block in cbd.getBlocks():
+		writeBlock(block)
+		for (name, other) in  block.getLinksIn().iteritems():
+			label = ""
+
+			if not name.startswith("IN"):
+				label=name
+
+			if not other.output_port.startswith("OUT"):
+				label = label + " / " + other.output_port
+
+			write("{a} -> {b} [label=\"{lbl}\"];\n".format(a=other.block.getBlockName(),
+				b=block.getBlockName(),
+				lbl=label))
+
+	write("\n}")
+

+ 0 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/__init__.py


+ 129 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/naivelog.py

@@ -0,0 +1,129 @@
+import os
+import sys
+import datetime
+(DEBUG, INFO, WARNING, ERROR, FATAL) = (0, 1, 2, 3, 4)
+
+def strToLevel(elvl):
+	if elvl == "DEBUG":
+		return DEBUG
+	if elvl == "INFO":
+		return INFO
+	if elvl == "WARNING":
+		return WARNING
+	if elvl == "ERROR":
+		return ERROR
+	if elvl == "FATAL":
+		return FATAL
+	else:
+		return None
+
+def levelToStr(lvl):
+	if lvl == DEBUG:
+		return "DEBUG"
+	if lvl == INFO:
+		return "INFO"
+	if lvl == WARNING:
+		return "WARNING"
+	if lvl == ERROR:
+		return "ERROR"
+	if lvl == FATAL:
+		return "FATAL"
+	return None
+
+
+def levelToShortStr(lvl):
+	if lvl == DEBUG:
+		return "DBUG"
+	if lvl == INFO:
+		return "INFO"
+	if lvl == WARNING:
+		return "WARN"
+	if lvl == ERROR:
+		return "ERROR"
+	if lvl == FATAL:
+		return "FATAL"
+	return None
+
+class Logger:
+	def __init__(self, modulename, level, crashlevel):
+		self.__modulename = modulename
+		self.__level = level
+		self.__crashlevel = crashlevel
+
+	def debug(self, mainstr, *args, **kwargs):
+		self.log(DEBUG, mainstr, *args, **kwargs)
+	def info(self, mainstr, *args, **kwargs):
+		self.log(INFO, mainstr, *args, **kwargs)
+	def warning(self, mainstr, *args, **kwargs):
+		self.log(WARNING, mainstr, *args, **kwargs)
+	def error(self, mainstr, *args, **kwargs):
+		self.log(ERROR, mainstr, *args, **kwargs)
+	def fatal(self, mainstr, *args, **kwargs):
+		self.log(FATAL, mainstr, *args, **kwargs)
+
+	def log(self, level, mainstr, *args, **kwargs):
+		if level >= self.__level:
+			sys.stdout.write(self.formatmsg(level,str(mainstr).format(*args, **kwargs)))
+
+		if level >= self.__crashlevel:
+			exit(1)
+
+	def setLevel(self, level):
+		self.__level = level
+
+	def formatmsg(self, level, mainstr):
+		class bcolors:
+			HEADER = '\033[95m'
+			OKBLUE = '\033[94m'
+			OKGREEN = '\033[92m'
+			WARNING = '\033[93m'
+			FAIL = '\033[91m'
+			ENDC = '\033[0m'
+	
+
+		col = bcolors.OKGREEN
+		if level >= WARNING:
+			col = bcolors.WARNING
+		if level >= ERROR:
+			col = bcolors.FAIL
+
+		return "{startcol}[{now:%H:%M:%S.%f} {module} {lvl}] {mainstr}{endcol}\n".format(
+				lvl=levelToShortStr(level),
+				module=self.__modulename,
+				now=datetime.datetime.today(),
+				mainstr=mainstr,
+				startcol=col,
+				endcol=bcolors.ENDC);
+
+defaultLogLevel = INFO
+defaultCrashLevel = FATAL
+
+def getAbstractLogLevel(env, default):
+	elvl = os.environ[env] if env in os.environ else ''
+
+	lvl = strToLevel(elvl)
+	if lvl:
+		return lvl
+	else:
+		return default
+
+def getLogLevel():
+	return getAbstractLogLevel('NAIVE_LOGLEVEL', defaultLogLevel)
+
+def getCrashLevel():
+	return getAbstractLogLevel('NAIVE_CRASHLEVEL', defaultCrashLevel)
+
+def getLogger(modulename):
+	return Logger(modulename, getLogLevel(), getCrashLevel())
+
+if __name__ == "__main__":
+	l = getLogger('testmodule')
+	l.info("bla");
+	l.info("test nummer {}{}", 2, " is good")
+	l.info("test {hier} is ook ok", hier=3, daar=4)
+	l.info("should not see this")
+
+
+	l2 = getLogger('testmodule.m2')
+	l2.info("More info")
+	l2.info("and even more")

+ 49 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/plot.py

@@ -0,0 +1,49 @@
+__author__ = 'joachimdenil'
+
+from math import ceil
+import matplotlib
+matplotlib.use('TkAgg')
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
+from matplotlib.figure import Figure
+from matplotlib.lines import Line2D
+import numpy as np
+import threading
+
+try:
+    import Tkinter as Tk
+except ImportError:
+    import tkinter as Tk
+
+class ScopeWindow():
+    def __init__(self, theOutportRefs, names):
+        """
+        Plot results in a Tk window using matlplotlib
+        @param theOutportRefs: array of values to plot: [[x1,x2,xn], ... ,[y1,y2, , yn]]
+        @param names: the labels for each of the plots: list [name1, name2, ...,  namen]
+        @return:
+        """
+        self.root = Tk.Tk()
+        self.f = Figure()
+        n = len(theOutportRefs)
+        n = int(ceil(n*1.00/2))
+        index = 1
+        self.ax = []
+        for outport in theOutportRefs:
+            self.ax.append(self.f.add_subplot(n, 2, index))
+            # add values:
+            self.ax[index-1].plot(outport, 'ro')
+            self.ax[index-1].set_xlabel('t')
+            self.ax[index-1].set_ylabel(names[index-1])
+            index+=1
+
+        self.canvas = FigureCanvasTkAgg(self.f, master=self.root)
+        self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
+        self.canvas.show()
+
+        self.toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
+        self.toolbar.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
+        self.toolbar.update()
+
+        self.button = Tk.Button(master=self.root, text='Quit', command=self.root.destroy)
+        self.button.pack(side=Tk.BOTTOM)
+        self.root.mainloop()

+ 48 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/CounterTest.py

@@ -0,0 +1,48 @@
+__author__ = 'joachimdenil'
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from CBDMultipleOutput.Source.plot import ScopeWindow
+from basicCBDTest import BasicCBDTestCase
+
+NUM_DISCR_TIME_STEPS = 10
+
+class FlattenCBDTest(unittest.TestCase):
+    def setUp(self):
+        self.CBD = CBD("block_under_test")
+
+    def _run(self, num_steps=1, step = 1):
+        self.CBD.run(num_steps, step)
+
+    def _getSignal(self, blockname, output_port = None):
+        foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+        signal =  foundBlocks[0].getSignal(name_output = output_port)
+        if len(foundBlocks) == 1:
+            return [x.value for x in signal]
+        else:
+            raise Exception("No single block with name " + blockname + " found")
+
+    def testCounter(self):
+        self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.CBD.addBlock(DelayBlock(block_name="s"))
+        self.CBD.addConnection("zero", "s", input_port_name="IC")
+        self.CBD.addBlock(ConstantBlock(block_name="one", value=1.0))
+        self.CBD.addBlock(AdderBlock(block_name="plusOne"))
+        self.CBD.addConnection("one", "plusOne")
+        self.CBD.addConnection("s", "plusOne")
+        self.CBD.addConnection("plusOne", "s")
+
+        self._run(NUM_DISCR_TIME_STEPS)
+        ScopeWindow([self._getSignal("zero"), self._getSignal("one"), self._getSignal("s")],
+            ["zero", "one", "s"] )
+        self.assertEquals(self._getSignal("s"), [float(x) for x in range(NUM_DISCR_TIME_STEPS)])
+
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()

+ 0 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/__init__.py


+ 551 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/basicCBDTest.py

@@ -0,0 +1,551 @@
+#!/usr/bin/env python
+#
+# Unit tests for all the basic CBD blocks, discrete-time CBD. 
+
+import unittest
+
+from CBDMultipleOutput.Source.CBD import *
+
+NUM_DISCR_TIME_STEPS = 5
+
+class BasicCBDTestCase(unittest.TestCase):
+  def setUp(self):
+    self.CBD = CBD("CBD_for_block_under_test")    
+    
+  def _run(self, num_steps=1, delta_t = 1.0):
+    self.CBD.run(num_steps, delta_t)      
+      
+  def _getSignal(self, blockname, output_port = None):
+    foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+    numFoundBlocks = len(foundBlocks)  
+    if numFoundBlocks == 1:
+      signal =  foundBlocks[0].getSignal(name_output = output_port)
+      return [x.value for x in signal]
+    else:
+      raise Exception(str(numFoundBlocks) + " blocks with name " + blockname + " found.\nExpected a single block.")  
+  
+  def testConstantBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.3))
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("c1"), [3.3] * NUM_DISCR_TIME_STEPS)
+    
+  def testNegatorBlockPos(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [-6.0] * NUM_DISCR_TIME_STEPS)  
+  
+  def testNegatorBlockNeg(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=-6.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [6.0] * NUM_DISCR_TIME_STEPS)  
+    
+  def testNegatorBlockZero(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=0.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [0.0] * NUM_DISCR_TIME_STEPS)  
+    
+  def testInverterBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+    self.CBD.addBlock(InverterBlock(block_name="i1"))
+    self.CBD.addBlock(InverterBlock(block_name="i2"))
+
+    self.CBD.addConnection("c1", "i1")
+    self.CBD.addConnection("i1", "i2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("i1"), [0.2] * NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("i2"), [5.0] * NUM_DISCR_TIME_STEPS)
+
+  def testAdderBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=6.0))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("c2", "a")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [8.0] * NUM_DISCR_TIME_STEPS)
+    
+  def testAdderBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-6.0))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("c2", "a")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [-4.0] * NUM_DISCR_TIME_STEPS)    
+    
+  def testProductBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    
+    self.CBD.addConnection("c1", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("p"), [10.0] * 5)
+
+  def testProductBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0/2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=4.0))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    
+    self.CBD.addConnection("c1", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("p"), [2.0] * 5)
+    
+  def testGenericBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.2))
+    self.CBD.addBlock(GenericBlock(block_name="g", block_operator="ceil"))
+    
+    self.CBD.addConnection("c1", "g")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("g"), [3.0] * 5)  
+    
+  def testRootBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(RootBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [2.0])
+        
+  def testRootBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=9.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=2.0))
+    self.CBD.addBlock(RootBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [3.0])
+        
+  def testModuloBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [2.0])
+
+  def testModuloBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=8.0))
+    self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [0.0])
+
+  def testPreviousValueDelayBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="ZeroConstant", value=0.0))
+    self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=[0, 2, 4, 6, 8, 10, 12]))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addConnection("ZeroConstant", "d", input_port_name="IC")
+    self.CBD.addConnection("seq", "d")
+    
+    self._run(7, 0.5)
+    self.assertEquals(self._getSignal("d"), [0, 0, 2, 4, 6, 8, 10])    
+    
+  def testPreviousValueDelayBlock2(self):
+    self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 12, 22, 23, 32, 11, 91]))
+    self.CBD.addBlock(SequenceBlock(block_name="SecSeq", sequence=[5, 5, 5, 5, 3, 3, 3]))
+    self.CBD.addBlock(DelayBlock(block_name="prev"))
+    self.CBD.addConnection(self.CBD.getBlockByName("FirstSeq"), "prev")
+    self.CBD.addConnection(self.CBD.getBlockByName("SecSeq"), "prev", input_port_name="IC")
+    self._run(7)  
+    self.assertEquals(self._getSignal("prev"), [5, 2, 12, 22, 23, 32, 11])    
+          
+  def testTimeBlock(self):
+    self.CBD.addBlock(TimeBlock(block_name="t"))
+    self._run(4)
+    self.assertEquals(self._getSignal("t"), [0.0, 1.0, 2.0, 3.0])
+
+  def testLessThanBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-5.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=0))
+    self.CBD.addBlock(LessThanBlock(block_name="lt1"))
+    self.CBD.addBlock(LessThanBlock(block_name="lt2"))
+    self.CBD.addBlock(LessThanBlock(block_name="lt3"))
+    
+    self.CBD.addConnection("c1", "lt1")
+    self.CBD.addConnection("c1", "lt1", input_port_name="IC")
+    self.CBD.addConnection("c1", "lt2")
+    self.CBD.addConnection("c2", "lt2", input_port_name="IC")
+    self.CBD.addConnection("c2", "lt3")
+    self.CBD.addConnection("c3", "lt3", input_port_name="IC")
+
+    self._run(1)
+    self.assertEquals(self._getSignal("lt1"), [0.0])  
+    self.assertEquals(self._getSignal("lt2"), [0.0])  
+    self.assertEquals(self._getSignal("lt3"), [1.0])  
+    
+  def testEqualsBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-5.0))
+    self.CBD.addBlock(EqualsBlock(block_name="eq1"))
+    self.CBD.addBlock(EqualsBlock(block_name="eq2"))
+    
+    self.CBD.addConnection("c1", "eq1")
+    self.CBD.addConnection("c1", "eq1", input_port_name="IC")
+    self.CBD.addConnection("c1", "eq2")
+    self.CBD.addConnection("c2", "eq2", input_port_name="IC")
+    
+    self._run(1)
+    self.assertEquals(self._getSignal("eq1"), [1.0])  
+    self.assertEquals(self._getSignal("eq2"), [0.0])  
+    
+  def testNotBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(NotBlock(block_name="NotBlock"))
+    self.CBD.addConnection("One", "NotBlock")      
+    self._run(1)
+    self.assertEquals(self._getSignal("NotBlock"), [0])    
+    
+  def testNotBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(NotBlock(block_name="NotBlock"))
+    self.CBD.addConnection("Zero", "NotBlock")      
+    self._run(1)      
+    self.assertEquals(self._getSignal("NotBlock"), [1])        
+    
+  def testOrBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(OrBlock(block_name="OrBlock1"))
+    self.CBD.addConnection("Zero", "OrBlock1")    
+    self.CBD.addConnection("Zero", "OrBlock1")  
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock2"))
+    self.CBD.addConnection("One", "OrBlock2")    
+    self.CBD.addConnection("Zero", "OrBlock2")
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock3"))    
+    self.CBD.addConnection("One", "OrBlock3")    
+    self.CBD.addConnection("One", "OrBlock3")
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock4", numberOfInputs=4))
+    self.CBD.addConnection("Zero", "OrBlock4")    
+    self.CBD.addConnection("Zero", "OrBlock4")
+    self.CBD.addConnection("One", "OrBlock4")
+    self.CBD.addConnection("Zero", "OrBlock4")
+        
+    self._run(1)
+    self.assertEquals(self._getSignal("OrBlock1"), [0])      
+    self.assertEquals(self._getSignal("OrBlock2"), [1])      
+    self.assertEquals(self._getSignal("OrBlock3"), [1])      
+    self.assertEquals(self._getSignal("OrBlock4"), [1])      
+    
+  def testAndBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(AndBlock(block_name="AndBlock1"))
+    self.CBD.addConnection("Zero", "AndBlock1")    
+    self.CBD.addConnection("Zero", "AndBlock1")  
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock2"))
+    self.CBD.addConnection("One", "AndBlock2")    
+    self.CBD.addConnection("Zero", "AndBlock2")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock3"))    
+    self.CBD.addConnection("One", "AndBlock3")    
+    self.CBD.addConnection("One", "AndBlock3")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock4"))    
+    self.CBD.addConnection("Zero", "AndBlock4")    
+    self.CBD.addConnection("One", "AndBlock4")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock5", numberOfInputs=4))
+    self.CBD.addConnection("Zero", "AndBlock5")    
+    self.CBD.addConnection("Zero", "AndBlock5")
+    self.CBD.addConnection("One", "AndBlock5")
+    self.CBD.addConnection("Zero", "AndBlock5")
+        
+    self._run(1)
+    self.assertEquals(self._getSignal("AndBlock1"), [0])      
+    self.assertEquals(self._getSignal("AndBlock2"), [0])      
+    self.assertEquals(self._getSignal("AndBlock3"), [1])      
+    self.assertEquals(self._getSignal("AndBlock4"), [0])      
+    self.assertEquals(self._getSignal("AndBlock5"), [0])      
+    
+  def testSequenceBlock(self):
+    self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 2, 2, 3, 2, 1, 1]))
+    self._run(7)  
+    self.assertEquals(self._getSignal("FirstSeq"), [2, 2, 2, 3, 2, 1, 1])
+
+  def testLoggingBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(LoggingBlock("Test", "Logging block test with level is error", level.ERROR))
+    self.CBD.addConnection("One", "Test")
+    self._run(1)
+    
+
+  def testLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a3"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+
+    self.CBD.addConnection("a3", "a1")
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("a1", "a3")
+    self.CBD.addConnection("a2", "a3")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("a3", "a2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [-5.5]*5)
+    self.assertEquals(self._getSignal("a2"), [5.0]*5)
+    self.assertEquals(self._getSignal("a3"), [-0.5]*5)
+    
+  def testLinearStrongComponentWithDelay(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.0))
+    self.CBD.addBlock(AdderBlock(block_name="sum"))
+    self.CBD.addBlock(DelayBlock(block_name="delay"))
+    self.CBD.addBlock(NegatorBlock(block_name="neg"))
+
+    self.CBD.addConnection("c1", "sum")
+    self.CBD.addConnection("neg", "sum")
+    self.CBD.addConnection("sum", "delay", input_port_name="IC")
+    self.CBD.addConnection("delay", "neg")
+    self.CBD.addConnection("neg", "delay")
+    
+    self._run(1)
+    self.assertEquals(self._getSignal("delay"), [1.5])
+    
+  def testLinearStrongComponentWithMult(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("p", "a")
+    self.CBD.addConnection("a", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [-0.75]*5)
+    self.assertEquals(self._getSignal("p"), [-3.75]*5)
+    
+  def testLinearStrongComponentWithNeg(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=8))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("a2", "a1")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("n", "a2")
+    self.CBD.addConnection("a1", "n")  
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [6.5]*5)
+    self.assertEquals(self._getSignal("a2"), [1.5]*5)  
+    self.assertEquals(self._getSignal("n"), [-6.5]*5)  
+    
+  def testTwoLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=2))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.5))
+    self.CBD.addBlock(ConstantBlock(block_name="c4", value=1))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(AdderBlock(block_name="a3"))
+    self.CBD.addBlock(AdderBlock(block_name="a4"))
+    self.CBD.addBlock(AdderBlock(block_name="a5"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    self.CBD.addBlock(NegatorBlock(block_name="n1"))
+    self.CBD.addBlock(NegatorBlock(block_name="n2"))
+
+    self.CBD.addConnection("a3", "a1")
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("a3", "a2")
+    self.CBD.addConnection("a1", "a3")
+    self.CBD.addConnection("a2", "a3")
+    self.CBD.addConnection("a3", "p")
+    self.CBD.addConnection("c3", "p")
+    self.CBD.addConnection("p", "n1")
+    self.CBD.addConnection("n1", "a4")
+    self.CBD.addConnection("a5", "a4")
+    self.CBD.addConnection("c4", "a5")
+    self.CBD.addConnection("n2", "a5")
+    self.CBD.addConnection("a4", "n2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [-2.0]*5)
+    self.assertEquals(self._getSignal("a2"), [-3.0]*5)
+    self.assertEquals(self._getSignal("a3"), [-5.0]*5)
+    self.assertEquals(self._getSignal("a4"), [4.25]*5)
+    self.assertEquals(self._getSignal("a5"), [-3.25]*5)
+    self.assertEquals(self._getSignal("p"), [-7.5]*5)
+    self.assertEquals(self._getSignal("n1"), [7.5]*5)
+    self.assertEquals(self._getSignal("n2"), [-4.25]*5)
+        
+  def testNonLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=15))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=10))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+
+    self.CBD.addConnection("c2", "a1")
+    self.CBD.addConnection("p", "a1")
+    self.CBD.addConnection("a1", "p")
+    self.CBD.addConnection("a2", "p")
+    self.CBD.addConnection("p", "a2")
+    self.CBD.addConnection("c1", "a2")
+    self.assertRaises(SystemExit, self._run, 5)    
+    
+  def initializeFuncDerBas(self):
+    #f(t) = 5*t  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=5.0))
+    CBDFunc.addConnection("t", "p") 
+    CBDFunc.addConnection("c", "p")
+    CBDFunc.addConnection("p", "OUT1")
+    return CBDFunc      
+      
+  def initializeFunc(self):
+    #f(t) = (t-2)^3  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ProductBlock(block_name="p2"))
+    CBDFunc.addBlock(AdderBlock(block_name="a"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
+    CBDFunc.addConnection("t", "a") 
+    CBDFunc.addConnection("c", "a")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("p", "p2")
+    CBDFunc.addConnection("a", "p2")
+    CBDFunc.addConnection("p2", "OUT1")
+    return CBDFunc  
+      
+  def initializeFunc2(self):
+    #f(t) = (t-2)^4
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ProductBlock(block_name="p2"))
+    CBDFunc.addBlock(ProductBlock(block_name="p3"))
+    CBDFunc.addBlock(AdderBlock(block_name="a"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
+    CBDFunc.addConnection("t", "a") 
+    CBDFunc.addConnection("c", "a")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("p", "p2")
+    CBDFunc.addConnection("a", "p2")
+    CBDFunc.addConnection("p2", "p3")
+    CBDFunc.addConnection("a", "p3")
+    CBDFunc.addConnection("p3", "OUT1")
+    return CBDFunc      
+  
+  def initializeFuncInt(self):
+    #f(t) = 2*t  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=2.0))
+    CBDFunc.addConnection("t", "p") 
+    CBDFunc.addConnection("c", "p")
+    CBDFunc.addConnection("p", "OUT1")
+    return CBDFunc  
+     
+  def testDerivatorBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.0))
+    self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
+    CBDFunc = self.initializeFuncDerBas()
+    self.CBD.addBlock(CBDFunc) 
+    self.CBD.addBlock(DerivatorBlock(block_name="der"))
+    
+    self.CBD.addConnection("c3", "der", input_port_name="delta_t")
+    self.CBD.addConnection("zero", "der", input_port_name="IC")
+    self.CBD.addConnection("function", "der")
+    self._run(5)
+    self.assertEquals(self._getSignal("der"), [0.0]+[5.0]*4)    
+
+            
+  def testIntegratorBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=0.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=0.001))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addBlock(IntegratorBlock(block_name="int"))
+    self.CBD.addConnection("c3", "int", input_port_name="delta_t")
+    self.CBD.addConnection("a", "int")
+    self.CBD.addConnection("c2", "int", input_port_name="IC")
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("d", "a")
+    self.CBD.addConnection("a", "d")
+    self.CBD.addConnection("c2", "d", input_port_name="IC")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("int"), [0.0, 0.006, 0.018000000000000002, 0.036000000000000004, 0.060000000000000005])
+  
+  def testDelayBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addConnection("c2", "d")
+    self.CBD.addConnection("c1", "d", input_port_name="IC")
+    self._run(4)
+    self.assertEquals(self._getSignal("d"), [5.0, 3.0, 3.0, 3.0])
+
+  def testDelayBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+
+    self.CBD.addConnection("c2", "a")
+    self.CBD.addConnection("d", "a")
+    self.CBD.addConnection("c1", "d", input_port_name="IC")
+    self.CBD.addConnection("a", "d")
+    self._run(5)
+    self.assertEquals(self._getSignal("d"), [1.0, 6.0, 11.0, 16.0, 21.0])
+      
+
+def suite():
+    """Returns a test suite containing all the test cases in this module."""
+    suite = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main(verbosity=2)
+
+  
+  
+  
+  
+  
+  
+  
+  

+ 201 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/flattenCBDTest.py

@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Unit tests for the flatten function on the CBD
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class FlattenCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1, step = 1):
+		self.CBD.run(num_steps, step)			
+			
+	def _getSignal(self, blockname, output_port = None):
+		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+		
+		signal =  foundBlocks[0].getSignal(name_output = output_port)
+		
+		if len(foundBlocks) == 1:
+			return [x.value for x in signal]
+		else:
+			raise Exception("No single block with name " + blockname + " found")
+							
+	def testInterCBD(self):
+		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
+		CBDLittle2 = CBD("second_child", input_ports = ["inCBD2"])
+		
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addBlock(CBDLittle2)
+		self.CBD.addConnection("first_child", "second_child", input_port_name = "inCBD2", output_port_name = "outCBD1") 
+
+		CBDLittle1.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		CBDLittle1.addConnection("c1", "outCBD1")
+		
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("second_child.inCBD2"), [2.0]*5)
+
+		
+	def testLinearStrongComponentWithMult(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=3))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder = CBD("adderCBD", input_ports = ["in1Add", "in2Add"], output_ports = ["outAdd"])
+		CBDAdder.addBlock(AdderBlock(block_name="a"))
+		CBDAdder.addConnection("in1Add", "a")
+		CBDAdder.addConnection("in2Add", "a")
+		CBDAdder.addConnection("a", "outAdd")
+		
+		CBDProduct = CBD("productCBD", input_ports = ["in1Prod", "in2Prod"], output_ports = ["outProd"])
+		CBDProduct.addBlock(ProductBlock(block_name="p"))
+		CBDProduct.addConnection("in1Prod", "p")
+		CBDProduct.addConnection("in2Prod", "p")
+		CBDProduct.addConnection("p", "outProd")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addBlock(CBDProduct)
+		self.CBD.addConnection("constantCBD1", "adderCBD", input_port_name="in1Add", output_port_name = "outConstant1")
+		self.CBD.addConnection("productCBD", "adderCBD", input_port_name="in2Add", output_port_name = "outProd")
+		self.CBD.addConnection("adderCBD", "productCBD", input_port_name="in1Prod", output_port_name = "outAdd")
+		self.CBD.addConnection("constantCBD2", "productCBD", input_port_name="in2Prod", output_port_name = "outConstant2")
+			
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("adderCBD.outAdd"), [-0.75]*5)
+		self.assertEquals(self._getSignal("productCBD.outProd"), [-3.75]*5)
+		
+	def testLinearStrongComponentWithNeg(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=8))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder1 = CBD("adder1CBD", input_ports = ["in1Add1", "in2Add1"], output_ports = ["outAdd1"])
+		CBDAdder1.addBlock(AdderBlock(block_name="a"))
+		CBDAdder1.addConnection("in1Add1", "a")
+		CBDAdder1.addConnection("in2Add1", "a")
+		CBDAdder1.addConnection("a", "outAdd1")
+		
+		CBDAdder2 = CBD("adder2CBD", input_ports = ["in1Add2", "in2Add2"], output_ports = ["outAdd2"])
+		CBDAdder2.addBlock(AdderBlock(block_name="a"))
+		CBDAdder2.addConnection("in1Add2", "a")
+		CBDAdder2.addConnection("in2Add2", "a")
+		CBDAdder2.addConnection("a", "outAdd2")
+		
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNeg"], output_ports = ["outNeg"])
+		CBDNegator.addBlock(NegatorBlock(block_name="n"))
+		CBDNegator.addConnection("inNeg", "n")
+		CBDNegator.addConnection("n", "outNeg")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder1)
+		self.CBD.addBlock(CBDAdder2)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("constantCBD1", "adder1CBD", input_port_name="in1Add1", output_port_name = "outConstant1")
+		self.CBD.addConnection("adder2CBD", "adder1CBD", input_port_name="in2Add1", output_port_name = "outAdd2")
+		self.CBD.addConnection("constantCBD2", "adder2CBD", input_port_name="in1Add2", output_port_name = "outConstant2")
+		self.CBD.addConnection("negatorCBD", "adder2CBD", input_port_name="in2Add2", output_port_name = "outNeg")
+		self.CBD.addConnection("adder1CBD", "negatorCBD", input_port_name="inNeg", output_port_name = "outAdd1")
+		
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("adder1CBD.outAdd1"), [6.5]*5)
+		self.assertEquals(self._getSignal("adder2CBD.outAdd2"), [1.5]*5)	
+		self.assertEquals(self._getSignal("negatorCBD.outNeg"), [-6.5]*5)		
+		
+	def testInterInterCBD(self):
+		"""
+							  +--------------------------------------------+
+				   +----+     |                    +------+                |
+				   |    |+--->|+------------------>|      |                |
+				   |  2 |     ||                   |  +   +--------------->+-------+
+		+----+     +----+     || +---------+   +-->|      |                |       |
+		|    |                |+>|         |   |   +------+                |       v
+		| 5  |   +------+     |  |         |   |                           |    +------+
+		+----++->|      |     |  |    *    |   |                           |    |      |
+				 |  +   |     |  |         |   |                           |    |  +   +------> 0
+		+----++->|      |+--->|+>|         |   |                           |    |      |
+		| 2  |   +------+     |  +--+------+   +--------------+            |    +------+
+		|    |                |     |                         |   +-----+  |       ^
+		+----+                |     |   +--------------------+|   |     |  |       |
+							  |     |   |     +-----+        ||   | 12  +->+-------+
+							  |     |   |     |     |        ||   |     |  |
+							  |     +-->+---->|  -  +------->++   +-----+  |
+							  |         |     |     |        |             |
+							  |         |     +-----+        |             |
+							  |         +--------------------+             |
+							  +--------------------------------------------+
+		"""		  
+		CBDLittle1 = CBD("first_child", input_ports = ["in1CBD1", "in2CBD1"], output_ports = ["out1CBD1", "out2CBD1"])
+		CBDLittle2 = CBD("first_child_of_first_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=2.0))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+		self.CBD.addBlock(AdderBlock(block_name="a2"))
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addConnection("c3", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "first_child", input_port_name = "in1CBD1")
+		self.CBD.addConnection("a", "first_child", input_port_name = "in2CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out1CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out2CBD1")
+				
+		CBDLittle1.addBlock(ProductBlock(block_name="p"))
+		CBDLittle1.addBlock(AdderBlock(block_name="a"))
+		CBDLittle1.addBlock(CBDLittle2)
+		CBDLittle1.addBlock(ConstantBlock(block_name="c", value=12.0))
+		CBDLittle1.addConnection("in1CBD1", "p")
+		CBDLittle1.addConnection("in2CBD1", "p")
+		CBDLittle1.addConnection("in1CBD1", "a")
+		CBDLittle1.addConnection("first_child_of_first_child", "a", output_port_name = "outCBD2")
+		CBDLittle1.addConnection("p", "first_child_of_first_child", input_port_name = "inCBD2")
+		CBDLittle1.addConnection("c", "out1CBD1")
+		CBDLittle1.addConnection("a", "out2CBD1")
+		
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self.CBD.flatten()
+		self._run(5)		
+		self.assertEquals(self._getSignal("first_child.p"), [14.0]*5)
+		self.assertEquals(self._getSignal("first_child.first_child_of_first_child.n"), [-14.0]*5)
+		self.assertEquals(self._getSignal("first_child.in1CBD1"), [2.0]*5)
+		self.assertEquals(self._getSignal("first_child.a"), [-12.0]*5)		
+		self.assertEquals(self._getSignal("a2"), [0.0]*5)
+		
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 201 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/hierarchyCBDTest.py

@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Unit tests for the hierarchy functionality of the CBD
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class HierarchyCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1, step = 1):
+		self.CBD.run(num_steps, step)			
+			
+	def _getSignal(self, blockname, output_port = None):
+		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+		
+		signal =  foundBlocks[0].getSignal(name_output = output_port)
+		
+		if len(foundBlocks) == 1:
+			return [x.value for x in signal]
+		else:
+			raise Exception("No single block with name " + blockname + " found")			
+		
+	def testInterCBD(self):		
+		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
+		CBDLittle1.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		CBDLittle1.addConnection("c1", "outCBD1")
+		
+		CBDLittle2 = CBD("second_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addBlock(CBDLittle2)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addConnection("first_child", "second_child", input_port_name = "inCBD2", output_port_name = "outCBD1") 
+		self.CBD.addConnection("second_child", "n", output_port_name = "outCBD2") 
+
+		self._run(5)
+		self.assertEquals(self._getSignal("n"), [2.0]*5)
+
+		
+	def testLinearStrongComponentWithMult(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=3))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder = CBD("adderCBD", input_ports = ["in1Add", "in2Add"], output_ports = ["outAdd"])
+		CBDAdder.addBlock(AdderBlock(block_name="a"))
+		CBDAdder.addConnection("in1Add", "a")
+		CBDAdder.addConnection("in2Add", "a")
+		CBDAdder.addConnection("a", "outAdd")
+		
+		CBDProduct = CBD("productCBD", input_ports = ["in1Prod", "in2Prod"], output_ports = ["outProd"])
+		CBDProduct.addBlock(ProductBlock(block_name="p"))
+		CBDProduct.addConnection("in1Prod", "p")
+		CBDProduct.addConnection("in2Prod", "p")
+		CBDProduct.addConnection("p", "outProd")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addBlock(CBDProduct)
+		self.CBD.addConnection("constantCBD1", "adderCBD", input_port_name="in1Add", output_port_name = "outConstant1")
+		self.CBD.addConnection("productCBD", "adderCBD", input_port_name="in2Add", output_port_name = "outProd")
+		self.CBD.addConnection("adderCBD", "productCBD", input_port_name="in1Prod", output_port_name = "outAdd")
+		self.CBD.addConnection("constantCBD2", "productCBD", input_port_name="in2Prod", output_port_name = "outConstant2")
+
+		self._run(5)
+		self.assertEquals(self._getSignal("adderCBD", output_port = "outAdd"), [-0.75]*5)
+		self.assertEquals(self._getSignal("productCBD", output_port = "outProd"), [-3.75]*5)	
+		
+	def testLinearStrongComponentWithNeg(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=8))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder1 = CBD("adder1CBD", input_ports = ["in1Add1", "in2Add1"], output_ports = ["outAdd1"])
+		CBDAdder1.addBlock(AdderBlock(block_name="a"))
+		CBDAdder1.addConnection("in1Add1", "a")
+		CBDAdder1.addConnection("in2Add1", "a")
+		CBDAdder1.addConnection("a", "outAdd1")
+		
+		CBDAdder2 = CBD("adder2CBD", input_ports = ["in1Add2", "in2Add2"], output_ports = ["outAdd2"])
+		CBDAdder2.addBlock(AdderBlock(block_name="a"))
+		CBDAdder2.addConnection("in1Add2", "a")
+		CBDAdder2.addConnection("in2Add2", "a")
+		CBDAdder2.addConnection("a", "outAdd2")
+		
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNeg"], output_ports = ["outNeg"])
+		CBDNegator.addBlock(NegatorBlock(block_name="n"))
+		CBDNegator.addConnection("inNeg", "n")
+		CBDNegator.addConnection("n", "outNeg")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder1)
+		self.CBD.addBlock(CBDAdder2)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("constantCBD1", "adder1CBD", input_port_name="in1Add1", output_port_name = "outConstant1")
+		self.CBD.addConnection("adder2CBD", "adder1CBD", input_port_name="in2Add1", output_port_name = "outAdd2")
+		self.CBD.addConnection("constantCBD2", "adder2CBD", input_port_name="in1Add2", output_port_name = "outConstant2")
+		self.CBD.addConnection("negatorCBD", "adder2CBD", input_port_name="in2Add2", output_port_name = "outNeg")
+		self.CBD.addConnection("adder1CBD", "negatorCBD", input_port_name="inNeg", output_port_name = "outAdd1")
+
+		self._run(5)
+		self.assertEquals(self._getSignal("adder1CBD", output_port = "outAdd1"), [6.5]*5)
+		self.assertEquals(self._getSignal("adder2CBD", output_port = "outAdd2"), [1.5]*5)	
+		self.assertEquals(self._getSignal("negatorCBD", output_port = "outNeg"), [-6.5]*5)	
+		
+	def testInterInterCBD(self):
+		"""
+							  +--------------------------------------------+
+				   +----+     |                    +------+                |
+				   |    |+--->|+------------------>|      |                |
+				   |  2 |     ||                   |  +   +--------------->+-------+
+		+----+     +----+     || +---------+   +-->|      |                |       |
+		|    |                |+>|         |   |   +------+                |       v
+		| 5  |   +------+     |  |         |   |                           |    +------+
+		+----++->|      |     |  |    *    |   |                           |    |      |
+				 |  +   |     |  |         |   |                           |    |  +   +------> 0
+		+----++->|      |+--->|+>|         |   |                           |    |      |
+		| 2  |   +------+     |  +--+------+   +--------------+            |    +------+
+		|    |                |     |                         |   +-----+  |       ^
+		+----+                |     |   +--------------------+|   |     |  |       |
+							  |     |   |     +-----+        ||   | 12  +->+-------+
+							  |     |   |     |     |        ||   |     |  |
+							  |     +-->+---->|  -  +------->++   +-----+  |
+							  |         |     |     |        |             |
+							  |         |     +-----+        |             |
+							  |         +--------------------+             |
+							  +--------------------------------------------+
+		"""		  
+		CBDLittle1 = CBD("first_child", input_ports = ["in1CBD1", "in2CBD1"], output_ports = ["out1CBD1", "out2CBD1"])
+		CBDLittle2 = CBD("first_child_of_first_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=2.0))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+		self.CBD.addBlock(AdderBlock(block_name="a2"))
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addConnection("c3", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "first_child", input_port_name = "in1CBD1")
+		self.CBD.addConnection("a", "first_child", input_port_name = "in2CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out1CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out2CBD1")
+				
+		CBDLittle1.addBlock(ProductBlock(block_name="p"))
+		CBDLittle1.addBlock(AdderBlock(block_name="a"))
+		CBDLittle1.addBlock(CBDLittle2)
+		CBDLittle1.addBlock(ConstantBlock(block_name="c", value=12.0))
+		CBDLittle1.addConnection("in1CBD1", "p")
+		CBDLittle1.addConnection("in2CBD1", "p")
+		CBDLittle1.addConnection("in1CBD1", "a")
+		CBDLittle1.addConnection("first_child_of_first_child", "a", output_port_name = "outCBD2")
+		CBDLittle1.addConnection("p", "first_child_of_first_child", input_port_name = "inCBD2")
+		CBDLittle1.addConnection("c", "out1CBD1")
+		CBDLittle1.addConnection("a", "out2CBD1")
+		
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self._run(5)		
+		self.assertEquals(self._getSignal("first_child", output_port = "p"), [14.0]*5)
+		self.assertEquals(self._getSignal("first_child", output_port = "in1CBD1"), [2.0]*5)
+		self.assertEquals(self._getSignal("first_child", output_port = "a"), [-12.0]*5)		
+		self.assertEquals(self._getSignal("a2"), [0.0]*5)	
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 172 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/sortedGraphCBDTest.py

@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Unit tests for the sorting of a CBD.
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class SortedGraphCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1):
+		self.CBD.run(num_steps)			
+	
+	def testSortedGraph(self):
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNegator"], output_ports = ["outNegator"])
+		negCbd = NegatorBlock(block_name="nC")
+		CBDNegator.addBlock(negCbd)
+		CBDNegator.addConnection("inNegator", "nC")	
+		CBDNegator.addConnection("nC", "outNegator")	
+		
+		const = ConstantBlock(block_name="c", value=5.5)
+		self.CBD.addBlock(const)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("negatorCBD", "n", output_port_name = "outNegator")
+		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(sortedGraph[0][0], const)
+		self.assertEquals(sortedGraph[2][0], negCbd)
+		self.assertEquals(sortedGraph[4][0], neg)
+		
+	def testSortedGraph2(self):
+		CBDAdder = CBD("adderCBD", input_ports = ["in1", "in2"], output_ports = ["outAdd"])
+		addCBD = AdderBlock(block_name="aC")
+		CBDAdder.addBlock(addCBD)
+		CBDAdder.addConnection("in1", "aC")	
+		CBDAdder.addConnection("in2", "aC")	
+		CBDAdder.addConnection("aC", "outAdd")	
+		
+		const1 = ConstantBlock(block_name="c1", value=5.5)
+		const2 = ConstantBlock(block_name="c2", value=4.5)
+		self.CBD.addBlock(const1)
+		self.CBD.addBlock(const2)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addConnection("adderCBD", "n", output_port_name = "outAdd")
+		self.CBD.addConnection("c1", "adderCBD", input_port_name = "in1")
+		self.CBD.addConnection("c2", "adderCBD", input_port_name = "in2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		comps = [ x[0] for x in sortedGraph ]
+		
+		tester = self
+		ag = lambda x,y: tester.assertTrue(comps.index(x) > comps.index(y))
+		
+		self.assertEquals(len(sortedGraph), 7)
+		ag(addCBD, const1)
+		ag(addCBD, const2)
+		ag(neg, addCBD)
+		
+	def testSortedGraph3(self):	
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNegator"], output_ports = ["outNegator", "outInverter"])
+		negCbd = NegatorBlock(block_name="nC")
+		invCBD = InverterBlock(block_name="iC")
+		CBDNegator.addBlock(negCbd)
+		CBDNegator.addBlock(invCBD)
+		CBDNegator.addConnection("inNegator", "nC")	
+		CBDNegator.addConnection("inNegator", "iC")	
+		CBDNegator.addConnection("nC", "outNegator")	
+		CBDNegator.addConnection("iC", "outInverter")	
+		
+		const = ConstantBlock(block_name="c", value=5.5)
+		self.CBD.addBlock(const)
+		add = AdderBlock(block_name="a")
+		self.CBD.addBlock(add)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("negatorCBD", "a", output_port_name = "outNegator")
+		self.CBD.addConnection("negatorCBD", "a", output_port_name = "outInverter")
+		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		comps = [ x[0] for x in sortedGraph ]
+		
+		tester = self
+		ag = lambda x,y: tester.assertTrue(comps.index(x) > comps.index(y))
+
+		self.assertEquals(len(sortedGraph), 7)
+		ag(negCbd, const)
+		ag(invCBD, const)
+		ag(add, negCbd)
+		ag(add, invCBD)
+		
+	def testSortedGraph4(self):
+		CBDStrong = CBD("strongCBD", input_ports = ["inC1", "inC2"], output_ports = [])
+		CBDStrong.addBlock(AdderBlock(block_name="a1"))
+		CBDStrong.addBlock(AdderBlock(block_name="a3"))
+		CBDStrong.addBlock(AdderBlock(block_name="a2"))
+		CBDStrong.addConnection("a3", "a1")		
+		CBDStrong.addConnection("a1", "a3")
+		CBDStrong.addConnection("a2", "a3")
+		CBDStrong.addConnection("inC1", "a1")
+		CBDStrong.addConnection("inC2", "a2")
+		CBDStrong.addConnection("a3", "a2")
+		
+		self.CBD.addBlock(CBDStrong)
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+		self.CBD.addConnection("c1", "strongCBD", input_port_name = "inC1")
+		self.CBD.addConnection("c2", "strongCBD", input_port_name = "inC2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+				
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(len(sortedGraph[4]), 3)
+		
+	def testSortedGraph5(self):
+		CBDStrong = CBD("strongCBD", input_ports = ["inC1", "inC2", "inA"], output_ports = ["out1", "out2"])
+		CBDStrong.addBlock(AdderBlock(block_name="a1"))
+		CBDStrong.addBlock(AdderBlock(block_name="a2"))
+		CBDStrong.addConnection("inA", "a1")		
+		CBDStrong.addConnection("a1", "out1")
+		CBDStrong.addConnection("a2", "out2")
+		CBDStrong.addConnection("inC1", "a1")
+		CBDStrong.addConnection("inC2", "a2")
+		CBDStrong.addConnection("inA", "a2")
+		
+		self.CBD.addBlock(CBDStrong)
+		self.CBD.addBlock(AdderBlock(block_name="a3"))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+		self.CBD.addConnection("c1", "strongCBD", input_port_name = "inC1")
+		self.CBD.addConnection("c2", "strongCBD", input_port_name = "inC2")
+		self.CBD.addConnection("a3", "strongCBD", input_port_name = "inA")
+		self.CBD.addConnection("strongCBD", "a3", output_port_name = "out1")
+		self.CBD.addConnection("strongCBD", "a3", output_port_name = "out2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+				
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(len(sortedGraph[4]), 6)	
+		
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 0 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/__init__.py


+ 80 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/EvenNumbersCBD.py

@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+from bokeh.plotting import figure, output_file, show
+from CBDMultipleOutput.Source.CBD import *
+from CBDMultipleOutput.Source.CBDDraw import draw
+
+
+class Counter(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                    block_name, 
+                    input_ports=[], 
+                    output_ports=["OutCount"])
+        
+        self.addBlock(DelayBlock(block_name="delay"))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(ConstantBlock(block_name="one", value=1.0))
+        
+        self.addConnection("zero", "delay", 
+                            input_port_name="IC")
+        self.addConnection("delay", "OutCount")
+        self.addConnection("delay", "sum")
+        self.addConnection("sum", "delay", input_port_name="IN1")
+        self.addConnection("one", "sum")
+        
+class Double(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                     block_name, 
+                     input_ports=["InNumber"], 
+                     output_ports=["OutDouble"])
+        self.addBlock(ProductBlock(block_name="mult"))
+        self.addBlock(ConstantBlock(block_name="two", value=2.0))
+        
+        self.addConnection("InNumber", "mult")
+        self.addConnection("two", "mult")
+        self.addConnection("mult", "OutDouble")
+    
+    
+class EvenNumberGen(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                     block_name, 
+                     input_ports=[],
+                     output_ports=["OutEven"])
+        
+        self.addBlock(Counter(block_name="counter"))
+        self.addBlock(Double(block_name="double"))
+        
+        self.addConnection("counter", "double", 
+                           input_port_name="InNumber",
+                           output_port_name="OutCount")
+        self.addConnection("double", "OutEven",
+                           output_port_name="OutDouble")
+        
+
+
+if __name__ == "__main__":
+    
+    cbd = EvenNumberGen("number_gen")
+    draw(cbd, "number_gen.dot")
+    draw(cbd.getBlockByName("counter"), "counter.dot")
+    cbd.run(10)
+    
+    times = []
+    output = []
+    
+    for timeValuePair in cbd.getSignal("OutEven"):
+        times.append(timeValuePair.time)
+        output.append(timeValuePair.value)
+                
+    #Plot
+    output_file("./number_gen.html", title="Even Numbers")
+    p = figure(title="Even Numbers", x_axis_label='time', y_axis_label='N')
+    p.circle(x=times, y=output, legend="Even numbers")
+    show(p)
+
+
+
+

+ 21 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/HarmonicOscilator.py

@@ -0,0 +1,21 @@
+from CBDMultipleOutput.Source.CBD import *
+
+class CircleCBDDerivative(CBD):
+    def __init__(self, blockName, delta_t):
+        CBD.__init__(self,blockName, [], [])
+        self.delta=delta_t;
+        self.addBlock(ConstantBlock(block_name="one", value=1.0))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(ConstantBlock(block_name="delta", value=self.delta))
+        self.addBlock(NegatorBlock(block_name="neg"))
+        self.addBlock(DerivatorBlock(block_name="derxv"))
+        self.addBlock(DerivatorBlock(block_name="derva"))
+        
+        self.addConnection("delta", "derxv",  input_port_name="delta_t")
+        self.addConnection("delta", "derva",  input_port_name="delta_t")
+        self.addConnection("zero", "derva",  input_port_name="IC")
+        self.addConnection("one", "derxv",  input_port_name="IC")
+        self.addConnection("derva", "neg")
+        self.addConnection("neg", "derxv")
+        self.addConnection("derxv", "derva")
+        

+ 300 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/TrainControlCBD.py

@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+from CBDMultipleOutput.Source.CBD import *
+
+DELTA = 0.1
+MASS_PERSON = 73
+MASS_TRAIN = 6000
+K = 300
+C = 150
+
+
+
+class TrainControlCBD(CBD):
+    def __init__(self, block_name, kp, ki, kd):
+        CBD.__init__(self, block_name)
+        self.addBlock(FixedTimeCBD(block_name="time"))
+        self.addBlock(LookUpBlockFixed(block_name="computer"))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(NegatorBlock(block_name="neg"))
+        self.addBlock(TrainPIDController("controller", kp, ki, kd))
+        self.addBlock(TrainPerson(block_name="plant"))
+        self.addBlock(CostFunctionCBD(block_name="cost"))
+        
+        # the connections follow the topological sort.
+        self.addConnection("time", "computer", 
+                            input_port_name="IN1", output_port_name="OutTime")
+        self.addConnection("time", "plant", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("time", "controller", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("computer", "sum", 
+                            input_port_name="IN1", output_port_name="OUT1")
+        self.addConnection("plant", "neg", 
+                            input_port_name="IN1", output_port_name="OutVTrain")
+        self.addConnection("neg", "sum", 
+                            input_port_name="IN2", output_port_name="OUT1")
+        self.addConnection("sum", "controller", 
+                            input_port_name="InError", output_port_name="OUT1")
+        self.addConnection("controller", "plant", 
+                            input_port_name="InTraction", output_port_name="OutTraction")
+        self.addConnection("sum", "cost", 
+                            input_port_name="InError")
+        self.addConnection("time", "cost", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("plant", "cost", 
+                            input_port_name="InXPerson", output_port_name="OutXPerson")
+        
+        
+
+class CostFunctionCBD(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InError","InDelta","InXPerson"], ["OutCost"])
+        self.addBlock(ABSBlock(block_name="abs"))
+        self.addBlock(ABSBlock(block_name="absError"))
+        self.addBlock(IntegratorBlock(block_name="integral"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AboveThresholdBlock(block_name="above04", threshold=0.4))
+        self.addBlock(StopSimulationBlock(block_name="stop"))
+        
+        self.addConnection("InError", "absError")
+        self.addConnection("absError", "integral", input_port_name="IN1")
+        self.addConnection("InDelta", "integral", input_port_name="delta_t")
+        self.addConnection("zero", "integral", input_port_name="IC")
+        self.addConnection("integral", "OutCost")
+        self.addConnection("InXPerson", "abs")
+        self.addConnection("abs", "above04")
+        self.addConnection("above04", "stop")
+        
+
+class ABSBlock(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(abs(self.getInputSignal(curIteration).value))
+
+class LookUpBlockFixed(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        
+    def compute(self, curIteration):
+        currentTime = self.getInputSignal(curIteration, "IN1").value
+        if currentTime < 0:
+            result = 0
+        elif currentTime < 160:
+            result = 14
+        elif currentTime < 200:
+            result = 2
+        elif currentTime < 260:
+            result = 15
+        else:
+            result = 0
+        
+        self.appendToSignal(result)
+
+
+
+class AboveThresholdBlock(BaseBlock):
+    def __init__(self, block_name, threshold):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.threshold = threshold
+
+    def compute(self, curIteration):
+        self.appendToSignal(1.0 if self.getInputSignal(curIteration).value > self.threshold else -1.0)
+
+
+
+class StopSimulationBlock(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], [])
+
+    def compute(self, curIteration):
+        inSignalValue = self.getInputSignal(curIteration).value
+        if inSignalValue > 0.0:
+            raise StopSimulationException()
+        
+
+class StopSimulationException(Exception):
+    pass
+        
+class FixedTimeCBD(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, [], ["OutTime", "OutDelta"])
+        self.addBlock(ConstantBlock(block_name="delta", value=DELTA))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(DelayBlock(block_name="delay"))
+        
+        self.addConnection("delta", "OutDelta")
+        self.addConnection("delay", "OutTime")
+        self.addConnection("delay", "sum")
+        self.addConnection("delta", "sum")
+        self.addConnection("sum", "delay")
+        self.addConnection("zero", "delay",
+                            input_port_name="IC")
+    
+
+class TrainPIDController(CBD):
+    def __init__(self, block_name, kp, ki, kd):
+        CBD.__init__(self, block_name, ["InError","InDelta"],["OutTraction"])
+        self.addBlock(IntegratorBlock(block_name="integral"))
+        self.addBlock(DerivatorBlock(block_name="derivative"))
+        self.addBlock(ConstantBlock(block_name="Kp", value=kp))
+        self.addBlock(ProductBlock(block_name="multKp"))
+        self.addBlock(ConstantBlock(block_name="Ki", value=ki))
+        self.addBlock(ProductBlock(block_name="multKi"))
+        self.addBlock(ConstantBlock(block_name="Kd", value=kd))
+        self.addBlock(ProductBlock(block_name="multKd"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AdderBlock(block_name="sum1"))
+        self.addBlock(AdderBlock(block_name="sum2"))
+        
+        self.addConnection("InError", "multKp")
+        self.addConnection("Kp", "multKp")
+        self.addConnection("InError", "integral")
+        self.addConnection("InError", "derivative")
+        self.addConnection("InDelta", "derivative", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral", 
+                            input_port_name="delta_t")
+        self.addConnection("zero", "derivative", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral", 
+                            input_port_name="IC")
+        self.addConnection("integral", "multKi")
+        self.addConnection("Ki", "multKi")
+        self.addConnection("derivative", "multKd")
+        self.addConnection("Kd", "multKd")
+        self.addConnection("multKd", "sum1")
+        self.addConnection("multKi", "sum1")
+        self.addConnection("sum1", "sum2")
+        self.addConnection("multKp", "sum2")
+        self.addConnection("sum2", "OutTraction")
+        
+        
+class TrainPerson(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction","InDelta"],["OutVTrain", "OutXPerson", "OutATrain"])
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AccelerationPerson(block_name="accelerationPerson"))
+        self.addBlock(AccelerationTrain(block_name="accelerationTrain"))
+        self.addBlock(IntegratorBlock(block_name="integral_person_a_v"))
+        self.addBlock(IntegratorBlock(block_name="integral_person_v_x"))
+        self.addBlock(IntegratorBlock(block_name="integral_train_a_v"))
+        
+        self.addConnection("zero", "integral_person_a_v", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral_person_v_x", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral_train_a_v", 
+                            input_port_name="IC")
+        
+        self.addConnection("InDelta", "integral_person_a_v", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral_person_v_x", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral_train_a_v", 
+                            input_port_name="delta_t")
+        
+        self.addConnection("InTraction", "accelerationPerson", 
+                            input_port_name="InTraction")
+        self.addConnection("InTraction", "accelerationTrain", 
+                            input_port_name="InTraction")
+        
+        self.addConnection("accelerationPerson", "integral_person_a_v", 
+                            input_port_name="IN1", output_port_name="OutAPerson")
+        self.addConnection("integral_person_a_v", "accelerationPerson", 
+                            input_port_name="InVPerson", output_port_name="OUT1")
+        self.addConnection("integral_person_a_v", "integral_person_v_x", 
+                            input_port_name="IN1", output_port_name="OUT1")
+        self.addConnection("integral_person_v_x", "accelerationPerson", 
+                            input_port_name="InXPerson", output_port_name="OUT1")
+        
+        self.addConnection("accelerationTrain", "integral_train_a_v", 
+                            input_port_name="IN1", output_port_name="OutATrain")
+        
+        self.addConnection("integral_train_a_v", "OutVTrain")
+        
+        self.addConnection("integral_person_v_x", "OutXPerson")
+        
+        self.addConnection("accelerationTrain", "OutATrain", input_port_name=None, output_port_name="OutATrain")
+        
+        
+        
+class AccelerationPerson(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction","InVPerson","InXPerson"],["OutAPerson"])
+        self.addBlock(ConstantBlock(block_name="m_train", value=MASS_TRAIN))
+        self.addBlock(ConstantBlock(block_name="m_person", value=MASS_PERSON))
+        self.addBlock(ConstantBlock(block_name="c", value=C))
+        self.addBlock(ConstantBlock(block_name="k", value=K))
+        self.addBlock(AdderBlock(block_name="sum_masses"))
+        self.addBlock(InverterBlock(block_name="inv_sum_masses"))
+        self.addBlock(ProductBlock(block_name="mult_inv_sum_masses"))
+        self.addBlock(ProductBlock(block_name="mult_mult_inv_sum_masses"))
+        self.addBlock(InverterBlock(block_name="inv_mperson"))
+        self.addBlock(NegatorBlock(block_name="neg_mult_mult_inv_sum_masses"))
+        self.addBlock(NegatorBlock(block_name="neg_vperson"))
+        self.addBlock(NegatorBlock(block_name="neg_xperson"))
+        self.addBlock(ProductBlock(block_name="mult_neg_vperson"))
+        self.addBlock(ProductBlock(block_name="mult_neg_xperson"))
+        self.addBlock(AdderBlock(block_name="sum_mults_person"))
+        self.addBlock(AdderBlock(block_name="sum_sum_mults_person"))
+        self.addBlock(ProductBlock(block_name="mult_inv_mperson"))
+        
+        self.addConnection("m_train", "sum_masses")
+        self.addConnection("m_person", "sum_masses")
+        self.addConnection("sum_masses", "inv_sum_masses")
+        self.addConnection("inv_sum_masses", "mult_inv_sum_masses")
+        self.addConnection("InTraction", "mult_inv_sum_masses")
+        self.addConnection("mult_inv_sum_masses", "mult_mult_inv_sum_masses")
+        
+        self.addConnection("m_person", "mult_mult_inv_sum_masses")
+        
+        self.addConnection("m_person", "inv_mperson")
+        self.addConnection("inv_mperson", "mult_inv_mperson")
+        
+        self.addConnection("mult_mult_inv_sum_masses", "neg_mult_mult_inv_sum_masses")
+        self.addConnection("neg_mult_mult_inv_sum_masses", "sum_sum_mults_person")
+        
+        self.addConnection("InVPerson", "neg_vperson")
+        self.addConnection("neg_vperson", "mult_neg_vperson")
+        self.addConnection("c", "mult_neg_vperson")
+        
+        self.addConnection("InXPerson", "neg_xperson")
+        self.addConnection("neg_xperson", "mult_neg_xperson")
+        self.addConnection("k", "mult_neg_xperson")
+        
+        self.addConnection("mult_neg_vperson", "sum_mults_person")
+        self.addConnection("mult_neg_xperson", "sum_mults_person")
+        
+        self.addConnection("sum_mults_person", "sum_sum_mults_person")
+        self.addConnection("sum_sum_mults_person", "mult_inv_mperson")
+        self.addConnection("mult_inv_mperson", "OutAPerson")
+        
+        
+        
+class AccelerationTrain(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction"],["OutATrain"])
+        self.addBlock(ConstantBlock(block_name="m_train", value=MASS_TRAIN))
+        self.addBlock(ConstantBlock(block_name="m_person", value=MASS_PERSON))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(InverterBlock(block_name="inv"))
+        self.addBlock(ProductBlock(block_name="mult"))
+        
+        self.addConnection("InTraction", "mult")
+        self.addConnection("m_train", "sum")
+        self.addConnection("m_person", "sum")
+        self.addConnection("sum", "inv")
+        self.addConnection("inv", "mult")
+        self.addConnection("mult", "OutATrain")
+
+
+
+
+
+
+
+
+

+ 0 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/__init__.py


+ 262 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBD_Controller.py

@@ -0,0 +1,262 @@
+"""
+This is CBD simulator controller exposing the most relevant methods of 
+a CBD simulator (See CBDMultipleOutput.Source.CBD.run) to allow for control from a SCCD.
+
+date: Oct 2015
+author (responsible): Claudio Gomes
+"""
+
+import math
+from CBDMultipleOutput.Source.CBD import Clock, DepGraph
+from CBDMultipleOutput.Source.CBD import CBD
+
+
+class CBDController:
+    """The CBD contoller acts as a facade to the simulator methods that are in the CBD objects.
+    The original design decision to keep the methods in the CBD Domain classes 
+    (as opposed to, for instance, keep them in a visitor/interpreter was not the decision of the current author.)"""
+    
+    def __init__(self, cbdModel, delta_t):
+        self.model = cbdModel
+        self.model.setDeltaT(delta_t)
+        self.delta = delta_t
+        
+    def initSimulation(self):
+        self.model.resetSignals();
+        self.model.setClock(Clock(self.delta))
+    
+    def createDepGraph(self, iteratonStep):
+        return self.__createDepGraph(iteratonStep)
+    
+    def createStrongComponents(self, depGraph, iteratonStep):
+        return depGraph.getStrongComponents(iteratonStep)
+    
+    def componentIsCycle(self, component, depGraph):
+        return self.__hasCycle(component, depGraph)    
+    
+    def computeNextBlock(self, comp, iteratonStep):
+        block = comp[0]   # the strongly connected component has a single element
+        block.compute(iteratonStep)
+    
+    def computeNextAlgebraicLoop(self, comp, iteratonStep):
+        currentComponent = comp
+        # Detected a strongly connected component
+        if not self.__isLinear(currentComponent):
+            raise NotImplementedError("Cannot solve non-linear algebraic loop")
+        solverInput = self.__constructLinearInput(currentComponent, iteratonStep)
+        self.__gaussjLinearSolver(solverInput)
+        solutionVector = solverInput[1]
+        for block in currentComponent:
+            blockIndex = currentComponent.index(block)
+            block.appendToSignal(solutionVector[blockIndex])
+    
+    def advanceTimeStep(self):
+        self.model.getClock().step()
+    
+    def getCurrentSimulationTime(self):
+        return self.model.getClock().getTime()
+    
+    def __isLinear(self, strongComponent):
+        """
+        Determines if an algebraic loop describes a linear equation or not
+        As input you get the detected loop in a list.
+        If the loop is linear return True
+        Else: call exit(1) to exit the simulation with exit code 1
+        
+        The strong component parameter is a list of blocks that comprise the strong component.
+        For a block to comprise the strong component, at least one of its dependencies must be in the strong component as well.
+        A non-linear equation is generated when the following conditions occur:
+         (1) there is a multiplication operation being performed between two unknowns.
+         (2) there is an invertion operatioon being performed in an unknown.
+         (3) some non linear block belongs to the strong component
+        
+        The condition (1) can be operationalized by finding a product block that has two dependencies belonging to the strong component.
+        This will immediatly tell us that it is a product between two unknowns.
+        The condition (2) can be operationalized simply by finding an inverter block in the strong component. 
+        Because the inverter block only has one input, if it is in the strong component, it means that its only dependency is in the strong component.
+        
+        """
+        for block in strongComponent:
+            if not block.getBlockType() == "AdderBlock" and not block.getBlockType() == "NegatorBlock":
+                # condition (1)
+                if block.getBlockType() == "ProductBlock":
+                    dependenciesUnknown = [x for x in block.getDependencies(0) if x in strongComponent ]
+                    if (len(dependenciesUnknown) == 2):
+                        return False
+                
+                # conditions (2) and (3)
+                if block.getBlockType() in ["InverterBlock", "LessThanBlock", "ModuloBlock", "RootBlock", "EqualsBlock", "NotBlock", "OrBlock", "AndBlock", "SequenceBlock"]:
+                    return False
+        
+        return True
+    
+    def __hasCycle(self, component, depGraph):
+        """
+        Determine whether a component is cyclic
+        """
+        assert len(component)>=1, "A component should have at least one element"
+        if len(component)>1:
+            return True
+        else: # a strong component of size one may still have a cycle: a self-loop
+            if depGraph.hasDependency(component[0], component[0]):
+                return True
+            else:
+                return False
+
+    def __constructLinearInput(self, strongComponent, curIteration):
+        """
+        Constructs input for a solver of systems of linear equations
+        Input consists of two matrices:
+        M1: coefficient matrix, where each row represents an equation of the system
+        M2: result matrix, where each element is the result for the corresponding equation in M1
+        """
+        size = len(strongComponent)
+        row = []
+        M1 = []
+        M2 = []
+
+        # Initialize matrices with zeros
+        i = 0
+        while (i < size):
+            j = 0
+            row = []
+            while (j < size):
+                row.append(0)
+                j += 1
+            M1.append(row)
+            M2.append(0)
+            i += 1
+
+        # block -> index of block
+        indexdict = dict()
+
+        for (i,block) in enumerate(strongComponent):
+            indexdict[block] = i
+
+        resolveBlock = lambda possibleDep, output_port: possibleDep if not isinstance(possibleDep, CBD) else possibleDep.getBlockByName(output_port)
+
+        def getBlockDependencies2(block):
+            return [ resolveBlock(b,output_port) for (b, output_port) in [block.getBlockConnectedToInput("IN1"),  block.getBlockConnectedToInput("IN2")]]
+
+        for (i, block) in enumerate(strongComponent):
+            if block.getBlockType() == "AdderBlock":
+                for external in [ x for x in getBlockDependencies2(block) if x not in strongComponent ]:
+                    M2[i] -= external.getSignal()[curIteration].value
+                M1[i][i] = -1
+
+                for compInStrong in [ x for x in getBlockDependencies2(block) if x in strongComponent ]:
+                    M1[i][indexdict[compInStrong]] = 1
+            elif block.getBlockType() == "ProductBlock":
+                #M2 can stay 0
+                M1[i][i] = -1
+                M1[i][indexdict[[ x for x in getBlockDependencies2(block)  if x in strongComponent ][0]]] = reduce(lambda x,y: x*y, [ x.getSignal()[curIteration].value for x in getBlockDependencies2(block) if x not in strongComponent ])
+            elif block.getBlockType() == "NegatorBlock":
+                #M2 can stay 0
+                M1[i][i] = -1
+                possibleDep, output_port = block.getBlockConnectedToInput("IN1")
+                M1[i][indexdict[resolveBlock(possibleDep, output_port)]] = - 1
+            elif block.getBlockType() == "InputPortBlock":
+                #M2 can stay 0
+                M1[i][i] = 1
+                possibleDep, output_port = block.parent.getBlockConnectedToInput(block.getBlockName())
+                M1[i][indexdict[resolveBlock(possibleDep, output_port)]] = - 1
+            elif block.getBlockType() == "OutputPortBlock" or block.getBlockType() == "WireBlock":
+                #M2 can stay 0
+                M1[i][i] = 1
+                M1[i][indexdict[block.getDependencies(0)[0]]] = - 1
+            elif block.getBlockType() == "DelayBlock":
+                # If a delay is in a strong component, this is the first iteration
+                assert curIteration == 0
+                # And so the dependency is the IC
+                # M2 can stay 0 because we have an equation of the type -x = -ic <=> -x + ic = 0
+                M1[i][i] = -1
+                possibleDep, output_port = block.getBlockConnectedToInput("IC")
+                dependency = resolveBlock(possibleDep, output_port)
+                assert dependency in strongComponent
+                M1[i][indexdict[dependency]] = 1
+            else:
+                self.__logger.fatal("Unknown element, please implement")
+        return [M1, M2]
+
+    
+    def __gaussjLinearSolver(self, solverInput):
+        M1 = solverInput[0]
+        M2 = solverInput[1]
+        n = len(M1)
+        indxc = self.__ivector(n)
+        indxr = self.__ivector(n)
+        ipiv = self.__ivector(n)
+        icol = 0
+        irow = 0
+        for i in range(n):
+            big = 0.0
+            for j in range(n):
+                if (ipiv[j] != 1):
+                    for k in range(n):
+                        if (ipiv[k] == 0):
+                            if (math.fabs(M1[j][k]) >= big):
+                                big = math.fabs(M1[j][k])
+                                irow = j
+                                icol = k
+                        elif (ipiv[k] > 1):
+                            raise ValueError("GAUSSJ: Singular Matrix-1")
+            ipiv[icol] += 1
+            if (irow != icol):
+                for l in range(n):
+                    (M1[irow][l], M1[icol][l]) = self.__swap(M1[irow][l], M1[icol][l])
+                (M2[irow], M2[icol]) = self.__swap(M2[irow], M2[icol])
+            indxr[i] = irow
+            indxc[i] = icol
+            if (M1[icol][icol] == 0.0):
+                raise ValueError("GAUSSJ: Singular Matrix-2")
+            pivinv = 1.0/M1[icol][icol]
+            M1[icol][icol] = 1.0
+            for l in range(n):
+                M1[icol][l] *= pivinv
+            M2[icol] *= pivinv
+            for ll in range(n):
+                if (ll != icol):
+                    dum = M1[ll][icol]
+                    M1[ll][icol] = 0.0
+                    for l in range(n):
+                        M1[ll][l] -= M1[icol][l] * dum
+                    M2[ll] -= M2[icol] * dum
+        l = n
+        while (l > 0):
+            l -= 1
+            if (indxr[l] != indxc[l]):
+                for k in range(n):
+                    (M1[k][indxr[l]], M1[k][indxc[l]]) = self.__swap(M1[k][indxr[l]], M1[k][indxc[l]])
+
+    def __createDepGraph(self, curIteration):
+        """
+         Create a dependency graph of the CBD model.
+         Use the curIteration to differentiate between the first and other iterations
+         Watch out for dependencies with sub-models.
+        """
+        blocks = self.model.getBlocks()
+        depGraph = DepGraph()
+        for block in blocks:      
+            depGraph.addMember(block);
+        
+        def recSetInternalDependencies(blocks, curIteration):
+            for block in blocks:
+                for dep in block.getDependencies(curIteration):
+                    depGraph.setDependency(block, dep, curIteration)
+                if isinstance(block, CBD):
+                    recSetInternalDependencies(block.getBlocks(), curIteration)
+        
+        recSetInternalDependencies(blocks, curIteration);
+        
+        return depGraph
+    
+    def __ivector(self, n):
+        v = []
+        for i in range(n):
+            v.append(0)
+        return v
+
+    def __swap(self, a, b):
+        return (b, a)
+
+    

+ 56 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/Options.py

@@ -0,0 +1,56 @@
+AUTO_TIME_MODE = 0X01
+MANUAL_TIME_MODE = 0x02
+MANUAL_STEP_TIME_MODE = 0x03
+FAST_TIME_MODE = 0x04
+
+#a list containg the aboves modes so that the option class can do an 'in' check instead of == one by one
+#to check the legality of a received mode. 
+LEGAL_TIME_MODES = [AUTO_TIME_MODE, MANUAL_TIME_MODE, MANUAL_STEP_TIME_MODE, FAST_TIME_MODE]
+
+class Options:
+  """A class that contains options that should be given trough the interface)"""
+  def __init__(self,maxIter = 10, mode = AUTO_TIME_MODE, scaleFactor = 1, delta = 0.001):
+    """
+    a couple of options
+    @param maxIter the number or iterations of 1 simulation
+    @param mode the time mode
+    @param scaleFactor the scale factor by which to run an iteration default 1
+    """
+    self.__max_iter = maxIter
+    self.setTimeMode(mode)
+    self.setDeltaT(delta)
+    if scaleFactor >= 0:
+      self.__factor = scaleFactor 
+    else:
+      self.__factor  = 1
+        
+  def setMaxIterations(self, max):
+    self.__max_iter = max
+   
+  def getMaxIterations(self):
+    return self.__max_iter 
+  
+  def setDeltaT(self, delta):
+    self.__delta = delta
+   
+  def getDeltaT(self):
+    return self.__delta 
+  
+  
+  def setScaleFactor(self, factor):
+    if factor >= 0:
+      self.__factor = factor
+      #if value is illegal keep simply keep previous value
+
+  def getScaleFactor(self):
+    return self.__factor
+  
+  def setTimeMode(self, mode):
+    """Set the time mode. If it isn't a legal value set it to AUTO_TIME_MODE"""
+    if (mode in LEGAL_TIME_MODES): #since there is no enumeration in python this is a check to make sure a level has been added and not a random int
+      self.__mode = mode
+    else:
+      self.__mode = AUTO_TIME_MODE 
+
+  def getTimeMode(self):
+    return self.__mode

+ 129 - 129
debugging_fsa_cbd_composition/fsa_cbd_simulator/events.csv

@@ -1,130 +1,130 @@
 fsatime,Event

 fsatime,Event

-3.6299999999999666,when(x +-)

-7.009999999999895,when(x +-)

-9.729999999999837,when(x +-)

-11.91999999999979,when(x +-)

-12.999999999999767,kick

-16.87999999999984,when(x +-)

-20.160000000000352,when(x +-)

-22.800000000000765,when(x +-)

-23.000000000000796,kick

-28.870000000001713,when(x +-)

-33.640000000001876,when(x +-)

-37.00000000000121,kick

-38.99000000000081,when(x +-)

-41.240000000000364,when(x +-)

-43.050000000000004,when(x +-)

-44.509999999999714,when(x +-)

-45.69999999999948,when(x +-)

-46.669999999999284,when(x +-)

-47.45999999999913,when(x +-)

-48.109999999999,when(x +-)

-48.63999999999889,when(x +-)

-49.079999999998805,when(x +-)

-49.44999999999873,when(x +-)

-49.75999999999867,when(x +-)

-50.029999999998616,when(x +-)

-50.25999999999857,when(x +-)

-50.45999999999853,when(x +-)

-50.639999999998494,when(x +-)

-50.79999999999846,when(x +-)

-50.94999999999843,when(x +-)

-51.089999999998405,when(x +-)

-51.20999999999838,when(x +-)

-51.31999999999836,when(x +-)

-51.42999999999834,when(x +-)

-51.539999999998315,when(x +-)

-51.639999999998295,when(x +-)

-51.739999999998275,when(x +-)

-51.839999999998255,when(x +-)

-51.92999999999824,when(x +-)

-52.01999999999822,when(x +-)

-52.1099999999982,when(x +-)

-52.199999999998184,when(x +-)

-52.289999999998166,when(x +-)

-52.37999999999815,when(x +-)

-52.46999999999813,when(x +-)

-52.55999999999811,when(x +-)

-52.649999999998094,when(x +-)

-52.739999999998076,when(x +-)

-52.82999999999806,when(x +-)

-52.91999999999804,when(x +-)

-53.00999999999802,when(x +-)

-53.099999999998005,when(x +-)

-53.18999999999799,when(x +-)

-53.27999999999797,when(x +-)

-53.36999999999795,when(x +-)

-53.45999999999793,when(x +-)

-53.549999999997915,when(x +-)

-53.6399999999979,when(x +-)

-53.72999999999788,when(x +-)

-53.81999999999786,when(x +-)

-53.909999999997844,when(x +-)

-53.999999999997826,when(x +-)

-54.08999999999781,when(x +-)

-54.17999999999779,when(x +-)

-54.26999999999777,when(x +-)

-54.359999999997754,when(x +-)

-54.449999999997736,when(x +-)

-54.53999999999772,when(x +-)

-54.6299999999977,when(x +-)

-54.71999999999768,when(x +-)

-54.809999999997665,when(x +-)

-54.89999999999765,when(x +-)

-54.98999999999763,when(x +-)

-55.07999999999761,when(x +-)

-55.16999999999759,when(x +-)

-55.259999999997575,when(x +-)

-55.34999999999756,when(x +-)

-55.43999999999754,when(x +-)

-55.52999999999752,when(x +-)

-55.6199999999975,when(x +-)

-55.709999999997486,when(x +-)

-55.79999999999747,when(x +-)

-55.88999999999745,when(x +-)

-55.97999999999743,when(x +-)

-56.069999999997414,when(x +-)

-56.159999999997396,when(x +-)

-56.24999999999738,when(x +-)

-56.33999999999736,when(x +-)

-56.42999999999734,when(x +-)

-56.519999999997324,when(x +-)

-56.60999999999731,when(x +-)

-56.69999999999729,when(x +-)

-56.78999999999727,when(x +-)

-56.87999999999725,when(x +-)

-56.969999999997235,when(x +-)

-57.05999999999722,when(x +-)

-57.1499999999972,when(x +-)

-57.23999999999718,when(x +-)

-57.32999999999716,when(x +-)

-57.419999999997145,when(x +-)

-57.50999999999713,when(x +-)

-57.59999999999711,when(x +-)

-57.68999999999709,when(x +-)

-57.779999999997074,when(x +-)

-57.869999999997056,when(x +-)

-57.95999999999704,when(x +-)

-58.04999999999702,when(x +-)

-58.139999999997,when(x +-)

-58.229999999996984,when(x +-)

-58.319999999996966,when(x +-)

-58.40999999999695,when(x +-)

-58.49999999999693,when(x +-)

-58.58999999999691,when(x +-)

-58.679999999996895,when(x +-)

-58.76999999999688,when(x +-)

-58.85999999999686,when(x +-)

-58.94999999999684,when(x +-)

-59.03999999999682,when(x +-)

-59.129999999996805,when(x +-)

-59.21999999999679,when(x +-)

-59.30999999999677,when(x +-)

-59.39999999999675,when(x +-)

-59.48999999999673,when(x +-)

-59.579999999996716,when(x +-)

-59.6699999999967,when(x +-)

-59.75999999999668,when(x +-)

-59.84999999999666,when(x +-)

-59.939999999996644,when(x +-)

-59.99999999999663,enough

+3.63,when(x +-)

+7.01,when(x +-)

+9.73,when(x +-)

+11.92,when(x +-)

+13.0,kick

+16.88,when(x +-)

+20.16,when(x +-)

+22.8,when(x +-)

+23.0,kick

+28.87,when(x +-)

+33.64,when(x +-)

+37.0,kick

+38.99,when(x +-)

+41.24,when(x +-)

+43.05,when(x +-)

+44.51,when(x +-)

+45.7,when(x +-)

+46.67,when(x +-)

+47.46,when(x +-)

+48.11,when(x +-)

+48.64,when(x +-)

+49.08,when(x +-)

+49.45,when(x +-)

+49.76,when(x +-)

+50.03,when(x +-)

+50.26,when(x +-)

+50.46,when(x +-)

+50.64,when(x +-)

+50.8,when(x +-)

+50.95,when(x +-)

+51.09,when(x +-)

+51.21,when(x +-)

+51.32,when(x +-)

+51.43,when(x +-)

+51.54,when(x +-)

+51.64,when(x +-)

+51.74,when(x +-)

+51.84,when(x +-)

+51.93,when(x +-)

+52.02,when(x +-)

+52.11,when(x +-)

+52.2,when(x +-)

+52.29,when(x +-)

+52.38,when(x +-)

+52.47,when(x +-)

+52.56,when(x +-)

+52.65,when(x +-)

+52.74,when(x +-)

+52.83,when(x +-)

+52.92,when(x +-)

+53.01,when(x +-)

+53.1,when(x +-)

+53.19,when(x +-)

+53.28,when(x +-)

+53.37,when(x +-)

+53.46,when(x +-)

+53.55,when(x +-)

+53.64,when(x +-)

+53.73,when(x +-)

+53.82,when(x +-)

+53.91,when(x +-)

+54.0,when(x +-)

+54.09,when(x +-)

+54.18,when(x +-)

+54.27,when(x +-)

+54.36,when(x +-)

+54.45,when(x +-)

+54.54,when(x +-)

+54.63,when(x +-)

+54.72,when(x +-)

+54.81,when(x +-)

+54.9,when(x +-)

+54.99,when(x +-)

+55.08,when(x +-)

+55.17,when(x +-)

+55.26,when(x +-)

+55.35,when(x +-)

+55.44,when(x +-)

+55.53,when(x +-)

+55.62,when(x +-)

+55.71,when(x +-)

+55.8,when(x +-)

+55.89,when(x +-)

+55.98,when(x +-)

+56.07,when(x +-)

+56.16,when(x +-)

+56.25,when(x +-)

+56.34,when(x +-)

+56.43,when(x +-)

+56.52,when(x +-)

+56.61,when(x +-)

+56.7,when(x +-)

+56.79,when(x +-)

+56.88,when(x +-)

+56.97,when(x +-)

+57.06,when(x +-)

+57.15,when(x +-)

+57.24,when(x +-)

+57.33,when(x +-)

+57.42,when(x +-)

+57.51,when(x +-)

+57.6,when(x +-)

+57.69,when(x +-)

+57.78,when(x +-)

+57.87,when(x +-)

+57.96,when(x +-)

+58.05,when(x +-)

+58.14,when(x +-)

+58.23,when(x +-)

+58.32,when(x +-)

+58.41,when(x +-)

+58.5,when(x +-)

+58.59,when(x +-)

+58.68,when(x +-)

+58.77,when(x +-)

+58.86,when(x +-)

+58.95,when(x +-)

+59.04,when(x +-)

+59.13,when(x +-)

+59.22,when(x +-)

+59.31,when(x +-)

+59.4,when(x +-)

+59.49,when(x +-)

+59.58,when(x +-)

+59.67,when(x +-)

+59.76,when(x +-)

+59.85,when(x +-)

+59.94,when(x +-)

+60.0,enough


+ 222 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/fsaclasses.py

@@ -0,0 +1,222 @@
+import numpy
+from operator import attrgetter
+
+############### runtime classes
+
+class RunTimeEvent:
+    def __init__(self, name, time):
+        self.name = name
+        self.time = time
+        self.processed = False
+
+class Events:
+    def __init__(self, events):
+        self.events = sorted(events, key=attrgetter('time'))
+    
+    '''
+    Returns the most recent event with the timestamp smaller than time.
+    '''
+    def getInputAt(self,time):
+        event = None
+        if self.events != []:
+            # Claudio: this approach is assuming that the queue is sorted according the time of the events.
+            for e in self.events:
+                if e.time < time or numpy.isclose(e.time, time, 1e-05, 1e-08):
+                    event = e
+                else:
+                    # stop at the first event that satisfies e.time > time
+                    break
+        return event
+    
+    '''
+        Removes event all other older events from the queue.
+    '''
+    def popEvent(self, event):
+        if event == None:
+            return
+        
+        assert event in self.events
+        # Claudio: this approach is assuming that the queue is sorted according the time of the events.
+        # first collect list of events to be removed.
+        # then remove them.
+        eventsToBeRemoved = []
+        for e in self.events:
+            eventsToBeRemoved.append(e)
+            if e == event:
+                break
+        assert len(eventsToBeRemoved)>0
+        for e in eventsToBeRemoved:
+            self.events.remove(e)
+        
+
+############### static classes - invariants
+
+class Expression:
+    def __init__(self):
+        pass
+
+class FSAModel:
+    def __init__(self,states,transitions):
+        self.transitions = transitions
+        self.states = states
+        self.initialState = None
+        
+    def getTransitionFrom(self, state, event, elapsed):
+        assert state != None
+        assert elapsed >= 0.0
+        
+        # Priotiry goes to event.
+        selectedTransition = None
+        
+        if event!=None:
+            selectedTransition = self.getTriggeredTransition(state, event)
+        
+        # Then to after 
+        if (selectedTransition == None):
+            selectedTransition = self.getTransitionAfter(state, elapsed)
+        
+        # And finally to default transitions
+        if (selectedTransition == None):
+            selectedTransition = self.getDefaultTransition(state)
+        
+        return selectedTransition
+    
+    def getDefaultTransition(self, state):
+        assert state != None
+        for t in self.transitions:
+                if t.source == state and t.trigger == None:
+                    return t
+        
+        return None
+    
+    
+    def getTriggeredTransition(self, state, event):
+        assert event != None
+        for t in self.transitions:
+                if t.source == state and isinstance(t.trigger,Event) and t.trigger.name == event.name:
+                        return t
+        
+        return None
+    
+    def getTransitionAfter(self, state, elapsed):
+        for t in self.transitions:
+            if t.source == state and isinstance(t.trigger,After):
+                if ExpressionVisitor(t.trigger.after).visit() <= elapsed:
+                    return t
+        return None 
+
+class ExpressionVisitor:
+    def __init__(self, expression):
+        self.expression = expression
+        
+    def visit(self):
+        if(isinstance(self.expression,AtomValue)):
+            return self.expression.value
+        if(isinstance(self.expression,Operation)):
+            left = ExpressionVisitor(self.expression.left).visit()
+            right = ExpressionVisitor(self.expression.right).visit()
+            if(self.expression.op == '+'):
+                return left + right
+            if(self.expression.op == '-'):
+                return left - right
+            if(self.expression.op == '*'):
+                return left * right
+            if(self.expression.op == '/'):
+                return left / right
+            if(self.expression.op == 'and'):
+                return left and right
+            if(self.expression.op == 'or'):
+                return left or right
+        if(isinstance(self.expression,Not)):
+            return not ExpressionVisitor(self.expression.expression).visit()
+
+class State:
+    def __init__(self, name, final = False):
+        self.name = name
+        self.final = final
+        
+    def getName(self):
+        return self.name
+    
+    def __str__(self):
+        return self.name
+    
+    
+class Operation(Expression):
+    def __init__(self, left, right, op):
+        self.op = op
+        self.left = left
+        self.right = right
+        
+class Transition:
+    def __init__(self,name, source,target):
+        self.name = name
+        self.source = source
+        self.target = target
+        self.trigger = None
+        self.guard = None
+    
+    def __str__(self):
+        return str(self.source) + "--" + self.name + ": " +  str(self.trigger) + "-->" + str(self.target)
+    
+class Trigger:
+    def __init__(self):
+        pass
+
+class Event(Trigger):
+    def __init__(self,name):
+        self.name = name
+        
+    def __str__(self):
+        return self.name
+    
+class After(Trigger):
+    def __init__(self, expression):
+        self.after = expression
+    
+    def __str__(self):
+        return "after("+ str(self.after) + ")"
+    
+class Guard:
+    def __init__(self, expression):
+        self.expression = expression
+
+class And(Operation):
+    def __init__(self, lexpression, rexpression):
+        self.left = lexpression
+        self.right = rexpression
+        self.op = "and"
+
+class Or(Operation):
+    def __init__(self, lexpression, rexpression):
+        self.left = lexpression
+        self.right = rexpression
+        self.op = "or"
+
+class Not(Expression):
+    def __init__(self, expression):
+        self.expression = expression
+
+class Variable(Expression):
+    def __init__(self, varname):
+        self.name = varname
+
+class AtomValue(Expression):
+    def __init__(self, value):
+        self.value = value
+        
+    def __str__(self):
+        return str(self.value)
+    
+
+class Integer(AtomValue):
+    def __init__(self, value):
+        self.value = value
+    
+class Float(AtomValue):
+    def __init__(self, value):
+        self.value = value
+
+class String(AtomValue):
+    def __init__(self, value):
+        self.value = value

+ 149 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/run_debug.py

@@ -0,0 +1,149 @@
+import target
+from sccd.runtime.statecharts_core import Event
+import threading
+import fsaclasses
+from fsa_cbd_weaved_classes import CBDState
+from CBDMultipleOutput.models.HarmonicOscilator import CircleCBDDerivative
+from weaved_cbd_fsa_simulator import Controller
+from Options import Options
+from models.bouncingball import BouncingBallFSA
+import os
+from weaved_cbd_fsa_lib import FSACBDLib
+
+CBD_DELTA = 0.01
+
+def buildModel():
+    statea = fsaclasses.State("a")
+    stateb = fsaclasses.State("b")
+    statec = CBDState("c", CircleCBDDerivative("Harmonic Oscilator", CBD_DELTA))
+    stated = fsaclasses.State("d")
+    statef = State("f", True)
+    
+    transitionab = fsaclasses.Transition("a2b",statea,stateb)
+    transitionab.trigger = fsaclasses.After(fsaclasses.Float(5.0))
+    
+    transitionbc = fsaclasses.Transition("b2c",stateb,statec)
+    transitionbc.trigger = fsaclasses.After(fsaclasses.Float(2.0))
+    
+    transitioncd = fsaclasses.Transition("c2d",statec,stated)
+    transitioncd.trigger = fsaclasses.Event("c")
+
+    transitiondf = fsaclasses.Transition("d2f",stated,statef)
+    transitiondf.trigger = fsaclasses.After(fsaclasses.Float(5.0))
+
+    fsamodel = fsaclasses.FSAModel(
+                        [statea,stateb,statec,stated,statef],
+                        [transitionab,transitionbc,transitioncd,transitiondf]
+                        )
+    fsamodel.initialState = statea
+    return fsamodel
+
+if __name__ == '__main__':    
+    if os.path.exists(FSACBDLib.OUTPUT_EVENTS):
+        os.remove(FSACBDLib.OUTPUT_EVENTS)
+    if os.path.exists(FSACBDLib.OUTPUT_SIGNALS):
+        os.remove(FSACBDLib.OUTPUT_SIGNALS)
+        
+    options = Options(delta = CBD_DELTA)
+    options.setMaxIterations(10000);
+    fsamodel = BouncingBallFSA()
+    events = fsaclasses.Events([fsaclasses.RunTimeEvent('kick',13.0), fsaclasses.RunTimeEvent('kick',23.0), fsaclasses.RunTimeEvent('kick',37.0) ,fsaclasses.RunTimeEvent('enough',60.0)])
+    controller = target.Controller(options, fsamodel, events, keep_running=True)
+    
+    def set_defaults(inp, defaultlist):
+        for i, v in enumerate(defaultlist):
+            if len(inp) == i + 1:
+                inp.append(v)
+                
+    def get_bool(val):
+        if val.lower() in ["true", "yes", "1"]:
+            return True
+        else:
+            return False
+
+    def raw_inputter():
+        while 1:
+            inp = raw_input().split(" ")
+            action = inp[0]
+            if action == "continuous":
+                params = []
+            elif action == "realtime":
+                set_defaults(inp, [1.0])
+                params = [inp[1]]
+            elif action == "big_step":
+                params = []
+            elif action == "small_step":
+                params = []
+            elif action == "pause":
+                params = []
+            elif action == "add_breakpoint":
+                if len(inp) < 5:
+                    print("Adding a breakpoint requires 4 parameters!")
+                    continue
+                # Merge together the final part again
+                params = [inp[1], " ".join(inp[2:-2]).replace("\\n", "\n").replace("\\t", "\t"), get_bool(inp[-2]), get_bool(inp[-1])]
+                print("Generated parameters: " + str(params))
+            elif action == "del_breakpoint":
+                if len(inp) < 2:
+                    print("Breakpoint removal requires 1 parameter!")
+                    continue
+                params = [inp[1]]
+            elif action == "toggle_breakpoint":
+                params = [inp[1]]
+            elif action == "list_breakpoints":
+                params = []
+            elif action == "god_event":
+                if len(inp) != 2:
+                    print("God events require 1 parameter!")
+                    continue
+                params = [inp[1]]
+            elif action == "help":
+                print("Supported operations:")
+                print("  continuous")
+                print("   --> Simulate until termination time is reached")
+                print("  pause")
+                print("   --> Pause the simulation")
+                print("  realtime [realtime_scale]")
+                print("   --> Simulate in realtime")
+                print("       realtime_scale can speed up or slow down the pace")
+                print("  big_step")
+                print("   --> Simulate a big step")
+                print("  small_step")
+                print("   --> Simulate a small step")
+                print("  add_breakpoint name function enabled disable_on_trigger")
+                print("   --> Add a breakpoint that will pause simulation when function returns True")
+                print("       the function should contain a definition of the 'breakpoint' function")
+                print("       and must take 1 parameter")
+                print("       enabled indicates whether or not the breakpoint should be checked")
+                print("       disable_on_trigger determines if the breakpoint should auto-disable")
+                print("       after being triggered")
+                print("  del_breakpoint name")
+                print("   --> Remove a breakpoint")
+                print("  toggle_breakpoint name")
+                print("   --> Toggle the designated breakpoint")
+                print("  list_breakpoints")
+                print("   --> List all breakpoints")
+                print("  god_event new_state")
+                print("   --> Updates the current state")
+                print("")
+                print("Defaults: ")
+                print("  realtime_scale   --> 1.0")
+                continue
+            else:
+                print("Command not understood: " + str(inp))
+                continue
+            controller.addInput(Event(action, "user_input", params))
+            
+    input_thread = threading.Thread(target=raw_inputter)
+    input_thread.daemon = True
+    input_thread.start()
+
+    output_listener = controller.addOutputListener(["user_output"])
+    def outputter():
+        while 1:
+            print output_listener.fetch(-1)
+    output_thread = threading.Thread(target=outputter)
+    output_thread.daemon = True
+    output_thread.start()
+
+    controller.start()

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 6494 - 6494
debugging_fsa_cbd_composition/fsa_cbd_simulator/signals.csv


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1079 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/target.py


+ 158 - 157
debugging_fsa_cbd_composition/fsa_cbd_simulator/weaved_cbd_fsa_lib.py

@@ -3,7 +3,7 @@
 '''
 '''
 
 
 from fsa_cbd_weaved_classes import WhenCrossesZeroTrigger, InputConstantBlock,\
 from fsa_cbd_weaved_classes import WhenCrossesZeroTrigger, InputConstantBlock,\
-	CBDState
+    CBDState
 from CBDMultipleOutput.Source.CBD import OutputPortBlock
 from CBDMultipleOutput.Source.CBD import OutputPortBlock
 import numpy
 import numpy
 import os
 import os
@@ -11,159 +11,160 @@ import csv
 from fsaclasses import Event, After
 from fsaclasses import Event, After
 
 
 class FSACBDLib():
 class FSACBDLib():
-	BLOCK_NAME_OUT = "out_"
-	OUTPUT_SIGNALS = "./signals.csv"
-	OUTPUT_EVENTS = "./events.csv"
-		
-	def __init__(self):
-		pass
-	
-	def getTriggeredWhenTransition(self, fsaCbdModel, currentFSAState, globalState, previousGlobalState):
-		'''
-		This method will check whether there is any transition triggered by a zero crossing detection and if so,
-		if that zero crossing has in fact occurred when comparing the new globalState with the previousGlobalState.
-		'''
-		triggeredTransiton = None
-		
-		for t in fsaCbdModel.transitions:
-			if t.source == currentFSAState and isinstance(t.trigger,WhenCrossesZeroTrigger):
-				varNameToCheck = t.trigger.varname
-				if varNameToCheck in globalState and varNameToCheck in previousGlobalState:
-					if t.trigger.up_direction and previousGlobalState[varNameToCheck] <= 0 and 0 < globalState[varNameToCheck] :
-						triggeredTransiton = t
-						break
-					if not t.trigger.up_direction and globalState[varNameToCheck] < 0 and 0 <= previousGlobalState[varNameToCheck] :
-						triggeredTransiton = t
-						break
-		
-		assert triggeredTransiton == None or t.source == currentFSAState
-		
-		return triggeredTransiton
-	
-	def updateGlobalState(self ,globalState, cbdModel, cbdTime):
-		'''
-		The globalState is a dictionary mapping variable names to values.
-		This function will get the signals for the outputPorts in the cbdModel and then
-		update the globalState with the values of the outputPorts at time cbdTime
-		'''
-		for block in cbdModel.getBlocks():
-			if (isinstance(block, OutputPortBlock)):
-				port = block.getBlockName()
-				signal = block.getSignal()
-				# Convention: port is of the form "out_varName" to represent the global varName
-				assert port.startswith(self.BLOCK_NAME_OUT), "Convention violated for output port: " + str(port)
-				varName = self.stripConventionOutname(port)
-				assert len(varName)>0 , "Convention violated for output port: " + str(port)
-				
-				mostRecentSignal = signal[-1]
-				
-				assert numpy.isclose(mostRecentSignal.time,cbdTime, 1e-05, 1e-08), "Signal as not been computed up to time " + str(cbdTime)
-				
-				signalValue = mostRecentSignal.value
-				globalState[varName] = signalValue
-	
-	def stripConventionOutname(self, name):
-		return name.replace(self.BLOCK_NAME_OUT, "", 1)
-	
-	def updateCBDState(self, globalState, cbdModel):
-		'''
-		The globalState is a dictionary mapping variable names to values.
-		
-		This function is to be called when initializing the cbdModel.
-		This function will iterate the input blocks of the CBD, which have conventioned name as "in_varName" and it will set the values for those blocks. 
-		'''	
-		for block in cbdModel.getBlocks():
-			if isinstance(block, InputConstantBlock):
-				assert block.getBlockName().startswith("in_"), "Convention violated for input block of the CBD: " + str(block.getBlockName())
-				varName = block.getBlockName().replace("in_", "", 1)
-				assert len(varName)>0 , "Convention violated for input block of the CBD: " + str(block.getBlockName())
-				assert varName in globalState, "Input block not initialized before: " + str(block.getBlockName())
-				
-				block.setValue(globalState[varName])
-		
-		
-	def dumpGlobalState(self, fsaCbdModel, globalState, fsaTime, fsaState):
-		create_header = not os.path.exists(self.OUTPUT_SIGNALS);
-		
-		if create_header:
-			self.addRemainingSignals(globalState, fsaCbdModel)
-		
-		# It is not a good idea to write this directly to the global state but it is more efficient.
-		
-		globalState["fsatime"] = fsaTime
-		
-		if isinstance(fsaState, CBDState):
-			assert fsaState.cbd != None
-			if fsaState.cbd.getClock() != None:
-				globalState["current_cbdtime"] = fsaState.cbd.getClock().getTime()
-			else:
-				# Clock not yet initialized. Can happen.
-				globalState["current_cbdtime"] = -1.0
-		else:
-			globalState["current_cbdtime"] = -1.0
-		
-		globalState["fsastate"] = fsaState.name
-		
-		with open(self.OUTPUT_SIGNALS, "a") as csvFile:
-			writerCsv = csv.DictWriter(csvFile, fieldnames=globalState.keys())
-			if create_header:
-				writerCsv.writeheader()
-			writerCsv.writerow(globalState)
-	
-	def addRemainingSignals(self, stateDict, fsaCbdModel):
-		
-		for state in fsaCbdModel.states:
-			if (isinstance(state, CBDState)):
-				for block in state.cbd.getBlocks():
-					if isinstance(block, OutputPortBlock):
-						varName = self.stripConventionOutname(block.getBlockName())
-						if not varName in stateDict:
-							stateDict[varName] = None
-		
-		
-		return stateDict
-	
-	def dumpDiscreteEvent(self, fsaCbdModel, fsaTime, fsa_currentState, fsa_selectedTransition):
-		create_header = not os.path.exists(self.OUTPUT_EVENTS);
-		
-		event = None
-		if (fsa_selectedTransition != None):
-			if fsa_selectedTransition.trigger != None:
-				if isinstance(fsa_selectedTransition.trigger, Event):
-					event = fsa_selectedTransition.trigger.name
-				elif isinstance(fsa_selectedTransition.trigger, After):
-					event = "after("+str(fsa_selectedTransition.trigger.expression)+")"
-				elif isinstance(fsa_selectedTransition.trigger, WhenCrossesZeroTrigger):
-					event = "when("+str(fsa_selectedTransition.trigger.varname)+" " + ("-+" if fsa_selectedTransition.trigger.up_direction else "+-") + ")"
-		
-		if (event != None):
-			with open(self.OUTPUT_EVENTS, "a") as csvFile:
-				eventDict = {"fsatime" : fsaTime , "Event" : event}
-				writerCsv = csv.DictWriter(csvFile, fieldnames=eventDict.keys())
-				if create_header:
-					writerCsv.writeheader()
-				writerCsv.writerow(eventDict)
-				
-				
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-				
+    BLOCK_NAME_OUT = "out_"
+    OUTPUT_SIGNALS = "./signals.csv"
+    OUTPUT_EVENTS = "./events.csv"
+        
+    def __init__(self):
+        pass
+    
+    def getTriggeredWhenTransition(self, fsaCbdModel, currentFSAState, globalState, previousGlobalState):
+        '''
+        This method will check whether there is any transition triggered by a zero crossing detection and if so,
+        if that zero crossing has in fact occurred when comparing the new globalState with the previousGlobalState.
+        '''
+        triggeredTransiton = None
+        
+        for t in fsaCbdModel.transitions:
+            if t.source == currentFSAState and isinstance(t.trigger,WhenCrossesZeroTrigger):
+                varNameToCheck = t.trigger.varname
+                if varNameToCheck in globalState and varNameToCheck in previousGlobalState:
+                    if t.trigger.up_direction and previousGlobalState[varNameToCheck] <= 0 and 0 < globalState[varNameToCheck] :
+                        triggeredTransiton = t
+                        break
+                    if not t.trigger.up_direction and globalState[varNameToCheck] < 0 and 0 <= previousGlobalState[varNameToCheck] :
+                        triggeredTransiton = t
+                        break
+        
+        assert triggeredTransiton == None or t.source == currentFSAState
+        
+        return triggeredTransiton
+    
+    def updateGlobalState(self ,globalState, cbdModel, cbdTime):
+        '''
+        The globalState is a dictionary mapping variable names to values.
+        This function will get the signals for the outputPorts in the cbdModel and then
+        update the globalState with the values of the outputPorts at time cbdTime
+        '''
+        for block in cbdModel.getBlocks():
+            if (isinstance(block, OutputPortBlock)):
+                port = block.getBlockName()
+                signal = block.getSignal()
+                # Convention: port is of the form "out_varName" to represent the global varName
+                assert port.startswith(self.BLOCK_NAME_OUT), "Convention violated for output port: " + str(port)
+                varName = self.stripConventionOutname(port)
+                assert len(varName)>0 , "Convention violated for output port: " + str(port)
+                
+                mostRecentSignal = signal[-1]
+                
+                print mostRecentSignal.time,cbdTime
+                assert numpy.isclose(mostRecentSignal.time,cbdTime, 1e-05, 1e-08), "Signal has not been computed up to time " + str(cbdTime)
+                
+                signalValue = mostRecentSignal.value
+                globalState[varName] = signalValue
+    
+    def stripConventionOutname(self, name):
+        return name.replace(self.BLOCK_NAME_OUT, "", 1)
+    
+    def updateCBDState(self, globalState, cbdModel):
+        '''
+        The globalState is a dictionary mapping variable names to values.
+        
+        This function is to be called when initializing the cbdModel.
+        This function will iterate the input blocks of the CBD, which have conventioned name as "in_varName" and it will set the values for those blocks. 
+        '''    
+        for block in cbdModel.getBlocks():
+            if isinstance(block, InputConstantBlock):
+                assert block.getBlockName().startswith("in_"), "Convention violated for input block of the CBD: " + str(block.getBlockName())
+                varName = block.getBlockName().replace("in_", "", 1)
+                assert len(varName)>0 , "Convention violated for input block of the CBD: " + str(block.getBlockName())
+                assert varName in globalState, "Input block not initialized before: " + str(block.getBlockName())
+                
+                block.setValue(globalState[varName])
+        
+        
+    def dumpGlobalState(self, fsaCbdModel, globalState, fsaTime, fsaState):
+        create_header = not os.path.exists(self.OUTPUT_SIGNALS);
+        
+        if create_header:
+            self.addRemainingSignals(globalState, fsaCbdModel)
+        
+        # It is not a good idea to write this directly to the global state but it is more efficient.
+        
+        globalState["fsatime"] = fsaTime
+        
+        if isinstance(fsaState, CBDState):
+            assert fsaState.cbd != None
+            if fsaState.cbd.getClock() != None:
+                globalState["current_cbdtime"] = fsaState.cbd.getClock().getTime()
+            else:
+                # Clock not yet initialized. Can happen.
+                globalState["current_cbdtime"] = -1.0
+        else:
+            globalState["current_cbdtime"] = -1.0
+        
+        globalState["fsastate"] = fsaState.name
+        
+        with open(self.OUTPUT_SIGNALS, "a") as csvFile:
+            writerCsv = csv.DictWriter(csvFile, fieldnames=globalState.keys())
+            if create_header:
+                writerCsv.writeheader()
+            writerCsv.writerow(globalState)
+    
+    def addRemainingSignals(self, stateDict, fsaCbdModel):
+        
+        for state in fsaCbdModel.states:
+            if (isinstance(state, CBDState)):
+                for block in state.cbd.getBlocks():
+                    if isinstance(block, OutputPortBlock):
+                        varName = self.stripConventionOutname(block.getBlockName())
+                        if not varName in stateDict:
+                            stateDict[varName] = None
+        
+        
+        return stateDict
+    
+    def dumpDiscreteEvent(self, fsaCbdModel, fsaTime, fsa_currentState, fsa_selectedTransition):
+        create_header = not os.path.exists(self.OUTPUT_EVENTS);
+        
+        event = None
+        if (fsa_selectedTransition != None):
+            if fsa_selectedTransition.trigger != None:
+                if isinstance(fsa_selectedTransition.trigger, Event):
+                    event = fsa_selectedTransition.trigger.name
+                elif isinstance(fsa_selectedTransition.trigger, After):
+                    event = "after("+str(fsa_selectedTransition.trigger.expression)+")"
+                elif isinstance(fsa_selectedTransition.trigger, WhenCrossesZeroTrigger):
+                    event = "when("+str(fsa_selectedTransition.trigger.varname)+" " + ("-+" if fsa_selectedTransition.trigger.up_direction else "+-") + ")"
+        
+        if (event != None):
+            with open(self.OUTPUT_EVENTS, "a") as csvFile:
+                eventDict = {"fsatime" : fsaTime , "Event" : event}
+                writerCsv = csv.DictWriter(csvFile, fieldnames=eventDict.keys())
+                if create_header:
+                    writerCsv.writeheader()
+                writerCsv.writerow(eventDict)
+                
+                
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                

+ 711 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/woven_fsa_cbd_simulator_hierarchical_debugging.xml

@@ -0,0 +1,711 @@
+<?xml version="1.0" ?>
+<diagram name="Weaved_CBD_FSA_Simulator_Manual" author="Sadaf Mustafiz and Bruno Barroca and Claudio Gomes">
+    <description>
+        Automatically woven CBD and FSA simulators with the FSA being the dominant.
+    </description>
+    
+    <inport name="user_input" />
+    <outport name="user_output" />
+    
+    <top>
+        <![CDATA[
+            from sccd.runtime.libs.ui import *
+            from sccd.runtime.libs.utils import *
+            import copy
+            from CBD_Controller import CBDController
+            import Options
+            from fsa_cbd_weaved_classes import CBDState
+            from weaved_cbd_fsa_lib import FSACBDLib
+        ]]>
+    </top>
+    <class name="Weaved_CBD_FSA_Simulator" default="True">
+        <attribute name="weaved_global_state"/>
+        <attribute name="fsa_elapsed"/>
+        <attribute name="cbd_options"/>
+        <attribute name="weaved_lib"/>
+        <attribute name="woven_child_initialized"/>
+        <attribute name="cbd_clock"/>
+        <attribute name="fsa_currentEvent"/>
+        <attribute name="weaved_delta"/>
+        <attribute name="weaved_model"/>
+        <attribute name="cbd_controller"/>
+        <attribute name="fsa_timestep"/>
+        <attribute name="cbd_currentCompIdx"/>
+        <attribute name="fsa_eventList"/>
+        <attribute name="cbd_depGraph"/>
+        <attribute name="fsa_selectedTransition"/>
+        <attribute name="cbd_strongComponentList"/>
+        <attribute name="weaved_previous_global_state"/>
+        <attribute name="cbd_delta"/>
+        <attribute name="weaved_triggered_when_transition"/>
+        <attribute name="cbd_iteration"/>
+        <attribute name="fsa_logicalTime"/>
+        <attribute name="fsa_currentState"/>
+        <method name="Weaved_CBD_FSA_Simulator">
+            <parameter name="cbd_options"/>
+            <parameter name="amodel"/>
+            <parameter name="fsa_events"/>
+            <body>
+            <![CDATA[
+                self.weaved_lib = FSACBDLib()
+                self.cbd_options = cbd_options
+                self.cbd_delta = self.cbd_options.getDeltaT() * 1000.0
+                self.weaved_model = amodel
+                self.fsa_eventList = fsa_events
+                self.fsa_timestep = 1.0 * 1000.0
+                self.initialized = False
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_processEvent">
+            <parameter name="event"/>
+            <body>
+            <![CDATA[
+                if (event != None):
+                    self.fsa_eventList.popEvent(event)
+                    event.processed = True
+            ]]>
+            </body>
+        </method>
+        <method name="updateCBDState">
+            <body>
+            <![CDATA[
+                self.weaved_lib.updateCBDState(self.weaved_global_state, self.fsa_currentState.cbd)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_maxIterationsReached">
+            <body>
+            <![CDATA[
+                return self.cbd_iteration >= self.cbd_options.getMaxIterations()
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_getInputEventAt">
+            <parameter name="time"/>
+            <body>
+            <![CDATA[
+                return self.fsa_eventList.getInputAt(time)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_computeBlock">
+            <body>
+            <![CDATA[
+                if self.cbd_currentComponentIsCycle():
+                    self.cbd_controller.computeNextAlgebraicLoop(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_iteration)
+                else:
+                    self.cbd_controller.computeNextBlock(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_iteration)
+            ]]>
+            </body>
+        </method>
+        <method name="updateGlobalState">
+            <body>
+            <![CDATA[
+                self.weaved_previous_global_state = copy.deepcopy(self.weaved_global_state)
+                self.weaved_lib.updateGlobalState(self.weaved_global_state, self.fsa_currentState.cbd, self.cbd_clock / 1000.0)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_currentComponentIsCycle">
+            <body>
+            <![CDATA[
+                return self.cbd_controller.componentIsCycle(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_depGraph)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_hasNextStrongComponent">
+            <body>
+            <![CDATA[
+                return (self.cbd_currentCompIdx) < len(self.cbd_strongComponentList)
+            ]]>
+            </body>
+        </method>
+        <method name="getTriggeredWhenTransition">
+            <body>
+            <![CDATA[
+                return self.weaved_lib.getTriggeredWhenTransition(self.weaved_model, self.fsa_currentState, self.weaved_global_state, self.weaved_previous_global_state)
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_initialize">
+            <body>
+            <![CDATA[
+                self.weaved_delta = min(self.fsa_timestep, self.cbd_delta)
+                self.fsa_logicalTime = 0.0
+                self.fsa_elapsed = 0
+                self.fsa_timestep = self.weaved_delta
+                self.fsa_currentState = self.weaved_model.initialState
+                self.initialized = True
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_finalize">
+            <body>
+            <![CDATA[
+                print 'Simulation finalized.'
+            ]]>
+            </body>
+        </method>
+        <method name="weaved_initialize">
+            <body>
+            <![CDATA[
+                self.weaved_global_state = dict()
+                self.weaved_previous_global_state = dict()
+                self.woven_child_initialized = False
+            ]]>
+            </body>
+        </method>
+        <method name="initializeDebugger">
+            <body>
+            <![CDATA[
+                self.breakpoints = []
+                self.triggered_bp = None
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_endCondition">
+            <body>
+            <![CDATA[
+                return self.initialized and self.fsa_currentState and self.fsa_currentState.final
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_endCondition">
+            <body>
+            <![CDATA[
+                return self.initialized and self.cbd_iteration >= self.cbd_options.getMaxIterations()
+            ]]>
+            </body>
+        </method>
+        <method name="addBreakpoint">
+            <parameter name="name" />
+            <parameter name="function" />
+            <parameter name="enabled" default="true" />
+            <parameter name="disable_on_trigger" default="true" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) > 0:
+                    return -1
+                self.breakpoints.append(Breakpoint(name, function, enabled, disable_on_trigger))
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="delBreakpoint">
+            <parameter name="name" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+                    return -1
+                self.breakpoints = [bp for bp in self.breakpoints if bp.name != name]
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="toggleBreakpoint">
+            <parameter name="name" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+                    return -1
+                for bp in self.breakpoints:
+                    if bp.name == name:
+                        bp.enabled = enabled
+                        break
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="breakpointTriggers">
+            <parameter name="is_realtime_simulation" />
+            <body>
+            <![CDATA[
+                self.triggered_bp = None
+                for bp in self.breakpoints:
+                    if not bp.enabled:
+                        continue
+                    # include the function in the scope...
+                    exec(bp.function)
+                    # ... and execute it, note that the breakpoint thus has to start with "def breakpoint("
+                    # note that we pass self.time_next instead of self.simulated_time in the case of as-fast-as-possible simulation (or stepping)
+                    # 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')
+                    # in case of realtime simulation, we do pass the current simulated time, since we can stop at (more or less) exactly the right time
+                    if breakpoint({'clock': (self.clock if is_realtime_simulation else self.time_next) / 1000.0, 'state': self.currentState, 'event': self.currentEvent}):
+                        # triggered!
+                        self.triggered_bp = bp.name
+                        if bp.disable_on_trigger:
+                            bp.enabled = False
+                        return True
+                    else:
+                        # not triggered, so continue
+                        continue
+                return False
+            ]]>
+            </body>
+        </method>
+        <method name="godEvent">
+            <parameter name="new_state" />
+            <body>
+            <![CDATA[
+                filtered_states = [s for s in self.model.states if s.name == new_state]
+                if not len(filtered_states) == 1:
+                    return -1
+                self.currentState = filtered_states[0]
+                return 0
+            ]]>
+            </body>
+        </method>
+        <scxml initial="Main" final="HybridTerminated">
+            <parallel id="Main">
+                <state id="SimulationState" initial="Paused">
+                    <state id="Paused">
+                        <transition target="../Running/Continuous" event="continuous" port="user_input" />
+                        <transition target="../Running/Realtime" event="realtime" port="user_input">
+                            <parameter name="realtime_scale" default="1.0" />
+                            <script>
+                                self.realtime_scale = float(realtime_scale)
+                            </script>
+                        </transition>
+                        <transition target="../Running/BigStep" event="big_step" port="user_input" />
+                        <transition target="../Running/SmallStep" event="small_step" port="user_input" />
+                        <!-- If a god event enables the end condition, the simulation should stop. -->
+                        <transition target="../PreStopped" cond="self.fsa_endCondition()" />
+                    </state>
+                    <state id="PrePaused">
+                        <!-- Here, we make sure the current step has finished, before we raise the 'paused' event. Otherwise, UserOutput will output the old state, not the latest one. -->
+                        <transition target="../Paused" after="self.sccd_yield() * 2">
+                            <raise event="paused" />
+                        </transition>
+                    </state>
+                    <state id="PreBreakpointTriggered">
+                        <!-- Here, we make sure the current step has finished, before we raise the 'paused' event. Otherwise, UserOutput will output the old state, not the latest one. -->
+                        <transition target="../Paused" after="self.sccd_yield() * 2">
+                            <raise event="breakpoint_triggered" />
+                        </transition>
+                    </state>
+                    <state id="Running" initial="Continuous">
+                        <transition target="../PreStopped" cond="self.fsa_endCondition()" />
+                        <transition target="../PrePaused" event="pause" port="user_input" />
+                        <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
+                        <state id="Continuous" />
+                        <state id="BigStep">
+                            <!-- 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.  -->
+                            <transition target="../BigStepDone" event="big_step_done" />
+                        </state>
+                        <state id="BigStepDone">
+                            <!-- We go back to the 'Paused' state once the big step has finished. -->
+                            <transition target="../../Paused" after="self.sccd_yield()" />
+                        </state>
+                        <state id="SmallStep">
+                            <!-- We go to a special 'SmallStepDone' state because in the 'user_output' state, we need to check whether we are currently executing a small step.  -->
+                            <transition target="../SmallStepDone" event="small_step_done" />
+                        </state>
+                        <state id="SmallStepDone">
+                            <!-- We go back to the 'Paused' state once the small step has finished. -->
+                            <transition target="../../Paused" after="self.sccd_yield()" />
+                        </state>
+                        <state id="Realtime">
+                            <onentry>
+                                <script>
+                                    # If the simulation was paused, we need to reset the start time of the simulation.
+                                    # The start time of the simulation is equal to the point in wall-clock time where simulated time is 0.
+                                    # 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.
+                                    # 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)
+                                    self.realtime_start_time = accurate_time.time() - (self.clock / self.realtime_scale)
+                                </script>
+                            </onentry>
+                        </state>
+                    </state>
+                    <state id="PreStopped">
+                        <transition target="../Stopped" after="self.sccd_yield() * 2">
+                            <raise event="termination_condition" />
+                        </transition>
+                    </state>
+                    <state id="Stopped" />
+                </state>
+                <state id="SimulationFlow" initial="FSA">
+                    <state id="FSA" initial="Started">
+                        <state id="Started">
+                            <transition target="../../ParentStarted">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Started to ParentStarted... ')
+                                        self.fsa_initialize()
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="Initialized">
+                            <transition target="../DebuggerInitialized">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Initialized to FSA/CheckTermination... ')
+                                        self.initializeDebugger()
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="DebuggerInitialized">
+                            <transition target="../CheckTermination">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Initialized to FSA/CheckTermination... ')
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="CheckTermination" initial="MacroStepProcessed">
+                            <state id="MacroStepProcessed">
+                                <transition target="../../Terminated" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/CheckTermination/MacroStepProcessed to Terminated... ')
+                                        ]]>
+                                    </script>
+                                </transition>
+                                <transition target="../../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
+                                <transition target="../../DoSimulation" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/CheckTermination/MacroStepProcessed to FSA/DoSimulation and reading events... ')
+                                            self.fsa_currentEvent = self.fsa_getInputEventAt(self.fsa_logicalTime / 1000.0)
+                                            self.fsa_selectedTransition = self.weaved_model.getTransitionFrom(self.fsa_currentState, self.fsa_currentEvent, self.fsa_elapsed)
+                                            print('Current event:' + str(self.fsa_currentEvent))
+                                            print('Current transition:' + str(self.fsa_selectedTransition))
+                                            print('Child detected?:' + str(isinstance(self.fsa_currentState, CBDState)))
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                        </state>
+                        <state id="Waiting" />
+                        <state id="DoSimulation" initial="MacroStepPrepared">
+                            <state id="MacroStepPrepared" initial="ParentPaused">
+                                <state id="ParentPaused">
+                                    <transition target="../ChildDetected" cond="isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/ParentPaused to FSA/ChildDetected... ')
+                                                self.cbd_model = self.fsa_currentState.cbd
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotDetected" cond="not isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ParentPaused to ChildNotDetected without any child to process... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildDetected">
+                                    <transition target="../ChildInitialized" cond="self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotInitialized" cond="not self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildNotInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildInitialized">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildInitialized to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotInitialized">
+                                    <transition target="../CBD/Started">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotInitialized to CBD/Started... ')
+                                                self.cbd_delta = self.weaved_delta
+                                                self.updateCBDState()
+                                                self.woven_child_initialized = True
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="CBD" initial="Started">
+                                    <state id="Started">
+                                        <transition target="../Initialized">
+                                            <script>
+                                                <![CDATA[
+                                                    print('From CBD/Started to Initialized... ')
+                                                    print('Performing initialization...')
+                                                    self.cbd_iteration = 0
+                                                    self.cbd_clock = 0
+                                                    self.cbd_controller = CBDController(self.cbd_model, self.cbd_delta / 1000.0)
+                                                    self.cbd_controller.initSimulation()
+                                                    print('Performing initialization... DONE')
+                                                ]]>
+                                            </script>
+                                        </transition>
+                                    </state>
+                                    <state id="Initialized">
+                                        <transition target="../../ChildInitialized">
+                                            <script>
+                                                <![CDATA[
+                                                    print('From CBD/Initialized to ChildInitialized... ')
+                                                ]]>
+                                            </script>
+                                        </transition>
+                                    </state>
+                                </state>
+                                <state id="ChildProcessed">
+                                    <transition target="../../MicroStepProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From MacroStepPrepared/ChildProcessed to MicroStepProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                            </state>
+                            <state id="MicroStepProcessed" initial="ParentPaused">
+                                <state id="ParentPaused">
+                                    <transition target="../ChildDetected" cond="isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/ParentPaused to FSA/ChildDetected... ')
+                                                self.cbd_model = self.fsa_currentState.cbd
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotDetected" cond="not isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ParentPaused to ChildNotDetected without any child to process... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildDetected">
+                                    <transition target="../ChildInitialized" cond="self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildInitialized">
+                                    <transition target="../CBD/CheckTermination">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildInitialized to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="CBD" initial="CheckTermination">
+                                    <state id="CheckTermination" initial="MacroStepProcessed">
+                                        <state id="MacroStepProcessed">
+                                            <transition target="../../Terminated" cond="self.cbd_endCondition()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepProcessed to Terminated... ')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                            <transition target="../../DoSimulation" cond="not self.cbd_endCondition()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepProcessed to MacroStepPrepared... ')
+                                                        self.cbd_currentCompIdx = 0
+                                                        self.cbd_depGraph = self.cbd_controller.createDepGraph(self.cbd_iteration)
+                                                        self.cbd_strongComponentList = self.cbd_controller.createStrongComponents(self.cbd_depGraph, self.cbd_iteration)
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                    </state>
+                                    <state id="DoSimulation" initial="MacroStepPrepared">
+                                        <state id="MacroStepPrepared">
+                                            <transition target="../MicroStepProcessed">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepPrepared to MicroStepProcessed... ')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                        <state id="MicroStepProcessed">
+                                            <transition target="../MicroStepPrepared" cond="self.cbd_hasNextStrongComponent()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepProcessed to MicroStepPrepared')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                            <transition target="../../../ChildPaused" cond="not self.cbd_hasNextStrongComponent()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepProcessed to ChildPaused and detecting triggered transitions... ')
+                                                        self.updateGlobalState()
+                                                        self.weaved_lib.dumpGlobalState(self.weaved_model, self.weaved_global_state, self.fsa_logicalTime / 1000.0, self.fsa_currentState)
+                                                        self.weaved_triggered_when_transition = self.getTriggeredWhenTransition()
+                                                        self.cbd_clock = self.cbd_clock + self.cbd_delta
+                                                        self.cbd_iteration = self.cbd_iteration + 1
+                                                        self.cbd_controller.advanceTimeStep()
+                                                        print('CBD clock: ' + str(self.cbd_clock / 1000.0))
+                                                        print('CBD iteration: ' + str(self.cbd_iteration))
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                        <state id="MicroStepPrepared">
+                                            <transition target="../MicroStepProcessed">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepPrepared to MicroStepProcessed...')
+                                                        self.cbd_computeBlock()
+                                                        self.cbd_currentCompIdx = self.cbd_currentCompIdx + 1
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                    </state>
+                                    <state id="Terminated" />
+                                </state>
+                                <state id="ChildPaused">
+                                    <transition target="../NoStateEventDetected" cond="self.weaved_triggered_when_transition == None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildPaused to NoStateEventDetected... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../StateEventDetected" cond="self.weaved_triggered_when_transition != None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildPaused to StateEventDetected... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="NoStateEventDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From NoStateEventDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="StateEventDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From StateEventDetected to ChildProcessed... ')
+                                                if self.fsa_selectedTransition == None:
+                                                    self.fsa_selectedTransition = self.weaved_triggered_when_transition
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildProcessed">
+                                    <transition target="../../MicroStepPrepared" cond="self.fsa_selectedTransition != None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/MicroStepProcessed/ChildProcessed to MicroStepPrepared... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../../../CheckTermination" cond="self.fsa_selectedTransition == None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/MicroStepProcessed/ChildProcessed to FSA/CheckTermination and advancing time... ')
+                                                self.fsa_logicalTime = self.fsa_logicalTime + self.fsa_timestep
+                                                self.fsa_elapsed = self.fsa_elapsed + self.fsa_timestep
+                                                print('fsa_logicalTime: %s' % (self.fsa_logicalTime / 1000.0))
+                                                print('fsa_elapsed: %s' % (self.fsa_elapsed / 1000.0))
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                            </state>
+                            <state id="MicroStepPrepared">
+                                <transition target="../ParentMicroStepProcessed">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/MicroStepPrepared to ParentMicroStepProcessed and attempting to take transition... ')
+                                            print('Transition to be taken: ' + str(self.fsa_selectedTransition))
+                                            self.fsa_currentState = self.fsa_selectedTransition.target
+                                            self.fsa_elapsed = 0
+                                            self.fsa_processEvent(self.fsa_currentEvent)
+                                            self.weaved_lib.dumpDiscreteEvent(self.weaved_model, self.fsa_logicalTime / 1000.0, self.fsa_currentState, self.fsa_selectedTransition)
+                                            self.weaved_lib.dumpGlobalState(self.weaved_model, self.weaved_global_state, self.fsa_logicalTime / 1000.0, self.fsa_currentState)
+                                            print('New state: ' + str(self.fsa_currentState))
+                                            print('Reading events:')
+                                            self.fsa_currentEvent = self.fsa_getInputEventAt(self.fsa_logicalTime / 1000.0)
+                                            self.fsa_selectedTransition = self.weaved_model.getTransitionFrom(self.fsa_currentState, self.fsa_currentEvent, self.fsa_elapsed /1000.0)
+                                            print(self.fsa_currentEvent)
+                                            print(self.fsa_selectedTransition)
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                            <state id="ParentMicroStepProcessed">
+                                <transition target="../MacroStepPrepared">
+                                    <script>
+                                        <![CDATA[
+                                            print('From ParentMicroStepProcessed to ParentPaused and resetting the child... ')
+                                            self.woven_child_initialized = False
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                        </state>
+                        <state id="Terminated" />
+                    </state>
+                    <state id="ParentStarted">
+                        <transition target="../FSA/Initialized">
+                            <script>
+                                <![CDATA[
+                                    print('From ParentStarted to FSA/Initialized... ')
+                                    self.weaved_initialize()
+                                ]]>
+                            </script>
+                        </transition>
+                    </state>
+                </state>
+                <transition target="../HybridTerminated" cond="INSTATE('./SimulationState/Stopped') and (INSTATE('./SimulationFlow/FSA/Terminated') or INSTATE('./SimulationFlow/FSA/DoSimulation/MicroStepProcessed/CBD/Terminated'))">
+                    <script>
+                        self.fsa_finalize()
+                    </script>
+                </transition>
+            </parallel>
+            <state id="HybridTerminated">
+            </state>
+        </scxml>
+    </class>
+</diagram>