soc/interconnect/stream: add separators, mode Actor modules just after Endpoint
This commit is contained in:
parent
59995c5359
commit
59bf04d965
|
@ -4,14 +4,18 @@
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
from copy import copy
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
from migen.util.misc import xdir
|
||||||
from migen.genlib.record import *
|
from migen.genlib.record import *
|
||||||
from migen.genlib import fifo
|
from migen.genlib import fifo
|
||||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
||||||
|
|
||||||
from litex.soc.interconnect.csr import *
|
from litex.soc.interconnect.csr import *
|
||||||
|
|
||||||
|
# Endpoint -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
(DIR_SINK, DIR_SOURCE) = range(2)
|
(DIR_SINK, DIR_SOURCE) = range(2)
|
||||||
|
|
||||||
def _make_m2s(layout):
|
def _make_m2s(layout):
|
||||||
|
@ -64,6 +68,91 @@ class Endpoint(Record):
|
||||||
except:
|
except:
|
||||||
return getattr(object.__getattribute__(self, "param"), name)
|
return getattr(object.__getattribute__(self, "param"), name)
|
||||||
|
|
||||||
|
# Actor --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _rawbits_layout(l):
|
||||||
|
if isinstance(l, int):
|
||||||
|
return [("rawbits", l)]
|
||||||
|
else:
|
||||||
|
return l
|
||||||
|
|
||||||
|
def pack_layout(l, n):
|
||||||
|
return [("chunk"+str(i), l) for i in range(n)]
|
||||||
|
|
||||||
|
def get_endpoints(obj, filt=Endpoint):
|
||||||
|
if hasattr(obj, "get_endpoints") and callable(obj.get_endpoints):
|
||||||
|
return obj.get_endpoints(filt)
|
||||||
|
r = dict()
|
||||||
|
for k, v in xdir(obj, True):
|
||||||
|
if isinstance(v, filt):
|
||||||
|
r[k] = v
|
||||||
|
return r
|
||||||
|
|
||||||
|
def get_single_ep(obj, filt):
|
||||||
|
eps = get_endpoints(obj, filt)
|
||||||
|
if len(eps) != 1:
|
||||||
|
raise ValueError("More than one endpoint")
|
||||||
|
return list(eps.items())[0]
|
||||||
|
|
||||||
|
|
||||||
|
class BinaryActor(Module):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.build_binary_control(self.sink, self.source, *args, **kwargs)
|
||||||
|
|
||||||
|
def build_binary_control(self, sink, source):
|
||||||
|
raise NotImplementedError("Binary actor classes must overload build_binary_control_fragment")
|
||||||
|
|
||||||
|
|
||||||
|
class CombinatorialActor(BinaryActor):
|
||||||
|
def build_binary_control(self, sink, source):
|
||||||
|
self.comb += [
|
||||||
|
source.valid.eq(sink.valid),
|
||||||
|
source.first.eq(sink.first),
|
||||||
|
source.last.eq(sink.last),
|
||||||
|
sink.ready.eq(source.ready),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PipelinedActor(BinaryActor):
|
||||||
|
def __init__(self, latency):
|
||||||
|
self.latency = latency
|
||||||
|
self.pipe_ce = Signal()
|
||||||
|
self.busy = Signal()
|
||||||
|
BinaryActor.__init__(self, latency)
|
||||||
|
|
||||||
|
def build_binary_control(self, sink, source, latency):
|
||||||
|
busy = 0
|
||||||
|
valid = sink.valid
|
||||||
|
for i in range(latency):
|
||||||
|
valid_n = Signal()
|
||||||
|
self.sync += If(self.pipe_ce, valid_n.eq(valid))
|
||||||
|
valid = valid_n
|
||||||
|
busy = busy | valid
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
self.pipe_ce.eq(source.ready | ~valid),
|
||||||
|
sink.ready.eq(self.pipe_ce),
|
||||||
|
source.valid.eq(valid),
|
||||||
|
self.busy.eq(busy)
|
||||||
|
]
|
||||||
|
first = sink.valid & sink.first
|
||||||
|
last = sink.valid & sink.last
|
||||||
|
for i in range(latency):
|
||||||
|
first_n = Signal()
|
||||||
|
last_n = Signal()
|
||||||
|
self.sync += \
|
||||||
|
If(self.pipe_ce,
|
||||||
|
first_n.eq(first),
|
||||||
|
last_n.eq(last)
|
||||||
|
)
|
||||||
|
first = first_n
|
||||||
|
last = last_n
|
||||||
|
self.comb += [
|
||||||
|
source.first.eq(first),
|
||||||
|
source.last.eq(last)
|
||||||
|
]
|
||||||
|
|
||||||
|
# FIFO ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class _FIFOWrapper(Module):
|
class _FIFOWrapper(Module):
|
||||||
def __init__(self, fifo_class, layout, depth):
|
def __init__(self, fifo_class, layout, depth):
|
||||||
|
@ -120,6 +209,7 @@ class AsyncFIFO(_FIFOWrapper):
|
||||||
fifo.AsyncFIFOBuffered if buffered else fifo.AsyncFIFO,
|
fifo.AsyncFIFOBuffered if buffered else fifo.AsyncFIFO,
|
||||||
layout, depth)
|
layout, depth)
|
||||||
|
|
||||||
|
# Mux/Demux ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Multiplexer(Module):
|
class Multiplexer(Module):
|
||||||
def __init__(self, layout, n):
|
def __init__(self, layout, n):
|
||||||
|
@ -156,6 +246,7 @@ class Demultiplexer(Module):
|
||||||
cases[i] = self.sink.connect(source)
|
cases[i] = self.sink.connect(source)
|
||||||
self.comb += Case(self.sel, cases)
|
self.comb += Case(self.sel, cases)
|
||||||
|
|
||||||
|
# Converter ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class _UpConverter(Module):
|
class _UpConverter(Module):
|
||||||
def __init__(self, nbits_from, nbits_to, ratio, reverse):
|
def __init__(self, nbits_from, nbits_to, ratio, reverse):
|
||||||
|
@ -367,6 +458,7 @@ class StrideConverter(Module):
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
# Gearbox ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def lcm(a, b):
|
def lcm(a, b):
|
||||||
return (a*b)//math.gcd(a, b)
|
return (a*b)//math.gcd(a, b)
|
||||||
|
@ -433,6 +525,7 @@ class Gearbox(Module):
|
||||||
else:
|
else:
|
||||||
self.comb += source.data.eq(o_data[::-1])
|
self.comb += source.data.eq(o_data[::-1])
|
||||||
|
|
||||||
|
# Monitor ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Monitor(Module, AutoCSR):
|
class Monitor(Module, AutoCSR):
|
||||||
def __init__(self, endpoint, count_width=32, clock_domain="sys",
|
def __init__(self, endpoint, count_width=32, clock_domain="sys",
|
||||||
|
@ -501,94 +594,7 @@ class Monitor(Module, AutoCSR):
|
||||||
underflow_counter = MonitorCounter(reset, latch, ~endpoint.valid & endpoint.ready, self.underflows.status)
|
underflow_counter = MonitorCounter(reset, latch, ~endpoint.valid & endpoint.ready, self.underflows.status)
|
||||||
self.submodules += underflow_counter
|
self.submodules += underflow_counter
|
||||||
|
|
||||||
# TODO: clean up code below
|
# Buffer -------------------------------------------------------------------------------------------
|
||||||
# XXX
|
|
||||||
|
|
||||||
from copy import copy
|
|
||||||
from migen.util.misc import xdir
|
|
||||||
|
|
||||||
def _rawbits_layout(l):
|
|
||||||
if isinstance(l, int):
|
|
||||||
return [("rawbits", l)]
|
|
||||||
else:
|
|
||||||
return l
|
|
||||||
|
|
||||||
def pack_layout(l, n):
|
|
||||||
return [("chunk"+str(i), l) for i in range(n)]
|
|
||||||
|
|
||||||
def get_endpoints(obj, filt=Endpoint):
|
|
||||||
if hasattr(obj, "get_endpoints") and callable(obj.get_endpoints):
|
|
||||||
return obj.get_endpoints(filt)
|
|
||||||
r = dict()
|
|
||||||
for k, v in xdir(obj, True):
|
|
||||||
if isinstance(v, filt):
|
|
||||||
r[k] = v
|
|
||||||
return r
|
|
||||||
|
|
||||||
def get_single_ep(obj, filt):
|
|
||||||
eps = get_endpoints(obj, filt)
|
|
||||||
if len(eps) != 1:
|
|
||||||
raise ValueError("More than one endpoint")
|
|
||||||
return list(eps.items())[0]
|
|
||||||
|
|
||||||
|
|
||||||
class BinaryActor(Module):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.build_binary_control(self.sink, self.source, *args, **kwargs)
|
|
||||||
|
|
||||||
def build_binary_control(self, sink, source):
|
|
||||||
raise NotImplementedError("Binary actor classes must overload build_binary_control_fragment")
|
|
||||||
|
|
||||||
|
|
||||||
class CombinatorialActor(BinaryActor):
|
|
||||||
def build_binary_control(self, sink, source):
|
|
||||||
self.comb += [
|
|
||||||
source.valid.eq(sink.valid),
|
|
||||||
source.first.eq(sink.first),
|
|
||||||
source.last.eq(sink.last),
|
|
||||||
sink.ready.eq(source.ready),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class PipelinedActor(BinaryActor):
|
|
||||||
def __init__(self, latency):
|
|
||||||
self.latency = latency
|
|
||||||
self.pipe_ce = Signal()
|
|
||||||
self.busy = Signal()
|
|
||||||
BinaryActor.__init__(self, latency)
|
|
||||||
|
|
||||||
def build_binary_control(self, sink, source, latency):
|
|
||||||
busy = 0
|
|
||||||
valid = sink.valid
|
|
||||||
for i in range(latency):
|
|
||||||
valid_n = Signal()
|
|
||||||
self.sync += If(self.pipe_ce, valid_n.eq(valid))
|
|
||||||
valid = valid_n
|
|
||||||
busy = busy | valid
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.pipe_ce.eq(source.ready | ~valid),
|
|
||||||
sink.ready.eq(self.pipe_ce),
|
|
||||||
source.valid.eq(valid),
|
|
||||||
self.busy.eq(busy)
|
|
||||||
]
|
|
||||||
first = sink.valid & sink.first
|
|
||||||
last = sink.valid & sink.last
|
|
||||||
for i in range(latency):
|
|
||||||
first_n = Signal()
|
|
||||||
last_n = Signal()
|
|
||||||
self.sync += \
|
|
||||||
If(self.pipe_ce,
|
|
||||||
first_n.eq(first),
|
|
||||||
last_n.eq(last)
|
|
||||||
)
|
|
||||||
first = first_n
|
|
||||||
last = last_n
|
|
||||||
self.comb += [
|
|
||||||
source.first.eq(first),
|
|
||||||
source.last.eq(last)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Buffer(PipelinedActor):
|
class Buffer(PipelinedActor):
|
||||||
def __init__(self, layout):
|
def __init__(self, layout):
|
||||||
|
@ -601,6 +607,7 @@ class Buffer(PipelinedActor):
|
||||||
self.source.param.eq(self.sink.param)
|
self.source.param.eq(self.sink.param)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Cast ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Cast(CombinatorialActor):
|
class Cast(CombinatorialActor):
|
||||||
def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False):
|
def __init__(self, layout_from, layout_to, reverse_from=False, reverse_to=False):
|
||||||
|
@ -620,6 +627,7 @@ class Cast(CombinatorialActor):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
self.comb += Cat(*sigs_to).eq(Cat(*sigs_from))
|
self.comb += Cat(*sigs_to).eq(Cat(*sigs_from))
|
||||||
|
|
||||||
|
# Unpack/Pack --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Unpack(Module):
|
class Unpack(Module):
|
||||||
def __init__(self, n, layout_to, reverse=False):
|
def __init__(self, n, layout_to, reverse=False):
|
||||||
|
@ -715,6 +723,7 @@ class Pack(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Pipeline -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Pipeline(Module):
|
class Pipeline(Module):
|
||||||
def __init__(self, *modules):
|
def __init__(self, *modules):
|
||||||
|
@ -742,6 +751,7 @@ class Pipeline(Module):
|
||||||
if hasattr(m, "source"):
|
if hasattr(m, "source"):
|
||||||
self.source = m.source
|
self.source = m.source
|
||||||
|
|
||||||
|
# BufferizeEndpoints -------------------------------------------------------------------------------
|
||||||
|
|
||||||
# Add buffers on Endpoints (can be used to improve timings)
|
# Add buffers on Endpoints (can be used to improve timings)
|
||||||
class BufferizeEndpoints(ModuleTransformer):
|
class BufferizeEndpoints(ModuleTransformer):
|
||||||
|
@ -765,6 +775,3 @@ class BufferizeEndpoints(ModuleTransformer):
|
||||||
setattr(submodule, name, buf.source)
|
setattr(submodule, name, buf.source)
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
# XXX
|
|
||||||
|
|
Loading…
Reference in New Issue