rtio: use input collector module

This commit is contained in:
Sebastien Bourdeauducq 2017-09-19 15:53:35 +08:00
parent 4dc80e3d05
commit ff8e17ab89
1 changed files with 17 additions and 149 deletions

View File

@ -2,8 +2,6 @@ from functools import reduce
from operator import and_
from migen import *
from migen.genlib.record import Record
from migen.genlib.fifo import AsyncFIFO
from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.cdc import PulseSynchronizer
from misoc.interconnect.csr import *
@ -13,141 +11,7 @@ from artiq.gateware.rtio import rtlink
from artiq.gateware.rtio.channel import *
from artiq.gateware.rtio.cdc import *
from artiq.gateware.rtio.sed.core import *
class _InputManager(Module):
def __init__(self, interface, coarse_ts, fifo_depth):
data_width = rtlink.get_data_width(interface)
fine_ts_width = rtlink.get_fine_ts_width(interface)
ev_layout = []
if data_width:
ev_layout.append(("data", data_width))
if interface.timestamped:
ev_layout.append(("timestamp", len(coarse_ts) + fine_ts_width))
self.ev = Record(ev_layout)
self.readable = Signal()
self.re = Signal()
self.overflow = Signal() # pulsed
# # #
fifo = ClockDomainsRenamer({"read": "rsys", "write": "rio"})(
AsyncFIFO(layout_len(ev_layout), fifo_depth))
self.submodules += fifo
fifo_in = Record(ev_layout)
fifo_out = Record(ev_layout)
self.comb += [
fifo.din.eq(fifo_in.raw_bits()),
fifo_out.raw_bits().eq(fifo.dout)
]
# latency compensation
if interface.delay:
counter_rtio = Signal.like(coarse_ts, reset_less=True)
self.sync.rtio += counter_rtio.eq(coarse_ts -
(interface.delay + 1))
else:
counter_rtio = coarse_ts
# FIFO write
if data_width:
self.comb += fifo_in.data.eq(interface.data)
if interface.timestamped:
if fine_ts_width:
full_ts = Cat(interface.fine_ts, counter_rtio)
else:
full_ts = counter_rtio
self.comb += fifo_in.timestamp.eq(full_ts)
self.comb += fifo.we.eq(interface.stb)
# FIFO read
self.comb += [
self.ev.eq(fifo_out),
self.readable.eq(fifo.readable),
fifo.re.eq(self.re)
]
overflow_transfer = BlindTransfer()
self.submodules += overflow_transfer
self.comb += [
overflow_transfer.i.eq(fifo.we & ~fifo.writable),
self.overflow.eq(overflow_transfer.o),
]
class _Inputs(Module):
def __init__(self, interface, coarse_ts, channels):
self.cri = interface
# Inputs
i_statuses = []
i_datas, i_timestamps = [], []
i_ack = Signal()
sel = self.cri.chan_sel[:16]
for n, channel in enumerate(channels):
if isinstance(channel, LogChannel):
i_datas.append(0)
i_timestamps.append(0)
i_statuses.append(0)
continue
if channel.interface.i is not None:
selected = Signal()
self.comb += selected.eq(sel == n)
i_manager = _InputManager(channel.interface.i, coarse_ts,
channel.ififo_depth)
self.submodules += i_manager
if hasattr(i_manager.ev, "data"):
i_datas.append(i_manager.ev.data)
else:
i_datas.append(0)
if channel.interface.i.timestamped:
ts_shift = (len(self.cri.i_timestamp) - len(i_manager.ev.timestamp))
i_timestamps.append(i_manager.ev.timestamp << ts_shift)
else:
i_timestamps.append(0)
overflow = Signal()
self.sync.rsys += [
If(selected & i_ack,
overflow.eq(0)),
If(i_manager.overflow,
overflow.eq(1))
]
self.comb += i_manager.re.eq(selected & i_ack & ~overflow)
i_statuses.append(Cat(i_manager.readable & ~overflow, overflow))
else:
i_datas.append(0)
i_timestamps.append(0)
i_statuses.append(0)
i_status_raw = Signal(2)
self.comb += i_status_raw.eq(Array(i_statuses)[sel])
input_timeout = Signal.like(self.cri.timestamp)
input_pending = Signal()
self.sync.rsys += [
i_ack.eq(0),
If(i_ack,
self.cri.i_status.eq(Cat(~i_status_raw[0], i_status_raw[1], 0)),
self.cri.i_data.eq(Array(i_datas)[sel]),
self.cri.i_timestamp.eq(Array(i_timestamps)[sel]),
),
If((self.cri.counter >= input_timeout) | (i_status_raw != 0),
If(input_pending, i_ack.eq(1)),
input_pending.eq(0)
),
If(self.cri.cmd == cri.commands["read"],
input_timeout.eq(self.cri.timestamp),
input_pending.eq(1),
self.cri.i_status.eq(0b100)
)
]
from artiq.gateware.rtio.input_collector import *
class Core(Module, AutoCSR):
@ -190,17 +54,17 @@ class Core(Module, AutoCSR):
self.specials += AsyncResetSynchronizer(self.cd_rio_phy, cmd_reset_phy)
# TSC
fine_ts_width = max(max(rtlink.get_fine_ts_width(channel.interface.o)
for channel in channels),
max(rtlink.get_fine_ts_width(channel.interface.i)
for channel in channels))
coarse_ts = Signal(64-fine_ts_width)
glbl_fine_ts_width = max(max(rtlink.get_fine_ts_width(channel.interface.o)
for channel in channels),
max(rtlink.get_fine_ts_width(channel.interface.i)
for channel in channels))
coarse_ts = Signal(64-glbl_fine_ts_width)
self.sync.rtio += coarse_ts.eq(coarse_ts + 1)
coarse_ts_cdc = GrayCodeTransfer(len(coarse_ts))
self.submodules += coarse_ts_cdc
self.comb += [
coarse_ts_cdc.i.eq(coarse_ts),
self.cri.counter.eq(coarse_ts_cdc.o << fine_ts_width)
self.cri.counter.eq(coarse_ts_cdc.o << glbl_fine_ts_width)
]
# Asychronous output errors
@ -219,13 +83,12 @@ class Core(Module, AutoCSR):
]
self.comb += self.async_error.w.eq(Cat(o_collision, o_busy))
# Inputs
inputs = _Inputs(self.cri, coarse_ts, channels)
self.submodules += inputs
# Outputs
outputs = SED(channels, "async",
quash_channels=[n for n, c in enumerate(channels) if isinstance(c, LogChannel)],
# Outputs/Inputs
quash_channels = [n for n, c in enumerate(channels) if isinstance(c, LogChannel)]
outputs = SED(channels, glbl_fine_ts_width, "async",
quash_channels=quash_channels,
interface=self.cri)
self.submodules += outputs
self.comb += outputs.coarse_timestamp.eq(coarse_ts)
@ -234,3 +97,8 @@ class Core(Module, AutoCSR):
o_collision_sync.i.eq(outputs.collision),
o_busy_sync.i.eq(outputs.busy)
]
inputs = InputCollector(channels, glbl_fine_ts_width, "async",
quash_channels=quash_channels,
interface=self.cri)
self.submodules += inputs