litex/migen/flow/plumbing.py

75 lines
2.3 KiB
Python
Raw Normal View History

2012-01-06 11:24:05 -05:00
from migen.fhdl.structure import *
from migen.flow.actor import *
from migen.corelogic.record import *
from migen.corelogic.misc import optree
2012-06-07 08:44:43 -04:00
class Buffer(PipelinedActor):
2012-01-09 09:14:42 -05:00
def __init__(self, layout):
super().__init__(1,
2012-01-15 09:09:44 -05:00
("d", Sink, layout), ("q", Source, layout))
2012-01-06 11:24:05 -05:00
def get_process_fragment(self):
2012-01-15 09:09:44 -05:00
sigs_d = self.token("d").flatten()
sigs_q = self.token("q").flatten()
2012-01-06 18:33:28 -05:00
sync = [If(self.pipe_ce, Cat(*sigs_q).eq(Cat(*sigs_d)))]
2012-01-06 11:24:05 -05:00
return Fragment(sync=sync)
2012-06-07 08:44:43 -04:00
class Combinator(CombinatorialActor):
def __init__(self, layout, subrecords):
2012-01-15 09:09:44 -05:00
source = Record(layout)
subrecords = [source.subrecord(*subr) for subr in subrecords]
eps = [("sink{0}".format(n), Sink, r)
2012-06-07 08:44:43 -04:00
for n, r in enumerate(subrecords)]
2012-01-15 09:09:44 -05:00
ep_source = ("source", Source, source)
eps.append(ep_source)
super().__init__(*eps)
2012-01-06 11:24:05 -05:00
def get_fragment(self):
2012-01-15 09:09:44 -05:00
source = self.endpoints["source"]
sinks = [self.endpoints["sink{0}".format(n)]
for n in range(len(self.endpoints)-1)]
2012-02-14 07:12:43 -05:00
comb = [source.stb.eq(optree("&", [sink.stb for sink in sinks]))]
2012-01-06 18:33:28 -05:00
comb += [sink.ack.eq(source.ack & source.stb) for sink in sinks]
2012-01-06 11:24:05 -05:00
return Fragment(comb)
2012-06-07 08:44:43 -04:00
class Splitter(CombinatorialActor):
def __init__(self, layout, subrecords):
2012-01-15 09:09:44 -05:00
sink = Record(layout)
2012-06-16 15:23:42 -04:00
subr = []
for s in subrecords:
if s is None:
subr.append(sink)
else:
subr.append(sink.subrecord(*s))
eps = [("source{0}".format(n), Source, r)
2012-06-16 15:23:42 -04:00
for n, r in enumerate(subr)]
2012-01-15 09:09:44 -05:00
ep_sink = ("sink", Sink, sink)
eps.append(ep_sink)
super().__init__(*eps)
2012-01-06 11:24:05 -05:00
2012-06-16 15:23:42 -04:00
def get_fragment(self):
sources = [self.endpoints[e] for e in self.sources()]
sink = self.endpoints[self.sinks()[0]]
already_acked = Signal(BV(len(sources)))
sync = [
If(sink.stb,
already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),
If(sink.ack, already_acked.eq(0))
)
]
comb = [
sink.ack.eq(optree("&",
[s.ack | already_acked[n] for n, s in enumerate(sources)]))
]
for n, s in enumerate(sources):
comb.append(s.stb.eq(sink.stb & ~already_acked[n]))
return Fragment(comb, sync)
# 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}
# 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