2012-02-06 11:39:32 -05:00
|
|
|
from migen.fhdl.structure import *
|
2013-03-10 14:29:05 -04:00
|
|
|
from migen.fhdl.module import Module
|
2012-02-06 11:39:32 -05:00
|
|
|
from migen.bank.description import *
|
2013-02-22 17:19:37 -05:00
|
|
|
from migen.genlib.misc import optree
|
2012-02-06 11:39:32 -05:00
|
|
|
|
2013-03-10 14:47:21 -04:00
|
|
|
class _EventSource(HUID):
|
2012-02-06 11:39:32 -05:00
|
|
|
def __init__(self):
|
2013-03-10 14:29:05 -04:00
|
|
|
HUID.__init__(self)
|
2012-02-06 11:39:32 -05:00
|
|
|
self.trigger = Signal()
|
2012-05-21 13:56:23 -04:00
|
|
|
self.pending = Signal()
|
2012-02-06 11:39:32 -05:00
|
|
|
|
2013-03-10 14:47:21 -04:00
|
|
|
class EventSourcePulse(_EventSource):
|
2012-02-06 11:39:32 -05:00
|
|
|
pass
|
|
|
|
|
2013-03-10 14:47:21 -04:00
|
|
|
class EventSourceLevel(_EventSource):
|
2012-02-06 11:39:32 -05:00
|
|
|
pass
|
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
class EventManager(Module, AutoCSR):
|
2013-03-10 14:29:05 -04:00
|
|
|
def __init__(self):
|
2012-02-06 11:39:32 -05:00
|
|
|
self.irq = Signal()
|
2013-03-10 14:29:05 -04:00
|
|
|
|
|
|
|
def do_finalize(self):
|
2013-03-10 14:47:21 -04:00
|
|
|
sources_u = [v for v in self.__dict__.values() if isinstance(v, _EventSource)]
|
2013-03-10 14:29:05 -04:00
|
|
|
sources = sorted(sources_u, key=lambda x: x.huid)
|
|
|
|
n = len(sources)
|
2013-03-30 12:28:41 -04:00
|
|
|
self.status = CSR(n)
|
|
|
|
self.pending = CSR(n)
|
|
|
|
self.enable = CSRStorage(n)
|
2013-03-10 14:29:05 -04:00
|
|
|
|
2012-02-06 11:39:32 -05:00
|
|
|
# status
|
2013-03-10 14:29:05 -04:00
|
|
|
for i, source in enumerate(sources):
|
2012-02-06 11:39:32 -05:00
|
|
|
if isinstance(source, EventSourcePulse):
|
2013-03-10 14:29:05 -04:00
|
|
|
self.comb += self.status.w[i].eq(0)
|
2012-02-06 11:39:32 -05:00
|
|
|
elif isinstance(source, EventSourceLevel):
|
2013-03-10 14:29:05 -04:00
|
|
|
self.comb += self.status.w[i].eq(source.trigger)
|
2012-02-06 11:39:32 -05:00
|
|
|
else:
|
|
|
|
raise TypeError
|
|
|
|
|
|
|
|
# pending
|
2013-03-10 14:29:05 -04:00
|
|
|
for i, source in enumerate(sources):
|
2012-02-06 11:39:32 -05:00
|
|
|
# W1C
|
2013-03-10 14:29:05 -04:00
|
|
|
self.sync += If(self.pending.re & self.pending.r[i], source.pending.eq(0))
|
2012-02-06 11:39:32 -05:00
|
|
|
if isinstance(source, EventSourcePulse):
|
|
|
|
# set on a positive trigger pulse
|
2013-03-10 14:29:05 -04:00
|
|
|
self.sync += If(source.trigger, source.pending.eq(1))
|
2012-02-06 11:39:32 -05:00
|
|
|
elif isinstance(source, EventSourceLevel):
|
|
|
|
# set on the falling edge of the trigger
|
|
|
|
old_trigger = Signal()
|
2013-03-10 14:29:05 -04:00
|
|
|
self.sync += [
|
2012-02-06 11:39:32 -05:00
|
|
|
old_trigger.eq(source.trigger),
|
2012-05-21 13:56:23 -04:00
|
|
|
If(~source.trigger & old_trigger, source.pending.eq(1))
|
2012-02-06 11:39:32 -05:00
|
|
|
]
|
|
|
|
else:
|
|
|
|
raise TypeError
|
2013-03-10 14:29:05 -04:00
|
|
|
self.comb += self.pending.w[i].eq(source.pending)
|
2012-02-06 11:39:32 -05:00
|
|
|
|
|
|
|
# IRQ
|
2013-03-30 12:28:41 -04:00
|
|
|
irqs = [self.pending.w[i] & self.enable.storage[i] for i in range(n)]
|
2013-03-10 14:29:05 -04:00
|
|
|
self.comb += self.irq.eq(optree("|", irqs))
|
|
|
|
|
|
|
|
def __setattr__(self, name, value):
|
2013-03-10 14:47:21 -04:00
|
|
|
if isinstance(value, _EventSource) and self.finalized:
|
2013-03-10 14:29:05 -04:00
|
|
|
raise FinalizeError
|
|
|
|
object.__setattr__(self, name, value)
|