Allow SimActors to produce/consume a constant stream of tokens
authorLars-Peter Clausen <lars@metafoo.de>
Tue, 12 Mar 2013 21:27:19 +0000 (22:27 +0100)
committerLars-Peter Clausen <lars@metafoo.de>
Tue, 12 Mar 2013 22:10:51 +0000 (23:10 +0100)
Currently a SimActor requires one clock period to recover from consuming or
producing a token. ack/stb are deasserted in the cycle where the token is
consumed/produced and only re-asserted in the next cycle. This patch updates the
code to keep the control signals asserted if the actor is able to produce or
consume a token in the next cycle.

The patch also sets 'initialize' attribute on the simulation method, this will
make sure that the control and data signals will be ready right on the first
clock cycle.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
migen/actorlib/sim.py

index de11f1c9796812cda5ec14f380460cd5d4f3ac7d..18a7bfc9b1d7a18fc946d5cdf1f3011d1e4ea7d4 100644 (file)
@@ -22,27 +22,31 @@ class TokenExchanger(PureSimulable):
                for token in self.active:
                        ep = self.actor.endpoints[token.endpoint]
                        if isinstance(ep, Sink):
-                               if s.rd(ep.ack):
-                                       if s.rd(ep.stb):
-                                               token.value = s.multiread(ep.token)
-                                               completed.add(token)
-                                               s.wr(ep.ack, 0)
-                               else:
-                                       s.wr(ep.ack, 1)
+                               if s.rd(ep.ack) and s.rd(ep.stb):
+                                       token.value = s.multiread(ep.token)
+                                       completed.add(token)
+                                       s.wr(ep.ack, 0)
                        elif isinstance(ep, Source):
-                               if s.rd(ep.stb):
-                                       if s.rd(ep.ack):
-                                               completed.add(token)
-                                               s.wr(ep.stb, 0)
-                               else:
-                                       s.wr(ep.stb, 1)
-                                       s.multiwrite(ep.token, token.value)
+                               if s.rd(ep.ack) and s.rd(ep.stb):
+                                       completed.add(token)
+                                       s.wr(ep.stb, 0)
                        else:
                                raise TypeError
                self.active -= completed
                if not self.active:
                        self.busy = True
-       
+
+       def _update_control_signals(self, s):
+               for token in self.active:
+                       ep = self.actor.endpoints[token.endpoint]
+                       if isinstance(ep, Sink):
+                               s.wr(ep.ack, 1)
+                       elif isinstance(ep, Source):
+                               s.multiwrite(ep.token, token.value)
+                               s.wr(ep.stb, 1)
+                       else:
+                               raise TypeError
+
        def _next_transactions(self):
                try:
                        transactions = next(self.generator)
@@ -62,13 +66,16 @@ class TokenExchanger(PureSimulable):
                        raise TypeError
                if self.active and all(transaction.idle_wait for transaction in self.active):
                        self.busy = False
-       
+
        def do_simulation(self, s):
                if not self.done:
-                       if not self.active:
-                               self._next_transactions()
                        if self.active:
                                self._process_transactions(s)
+                       if not self.active:
+                               self._next_transactions()
+                               self._update_control_signals(s)
+
+       do_simulation.initialize = True
 
 class SimActor(Actor):
        def __init__(self, generator, *endpoint_descriptions, **misc):