From be68ecfc72973114e62e038db29a1cdea98dc8ff Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 17 Nov 2012 19:55:33 +0100 Subject: [PATCH] uio: add simulation I/O object --- migen/uio/ioo.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/migen/uio/ioo.py b/migen/uio/ioo.py index 934cbf32e..72dbb391e 100644 --- a/migen/uio/ioo.py +++ b/migen/uio/ioo.py @@ -7,3 +7,63 @@ class UnifiedIOObject(Actor): if dataflow is not None: super().__init__(*dataflow) self.buses = buses + +(_WAIT_COMPLETE, _WAIT_POLL) = range(2) + +class UnifiedIOSimulation(UnifiedIOObject): + def __init__(self, generator, dataflow=None, buses={}): + self.generator = generator + super().__init__(dataflow, buses) + + self.callers = [] + self.busname_to_caller_id = {} + if dataflow is not None: + self.callers.append(TokenExchanger(self.demux_g(0), self)) + for k, v in self.buses.items(): + caller_id = len(self.callers) + self.busname_to_caller_id[k] = caller_id + g = self.demux_g(caller_id) + if isinstance(v, wishbone.Interface): + caller = wishbone.Initiator(g, v) + else: + raise NotImplementedError + self.callers.append(caller) + + 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 + + def get_fragment(self): + return sum([c.get_fragment() for c in self.callers], Fragment())