bank: event manager
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 6 Feb 2012 16:39:32 +0000 (17:39 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 6 Feb 2012 16:39:32 +0000 (17:39 +0100)
migen/bank/eventmanager.py [new file with mode: 0644]

diff --git a/migen/bank/eventmanager.py b/migen/bank/eventmanager.py
new file mode 100644 (file)
index 0000000..406e355
--- /dev/null
@@ -0,0 +1,64 @@
+from migen.fhdl.structure import *
+from migen.bank.description import *
+from migen.corelogic.misc import optree
+
+class EventSource:
+       def __init__(self):
+               self.trigger = Signal()
+
+class EventSourcePulse(EventSource):
+       pass
+
+class EventSourceLevel(EventSource):
+       pass
+
+class EventManager:
+       def __init__(self, *sources):
+               self.sources = sources
+               self.irq = Signal()
+               n = len(self.sources)
+               self.status = RegisterRaw("status", n)
+               self.pending = RegisterRaw("pending", n)
+               self.enable = RegisterFields("enable",
+                 [Field("s" + str(i), access_bus=READ_WRITE, access_dev=READ_ONLY) for i in range(n)])
+       
+       def get_registers(self):
+               return [self.status, self.pending, self.enable]
+       
+       def get_fragment(self):
+               comb = []
+               sync = []
+               
+               # status
+               for i, source in enumerate(self.sources):
+                       if isinstance(source, EventSourcePulse):
+                               comb.append(self.status.w[i].eq(0))
+                       elif isinstance(source, EventSourceLevel):
+                               comb.append(self.status.w[i].eq(source.trigger))
+                       else:
+                               raise TypeError
+               
+               # pending
+               for i, source in enumerate(self.sources):
+                       pending = Signal()
+                       # W1C
+                       sync.append(If(self.pending.re & self.pending.r[i], pending.eq(0)))
+                       if isinstance(source, EventSourcePulse):
+                               # set on a positive trigger pulse
+                               sync.append(If(source.trigger, pending.eq(1)))
+                       elif isinstance(source, EventSourceLevel):
+                               # set on the falling edge of the trigger
+                               old_trigger = Signal()
+                               sync += [
+                                       old_trigger.eq(source.trigger),
+                                       If(~source.trigger & old_trigger, pending.eq(1))
+                               ]
+                       else:
+                               raise TypeError
+                       comb.append(self.pending.w[i].eq(pending))
+               
+               # IRQ
+               irqs = [self.pending.w[i] & field.r for i, field in enumerate(self.enable.fields)]
+               comb.append(self.irq.eq(optree('|', irqs)))
+               
+               return Fragment(comb, sync)