2013-05-22 11:11:09 -04:00
|
|
|
from migen.fhdl.std import *
|
2012-01-06 11:24:05 -05:00
|
|
|
from migen.flow.actor import *
|
2013-02-22 17:19:37 -05:00
|
|
|
from migen.genlib.record import *
|
|
|
|
from migen.genlib.misc import optree
|
2012-01-06 11:24:05 -05:00
|
|
|
|
2012-06-07 08:44:43 -04:00
|
|
|
class Buffer(PipelinedActor):
|
2012-01-09 09:14:42 -05:00
|
|
|
def __init__(self, layout):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.d = Sink(layout)
|
|
|
|
self.q = Source(layout)
|
|
|
|
PipelinedActor.__init__(self, 1)
|
|
|
|
self.sync += If(self.pipe_ce, self.q.payload.eq(self.d.payload))
|
2012-01-06 11:24:05 -05:00
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
class Combinator(Module):
|
2012-06-16 11:30:54 -04:00
|
|
|
def __init__(self, layout, subrecords):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.source = Source(layout)
|
|
|
|
sinks = []
|
|
|
|
for n, r in enumerate(subrecords):
|
|
|
|
s = Sink(layout_partial(layout, *r))
|
|
|
|
setattr(self, "sink"+str(n), s)
|
|
|
|
sinks.append(s)
|
|
|
|
self.busy = Signal()
|
2012-01-06 11:24:05 -05:00
|
|
|
|
2013-04-01 16:15:23 -04:00
|
|
|
###
|
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += [
|
|
|
|
self.busy.eq(0),
|
|
|
|
self.source.stb.eq(optree("&", [sink.stb for sink in sinks]))
|
|
|
|
]
|
|
|
|
self.comb += [sink.ack.eq(self.source.ack & self.source.stb) for sink in sinks]
|
|
|
|
self.comb += [self.source.payload.eq(sink.payload) for sink in sinks]
|
2012-01-06 11:24:05 -05:00
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
class Splitter(Module):
|
2012-06-16 11:30:54 -04:00
|
|
|
def __init__(self, layout, subrecords):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.sink = Sink(layout)
|
|
|
|
sources = []
|
|
|
|
for n, r in enumerate(subrecords):
|
|
|
|
s = Source(layout_partial(layout, *r))
|
|
|
|
setattr(self, "source"+str(n), s)
|
|
|
|
sources.append(s)
|
|
|
|
self.busy = Signal()
|
2012-01-06 11:24:05 -05:00
|
|
|
|
2013-04-01 16:15:23 -04:00
|
|
|
###
|
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += [source.payload.eq(self.sink.payload) for source in sources]
|
2012-11-29 15:22:38 -05:00
|
|
|
already_acked = Signal(len(sources))
|
2013-04-10 13:12:42 -04:00
|
|
|
self.sync += If(self.sink.stb,
|
2012-06-16 15:23:42 -04:00
|
|
|
already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),
|
2013-04-10 13:12:42 -04:00
|
|
|
If(self.sink.ack, already_acked.eq(0))
|
2012-06-16 15:23:42 -04:00
|
|
|
)
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += self.sink.ack.eq(optree("&",
|
2012-06-16 15:23:42 -04:00
|
|
|
[s.ack | already_acked[n] for n, s in enumerate(sources)]))
|
|
|
|
for n, s in enumerate(sources):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += s.stb.eq(self.sink.stb & ~already_acked[n])
|
2012-06-16 11:30:54 -04:00
|
|
|
|
|
|
|
# Actors whose layout should be inferred from what their single sink is connected to.
|
2012-06-16 15:23:42 -04:00
|
|
|
layout_sink = {Buffer, Splitter}
|
2012-06-16 11:30:54 -04:00
|
|
|
# Actors whose layout should be inferred from what their single source is connected to.
|
|
|
|
layout_source = {Buffer, Combinator}
|
|
|
|
# All actors.
|
|
|
|
actors = layout_sink | layout_source
|