sim: use (mandatory) ncycles when starting a simulation with no active functions
authorSebastien Bourdeauducq <sb@m-labs.hk>
Sun, 13 Apr 2014 13:16:27 +0000 (15:16 +0200)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sun, 13 Apr 2014 13:16:27 +0000 (15:16 +0200)
doc/simulation.rst
migen/sim/generic.py

index 323de56fe58db457049eabcb0874cb8a8e519037..fa93c9956a21dc70eb13de01e85a8021310fa020 100644 (file)
@@ -55,7 +55,7 @@ Running the simulation
 
 Running the simulation is achieved by calling the ``run`` method of the ``Simulator`` object.
 
-It takes an optional parameter that defines the maximum number of clock cycles that this call simulates. The default value of ``None`` sets no cycle limit.
+It takes an optional parameter ``ncycles`` that defines the maximum number of clock cycles that this call simulates. The default value of ``None`` sets no cycle limit.
 
 The cycle counter
 =================
@@ -111,6 +111,8 @@ Simulation functions and generators can raise the ``StopSimulation`` exception.
 
 Some simulation modules only respond to external stimuli - e.g. the ``bus.wishbone.Tap`` that snoops on bus transactions and prints them on the console - and have simulation functions that never end. To deal with those, the new API introduces "passive" simulation functions that are not taken into account when deciding to continue to run the simulation. A simulation function is declared passive by setting a "passive" attribute on it that evaluates to True. Raising ``StopSimulation`` in such a function still makes the simulator stop running it for the rest of the simulation.
 
+When starting the simulation of a design that contains no simulation functions or only passive simulation functions, the simulation will continue until the specified number of cycles is reached. The ``ncycles`` parameter is mandatory in this case.
+
 .. _simrunner:
 
 The external simulator runner
index c06d126533bd8cc29f60895633a06b69fed6b9ac..34f27ba0c274ce55b8f22b5a12658bb619300865 100644 (file)
@@ -106,7 +106,21 @@ class Simulator:
        
        def run(self, ncycles=None):
                counter = 0
-               while self.active_sim_functions and (ncycles is None or counter < ncycles):
+
+               if self.active_sim_functions:
+                       if ncycles is None:
+                               def continue_simulation():
+                                       return bool(self.active_sim_functions)
+                       else:
+                               def continue_simulation():
+                                       return self.active_sim_functions and counter < ncycles
+               else:
+                       if ncycles is None:
+                               raise ValueError("No active simulation function present - must specify ncycles to end simulation")
+                       def continue_simulation():
+                               return counter < ncycles
+
+               while continue_simulation():
                        self.cycle_counter += 1
                        counter += 1
                        self.ipc.send(MessageGo())