forked from M-Labs/artiq
drtio: rewrite/fix reset and link bringup/teardown
This commit is contained in:
parent
bfabf3c906
commit
ad2c9590d0
@ -54,11 +54,10 @@ pub mod drtio {
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_phy(linkno: u8) {
|
||||
fn link_reset(linkno: u8) {
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
(csr::DRTIO[linkno].reset_phy_write)(1);
|
||||
while (csr::DRTIO[linkno].o_wait_read)() == 1 {}
|
||||
(csr::DRTIO[linkno].reset_write)(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,12 +69,9 @@ pub mod drtio {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_link(linkno: u8) {
|
||||
fn init_buffer_space(linkno: u8) {
|
||||
let linkidx = linkno as usize;
|
||||
unsafe {
|
||||
(csr::DRTIO[linkidx].reset_write)(1);
|
||||
while (csr::DRTIO[linkidx].o_wait_read)() == 1 {}
|
||||
|
||||
(csr::DRTIO[linkidx].o_get_buffer_space_write)(1);
|
||||
while (csr::DRTIO[linkidx].o_wait_read)() == 1 {}
|
||||
info!("[LINK#{}] buffer space is {}",
|
||||
@ -83,12 +79,6 @@ pub mod drtio {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
for linkno in 0..csr::DRTIO.len() {
|
||||
init_link(linkno as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn ping_remote(linkno: u8, io: &Io) -> u32 {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
@ -114,7 +104,7 @@ pub mod drtio {
|
||||
(csr::DRTIO[linkidx].protocol_error_write)(errors);
|
||||
}
|
||||
if errors != 0 {
|
||||
error!("[LINK#{}] found error(s)", linkno);
|
||||
error!("[LINK#{}] error(s) found (0x{:02x}):", linkno, errors);
|
||||
if errors & 1 != 0 {
|
||||
error!("[LINK#{}] received packet of an unknown type", linkno);
|
||||
}
|
||||
@ -148,34 +138,40 @@ pub mod drtio {
|
||||
loop {
|
||||
for linkno in 0..csr::DRTIO.len() {
|
||||
let linkno = linkno as u8;
|
||||
if !link_up[linkno as usize] {
|
||||
if link_up[linkno as usize] {
|
||||
/* link was previously up */
|
||||
if link_rx_up(linkno) {
|
||||
process_local_errors(linkno);
|
||||
process_aux_errors(linkno);
|
||||
} else {
|
||||
info!("[LINK#{}] link is down", linkno);
|
||||
link_up[linkno as usize] = false;
|
||||
}
|
||||
} else {
|
||||
/* link was previously down */
|
||||
if link_rx_up(linkno) {
|
||||
info!("[LINK#{}] link RX became up, pinging", linkno);
|
||||
link_reset(linkno);
|
||||
let ping_count = ping_remote(linkno, &io);
|
||||
if ping_count > 0 {
|
||||
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
|
||||
init_link(linkno); // clear all FIFOs first
|
||||
reset_phy(linkno);
|
||||
init_buffer_space(linkno);
|
||||
sync_tsc(linkno);
|
||||
info!("[LINK#{}] link initialization completed", linkno);
|
||||
link_up[linkno as usize] = true;
|
||||
} else {
|
||||
info!("[LINK#{}] ping failed", linkno);
|
||||
}
|
||||
} else {
|
||||
if link_rx_up(linkno) {
|
||||
process_local_errors(linkno);
|
||||
process_aux_errors(linkno);
|
||||
} else {
|
||||
info!("[LINK#{}] link is down", linkno);
|
||||
link_up[linkno as usize] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
io.sleep(200).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
// TODO: send reset commands (over aux) to every link that is up
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(has_drtio))]
|
||||
|
@ -193,6 +193,14 @@ fn drtio_link_is_up() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn drtio_reset(reset: bool) {
|
||||
let reset = if reset { 1 } else { 0 };
|
||||
unsafe {
|
||||
(csr::DRTIO[0].reset_write)(reset);
|
||||
(csr::DRTIO[0].reset_phy_write)(reset);
|
||||
}
|
||||
}
|
||||
|
||||
fn startup() {
|
||||
board::clock::init();
|
||||
info!("ARTIQ satellite manager starting...");
|
||||
@ -216,10 +224,12 @@ fn startup() {
|
||||
}
|
||||
info!("link is up, switching to recovered clock");
|
||||
si5324::select_ext_input(true).expect("failed to switch clocks");
|
||||
drtio_reset(false);
|
||||
while drtio_link_is_up() {
|
||||
process_errors();
|
||||
process_aux_packets();
|
||||
}
|
||||
drtio_reset(true);
|
||||
info!("link is down, switching to local crystal clock");
|
||||
si5324::select_ext_input(false).expect("failed to switch clocks");
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ from types import SimpleNamespace
|
||||
|
||||
from migen import *
|
||||
from migen.genlib.cdc import ElasticBuffer
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from misoc.interconnect.csr import *
|
||||
|
||||
from artiq.gateware.rtio.sed.core import *
|
||||
@ -54,14 +55,36 @@ class GenericRXSynchronizer(Module):
|
||||
class DRTIOSatellite(Module):
|
||||
def __init__(self, chanif, channels, rx_synchronizer=None, fine_ts_width=3,
|
||||
lane_count=8, fifo_depth=128):
|
||||
if rx_synchronizer is None:
|
||||
rx_synchronizer = GenericRXSynchronizer()
|
||||
self.submodules += rx_synchronizer
|
||||
self.reset = CSRStorage(reset=1)
|
||||
self.reset_phy = CSRStorage(reset=1)
|
||||
|
||||
self.clock_domains.cd_rio = ClockDomain()
|
||||
self.clock_domains.cd_rio_phy = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_rio.clk.eq(ClockSignal("rtio")),
|
||||
self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
|
||||
]
|
||||
reset = Signal()
|
||||
reset_phy = Signal()
|
||||
reset.attr.add("no_retiming")
|
||||
reset_phy.attr.add("no_retiming")
|
||||
self.sync += [
|
||||
reset.eq(self.reset.storage),
|
||||
reset_phy.eq(self.reset_phy.storage)
|
||||
]
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_rio, reset),
|
||||
AsyncResetSynchronizer(self.cd_rio_phy, reset_phy)
|
||||
]
|
||||
|
||||
self.submodules.link_layer = link_layer.LinkLayer(
|
||||
chanif.encoder, chanif.decoders)
|
||||
self.comb += self.link_layer.rx_ready.eq(chanif.rx_ready)
|
||||
|
||||
if rx_synchronizer is None:
|
||||
rx_synchronizer = GenericRXSynchronizer()
|
||||
self.submodules += rx_synchronizer
|
||||
|
||||
link_layer_sync = SimpleNamespace(
|
||||
tx_aux_frame=self.link_layer.tx_aux_frame,
|
||||
tx_aux_data=self.link_layer.tx_aux_data,
|
||||
@ -80,6 +103,7 @@ class DRTIOSatellite(Module):
|
||||
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio")
|
||||
self.submodules.rt_packet = ClockDomainsRenamer("rtio")(
|
||||
rt_packet_satellite.RTPacketSatellite(link_layer_sync))
|
||||
self.comb += self.rt_packet.reset.eq(self.cd_rio.rst)
|
||||
|
||||
coarse_ts = Signal(64 - fine_ts_width)
|
||||
self.sync.rtio += \
|
||||
@ -106,20 +130,12 @@ class DRTIOSatellite(Module):
|
||||
self.submodules.rt_errors = rt_errors_satellite.RTErrorsSatellite(
|
||||
self.rt_packet, self.outputs)
|
||||
|
||||
self.clock_domains.cd_rio = ClockDomain()
|
||||
self.clock_domains.cd_rio_phy = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_rio.clk.eq(ClockSignal("rtio")),
|
||||
self.cd_rio.rst.eq(self.rt_packet.reset),
|
||||
self.cd_rio_phy.clk.eq(ClockSignal("rtio")),
|
||||
self.cd_rio_phy.rst.eq(self.rt_packet.reset_phy),
|
||||
]
|
||||
|
||||
self.submodules.aux_controller = aux_controller.AuxController(
|
||||
self.link_layer)
|
||||
|
||||
def get_csrs(self):
|
||||
return (self.link_layer.get_csrs() + self.link_stats.get_csrs() +
|
||||
return ([self.reset, self.reset_phy] +
|
||||
self.link_layer.get_csrs() + self.link_stats.get_csrs() +
|
||||
self.rt_errors.get_csrs() + self.aux_controller.get_csrs())
|
||||
|
||||
|
||||
|
@ -13,14 +13,14 @@ from artiq.gateware.rtio import cri
|
||||
|
||||
class _CSRs(AutoCSR):
|
||||
def __init__(self):
|
||||
self.reset = CSR()
|
||||
|
||||
self.protocol_error = CSR(3)
|
||||
|
||||
self.tsc_correction = CSRStorage(64)
|
||||
self.set_time = CSR()
|
||||
self.underflow_margin = CSRStorage(16, reset=200)
|
||||
|
||||
self.reset = CSR()
|
||||
self.reset_phy = CSR()
|
||||
|
||||
self.o_get_buffer_space = CSR()
|
||||
self.o_dbg_buffer_space = CSRStatus(16)
|
||||
@ -51,6 +51,19 @@ class RTController(Module):
|
||||
self.csrs = _CSRs()
|
||||
self.cri = cri.Interface()
|
||||
|
||||
# reset
|
||||
local_reset = Signal(reset=1)
|
||||
self.sync += local_reset.eq(self.csrs.reset.re)
|
||||
local_reset.attr.add("no_retiming")
|
||||
self.clock_domains.cd_sys_with_rst = ClockDomain()
|
||||
self.clock_domains.cd_rtio_with_rst = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_sys_with_rst.clk.eq(ClockSignal()),
|
||||
self.cd_sys_with_rst.rst.eq(local_reset)
|
||||
]
|
||||
self.comb += self.cd_rtio_with_rst.clk.eq(ClockSignal("rtio"))
|
||||
self.specials += AsyncResetSynchronizer(self.cd_rtio_with_rst, local_reset)
|
||||
|
||||
# protocol errors
|
||||
err_unknown_packet_type = Signal()
|
||||
err_packet_truncated = Signal()
|
||||
@ -85,31 +98,6 @@ class RTController(Module):
|
||||
If(self.csrs.set_time.re, rt_packet.set_time_stb.eq(1))
|
||||
]
|
||||
|
||||
# reset
|
||||
self.sync += [
|
||||
If(rt_packet.reset_ack, rt_packet.reset_stb.eq(0)),
|
||||
If(self.csrs.reset.re,
|
||||
rt_packet.reset_stb.eq(1),
|
||||
rt_packet.reset_phy.eq(0)
|
||||
),
|
||||
If(self.csrs.reset_phy.re,
|
||||
rt_packet.reset_stb.eq(1),
|
||||
rt_packet.reset_phy.eq(1)
|
||||
),
|
||||
]
|
||||
|
||||
local_reset = Signal(reset=1)
|
||||
self.sync += local_reset.eq(self.csrs.reset.re)
|
||||
local_reset.attr.add("no_retiming")
|
||||
self.clock_domains.cd_sys_with_rst = ClockDomain()
|
||||
self.clock_domains.cd_rtio_with_rst = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_sys_with_rst.clk.eq(ClockSignal()),
|
||||
self.cd_sys_with_rst.rst.eq(local_reset)
|
||||
]
|
||||
self.comb += self.cd_rtio_with_rst.clk.eq(ClockSignal("rtio"))
|
||||
self.specials += AsyncResetSynchronizer(self.cd_rtio_with_rst, local_reset)
|
||||
|
||||
# common packet fields
|
||||
chan_sel = self.cri.chan_sel[:16]
|
||||
rt_packet_buffer_request = Signal()
|
||||
|
@ -111,11 +111,6 @@ class RTPacketMaster(Module):
|
||||
# a set_time request pending
|
||||
self.tsc_value = Signal(64)
|
||||
|
||||
# reset interface
|
||||
self.reset_stb = Signal()
|
||||
self.reset_ack = Signal()
|
||||
self.reset_phy = Signal()
|
||||
|
||||
# rx errors
|
||||
self.err_unknown_packet_type = Signal()
|
||||
self.err_packet_truncated = Signal()
|
||||
@ -221,13 +216,6 @@ class RTPacketMaster(Module):
|
||||
self.set_time_stb, self.set_time_ack, None,
|
||||
set_time_stb, set_time_ack, None)
|
||||
|
||||
reset_stb = Signal()
|
||||
reset_ack = Signal()
|
||||
reset_phy = Signal()
|
||||
self.submodules += _CrossDomainRequest("rtio",
|
||||
self.reset_stb, self.reset_ack, self.reset_phy,
|
||||
reset_stb, reset_ack, reset_phy)
|
||||
|
||||
echo_stb = Signal()
|
||||
echo_ack = Signal()
|
||||
self.submodules += _CrossDomainRequest("rtio",
|
||||
@ -287,8 +275,6 @@ class RTPacketMaster(Module):
|
||||
).Elif(set_time_stb,
|
||||
tsc_value_load.eq(1),
|
||||
NextState("SET_TIME")
|
||||
).Elif(reset_stb,
|
||||
NextState("RESET")
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -344,13 +330,6 @@ class RTPacketMaster(Module):
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
tx_fsm.act("RESET",
|
||||
tx_dp.send("reset", phy=reset_phy),
|
||||
If(tx_dp.packet_last,
|
||||
reset_ack.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
|
||||
# RX FSM
|
||||
rx_fsm = ClockDomainsRenamer("rtio_rx")(FSM(reset_state="INPUT"))
|
||||
|
@ -9,15 +9,14 @@ from artiq.gateware.drtio.rt_serializer import *
|
||||
|
||||
class RTPacketSatellite(Module):
|
||||
def __init__(self, link_layer):
|
||||
self.reset = Signal()
|
||||
|
||||
self.unknown_packet_type = Signal()
|
||||
self.packet_truncated = Signal()
|
||||
|
||||
self.tsc_load = Signal()
|
||||
self.tsc_load_value = Signal(64)
|
||||
|
||||
self.reset = Signal(reset=1)
|
||||
self.reset_phy = Signal(reset=1)
|
||||
|
||||
self.cri = cri.Interface()
|
||||
|
||||
# # #
|
||||
@ -97,13 +96,6 @@ class RTPacketSatellite(Module):
|
||||
Cat(rx_dp.packet_as["write"].short_data, write_data_buffer)),
|
||||
]
|
||||
|
||||
reset = Signal()
|
||||
reset_phy = Signal()
|
||||
self.sync += [
|
||||
self.reset.eq(reset),
|
||||
self.reset_phy.eq(reset_phy)
|
||||
]
|
||||
|
||||
rx_fsm = FSM(reset_state="INPUT")
|
||||
self.submodules += rx_fsm
|
||||
|
||||
@ -120,7 +112,6 @@ class RTPacketSatellite(Module):
|
||||
# mechanism
|
||||
rx_plm.types["echo_request"]: echo_req.eq(1),
|
||||
rx_plm.types["set_time"]: NextState("SET_TIME"),
|
||||
rx_plm.types["reset"]: NextState("RESET"),
|
||||
rx_plm.types["write"]: NextState("WRITE"),
|
||||
rx_plm.types["buffer_space_request"]: NextState("BUFFER_SPACE"),
|
||||
rx_plm.types["read_request"]: NextState("READ_REQUEST"),
|
||||
@ -138,14 +129,6 @@ class RTPacketSatellite(Module):
|
||||
self.tsc_load.eq(1),
|
||||
NextState("INPUT")
|
||||
)
|
||||
rx_fsm.act("RESET",
|
||||
If(rx_dp.packet_as["reset"].phy,
|
||||
reset_phy.eq(1)
|
||||
).Else(
|
||||
reset.eq(1)
|
||||
),
|
||||
NextState("INPUT")
|
||||
)
|
||||
|
||||
rx_fsm.act("WRITE",
|
||||
If(write_data_buffer_cnt == rx_dp.packet_as["write"].extra_data_cnt,
|
||||
|
@ -47,7 +47,6 @@ def get_m2s_layouts(alignment):
|
||||
|
||||
plm.add_type("echo_request")
|
||||
plm.add_type("set_time", ("timestamp", 64))
|
||||
plm.add_type("reset", ("phy", 1))
|
||||
|
||||
plm.add_type("write", ("timestamp", 64),
|
||||
("channel", 16),
|
||||
|
Loading…
Reference in New Issue
Block a user