litex/migen/genlib/ioo.py

80 lines
2.4 KiB
Python
Raw Normal View History

2012-11-17 13:54:50 -05:00
from migen.fhdl.structure import *
2013-02-22 11:56:35 -05:00
from migen.fhdl.specials import Memory
2012-11-17 13:54:50 -05:00
from migen.flow.actor import *
2013-04-10 17:42:46 -04:00
from migen.flow.actor import _Endpoint
2012-12-14 09:55:38 -05:00
from migen.flow.transactions import *
from migen.actorlib.sim import TokenExchanger
2012-11-23 10:23:24 -05:00
from migen.bus import wishbone, memory
2012-11-17 16:25:42 -05:00
from migen.bus.transactions import *
2012-11-17 13:54:50 -05:00
2013-04-10 13:12:42 -04:00
class UnifiedIOObject(Module):
2013-04-10 17:42:46 -04:00
def do_finalize(self):
if self.get_dataflow():
2013-04-10 13:12:42 -04:00
self.busy = Signal()
2013-04-10 17:42:46 -04:00
self.specials += set(v for v in self.__dict__.values() if isinstance(v, Memory))
def get_dataflow(self):
return dict((k, v) for k, v in self.__dict__.items() if isinstance(v, _Endpoint))
def get_buses(self):
return dict((k, v) for k, v in self.__dict__.items() if isinstance(v, (wishbone.Interface, Memory)))
2012-11-17 13:55:33 -05:00
(_WAIT_COMPLETE, _WAIT_POLL) = range(2)
class UnifiedIOSimulation(UnifiedIOObject):
2013-04-10 17:42:46 -04:00
def __init__(self, generator):
self.generator = generator
2013-04-10 17:42:46 -04:00
def do_finalize(self):
UnifiedIOObject.do_finalize(self)
2013-04-10 13:12:42 -04:00
callers = []
2012-11-17 13:55:33 -05:00
self.busname_to_caller_id = {}
2013-04-10 17:42:46 -04:00
if self.get_dataflow():
2013-04-10 13:12:42 -04:00
callers.append(TokenExchanger(self.dispatch_g(0), self))
2013-04-10 17:42:46 -04:00
for k, v in self.get_buses().items():
2013-04-10 13:12:42 -04:00
caller_id = len(callers)
2012-11-17 13:55:33 -05:00
self.busname_to_caller_id[k] = caller_id
2012-11-17 16:25:42 -05:00
g = self.dispatch_g(caller_id)
2012-11-17 13:55:33 -05:00
if isinstance(v, wishbone.Interface):
caller = wishbone.Initiator(g, v)
2012-11-23 10:23:24 -05:00
elif isinstance(v, Memory):
caller = memory.Initiator(g, v)
2013-04-10 13:12:42 -04:00
callers.append(caller)
self.submodules += callers
2012-11-17 13:55:33 -05:00
self.dispatch_state = _WAIT_COMPLETE
self.dispatch_caller = 0
self.pending_transaction = None
def identify_transaction(self, t):
if isinstance(t, Token):
return 0
elif isinstance(t, TRead) or isinstance(t, TWrite):
if t.busname is None:
if len(self.busname_to_caller_id) != 1:
raise TypeError
else:
return list(self.busname_to_caller_id.values())[0]
else:
return self.busname_to_caller_id[t.busname]
else:
raise TypeError
def dispatch_g(self, caller_id):
while True:
if self.dispatch_state == _WAIT_COMPLETE and self.dispatch_caller == caller_id:
transaction = next(self.generator)
tr_cid = self.identify_transaction(transaction)
self.dispatch_caller = tr_cid
if tr_cid == caller_id:
yield transaction
else:
self.pending_transaction = transaction
self.dispatch_state = _WAIT_POLL
yield None
elif self.dispatch_state == _WAIT_POLL and self.dispatch_caller == caller_id:
self.dispatch_state = _WAIT_COMPLETE
yield self.pending_transaction
else:
yield None