flow/actor, actorlib/structuring: add packet support
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 31 Oct 2014 11:59:45 +0000 (12:59 +0100)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 1 Nov 2014 13:22:46 +0000 (21:22 +0800)
migen/actorlib/structuring.py
migen/flow/actor.py

index d2f690b9c176069f79d245e460ce37cdda31016d..eca6322103dae568e2fbff9560829ebe81afe9ba 100644 (file)
@@ -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),
+                       ]
index 5931ebb4662b0a175b89d5dc315fa39bbb6bbc55..8ce4cb6cafbc6e0803aeadefbed2be1ee1f4b6b7 100644 (file)
@@ -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)
+                       ]