forked from M-Labs/artiq
gateware: common RTIO interface
This commit is contained in:
parent
0aaf120ca7
commit
9acc7d135e
|
@ -57,13 +57,11 @@ class DRTIOMaster(Module):
|
||||||
self.submodules.rt_controller = rt_controller.RTController(
|
self.submodules.rt_controller = rt_controller.RTController(
|
||||||
self.rt_packets, channel_count, fine_ts_width)
|
self.rt_packets, channel_count, fine_ts_width)
|
||||||
self.submodules.rt_manager = rt_controller.RTManager(self.rt_packets)
|
self.submodules.rt_manager = rt_controller.RTManager(self.rt_packets)
|
||||||
|
self.cri = self.rt_controller.cri
|
||||||
|
|
||||||
self.submodules.aux_controller = aux_controller.AuxController(
|
self.submodules.aux_controller = aux_controller.AuxController(
|
||||||
self.link_layer)
|
self.link_layer)
|
||||||
|
|
||||||
def get_kernel_csrs(self):
|
|
||||||
return self.rt_controller.get_kernel_csrs()
|
|
||||||
|
|
||||||
def get_csrs(self):
|
def get_csrs(self):
|
||||||
return (self.link_layer.get_csrs() +
|
return (self.link_layer.get_csrs() +
|
||||||
self.rt_controller.get_csrs() +
|
self.rt_controller.get_csrs() +
|
||||||
|
|
|
@ -5,7 +5,7 @@ from migen.genlib.misc import WaitTimer
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
from artiq.gateware.rtio.cdc import RTIOCounter
|
from artiq.gateware.rtio.cdc import RTIOCounter
|
||||||
from artiq.gateware.rtio.kernel_csrs import KernelCSRs
|
from artiq.gateware.rtio import cri
|
||||||
|
|
||||||
|
|
||||||
class _CSRs(AutoCSR):
|
class _CSRs(AutoCSR):
|
||||||
|
@ -27,20 +27,20 @@ class _CSRs(AutoCSR):
|
||||||
|
|
||||||
class RTController(Module):
|
class RTController(Module):
|
||||||
def __init__(self, rt_packets, channel_count, fine_ts_width):
|
def __init__(self, rt_packets, channel_count, fine_ts_width):
|
||||||
self.kcsrs = KernelCSRs()
|
|
||||||
self.csrs = _CSRs()
|
self.csrs = _CSRs()
|
||||||
|
self.cri = cri.Interface()
|
||||||
|
self.comb += self.cri.arb_gnt.eq(1)
|
||||||
|
|
||||||
# channel selection
|
# channel selection
|
||||||
chan_sel = Signal(16)
|
chan_sel = Signal(16)
|
||||||
self.comb += chan_sel.eq(
|
self.comb += chan_sel.eq(
|
||||||
Mux(self.csrs.chan_sel_override_en.storage,
|
Mux(self.csrs.chan_sel_override_en.storage,
|
||||||
self.csrs.chan_sel_override.storage,
|
self.csrs.chan_sel_override.storage,
|
||||||
self.kcsrs.chan_sel.storage))
|
self.cri.chan_sel[:16]))
|
||||||
|
|
||||||
# master RTIO counter and counter synchronization
|
# master RTIO counter and counter synchronization
|
||||||
self.submodules.counter = RTIOCounter(64-fine_ts_width)
|
self.submodules.counter = RTIOCounter(64-fine_ts_width)
|
||||||
self.sync += If(self.kcsrs.counter_update.re,
|
self.comb += self.cri.counter.eq(self.counter.value_sys << fine_ts_width)
|
||||||
self.kcsrs.counter.status.eq(self.counter.value_sys << fine_ts_width))
|
|
||||||
tsc_correction = Signal(64)
|
tsc_correction = Signal(64)
|
||||||
self.csrs.tsc_correction.storage.attr.add("no_retiming")
|
self.csrs.tsc_correction.storage.attr.add("no_retiming")
|
||||||
self.specials += MultiReg(self.csrs.tsc_correction.storage, tsc_correction)
|
self.specials += MultiReg(self.csrs.tsc_correction.storage, tsc_correction)
|
||||||
|
@ -67,14 +67,14 @@ class RTController(Module):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
fifo_spaces.adr.eq(chan_sel),
|
fifo_spaces.adr.eq(chan_sel),
|
||||||
last_timestamps.adr.eq(chan_sel),
|
last_timestamps.adr.eq(chan_sel),
|
||||||
last_timestamps.dat_w.eq(self.kcsrs.o_timestamp.storage),
|
last_timestamps.dat_w.eq(self.cri.o_timestamp),
|
||||||
rt_packets.write_channel.eq(chan_sel),
|
rt_packets.write_channel.eq(chan_sel),
|
||||||
rt_packets.write_address.eq(self.kcsrs.o_address.storage),
|
rt_packets.write_address.eq(self.cri.o_address),
|
||||||
rt_packets.write_data.eq(self.kcsrs.o_data.storage),
|
rt_packets.write_data.eq(self.cri.o_data),
|
||||||
If(rt_packets_fifo_request,
|
If(rt_packets_fifo_request,
|
||||||
rt_packets.write_timestamp.eq(0xffff000000000000)
|
rt_packets.write_timestamp.eq(0xffff000000000000)
|
||||||
).Else(
|
).Else(
|
||||||
rt_packets.write_timestamp.eq(self.kcsrs.o_timestamp.storage)
|
rt_packets.write_timestamp.eq(self.cri.o_timestamp)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -85,15 +85,15 @@ class RTController(Module):
|
||||||
status_underflow = Signal()
|
status_underflow = Signal()
|
||||||
status_sequence_error = Signal()
|
status_sequence_error = Signal()
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.kcsrs.o_status.status.eq(Cat(
|
self.cri.o_status.eq(Cat(
|
||||||
status_wait, status_underflow, status_sequence_error)),
|
status_wait, status_underflow, status_sequence_error)),
|
||||||
self.csrs.o_wait.status.eq(status_wait)
|
self.csrs.o_wait.status.eq(status_wait)
|
||||||
]
|
]
|
||||||
sequence_error_set = Signal()
|
sequence_error_set = Signal()
|
||||||
underflow_set = Signal()
|
underflow_set = Signal()
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(self.kcsrs.o_underflow_reset.re, status_underflow.eq(0)),
|
If(self.cri.cmd == cri.commands["o_underflow_reset"], status_underflow.eq(0)),
|
||||||
If(self.kcsrs.o_sequence_error_reset.re, status_sequence_error.eq(0)),
|
If(self.cri.cmd == cri.commands["o_sequence_error_reset"], status_sequence_error.eq(0)),
|
||||||
If(underflow_set, status_underflow.eq(1)),
|
If(underflow_set, status_underflow.eq(1)),
|
||||||
If(sequence_error_set, status_sequence_error.eq(1)),
|
If(sequence_error_set, status_sequence_error.eq(1)),
|
||||||
]
|
]
|
||||||
|
@ -107,14 +107,14 @@ class RTController(Module):
|
||||||
self.submodules += timeout_counter
|
self.submodules += timeout_counter
|
||||||
|
|
||||||
# TODO: collision, replace, busy
|
# TODO: collision, replace, busy
|
||||||
cond_sequence_error = self.kcsrs.o_timestamp.storage < last_timestamps.dat_r
|
cond_sequence_error = self.cri.o_timestamp < last_timestamps.dat_r
|
||||||
cond_underflow = ((self.kcsrs.o_timestamp.storage[fine_ts_width:]
|
cond_underflow = ((self.cri.o_timestamp[fine_ts_width:]
|
||||||
- self.csrs.underflow_margin.storage[fine_ts_width:]) < self.counter.value_sys)
|
- self.csrs.underflow_margin.storage[fine_ts_width:]) < self.counter.value_sys)
|
||||||
cond_fifo_emptied = ((last_timestamps.dat_r[fine_ts_width:] < self.counter.value_sys)
|
cond_fifo_emptied = ((last_timestamps.dat_r[fine_ts_width:] < self.counter.value_sys)
|
||||||
& (last_timestamps.dat_r != 0))
|
& (last_timestamps.dat_r != 0))
|
||||||
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
If(self.kcsrs.o_we.re,
|
If(self.cri.cmd == cri.commands["write"],
|
||||||
If(cond_sequence_error,
|
If(cond_sequence_error,
|
||||||
sequence_error_set.eq(1)
|
sequence_error_set.eq(1)
|
||||||
).Elif(cond_underflow,
|
).Elif(cond_underflow,
|
||||||
|
@ -184,9 +184,6 @@ class RTController(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_kernel_csrs(self):
|
|
||||||
return self.kcsrs.get_csrs()
|
|
||||||
|
|
||||||
def get_csrs(self):
|
def get_csrs(self):
|
||||||
return self.csrs.get_csrs()
|
return self.csrs.get_csrs()
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
from artiq.gateware.rtio.core import Channel, LogChannel, RTIO
|
from artiq.gateware.rtio.cri import KernelInitiator
|
||||||
|
from artiq.gateware.rtio.core import Channel, LogChannel, Core
|
||||||
from artiq.gateware.rtio.analyzer import Analyzer
|
from artiq.gateware.rtio.analyzer import Analyzer
|
||||||
from artiq.gateware.rtio.moninj import MonInj
|
from artiq.gateware.rtio.moninj import MonInj
|
||||||
|
|
|
@ -42,7 +42,7 @@ assert layout_len(stopped_layout) == message_len
|
||||||
|
|
||||||
|
|
||||||
class MessageEncoder(Module, AutoCSR):
|
class MessageEncoder(Module, AutoCSR):
|
||||||
def __init__(self, rtio_core, enable):
|
def __init__(self, kcsrs, rtio_counter, enable):
|
||||||
self.source = stream.Endpoint([("data", message_len)])
|
self.source = stream.Endpoint([("data", message_len)])
|
||||||
|
|
||||||
self.overflow = CSRStatus()
|
self.overflow = CSRStatus()
|
||||||
|
@ -50,27 +50,15 @@ class MessageEncoder(Module, AutoCSR):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
kcsrs = rtio_core.kcsrs
|
|
||||||
|
|
||||||
input_output_stb = Signal()
|
input_output_stb = Signal()
|
||||||
input_output = Record(input_output_layout)
|
input_output = Record(input_output_layout)
|
||||||
if hasattr(kcsrs, "o_data"):
|
o_data = kcsrs.o_data.storage
|
||||||
o_data = kcsrs.o_data.storage
|
o_address = kcsrs.o_address.storage
|
||||||
else:
|
i_data = kcsrs.i_data.status
|
||||||
o_data = 0
|
|
||||||
if hasattr(kcsrs, "o_address"):
|
|
||||||
o_address = kcsrs.o_address.storage
|
|
||||||
else:
|
|
||||||
o_address = 0
|
|
||||||
if hasattr(kcsrs, "i_data"):
|
|
||||||
i_data = kcsrs.i_data.status
|
|
||||||
else:
|
|
||||||
i_data = 0
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
input_output.channel.eq(kcsrs.chan_sel.storage),
|
input_output.channel.eq(kcsrs.chan_sel.storage),
|
||||||
input_output.address_padding.eq(o_address),
|
input_output.address_padding.eq(o_address),
|
||||||
input_output.rtio_counter.eq(
|
input_output.rtio_counter.eq(rtio_counter),
|
||||||
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
|
|
||||||
If(kcsrs.o_we.re,
|
If(kcsrs.o_we.re,
|
||||||
input_output.message_type.eq(MessageType.output.value),
|
input_output.message_type.eq(MessageType.output.value),
|
||||||
input_output.timestamp.eq(kcsrs.o_timestamp.storage),
|
input_output.timestamp.eq(kcsrs.o_timestamp.storage),
|
||||||
|
@ -88,10 +76,10 @@ class MessageEncoder(Module, AutoCSR):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
exception.message_type.eq(MessageType.exception.value),
|
exception.message_type.eq(MessageType.exception.value),
|
||||||
exception.channel.eq(kcsrs.chan_sel.storage),
|
exception.channel.eq(kcsrs.chan_sel.storage),
|
||||||
exception.rtio_counter.eq(
|
exception.rtio_counter.eq(rtio_counter),
|
||||||
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
|
|
||||||
]
|
]
|
||||||
for ename in ("o_underflow_reset", "o_sequence_error_reset",
|
for ename in ("reset", "reset_phy",
|
||||||
|
"o_underflow_reset", "o_sequence_error_reset",
|
||||||
"o_collision_reset", "i_overflow_reset"):
|
"o_collision_reset", "i_overflow_reset"):
|
||||||
self.comb += \
|
self.comb += \
|
||||||
If(getattr(kcsrs, ename).re,
|
If(getattr(kcsrs, ename).re,
|
||||||
|
@ -99,28 +87,11 @@ class MessageEncoder(Module, AutoCSR):
|
||||||
exception.exception_type.eq(
|
exception.exception_type.eq(
|
||||||
getattr(ExceptionType, ename).value)
|
getattr(ExceptionType, ename).value)
|
||||||
)
|
)
|
||||||
for rname in "reset", "reset_phy":
|
|
||||||
r_d = Signal(reset=1)
|
|
||||||
r = getattr(kcsrs, rname).storage
|
|
||||||
self.sync += r_d.eq(r)
|
|
||||||
self.comb += [
|
|
||||||
If(r & ~r_d,
|
|
||||||
exception_stb.eq(1),
|
|
||||||
exception.exception_type.eq(
|
|
||||||
getattr(ExceptionType, rname+"_rising").value)
|
|
||||||
),
|
|
||||||
If(~r & r_d,
|
|
||||||
exception_stb.eq(1),
|
|
||||||
exception.exception_type.eq(
|
|
||||||
getattr(ExceptionType, rname+"_falling").value)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
stopped = Record(stopped_layout)
|
stopped = Record(stopped_layout)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
stopped.message_type.eq(MessageType.stopped.value),
|
stopped.message_type.eq(MessageType.stopped.value),
|
||||||
stopped.rtio_counter.eq(
|
stopped.rtio_counter.eq(rtio_counter),
|
||||||
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
enable_r = Signal()
|
enable_r = Signal()
|
||||||
|
@ -210,13 +181,13 @@ class DMAWriter(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
class Analyzer(Module, AutoCSR):
|
class Analyzer(Module, AutoCSR):
|
||||||
def __init__(self, rtio_core, membus, fifo_depth=128):
|
def __init__(self, kcsrs, rtio_counter, membus, fifo_depth=128):
|
||||||
# shutdown procedure: set enable to 0, wait until busy=0
|
# shutdown procedure: set enable to 0, wait until busy=0
|
||||||
self.enable = CSRStorage()
|
self.enable = CSRStorage()
|
||||||
self.busy = CSRStatus()
|
self.busy = CSRStatus()
|
||||||
|
|
||||||
self.submodules.message_encoder = MessageEncoder(
|
self.submodules.message_encoder = MessageEncoder(
|
||||||
rtio_core, self.enable.storage)
|
kcsrs, rtio_counter, self.enable.storage)
|
||||||
self.submodules.fifo = stream.SyncFIFO(
|
self.submodules.fifo = stream.SyncFIFO(
|
||||||
[("data", message_len)], fifo_depth, True)
|
[("data", message_len)], fifo_depth, True)
|
||||||
self.submodules.converter = stream.Converter(
|
self.submodules.converter = stream.Converter(
|
||||||
|
|
|
@ -6,8 +6,7 @@ from migen.genlib.record import Record
|
||||||
from migen.genlib.fifo import AsyncFIFO
|
from migen.genlib.fifo import AsyncFIFO
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
|
||||||
from artiq.gateware.rtio import rtlink
|
from artiq.gateware.rtio import cri, rtlink
|
||||||
from artiq.gateware.rtio.kernel_csrs import KernelCSRs
|
|
||||||
from artiq.gateware.rtio.cdc import *
|
from artiq.gateware.rtio.cdc import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,7 +264,7 @@ class LogChannel:
|
||||||
self.overrides = []
|
self.overrides = []
|
||||||
|
|
||||||
|
|
||||||
class RTIO(Module):
|
class Core(Module):
|
||||||
def __init__(self, channels, full_ts_width=63, guard_io_cycles=20):
|
def __init__(self, channels, full_ts_width=63, guard_io_cycles=20):
|
||||||
data_width = max(rtlink.get_data_width(c.interface)
|
data_width = max(rtlink.get_data_width(c.interface)
|
||||||
for c in channels)
|
for c in channels)
|
||||||
|
@ -278,35 +277,43 @@ class RTIO(Module):
|
||||||
self.address_width = address_width
|
self.address_width = address_width
|
||||||
self.fine_ts_width = fine_ts_width
|
self.fine_ts_width = fine_ts_width
|
||||||
|
|
||||||
self.kcsrs = KernelCSRs()
|
self.cri = cri.Interface()
|
||||||
|
self.comb += self.cri.arb_gnt.eq(1)
|
||||||
|
|
||||||
# Clocking/Reset
|
# Clocking/Reset
|
||||||
# Create rsys, rio and rio_phy domains based on sys and rtio
|
# Create rsys, rio and rio_phy domains based on sys and rtio
|
||||||
# with reset controlled by CSR.
|
# with reset controlled by CRI.
|
||||||
|
cmd_reset = Signal(reset=1)
|
||||||
|
cmd_reset_phy = Signal(reset=1)
|
||||||
|
self.sync += [
|
||||||
|
cmd_reset.eq(self.cri.cmd == cri.commands["reset"]),
|
||||||
|
cmd_reset_phy.eq(self.cri.cmd == cri.commands["reset_phy"])
|
||||||
|
]
|
||||||
|
cmd_reset.attr.add("no_retiming")
|
||||||
|
cmd_reset_phy.attr.add("no_retiming")
|
||||||
|
|
||||||
self.clock_domains.cd_rsys = ClockDomain()
|
self.clock_domains.cd_rsys = ClockDomain()
|
||||||
self.clock_domains.cd_rio = ClockDomain()
|
self.clock_domains.cd_rio = ClockDomain()
|
||||||
self.clock_domains.cd_rio_phy = ClockDomain()
|
self.clock_domains.cd_rio_phy = ClockDomain()
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.cd_rsys.clk.eq(ClockSignal()),
|
self.cd_rsys.clk.eq(ClockSignal()),
|
||||||
self.cd_rsys.rst.eq(self.kcsrs.reset.storage)
|
self.cd_rsys.rst.eq(cmd_reset)
|
||||||
]
|
]
|
||||||
self.comb += self.cd_rio.clk.eq(ClockSignal("rtio"))
|
self.comb += self.cd_rio.clk.eq(ClockSignal("rtio"))
|
||||||
self.specials += AsyncResetSynchronizer(
|
self.specials += AsyncResetSynchronizer(
|
||||||
self.cd_rio,
|
self.cd_rio,
|
||||||
self.kcsrs.reset.storage | ResetSignal("rtio",
|
cmd_reset | ResetSignal("rtio", allow_reset_less=True))
|
||||||
allow_reset_less=True))
|
|
||||||
self.comb += self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
|
self.comb += self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
|
||||||
self.specials += AsyncResetSynchronizer(
|
self.specials += AsyncResetSynchronizer(
|
||||||
self.cd_rio_phy,
|
self.cd_rio_phy,
|
||||||
self.kcsrs.reset_phy.storage | ResetSignal("rtio",
|
cmd_reset_phy | ResetSignal("rtio", allow_reset_less=True))
|
||||||
allow_reset_less=True))
|
|
||||||
|
|
||||||
# Managers
|
# Managers
|
||||||
self.submodules.counter = RTIOCounter(full_ts_width - fine_ts_width)
|
self.submodules.counter = RTIOCounter(full_ts_width - fine_ts_width)
|
||||||
|
|
||||||
i_datas, i_timestamps = [], []
|
i_datas, i_timestamps = [], []
|
||||||
o_statuses, i_statuses = [], []
|
o_statuses, i_statuses = [], []
|
||||||
sel = self.kcsrs.chan_sel.storage
|
sel = self.cri.chan_sel[:16]
|
||||||
for n, channel in enumerate(channels):
|
for n, channel in enumerate(channels):
|
||||||
if isinstance(channel, LogChannel):
|
if isinstance(channel, LogChannel):
|
||||||
i_datas.append(0)
|
i_datas.append(0)
|
||||||
|
@ -322,30 +329,27 @@ class RTIO(Module):
|
||||||
self.submodules += o_manager
|
self.submodules += o_manager
|
||||||
|
|
||||||
if hasattr(o_manager.ev, "data"):
|
if hasattr(o_manager.ev, "data"):
|
||||||
self.comb += o_manager.ev.data.eq(
|
self.comb += o_manager.ev.data.eq(self.cri.o_data)
|
||||||
self.kcsrs.o_data.storage)
|
|
||||||
if hasattr(o_manager.ev, "address"):
|
if hasattr(o_manager.ev, "address"):
|
||||||
self.comb += o_manager.ev.address.eq(
|
self.comb += o_manager.ev.address.eq(self.cri.o_address)
|
||||||
self.kcsrs.o_address.storage)
|
ts_shift = len(self.cri.o_timestamp) - len(o_manager.ev.timestamp)
|
||||||
ts_shift = (len(self.kcsrs.o_timestamp.storage)
|
self.comb += o_manager.ev.timestamp.eq(self.cri.o_timestamp[ts_shift:])
|
||||||
- len(o_manager.ev.timestamp))
|
|
||||||
self.comb += o_manager.ev.timestamp.eq(
|
|
||||||
self.kcsrs.o_timestamp.storage[ts_shift:])
|
|
||||||
|
|
||||||
self.comb += o_manager.we.eq(selected & self.kcsrs.o_we.re)
|
self.comb += o_manager.we.eq(selected &
|
||||||
|
(self.cri.cmd == cri.commands["write"]))
|
||||||
|
|
||||||
underflow = Signal()
|
underflow = Signal()
|
||||||
sequence_error = Signal()
|
sequence_error = Signal()
|
||||||
collision = Signal()
|
collision = Signal()
|
||||||
busy = Signal()
|
busy = Signal()
|
||||||
self.sync.rsys += [
|
self.sync.rsys += [
|
||||||
If(selected & self.kcsrs.o_underflow_reset.re,
|
If(selected & (self.cri.cmd == cri.commands["o_underflow_reset"]),
|
||||||
underflow.eq(0)),
|
underflow.eq(0)),
|
||||||
If(selected & self.kcsrs.o_sequence_error_reset.re,
|
If(selected & (self.cri.cmd == cri.commands["o_sequence_error_reset"]),
|
||||||
sequence_error.eq(0)),
|
sequence_error.eq(0)),
|
||||||
If(selected & self.kcsrs.o_collision_reset.re,
|
If(selected & (self.cri.cmd == cri.commands["o_collision_reset"]),
|
||||||
collision.eq(0)),
|
collision.eq(0)),
|
||||||
If(selected & self.kcsrs.o_busy_reset.re,
|
If(selected & (self.cri.cmd == cri.commands["o_busy_reset"]),
|
||||||
busy.eq(0)),
|
busy.eq(0)),
|
||||||
If(o_manager.underflow, underflow.eq(1)),
|
If(o_manager.underflow, underflow.eq(1)),
|
||||||
If(o_manager.sequence_error, sequence_error.eq(1)),
|
If(o_manager.sequence_error, sequence_error.eq(1)),
|
||||||
|
@ -368,17 +372,17 @@ class RTIO(Module):
|
||||||
else:
|
else:
|
||||||
i_datas.append(0)
|
i_datas.append(0)
|
||||||
if channel.interface.i.timestamped:
|
if channel.interface.i.timestamped:
|
||||||
ts_shift = (len(self.kcsrs.i_timestamp.status)
|
ts_shift = (len(self.cri.i_timestamp)
|
||||||
- len(i_manager.ev.timestamp))
|
- len(i_manager.ev.timestamp))
|
||||||
i_timestamps.append(i_manager.ev.timestamp << ts_shift)
|
i_timestamps.append(i_manager.ev.timestamp << ts_shift)
|
||||||
else:
|
else:
|
||||||
i_timestamps.append(0)
|
i_timestamps.append(0)
|
||||||
|
|
||||||
self.comb += i_manager.re.eq(selected & self.kcsrs.i_re.re)
|
self.comb += i_manager.re.eq(selected & (self.cri.cmd == cri.commands["read"]))
|
||||||
|
|
||||||
overflow = Signal()
|
overflow = Signal()
|
||||||
self.sync.rsys += [
|
self.sync.rsys += [
|
||||||
If(selected & self.kcsrs.i_overflow_reset.re,
|
If(selected & (self.cri.cmd == cri.commands["i_overflow_reset"]),
|
||||||
overflow.eq(0)),
|
overflow.eq(0)),
|
||||||
If(i_manager.overflow,
|
If(i_manager.overflow,
|
||||||
overflow.eq(1))
|
overflow.eq(1))
|
||||||
|
@ -389,20 +393,11 @@ class RTIO(Module):
|
||||||
i_datas.append(0)
|
i_datas.append(0)
|
||||||
i_timestamps.append(0)
|
i_timestamps.append(0)
|
||||||
i_statuses.append(0)
|
i_statuses.append(0)
|
||||||
if data_width:
|
|
||||||
self.comb += self.kcsrs.i_data.status.eq(Array(i_datas)[sel])
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.kcsrs.i_timestamp.status.eq(Array(i_timestamps)[sel]),
|
self.cri.i_data.eq(Array(i_datas)[sel]),
|
||||||
self.kcsrs.o_status.status.eq(Array(o_statuses)[sel]),
|
self.cri.i_timestamp.eq(Array(i_timestamps)[sel]),
|
||||||
self.kcsrs.i_status.status.eq(Array(i_statuses)[sel])
|
self.cri.o_status.eq(Array(o_statuses)[sel]),
|
||||||
|
self.cri.i_status.eq(Array(i_statuses)[sel])
|
||||||
]
|
]
|
||||||
|
|
||||||
# Counter access
|
self.cri.counter.eq(self.counter.value_sys << fine_ts_width)
|
||||||
self.sync += \
|
|
||||||
If(self.kcsrs.counter_update.re,
|
|
||||||
self.kcsrs.counter.status.eq(self.counter.value_sys
|
|
||||||
<< fine_ts_width)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_csrs(self):
|
|
||||||
return self.kcsrs.get_csrs()
|
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
"""Common RTIO Interface"""
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
from migen.genlib.record import *
|
||||||
|
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
"nop": 0,
|
||||||
|
"reset": 1,
|
||||||
|
"reset_phy": 2,
|
||||||
|
|
||||||
|
"write": 3,
|
||||||
|
"read": 4,
|
||||||
|
|
||||||
|
"o_underflow_reset": 5,
|
||||||
|
"o_sequence_error_reset": 6,
|
||||||
|
"o_collision_reset": 7,
|
||||||
|
"o_busy_reset": 8,
|
||||||
|
"i_overflow_reset": 9
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
layout = [
|
||||||
|
("arb_req", 1, DIR_M_TO_S),
|
||||||
|
("arb_gnt", 1, DIR_S_TO_M),
|
||||||
|
|
||||||
|
("cmd", 4, DIR_M_TO_S),
|
||||||
|
# 8 MSBs of chan_sel are used to select core
|
||||||
|
("chan_sel", 24, DIR_M_TO_S),
|
||||||
|
|
||||||
|
("o_data", 512, DIR_M_TO_S),
|
||||||
|
("o_address", 16, DIR_M_TO_S),
|
||||||
|
("o_timestamp", 64, DIR_M_TO_S),
|
||||||
|
# o_status bits:
|
||||||
|
# <0:wait> <1:underflow> <2:sequence_error> <3:collision> <4:busy>
|
||||||
|
("o_status", 5, DIR_S_TO_M),
|
||||||
|
|
||||||
|
("i_data", 32, DIR_S_TO_M),
|
||||||
|
("i_timestamp", 64, DIR_S_TO_M),
|
||||||
|
# i_status bits:
|
||||||
|
# <0:wait> <1:overflow>
|
||||||
|
("i_status", 2, DIR_S_TO_M),
|
||||||
|
|
||||||
|
("counter", 64, DIR_S_TO_M)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Interface(Record):
|
||||||
|
def __init__(self):
|
||||||
|
Record.__init__(self, layout)
|
||||||
|
|
||||||
|
|
||||||
|
class KernelInitiator(Module, AutoCSR):
|
||||||
|
def __init__(self, cri=None):
|
||||||
|
self.arb_req = CSRStorage()
|
||||||
|
self.arb_gnt = CSRStatus()
|
||||||
|
|
||||||
|
self.reset = CSR()
|
||||||
|
self.reset_phy = CSR()
|
||||||
|
self.chan_sel = CSRStorage(24)
|
||||||
|
|
||||||
|
self.o_data = CSRStorage(32, write_from_dev=True) # XXX -> 512
|
||||||
|
self.o_address = CSRStorage(16)
|
||||||
|
self.o_timestamp = CSRStorage(64)
|
||||||
|
self.o_we = CSR()
|
||||||
|
self.o_status = CSRStatus(5)
|
||||||
|
self.o_underflow_reset = CSR()
|
||||||
|
self.o_sequence_error_reset = CSR()
|
||||||
|
self.o_collision_reset = CSR()
|
||||||
|
self.o_busy_reset = CSR()
|
||||||
|
|
||||||
|
self.i_data = CSRStatus(32)
|
||||||
|
self.i_timestamp = CSRStatus(64)
|
||||||
|
self.i_re = CSR()
|
||||||
|
self.i_status = CSRStatus(2)
|
||||||
|
self.i_overflow_reset = CSR()
|
||||||
|
|
||||||
|
self.counter = CSRStatus(64)
|
||||||
|
self.counter_update = CSR()
|
||||||
|
|
||||||
|
if cri is None:
|
||||||
|
cri = Interface()
|
||||||
|
self.cri = cri
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
self.cri.arb_req.eq(self.arb_req.storage),
|
||||||
|
self.arb_gnt.status.eq(self.cri.arb_gnt),
|
||||||
|
|
||||||
|
self.cri.cmd.eq(commands["nop"]),
|
||||||
|
If(self.reset.re, self.cri.cmd.eq(commands["reset"])),
|
||||||
|
If(self.reset_phy.re, self.cri.cmd.eq(commands["reset_phy"])),
|
||||||
|
If(self.o_we.re, self.cri.cmd.eq(commands["write"])),
|
||||||
|
If(self.i_re.re, self.cri.cmd.eq(commands["read"])),
|
||||||
|
If(self.o_underflow_reset.re, self.cri.cmd.eq(commands["o_underflow_reset"])),
|
||||||
|
If(self.o_sequence_error_reset.re, self.cri.cmd.eq(commands["o_sequence_error_reset"])),
|
||||||
|
If(self.o_collision_reset.re, self.cri.cmd.eq(commands["o_collision_reset"])),
|
||||||
|
If(self.o_busy_reset.re, self.cri.cmd.eq(commands["o_busy_reset"])),
|
||||||
|
If(self.i_overflow_reset.re, self.cri.cmd.eq(commands["i_overflow_reset"])),
|
||||||
|
|
||||||
|
self.cri.chan_sel.eq(self.chan_sel.storage),
|
||||||
|
|
||||||
|
self.cri.o_data.eq(self.o_data.storage),
|
||||||
|
self.cri.o_address.eq(self.o_address.storage),
|
||||||
|
self.cri.o_timestamp.eq(self.o_timestamp.storage),
|
||||||
|
self.o_status.status.eq(self.cri.o_status),
|
||||||
|
|
||||||
|
self.i_data.status.eq(self.cri.i_data),
|
||||||
|
self.i_timestamp.status.eq(self.cri.i_timestamp),
|
||||||
|
self.i_status.status.eq(self.cri.i_status),
|
||||||
|
|
||||||
|
self.o_data.dat_w.eq(0),
|
||||||
|
self.o_data.we.eq(self.o_timestamp.re),
|
||||||
|
]
|
||||||
|
self.sync += If(self.counter_update.re, self.counter.status.eq(self.cri.counter))
|
||||||
|
|
||||||
|
def get_csrs(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_kernel_csrs(self):
|
||||||
|
return AutoCSR.get_csrs(self)
|
|
@ -1,27 +0,0 @@
|
||||||
from misoc.interconnect.csr import *
|
|
||||||
|
|
||||||
|
|
||||||
class KernelCSRs(AutoCSR):
|
|
||||||
def __init__(self):
|
|
||||||
self.reset = CSRStorage(reset=1)
|
|
||||||
self.reset_phy = CSRStorage(reset=1)
|
|
||||||
self.chan_sel = CSRStorage(16)
|
|
||||||
|
|
||||||
self.o_data = CSRStorage(32)
|
|
||||||
self.o_address = CSRStorage(16)
|
|
||||||
self.o_timestamp = CSRStorage(64)
|
|
||||||
self.o_we = CSR()
|
|
||||||
self.o_status = CSRStatus(5)
|
|
||||||
self.o_underflow_reset = CSR()
|
|
||||||
self.o_sequence_error_reset = CSR()
|
|
||||||
self.o_collision_reset = CSR()
|
|
||||||
self.o_busy_reset = CSR()
|
|
||||||
|
|
||||||
self.i_data = CSRStatus(32)
|
|
||||||
self.i_timestamp = CSRStatus(64)
|
|
||||||
self.i_re = CSR()
|
|
||||||
self.i_status = CSRStatus(2)
|
|
||||||
self.i_overflow_reset = CSR()
|
|
||||||
|
|
||||||
self.counter = CSRStatus(64)
|
|
||||||
self.counter_update = CSR()
|
|
|
@ -142,7 +142,8 @@ class _NIST_Ions(MiniSoC, AMPSoC):
|
||||||
def add_rtio(self, rtio_channels):
|
def add_rtio(self, rtio_channels):
|
||||||
self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk)
|
self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk)
|
||||||
self.csr_devices.append("rtio_crg")
|
self.csr_devices.append("rtio_crg")
|
||||||
self.submodules.rtio = rtio.RTIO(rtio_channels)
|
self.submodules.rtio_core = rtio.Core(rtio_channels)
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_core.cri)
|
||||||
self.register_kernel_cpu_csrdevice("rtio")
|
self.register_kernel_cpu_csrdevice("rtio")
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||||
self.csr_devices.append("rtio_moninj")
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
@ -153,8 +154,8 @@ class _NIST_Ions(MiniSoC, AMPSoC):
|
||||||
self.crg.cd_sys.clk,
|
self.crg.cd_sys.clk,
|
||||||
self.rtio_crg.cd_rtio.clk)
|
self.rtio_crg.cd_rtio.clk)
|
||||||
|
|
||||||
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio,
|
self.submodules.rtio_analyzer = rtio.Analyzer(
|
||||||
self.get_native_sdram_if())
|
self.rtio, self.rtio_core.cri.counter, self.get_native_sdram_if())
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict
|
||||||
from misoc.integration.builder import builder_args, builder_argdict
|
from misoc.integration.builder import builder_args, builder_argdict
|
||||||
|
|
||||||
from artiq.gateware.soc import AMPSoC, build_artiq_soc
|
from artiq.gateware.soc import AMPSoC, build_artiq_soc
|
||||||
|
from artiq.gateware import rtio
|
||||||
from artiq.gateware.drtio.transceiver import gtx_7series
|
from artiq.gateware.drtio.transceiver import gtx_7series
|
||||||
from artiq.gateware.drtio import DRTIOMaster
|
from artiq.gateware.drtio import DRTIOMaster
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
|
@ -41,7 +42,8 @@ class Master(MiniSoC, AMPSoC):
|
||||||
sys_clk_freq=self.clk_freq,
|
sys_clk_freq=self.clk_freq,
|
||||||
clock_div2=True)
|
clock_div2=True)
|
||||||
self.submodules.drtio = DRTIOMaster(self.transceiver)
|
self.submodules.drtio = DRTIOMaster(self.transceiver)
|
||||||
self.register_kernel_cpu_csrdevice("rtio", self.drtio.get_kernel_csrs())
|
self.submodules.rtio = rtio.KernelInitiator(self.drtio.cri)
|
||||||
|
self.register_kernel_cpu_csrdevice("rtio")
|
||||||
self.csr_devices.append("drtio")
|
self.csr_devices.append("drtio")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -216,12 +216,13 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
|
||||||
rtio_channels.append(rtio.LogChannel())
|
rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
# RTIO logic
|
# RTIO logic
|
||||||
self.submodules.rtio = rtio.RTIO(rtio_channels)
|
self.submodules.rtio_core = rtio.Core(rtio_channels)
|
||||||
|
self.submodules.rtio = rtio.KernelInitiator(self.rtio_core.cri)
|
||||||
self.register_kernel_cpu_csrdevice("rtio")
|
self.register_kernel_cpu_csrdevice("rtio")
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||||
self.csr_devices.append("rtio_moninj")
|
self.csr_devices.append("rtio_moninj")
|
||||||
self.submodules.rtio_analyzer = rtio.Analyzer(
|
self.submodules.rtio_analyzer = rtio.Analyzer(
|
||||||
self.rtio, self.get_native_sdram_if())
|
self.rtio, self.rtio_core.cri.counter, self.get_native_sdram_if())
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ class MessageType(Enum):
|
||||||
|
|
||||||
|
|
||||||
class ExceptionType(Enum):
|
class ExceptionType(Enum):
|
||||||
reset_rising = 0b000000
|
reset = 0b000000
|
||||||
reset_falling = 0b000001
|
legacy_reset_falling = 0b000001
|
||||||
reset_phy_rising = 0b000010
|
reset_phy = 0b000010
|
||||||
reset_phy_falling = 0b000011
|
legacy_reset_phy_falling = 0b000011
|
||||||
|
|
||||||
o_underflow_reset = 0b010000
|
o_underflow_reset = 0b010000
|
||||||
o_sequence_error_reset = 0b010001
|
o_sequence_error_reset = 0b010001
|
||||||
|
|
|
@ -11,8 +11,6 @@ const RTIO_I_STATUS_OVERFLOW: u32 = 2;
|
||||||
pub extern fn init() {
|
pub extern fn init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::rtio::reset_write(1);
|
csr::rtio::reset_write(1);
|
||||||
csr::rtio::reset_write(0);
|
|
||||||
csr::rtio::reset_phy_write(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue