class EndpointDescription:
- def __init__(self, payload_layout, param_layout=[], packetized=True):
+ def __init__(self, payload_layout, param_layout=[]):
self.payload_layout = payload_layout
self.param_layout = param_layout
- self.packetized = packetized
def get_full_layout(self):
- reserved = {"stb", "ack", "payload", "param", "sop", "eop", "description"}
+ reserved = {"stb", "ack", "payload", "param", "eop", "description"}
attributed = set()
for f in self.payload_layout + self.param_layout:
if f[0] in attributed:
("payload", _make_m2s(self.payload_layout)),
("param", _make_m2s(self.param_layout)),
("stb", 1, DIR_M_TO_S),
- ("ack", 1, DIR_S_TO_M)
+ ("ack", 1, DIR_S_TO_M),
+ ("eop", 1, DIR_M_TO_S)
]
- if self.packetized:
- full_layout += [
- ("sop", 1, DIR_M_TO_S),
- ("eop", 1, DIR_M_TO_S)
- ]
return full_layout
# # #
description = self.sink.description
- fifo_layout = [("payload", description.payload_layout)]
- if description.packetized:
- fifo_layout += [("sop", 1), ("eop", 1)]
+ fifo_layout = [("payload", description.payload_layout),
+ ("eop", 1)]
self.submodules.fifo = fifo_class(layout_len(fifo_layout), depth)
fifo_in = Record(fifo_layout)
self.comb += [
self.sink.ack.eq(self.fifo.writable),
self.fifo.we.eq(self.sink.stb),
+ fifo_in.eop.eq(self.sink.eop),
fifo_in.payload.eq(self.sink.payload),
self.source.stb.eq(self.fifo.readable),
+ self.source.eop.eq(fifo_out.eop),
self.source.payload.eq(fifo_out.payload),
self.fifo.re.eq(self.source.ack)
]
- if description.packetized:
- self.comb += [
- fifo_in.sop.eq(self.sink.sop),
- fifo_in.eop.eq(self.sink.eop),
- self.source.sop.eq(fifo_out.sop),
- self.source.eop.eq(fifo_out.eop)
- ]
class SyncFIFO(_FIFOWrapper):
def build_binary_control(self, sink, source):
self.comb += [
source.stb.eq(sink.stb),
+ source.eop.eq(sink.eop),
sink.ack.eq(source.ack),
self.busy.eq(0)
]
- if sink.description.packetized:
- self.comb += [
- source.sop.eq(sink.sop),
- source.eop.eq(sink.eop)
- ]
class PipelinedActor(BinaryActor):
source.stb.eq(valid),
self.busy.eq(busy)
]
- if sink.description.packetized:
- sop = sink.stb & sink.sop
- eop = sink.stb & 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)
- ]
+ eop = sink.stb & sink.eop
+ for i in range(latency):
+ eop_n = Signal()
+ self.sync += \
+ If(self.pipe_ce,
+ eop_n.eq(eop)
+ )
+ eop = eop_n
+ self.comb += source.eop.eq(eop)
class Buffer(PipelinedActor):
# # #
mux = Signal(max=n)
- first = Signal()
last = Signal()
self.comb += [
- first.eq(mux == 0),
last.eq(mux == (n-1)),
source.stb.eq(sink.stb),
sink.ack.eq(last & source.ack)
dst = getattr(self.source, f[0])
self.comb += dst.eq(src)
- if description_from.packetized:
- self.comb += [
- source.sop.eq(sink.sop & first),
- source.eop.eq(sink.eop & last)
- ]
+ self.comb += source.eop.eq(sink.eop & last)
class Pack(Module):
dst = getattr(self.source, f[0])
self.sync += If(load_part, dst.eq(src))
- if description_to.packetized:
- demux_last = ((demux == (n - 1)) | sink.eop)
- else:
- demux_last = (demux == (n - 1))
+ demux_last = ((demux == (n - 1)) | sink.eop)
self.sync += [
If(source.ack, strobe_all.eq(0)),
).Else(
demux.eq(demux + 1)
)
+ ),
+ If(source.stb & source.ack,
+ source.eop.eq(sink.eop),
+ ).Elif(sink.stb & sink.ack,
+ source.eop.eq(sink.eop | source.eop)
)
]
- if description_to.packetized:
- self.sync += [
- If(source.stb & source.ack,
- source.sop.eq(sink.sop),
- source.eop.eq(sink.eop),
- ).Elif(sink.stb & sink.ack,
- source.sop.eq(sink.sop | source.sop),
- source.eop.eq(sink.eop | source.eop)
- )
- ]
-
class Chunkerize(CombinatorialActor):
def __init__(self, layout_from, layout_to, n, reverse=False):
class Status(Module):
def __init__(self, endpoint):
- self.sop = sop = Signal()
- self.eop = eop =Signal()
+ self.first = first = Signal(reset=1)
+ self.eop = eop = Signal()
self.ongoing = Signal()
ongoing = Signal()
self.comb += \
If(endpoint.stb,
- sop.eq(endpoint.sop),
eop.eq(endpoint.eop & endpoint.ack)
)
- self.sync += ongoing.eq((sop | ongoing) & ~eop)
- self.comb += self.ongoing.eq((sop | ongoing) & ~eop)
+ self.sync += ongoing.eq((endpoint.stb | ongoing) & ~eop)
+ self.comb += self.ongoing.eq((endpoint.stb | ongoing) & ~eop)
+
+ self.sync += [
+ If(eop,
+ first.eq(1)
+ ).Elif(endpoint.stb & endpoint.ack,
+ first.eq(0)
+ )
+ ]
class Arbiter(Module):
sel = Signal.like(self.sel)
sel_ongoing = Signal.like(self.sel)
self.sync += \
- If(status.sop,
+ If(status.first,
sel_ongoing.eq(self.sel)
)
self.comb += \
- If(status.sop,
+ If(status.first,
sel.eq(self.sel)
).Else(
sel.eq(sel_ongoing)
fsm.act("IDLE",
sink.ack.eq(1),
counter_reset.eq(1),
- If(sink.stb & sink.sop,
+ If(sink.stb,
sink.ack.eq(0),
source.stb.eq(1),
- source.sop.eq(1),
source.eop.eq(0),
source.data.eq(self.header[:dw]),
If(source.stb & source.ack,
if header_words != 1:
fsm.act("SEND_HEADER",
source.stb.eq(1),
- source.sop.eq(0),
source.eop.eq(0),
source.data.eq(header_reg[dw:2*dw]),
If(source.stb & source.ack,
)
fsm.act("COPY",
source.stb.eq(sink.stb),
- source.sop.eq(0),
source.eop.eq(sink.eop),
source.data.eq(sink.data),
source.error.eq(sink.error),
no_payload = Signal()
self.sync += \
If(fsm.before_entering("COPY"),
- source.sop.eq(1),
no_payload.eq(sink.eop)
- ).Elif(source.stb & source.ack,
- source.sop.eq(0)
)
if hasattr(sink, "error"):
self.submodules += fsm
fsm.act("IDLE",
If(cmd_fifo.source.stb,
- NextState("SEEK_SOP")
- )
- )
- fsm.act("SEEK_SOP",
- If(~data_fifo.source.sop,
- data_fifo.source.ack.eq(1)
- ).Else(
NextState("OUTPUT")
)
)
self.packet = self.packets.pop(0)
if not self.packet.ongoing and not self.packet.done:
selfp.source.stb = 1
- if self.source.description.packetized:
- selfp.source.sop = 1
selfp.source.data = self.packet.pop(0)
self.packet.ongoing = True
elif selfp.source.stb == 1 and selfp.source.ack == 1:
- if self.source.description.packetized:
- selfp.source.sop = 0
- if len(self.packet) == 1:
- selfp.source.eop = 1
- if self.last_be is not None:
- selfp.source.last_be = self.last_be
- else:
- selfp.source.eop = 0
- if self.last_be is not None:
- selfp.source.last_be = 0
+ if len(self.packet) == 1:
+ selfp.source.eop = 1
+ if self.last_be is not None:
+ selfp.source.last_be = self.last_be
+ else:
+ selfp.source.eop = 0
+ if self.last_be is not None:
+ selfp.source.last_be = 0
if len(self.packet) > 0:
selfp.source.stb = 1
selfp.source.data = self.packet.pop(0)
# # #
self.packet = Packet()
+ self.first = True
def receive(self):
self.packet.done = False
def do_simulation(self, selfp):
selfp.sink.ack = 1
if selfp.sink.stb:
- if self.sink.description.packetized:
- if selfp.sink.sop:
- self.packet = Packet()
- self.packet.append(selfp.sink.data)
- else:
- self.packet.append(selfp.sink.data)
- if selfp.sink.eop:
- self.packet.done = True
+ if self.first:
+ self.packet = Packet()
+ self.packet.append(selfp.sink.data)
+ self.first = False
else:
self.packet.append(selfp.sink.data)
+ if selfp.sink.eop:
+ self.packet.done = True
+ self.first = True
class AckRandomizer(Module):