flow: endpoint description structure with packetized parameter
authorSebastien Bourdeauducq <sb@m-labs.hk>
Fri, 21 Nov 2014 06:31:56 +0000 (22:31 -0800)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Fri, 21 Nov 2014 06:31:56 +0000 (22:31 -0800)
migen/actorlib/crc.py
migen/actorlib/fifo.py
migen/actorlib/structuring.py
migen/flow/actor.py

index ab5ebf7a5f155dcb8e883ef351a85aed2b99f556..2e42344be7367203f3e9753cdb44be17d5b3f797 100644 (file)
@@ -23,8 +23,8 @@ class CRCInserter(Module):
                Packets output with CRC.
        """
        def __init__(self, crc_class, layout):
-               self.sink = sink = Sink(layout, True)
-               self.source = source = Source(layout, True)
+               self.sink = sink = Sink(layout)
+               self.source = source = Source(layout)
                self.busy = Signal()
 
                ###
@@ -93,8 +93,8 @@ class CRCChecker(Module):
                on eop when CRC OK / set to 1 when CRC KO.
        """
        def __init__(self, crc_class, layout):
-               self.sink = sink = Sink(layout, True)
-               self.source = source = Source(layout, True)
+               self.sink = sink = Sink(layout)
+               self.source = source = Source(layout)
                self.busy = Signal()
 
                ###
index 52d2b50a8339484cbad24318b8412470ffe4f78c..5663e61dce67477c1c104e09c137823659191726 100644 (file)
@@ -10,17 +10,29 @@ class _FIFOActor(Module):
 
                ###
 
-               self.submodules.fifo = fifo_class(layout, depth)
+               description = self.sink.description
+               fifo_layout = [("payload", description.payload_layout)]
+               if description.packetized:
+                       fifo_layout += [("sop", 1), ("eop", 1)]
+
+               self.submodules.fifo = fifo_class(fifo_layout, depth)
 
                self.comb += [
                        self.sink.ack.eq(self.fifo.writable),
                        self.fifo.we.eq(self.sink.stb),
-                       self.fifo.din.eq(self.sink.payload),
+                       self.fifo.din.payload.eq(self.sink.payload),
 
                        self.source.stb.eq(self.fifo.readable),
-                       self.source.payload.eq(self.fifo.dout),
+                       self.source.payload.eq(self.fifo.dout.payload),
                        self.fifo.re.eq(self.source.ack)
                ]
+               if description.packetized:
+                       self.comb += [
+                               self.fifo.din.sop.eq(self.sink.sop),
+                               self.fifo.din.eop.eq(self.sink.eop),
+                               self.source.sop.eq(self.fifo.dout.sop),
+                               self.source.eop.eq(self.fifo.dout.eop)
+                       ]
 
 class SyncFIFO(_FIFOActor):
        def __init__(self, layout, depth, buffered=False):
index ce465578b068b0cf995172bfc44b26d3d8c3d528..fa1e557621ee87a7a024c26ce4269f3f7d36741b 100644 (file)
@@ -1,3 +1,5 @@
+from copy import copy
+
 from migen.fhdl.std import *
 from migen.genlib.record import *
 from migen.flow.actor import *
@@ -9,9 +11,9 @@ def _rawbits_layout(l):
                return l
 
 class Cast(CombinatorialActor):
-       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)
+       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))
                CombinatorialActor.__init__(self)
 
                ###
@@ -30,9 +32,12 @@ 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, packetized=False):
-               self.sink = Sink(pack_layout(layout_to, n), packetized)
-               self.source = Source(layout_to, packetized)
+       def __init__(self, n, layout_to, reverse=False):
+               self.source = source = Source(layout_to)
+               description_from = copy(source.description)
+               description_from.payload_layout = pack_layout(description_from.payload_layout, n)
+               self.sink = sink = Sink(description_from)
+               
                self.busy = Signal()
 
                ###
@@ -43,11 +48,11 @@ class Unpack(Module):
                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)
