endpoints: add param_layout parameter (required to pass parameter data with converters and will allow logic optimizations)
This commit is contained in:
parent
319465445d
commit
452c60e0c3
|
@ -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
|
||||
===========
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
try:
|
||||
return getattr(object.__getattribute__(self, "payload"), name)
|
||||
except:
|
||||
return getattr(object.__getattribute__(self, "param"), name)
|
||||
|
||||
class Source(_Endpoint):
|
||||
def connect(self, sink):
|
||||
|
|
|
@ -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])),
|
||||
|
|
Loading…
Reference in New Issue