From bd1d456f5d866963cb27e63b5837a5a2b6a90c2f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 31 Oct 2014 12:59:45 +0100 Subject: [PATCH] flow/actor, actorlib/structuring: add packet support --- migen/actorlib/structuring.py | 60 +++++++++++++++++++++++++--------- migen/flow/actor.py | 61 +++++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 29 deletions(-) diff --git a/migen/actorlib/structuring.py b/migen/actorlib/structuring.py index d2f690b9c..eca632210 100644 --- a/migen/actorlib/structuring.py +++ b/migen/actorlib/structuring.py @@ -8,9 +8,9 @@ def _rawbits_layout(l): return l class Cast(CombinatorialActor): - def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False): - self.sink = Sink(_rawbits_layout(layout_from)) - self.source = Source(_rawbits_layout(layout_to)) + def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False, packetized=False): + self.sink = Sink(_rawbits_layout(layout_from), packetized) + self.source = Source(_rawbits_layout(layout_to), packetized) CombinatorialActor.__init__(self) ### @@ -29,16 +29,18 @@ def pack_layout(l, n): return [("chunk"+str(i), l) for i in range(n)] class Unpack(Module): - def __init__(self, n, layout_to, reverse=False): - self.sink = Sink(pack_layout(layout_to, n)) - self.source = Source(layout_to) + def __init__(self, n, layout_to, reverse=False, packetized=False): + self.sink = Sink(pack_layout(layout_to, n), packetized) + self.source = Source(layout_to, packetized) self.busy = Signal() ### mux = Signal(max=n) + first = Signal() last = Signal() self.comb += [ + first.eq(mux == 0), last.eq(mux == (n-1)), self.source.stb.eq(self.sink.stb), self.sink.ack.eq(last & self.source.ack) @@ -58,10 +60,16 @@ class Unpack(Module): cases[i] = [self.source.payload.raw_bits().eq(getattr(self.sink.payload, "chunk"+str(chunk)).raw_bits())] self.comb += Case(mux, cases).makedefault() + if packetized: + self.comb += [ + self.source.sop.eq(self.source.stb & self.sink.sop & first), + self.source.eop.eq(self.source.stb & self.sink.eop & last) + ] + class Pack(Module): - def __init__(self, layout_from, n, reverse=False): - self.sink = Sink(layout_from) - self.source = Source(pack_layout(layout_from, n)) + def __init__(self, layout_from, n, reverse=False, packetized=False): + self.sink = sink = Sink(layout_from, packetized) + self.source = source = Source(pack_layout(layout_from, n), packetized) self.busy = Signal() ### @@ -73,18 +81,24 @@ class Pack(Module): cases = {} for i in range(n): chunk = n-i-1 if reverse else i - cases[i] = [getattr(self.source.payload, "chunk"+str(chunk)).raw_bits().eq(self.sink.payload.raw_bits())] + cases[i] = [getattr(source.payload, "chunk"+str(chunk)).raw_bits().eq(sink.payload.raw_bits())] self.comb += [ self.busy.eq(strobe_all), - self.sink.ack.eq(~strobe_all | self.source.ack), - self.source.stb.eq(strobe_all), - load_part.eq(self.sink.stb & self.sink.ack) + sink.ack.eq(~strobe_all | source.ack), + source.stb.eq(strobe_all), + load_part.eq(sink.stb & sink.ack) ] + + if packetized: + demux_last = ((demux == (n - 1)) | sink.eop) + else: + demux_last = (demux == (n - 1)) + self.sync += [ - If(self.source.ack, strobe_all.eq(0)), + If(source.ack, strobe_all.eq(0)), If(load_part, Case(demux, cases), - If(demux == (n - 1), + If(demux_last, demux.eq(0), strobe_all.eq(1) ).Else( @@ -92,3 +106,19 @@ class Pack(Module): ) ) ] + + if packetized: + sop = Signal() + eop = Signal() + self.sync += [ + If(source.stb & source.ack, + sop.eq(load_part & sink.sop) + ).Else( + sop.eq((load_part & sink.sop) | sop) + ), + eop.eq(load_part & sink.eop) + ] + self.comb += [ + source.sop.eq(source.stb & sop), + source.eop.eq(source.stb & eop), + ] diff --git a/migen/flow/actor.py b/migen/flow/actor.py index 5931ebb46..8ce4cb6ca 100644 --- a/migen/flow/actor.py +++ b/migen/flow/actor.py @@ -22,6 +22,7 @@ def _check_layout(layout, packetized): class _Endpoint(Record): def __init__(self, layout, packetized=False): + self.packetized = packetized _check_layout(layout, packetized) endpoint_layout = [ ("payload", _make_m2s(layout)), @@ -66,21 +67,30 @@ class BinaryActor(Module): self.busy = Signal() sink = get_single_ep(self, Sink)[1] source = get_single_ep(self, Source)[1] - self.build_binary_control(sink.stb, sink.ack, source.stb, source.ack, *args, **kwargs) + self.build_binary_control(sink, source, *args, **kwargs) - def build_binary_control(self, stb_i, ack_o, stb_o, ack_i): + def build_binary_control(self, sink, source): raise NotImplementedError("Binary actor classes must overload build_binary_control_fragment") class CombinatorialActor(BinaryActor): - def build_binary_control(self, stb_i, ack_o, stb_o, ack_i): - self.comb += [stb_o.eq(stb_i), ack_o.eq(ack_i), self.busy.eq(0)] + def build_binary_control(self, sink, source): + self.comb += [ + source.stb.eq(sink.stb), + sink.ack.eq(source.ack), + self.busy.eq(0) + ] + if sink.packetized: + self.comb += [ + source.sop.eq(sink.sop), + source.eop.eq(sink.eop) + ] class SequentialActor(BinaryActor): def __init__(self, delay): self.trigger = Signal() BinaryActor.__init__(self, delay) - def build_binary_control(self, stb_i, ack_o, stb_o, ack_i, delay): + def build_binary_control(self, sink, source, delay): ready = Signal() timer = Signal(max=delay+1) self.comb += ready.eq(timer == 0) @@ -92,24 +102,29 @@ class SequentialActor(BinaryActor): mask = Signal() self.comb += [ - stb_o.eq(ready & mask), - self.trigger.eq(stb_i & (ack_i | ~mask) & ready), - ack_o.eq(self.trigger), + source.stb.eq(ready & mask), + self.trigger.eq(sink.stb & (source.ack | ~mask) & ready), + sink.ack.eq(self.trigger), self.busy.eq(~ready) ] self.sync += [ If(self.trigger, mask.eq(1)), - If(stb_o & ack_i, mask.eq(0)) + If(source.stb & source.ack, mask.eq(0)) ] + if sink.packetized: + self.comb += [ + source.sop.eq(sink.sop), + source.eop.eq(sink.eop) + ] class PipelinedActor(BinaryActor): def __init__(self, latency): self.pipe_ce = Signal() BinaryActor.__init__(self, latency) - def build_binary_control(self, stb_i, ack_o, stb_o, ack_i, latency): + def build_binary_control(self, sink, source, latency): busy = 0 - valid = stb_i + valid = sink.stb for i in range(latency): valid_n = Signal() self.sync += If(self.pipe_ce, valid_n.eq(valid)) @@ -117,8 +132,26 @@ class PipelinedActor(BinaryActor): busy = busy | valid self.comb += [ - self.pipe_ce.eq(ack_i | ~valid), - ack_o.eq(self.pipe_ce), - stb_o.eq(valid), + self.pipe_ce.eq(source.ack | ~valid), + sink.ack.eq(self.pipe_ce), + source.stb.eq(valid), self.busy.eq(busy) ] + if sink.packetized: + sop = sink.sop + eop = sink.eop + for i in range(latency): + sop_n = Signal() + eop_n = Signal() + self.sync += \ + If(self.pipe_ce, + sop_n.eq(sop), + eop_n.eq(eop) + ) + sop = sop_n + eop = eop_n + + self.comb += [ + source.eop.eq(eop), + source.sop.eq(sop) + ]