+from copy import copy
+
from migen.fhdl.std import *
from migen.genlib.record import *
from migen.flow.actor import *
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)
###
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()
###
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(
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()
###
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))
)
]
- 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()
###
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),
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),
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)
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)
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):