endpoints: add param_layout parameter (required to pass parameter data with converter...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 12 Feb 2015 22:36:57 +0000 (23:36 +0100)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 14 Feb 2015 11:10:56 +0000 (03:10 -0800)
doc/dataflow.rst
migen/actorlib/fifo.py
migen/actorlib/structuring.py
migen/flow/actor.py
migen/flow/plumbing.py

index c8478f048638a575647910f6a65e0dd492f68999..c435eddf9fb1219fd424771a064a1dd782e64713 100644 (file)
@@ -69,6 +69,14 @@ Accessing the endpoints is done by manipulating the signals inside the ``Source`
 * A signal object ``ack``.
 * The data payload ``payload``, which is a record with the layout given to the endpoint constructor.
 
+Endpoints can also be used to manipulate packets, this is done by setting packetized parameter to True which adds:
+
+* A signal object ``sop`` (Start Of Packet).
+* A signal object ``eop`` (End Of Packet).
+
+When used in packetized mode, packet parameters (signals that do no change for the duration of a packet) should to be declared in
+param_layout. Declaring these signals in payload_layout will works in most cases but will prevent logic optimizations.
+
 Busy signal
 ===========
 
index 5663e61dce67477c1c104e09c137823659191726..36312eb8d392092dd19a2e06cade9d13107997a2 100644 (file)
@@ -11,7 +11,13 @@ class _FIFOActor(Module):
                ###
 
                description = self.sink.description
-               fifo_layout = [("payload", description.payload_layout)]
+               fifo_layout = [
+                       ("payload", description.payload_layout),
+                       # Note : Can be optimized by passing parameters
+                       #        in another fifo. We will only have one
+                       #        data per packet.
+                       ("param", description.param_layout)
+               ]
                if description.packetized:
                        fifo_layout += [("sop", 1), ("eop", 1)]
 
@@ -21,9 +27,11 @@ class _FIFOActor(Module):
                        self.sink.ack.eq(self.fifo.writable),
                        self.fifo.we.eq(self.sink.stb),
                        self.fifo.din.payload.eq(self.sink.payload),
+                       self.fifo.din.param.eq(self.sink.param),
 
                        self.source.stb.eq(self.fifo.readable),
                        self.source.payload.eq(self.fifo.dout.payload),
+                       self.source.param.eq(self.fifo.dout.param),
                        self.fifo.re.eq(self.source.ack)
                ]
                if description.packetized:
index de733a26607fbe51799ea9b2a82dee6f25a1f0a9..1ad971c82e218ce60a7566a3ec94ef1f0718934c 100644 (file)
@@ -66,6 +66,11 @@ class Unpack(Module):
                        cases[i] = [source.payload.raw_bits().eq(getattr(sink.payload, "chunk"+str(chunk)).raw_bits())]
                self.comb += Case(mux, cases).makedefault()
 
+               for f in description_from.param_layout:
+                       src = getattr(self.sink, f[0])
+                       dst = getattr(self.source, f[0])
+                       self.comb += dst.eq(src)
+
                if description_from.packetized:
                        self.comb += [
                                source.sop.eq(sink.sop & first),
@@ -97,6 +102,11 @@ class Pack(Module):
                        load_part.eq(sink.stb & sink.ack)
                ]
 
+               for f in description_to.param_layout:
+                       src = getattr(self.sink, f[0])
+                       dst = getattr(self.source, f[0])
+                       self.comb += dst.eq(src)
+
                if description_to.packetized:
                        demux_last = ((demux == (n - 1)) | sink.eop)
                else:
@@ -146,6 +156,11 @@ class Chunkerize(CombinatorialActor):
                                dst = getattr(getattr(self.source, "chunk"+str(chunk)), f[0])
                                self.comb += dst.eq(src[i*flen(src)//n:(i+1)*flen(src)//n])
 
+               for f in self.sink.description.param_layout:
+                       src = getattr(self.sink, f[0])
+                       dst = getattr(self.source, f[0])
+                       self.comb += dst.eq(src)
+
 class Unchunkerize(CombinatorialActor):
        def __init__(self, layout_from, n, layout_to, reverse=False):
                if isinstance(layout_from, EndpointDescription):
@@ -168,6 +183,11 @@ class Unchunkerize(CombinatorialActor):
                                dst = getattr(self.source, f[0])
                                self.comb += dst[i*flen(dst)//n:(i+1)*flen(dst)//n].eq(src)
 
+               for f in self.sink.description.param_layout:
+                       src = getattr(self.sink, f[0])
+                       dst = getattr(self.source, f[0])
+                       self.comb += dst.eq(src)
+
 class Converter(Module):
        def __init__(self, layout_from, layout_to, reverse=False):
                self.sink = Sink(layout_from)
index cc539256f91c06045795e407100f4997b8c43ade..58ddcb402ce2c85c8d2d1a61c1bb56e656650d76 100644 (file)
@@ -13,18 +13,24 @@ def _make_m2s(layout):
        return r
 
 class EndpointDescription:
-       def __init__(self, payload_layout, packetized=False):
+       def __init__(self, payload_layout, param_layout=[], packetized=False):
                self.payload_layout = payload_layout
+               self.param_layout = param_layout
                self.packetized = packetized
 
        def get_full_layout(self):
-               reserved = {"stb", "ack", "payload", "sop", "eop", "description"}
-               for f in self.payload_layout:
+               reserved = {"stb", "ack", "payload", "param", "sop", "eop", "description"}
+               attributed = set()
+               for f in self.payload_layout + self.param_layout:
+                       if f[0] in attributed:
+                               raise ValueError(f[0] + " already attributed in payload or param layout")
                        if f[0] in reserved:
                                raise ValueError(f[0] + " cannot be used in endpoint layout")
+                       attributed.add(f[0])
 
                full_layout = [
                        ("payload", _make_m2s(self.payload_layout)),
+                       ("param", _make_m2s(self.param_layout)),
                        ("stb", 1, DIR_M_TO_S),
                        ("ack", 1, DIR_S_TO_M)
                ]
@@ -45,7 +51,10 @@ class _Endpoint(Record):
                Record.__init__(self, self.description.get_full_layout())
 
        def __getattr__(self, name):
-               return getattr(object.__getattribute__(self, "payload"), name)
+               try:
+                       return getattr(object.__getattribute__(self, "payload"), name)
+               except:
+                       return getattr(object.__getattribute__(self, "param"), name)
 
 class Source(_Endpoint):
        def connect(self, sink):
index 1ca13f8184e66eedae4781efa5f95074a7c07585..6e4f81aa3df17f9863f4758fbc9a949ab9654535 100644 (file)
@@ -8,7 +8,11 @@ class Buffer(PipelinedActor):
                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))
+               self.sync += \
+                       If(self.pipe_ce,
+                               self.q.payload.eq(self.d.payload),
+                               self.q.param.eq(self.d.param)
+                       )
 
 class Combinator(Module):
        def __init__(self, layout, subrecords):
@@ -28,6 +32,7 @@ class Combinator(Module):
                ]
                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]
+               self.comb += [self.source.param.eq(sink.param) for sink in sinks]
 
 class Splitter(Module):
        def __init__(self, layout, subrecords):
@@ -42,6 +47,7 @@ class Splitter(Module):
                ###
 
                self.comb += [source.payload.eq(self.sink.payload) for source in sources]
+               self.comb += [source.param.eq(self.sink.param) for source in sources]
                already_acked = Signal(len(sources))
                self.sync += If(self.sink.stb,
                                already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),