+                       source.stb.eq(sink.stb),
+                       sink.ack.eq(last & source.ack)
                ]
                self.sync += [
-                       If(self.source.stb & self.source.ack,
+                       If(source.stb & source.ack,
                                If(last,
                                        mux.eq(0)
                                ).Else(
@@ -58,19 +63,21 @@ class Unpack(Module):
                cases = {}
                for i in range(n):
                        chunk = n-i-1 if reverse else i
-                       cases[i] = [self.source.payload.raw_bits().eq(getattr(self.sink.payload, "chunk"+str(chunk)).raw_bits())]
+                       cases[i] = [source.payload.raw_bits().eq(getattr(sink.payload, "chunk"+str(chunk)).raw_bits())]
                self.comb += Case(mux, cases).makedefault()
 
-               if packetized:
+               if description_from.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)
+                               source.sop.eq(sink.sop & first),
+                               source.eop.eq(sink.eop & last)
                        ]
 
 class Pack(Module):
-       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)
+       def __init__(self, layout_from, n, reverse=False):
+               self.sink = sink = Sink(layout_from)
+               description_to = copy(sink.description)
+               description_to.payload_layout = pack_layout(description_to.payload_layout, n)
+               self.source = source = Source(description_to)
                self.busy = Signal()
 
                ###
@@ -90,7 +97,7 @@ class Pack(Module):
                        load_part.eq(sink.stb & sink.ack)
                ]
 
-               if packetized:
+               if description_to.packetized:
                        demux_last = ((demux == (n - 1)) | sink.eop)
                else:
                        demux_last = (demux == (n - 1))
@@ -108,56 +115,62 @@ class Pack(Module):
                        )
                ]
 
-               if packetized:
-                       sop = Signal()
-                       eop = Signal()
+               if description_to.packetized:
                        self.sync += [
                                If(source.stb & source.ack,
-                                       sop.eq(load_part & sink.sop)
+                                       source.sop.eq(load_part & sink.sop)
                                ).Else(
-                                       sop.eq((load_part & sink.sop) | sop)
+                                       source.sop.eq((load_part & sink.sop) | source.sop)
                                ),
-                               eop.eq(load_part & sink.eop)
-                       ]
-                       self.comb += [
-                               source.sop.eq(source.stb & sop),
-                               source.eop.eq(source.stb & eop),
+                               source.eop.eq(load_part & sink.eop)
                        ]
 
 class Chunkerize(CombinatorialActor):
-       def __init__(self, layout_from, layout_to, n, reverse=False, packetized=False):
-               self.sink = Sink(layout_from, packetized)
-               self.source = Source(pack_layout(layout_to, n), packetized)
+       def __init__(self, layout_from, layout_to, n, reverse=False):
+               self.sink = Sink(layout_from)
+               if isinstance(layout_to, EndpointDescription):
+                       layout_to = copy(layout_to)
+                       layout_to.payload_layout = pack_layout(layout_to.payload_layout, n)
+               else:
+                       layout_to = pack_layout(layout_to, n)
+               self.source = Source(layout_to)
                CombinatorialActor.__init__(self)
 
                ###
 
                for i in range(n):
                        chunk = n-i-1 if reverse else i
