endpoints: add param_layout parameter (required to pass parameter data with converters and will allow logic optimizations)

This commit is contained in:
Florent Kermarrec 2015-02-12 23:36:57 +01:00 committed by Sebastien Bourdeauducq
parent 319465445d
commit 452c60e0c3
5 changed files with 57 additions and 6 deletions

View File

@ -69,6 +69,14 @@ Accessing the endpoints is done by manipulating the signals inside the ``Source`
* A signal object ``ack``. * A signal object ``ack``.
* The data payload ``payload``, which is a record with the layout given to the endpoint constructor. * 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 Busy signal
=========== ===========

View File

@ -11,7 +11,13 @@ class _FIFOActor(Module):
### ###
description = self.sink.description 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: if description.packetized:
fifo_layout += [("sop", 1), ("eop", 1)] fifo_layout += [("sop", 1), ("eop", 1)]
@ -21,9 +27,11 @@ class _FIFOActor(Module):
self.sink.ack.eq(self.fifo.writable), self.sink.ack.eq(self.fifo.writable),
self.fifo.we.eq(self.sink.stb), self.fifo.we.eq(self.sink.stb),
self.fifo.din.payload.eq(self.sink.payload), 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.stb.eq(self.fifo.readable),
self.source.payload.eq(self.fifo.dout.payload), self.source.payload.eq(self.fifo.dout.payload),
self.source.param.eq(self.fifo.dout.param),
self.fifo.re.eq(self.source.ack) self.fifo.re.eq(self.source.ack)
] ]
if description.packetized: if description.packetized:

View File

@ -66,6 +66,11 @@ class Unpack(Module):
cases[i] = [source.payload.raw_bits().eq(getattr(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() 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: if description_from.packetized:
self.comb += [ self.comb += [
source.sop.eq(sink.sop & first), source.sop.eq(sink.sop & first),
@ -97,6 +102,11 @@ class Pack(Module):
load_part.eq(sink.stb & sink.ack) 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: if description_to.packetized:
demux_last = ((demux == (n - 1)) | sink.eop) demux_last = ((demux == (n - 1)) | sink.eop)
else: else:
@ -146,6 +156,11 @@ class Chunkerize(CombinatorialActor):
dst = getattr(getattr(self.source, "chunk"+str(chunk)), 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]) 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): class Unchunkerize(CombinatorialActor):
def __init__(self, layout_from, n, layout_to, reverse=False): def __init__(self, layout_from, n, layout_to, reverse=False):
if isinstance(layout_from, EndpointDescription): if isinstance(layout_from, EndpointDescription):
@ -168,6 +183,11 @@ class Unchunkerize(CombinatorialActor):
dst = getattr(self.source, f[0]) dst = getattr(self.source, f[0])
self.comb += dst[i*flen(dst)//n:(i+1)*flen(dst)//n].eq(src) 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): class Converter(Module):
def __init__(self, layout_from, layout_to, reverse=False): def __init__(self, layout_from, layout_to, reverse=False):
self.sink = Sink(layout_from) self.sink = Sink(layout_from)

View File

@ -13,18 +13,24 @@ def _make_m2s(layout):
return r return r
class EndpointDescription: class EndpointDescription:
def __init__(self, payload_layout, packetized=False): def __init__(self, payload_layout, param_layout=[], packetized=False):
self.payload_layout = payload_layout self.payload_layout = payload_layout
self.param_layout = param_layout
self.packetized = packetized self.packetized = packetized
def get_full_layout(self): def get_full_layout(self):
reserved = {"stb", "ack", "payload", "sop", "eop", "description"} reserved = {"stb", "ack", "payload", "param", "sop", "eop", "description"}
for f in self.payload_layout: 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: if f[0] in reserved:
raise ValueError(f[0] + " cannot be used in endpoint layout") raise ValueError(f[0] + " cannot be used in endpoint layout")
attributed.add(f[0])
full_layout = [ full_layout = [
("payload", _make_m2s(self.payload_layout)), ("payload", _make_m2s(self.payload_layout)),
("param", _make_m2s(self.param_layout)),
("stb", 1, DIR_M_TO_S), ("stb", 1, DIR_M_TO_S),
("ack", 1, DIR_S_TO_M) ("ack", 1, DIR_S_TO_M)
] ]
@ -45,7 +51,10 @@ class _Endpoint(Record):
Record.__init__(self, self.description.get_full_layout()) Record.__init__(self, self.description.get_full_layout())
def __getattr__(self, name): 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): class Source(_Endpoint):
def connect(self, sink): def connect(self, sink):

View File

@ -8,7 +8,11 @@ class Buffer(PipelinedActor):
self.d = Sink(layout) self.d = Sink(layout)
self.q = Source(layout) self.q = Source(layout)
PipelinedActor.__init__(self, 1) 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): class Combinator(Module):
def __init__(self, layout, subrecords): 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 += [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.payload.eq(sink.payload) for sink in sinks]
self.comb += [self.source.param.eq(sink.param) for sink in sinks]
class Splitter(Module): class Splitter(Module):
def __init__(self, layout, subrecords): 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.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)) already_acked = Signal(len(sources))
self.sync += If(self.sink.stb, self.sync += If(self.sink.stb,
already_acked.eq(already_acked | Cat(*[s.ack for s in sources])), already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),