bus/asmicon: initiator
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 30 Mar 2012 20:16:31 +0000 (22:16 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 30 Mar 2012 20:16:31 +0000 (22:16 +0200)
migen/bus/asmibus.py

index 3d4ed415f16345649c3b82f45856aaaade7035e4..ec34a6f512d441484f598e2c9f453e8793bd773b 100644 (file)
@@ -1,5 +1,6 @@
 from migen.fhdl.structure import *
 from migen.corelogic.misc import optree
+from migen.bus.transactions import *
 
 class FinalizeError(Exception):
        pass
@@ -166,3 +167,60 @@ class Hub:
                        self.dat_wm.eq(optree("|", [port.dat_wm for port in self.ports]))
                ]
                return ports + Fragment(comb)
+
+class Initiator:
+       def __init__(self, port, generator):
+               self.port = port
+               self.generator = generator
+               self.done = False
+               self._exe = None
+       
+       def _execute(self, s, port, generator):
+               while True:
+                       transaction = next(generator)
+                       transaction_start = s.cycle_counter
+                       if transaction is None:
+                               yield
+                       else:
+                               # tag phase
+                               s.wr(port.adr, transaction.address)
+                               if isinstance(transaction, TWrite):
+                                       s.wr(port.we, 1)
+                               else:
+                                       s.wr(port.we, 0)
+                               s.wr(port.stb, 1)
+                               yield
+                               while not s.rd(port.ack):
+                                       yield
+                               if hasattr(port, "tag_issue"):
+                                       tag = s.rd(port.tag_issue)
+                               else:
+                                       tag = 0
+                               tag += port.base
+                               s.wr(port.stb, 0)
+                               
+                               # data phase
+                               while not (s.rd(port.call) and (s.rd(port.tag_call) == tag)):
+                                       yield
+                               if isinstance(transaction, TWrite):
+                                       s.wr(port.dat_w, transaction.data)
+                                       s.wr(port.dat_wm, transaction.sel)
+                                       yield
+                                       s.wr(port.dat_w, 0)
+                                       s.wr(port.dat_wm, 0)
+                               else:
+                                       yield
+                                       transaction.data = s.rd(port.dat_r)
+                               transaction.latency = s.cycle_counter - transaction_start - 1
+       
+       def do_simulation(self, s):
+               if not self.done:
+                       if self._exe is None:
+                               self._exe = self._execute(s, self.port, self.generator)
+                       try:
+                               next(self._exe)
+                       except StopIteration:
+                               self.done = True
+       
+       def get_fragment(self):
+               return Fragment(sim=[self.do_simulation])