-                       for f in layout_from:
+                       for f in self.sink.description.payload_layout:
                                src = getattr(self.sink, f[0])
                                dst = getattr(getattr(self.source, "chunk"+str(chunk)), f[0])
                                self.comb += dst.eq(src[i*flen(src)//n:(i+1)*flen(src)//n])
 
 class Unchunkerize(CombinatorialActor):
-       def __init__(self, layout_from, n, layout_to, reverse=False, packetized=False):
-               self.sink = Sink(pack_layout(layout_from, n), packetized)
-               self.source = Source(layout_to, packetized)
+       def __init__(self, layout_from, n, layout_to, reverse=False):
+               if isinstance(layout_from, EndpointDescription):
+                       fields = layout_from.payload_layout
+                       layout_from = copy(layout_from)
+                       layout_from.payload_layout = pack_layout(layout_from.payload_layout, n)
+               else:
+                       fields = layout_from
+                       layout_from = pack_layout(layout_from, n)
+               self.sink = Sink(layout_from)
+               self.source = Source(layout_to)
                CombinatorialActor.__init__(self)
 
                ###
 
                for i in range(n):
                        chunk = n-i-1 if reverse else i
-                       for f in layout_from:
+                       for f in fields:
                                src = getattr(getattr(self.sink, "chunk"+str(chunk)), f[0])
                                dst = getattr(self.source, f[0])
                                self.comb += dst[i*flen(dst)//n:(i+1)*flen(dst)//n].eq(src)
 
 class Converter(Module):
-       def __init__(self, layout_from, layout_to, packetized=False, reverse=False):
-               self.sink = Sink(layout_from, packetized)
-               self.source = Source(layout_to, packetized)
+       def __init__(self, layout_from, layout_to, reverse=False):
+               self.sink = Sink(layout_from)
+               self.source = Source(layout_to)
                self.busy = Signal()
 
                ###
@@ -170,8 +183,8 @@ class Converter(Module):
                        if width_from % width_to:
                                raise ValueError
                        ratio = width_from//width_to
-                       self.submodules.chunkerize = Chunkerize(layout_from, layout_to, ratio, reverse, packetized)
-                       self.submodules.unpack = Unpack(ratio, layout_to, packetized=packetized)
+                       self.submodules.chunkerize = Chunkerize(layout_from, layout_to, ratio, reverse)
+                       self.submodules.unpack = Unpack(ratio, layout_to)
 
                        self.comb += [
                                Record.connect(self.sink, self.chunkerize.sink),
@@ -184,8 +197,8 @@ class Converter(Module):
                        if width_to % width_from:
                                raise ValueError
                        ratio = width_to//width_from
-                       self.submodules.pack = Pack(layout_from, ratio, packetized=packetized)
-                       self.submodules.unchunkerize = Unchunkerize(layout_from, ratio, layout_to, reverse, packetized)
+                       self.submodules.pack = Pack(layout_from, ratio)
+                       self.submodules.unchunkerize = Unchunkerize(layout_from, ratio, layout_to, reverse)
 
                        self.comb += [
                                Record.connect(self.sink, self.pack.sink),
index 8ce4cb6cafbc6e0803aeadefbed2be1ee1f4b6b7..cc539256f91c06045795e407100f4997b8c43ade 100644 (file)
@@ -12,29 +12,37 @@ def _make_m2s(layout):
                        r.append((f[0], _make_m2s(f[1])))
        return r
 
-def _check_layout(layout, packetized):
-       reserveds = ["stb", "ack", "payload"]
-       if packetized:
-               reserveds += ["sop", "eop"]
-       for f in layout:
-               if f[0] in reserveds:
-                       raise ValueError(f[0] + " cannot be used in Sink/Source layout")
-
-class _Endpoint(Record):
-       def __init__(self, layout, packetized=False):
+class EndpointDescription:
+       def __init__(self, payload_layout, packetized=False):
+               self.payload_layout = payload_layout
                self.packetized = packetized
-               _check_layout(layout, packetized)
-               endpoint_layout = [
-                       ("payload", _make_m2s(layout)),
+
+       def get_full_layout(self):
+               reserved = {"stb", "ack", "payload", "sop", "eop", "description"}
+               for f in self.payload_layout:
+                       if f[0] in reserved:
+                               raise ValueError(f[0] + " cannot be used in endpoint layout")
+
+               full_layout = [
+                       ("payload", _make_m2s(self.payload_layout)),
                        ("stb", 1, DIR_M_TO_S),
                        ("ack", 1, DIR_S_TO_M)
                ]
-               if packetized:
-                       endpoint_layout += [
+               if self.packetized:
+                       full_layout += [
                                ("sop", 1, DIR_M_TO_S),
                                ("eop", 1, DIR_M_TO_S)
                        ]
-               Record.__init__(self, endpoint_layout)
+               return full_layout
+
+
+class _Endpoint(Record):
+       def __init__(self, description_or_layout):
+               if isinstance(description_or_layout, EndpointDescription):
+                       self.description = description_or_layout
+               else:
+                       self.description = EndpointDescription(description_or_layout)
+               Record.__init__(self, self.description.get_full_layout())
 
        def __getattr__(self, name):
                return getattr(object.__getattribute__(self, "payload"), name)
@@ -79,7 +87,7 @@ class CombinatorialActor(BinaryActor):
                        sink.ack.eq(source.ack),
                        self.busy.eq(0)
                ]
-               if sink.packetized:
+               if sink.description.packetized:
                        self.comb += [
                                source.sop.eq(sink.sop),
                                source.eop.eq(sink.eop)
@@ -137,7 +145,7 @@ class PipelinedActor(BinaryActor):
                        source.stb.eq(valid),
                        self.busy.eq(busy)
                ]
-               if sink.packetized:
+               if sink.description.packetized:
                        sop = sink.sop
                        eop = sink.eop
                        for i in range(latency):