rtio: cleanup resets

This commit is contained in:
Sebastien Bourdeauducq 2018-09-20 10:58:38 +08:00
parent 251d90c3d5
commit 53a979e74d
11 changed files with 61 additions and 70 deletions

View File

@ -220,7 +220,7 @@ pub fn process_kern_hwreq(io: &Io, aux_mutex: &Mutex,
match request { match request {
&kern::RtioInitRequest => { &kern::RtioInitRequest => {
info!("resetting RTIO"); info!("resetting RTIO");
rtio_mgt::init_core(io, aux_mutex, false); rtio_mgt::reset(io, aux_mutex);
kern_acknowledge() kern_acknowledge()
} }

View File

@ -1,5 +1,6 @@
#![feature(lang_items, alloc, try_from, nonzero, asm, #![feature(lang_items, alloc, try_from, nonzero, asm,
panic_implementation, panic_info_message)] panic_implementation, panic_info_message,
const_slice_len)]
#![no_std] #![no_std]
extern crate eh; extern crate eh;

View File

@ -70,26 +70,6 @@ pub mod drtio {
} }
} }
pub fn link_up(linkno: u8) -> bool {
let linkno = linkno as usize;
/* This function may be called by kernels with arbitrary
* linkno values.
*/
if linkno >= csr::DRTIO.len() {
return false;
}
unsafe {
(csr::DRTIO[linkno].link_up_read)() == 1
}
}
fn set_link_up(linkno: u8, up: bool) {
let linkno = linkno as usize;
unsafe {
(csr::DRTIO[linkno].link_up_write)(if up { 1 } else { 0 });
}
}
fn recv_aux_timeout(io: &Io, linkno: u8, timeout: u32) -> Result<drtioaux::Packet, &'static str> { fn recv_aux_timeout(io: &Io, linkno: u8, timeout: u32) -> Result<drtioaux::Packet, &'static str> {
let max_time = clock::get_ms() + timeout as u64; let max_time = clock::get_ms() + timeout as u64;
loop { loop {
@ -238,6 +218,7 @@ pub mod drtio {
} }
fn destination_survey(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable, fn destination_survey(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
up_links: &[bool],
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) { up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
for destination in 0..drtio_routing::DEST_COUNT { for destination in 0..drtio_routing::DEST_COUNT {
let hop = routing_table.0[destination][0]; let hop = routing_table.0[destination][0];
@ -251,7 +232,7 @@ pub mod drtio {
} else if hop as usize <= csr::DRTIO.len() { } else if hop as usize <= csr::DRTIO.len() {
let linkno = hop - 1; let linkno = hop - 1;
if destination_up(up_destinations, destination) { if destination_up(up_destinations, destination) {
if link_up(linkno) { if up_links[linkno as usize] {
let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest { let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest {
destination: destination destination: destination
}); });
@ -272,7 +253,7 @@ pub mod drtio {
destination_set_up(routing_table, up_destinations, destination, false); destination_set_up(routing_table, up_destinations, destination, false);
} }
} else { } else {
if link_up(linkno) { if up_links[linkno as usize] {
let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest { let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest {
destination: destination destination: destination
}); });
@ -294,17 +275,18 @@ pub mod drtio {
pub fn link_thread(io: Io, aux_mutex: &Mutex, pub fn link_thread(io: Io, aux_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) { up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
let mut up_links = [false; csr::DRTIO.len()];
loop { loop {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if link_up(linkno) { if up_links[linkno as usize] {
/* link was previously up */ /* link was previously up */
if link_rx_up(linkno) { if link_rx_up(linkno) {
process_unsolicited_aux(&io, aux_mutex, linkno); process_unsolicited_aux(&io, aux_mutex, linkno);
process_local_errors(linkno); process_local_errors(linkno);
} else { } else {
info!("[LINK#{}] link is down", linkno); info!("[LINK#{}] link is down", linkno);
set_link_up(linkno, false); up_links[linkno as usize] = false;
} }
} else { } else {
/* link was previously down */ /* link was previously down */
@ -313,7 +295,7 @@ pub mod drtio {
let ping_count = ping_remote(&io, aux_mutex, linkno); let ping_count = ping_remote(&io, aux_mutex, linkno);
if ping_count > 0 { if ping_count > 0 {
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count); info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
set_link_up(linkno, true); up_links[linkno as usize] = true;
if let Err(e) = sync_tsc(&io, aux_mutex, linkno) { if let Err(e) = sync_tsc(&io, aux_mutex, linkno) {
error!("[LINK#{}] failed to sync TSC ({})", linkno, e); error!("[LINK#{}] failed to sync TSC ({})", linkno, e);
} }
@ -330,15 +312,27 @@ pub mod drtio {
} }
} }
} }
destination_survey(&io, aux_mutex, routing_table, up_destinations); destination_survey(&io, aux_mutex, routing_table, &up_links, up_destinations);
io.sleep(200).unwrap(); io.sleep(200).unwrap();
} }
} }
pub fn init(io: &Io, aux_mutex: &Mutex) { pub fn reset(io: &Io, aux_mutex: &Mutex) {
for linkno in 0..csr::DRTIO.len() {
unsafe {
(csr::DRTIO[linkno].reset_write)(1);
}
}
io.sleep(1).unwrap();
for linkno in 0..csr::DRTIO.len() {
unsafe {
(csr::DRTIO[linkno].reset_write)(0);
}
}
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if link_up(linkno) { if link_rx_up(linkno) {
let reply = aux_transact(io, aux_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::ResetRequest { phy: false }); &drtioaux::Packet::ResetRequest { phy: false });
match reply { match reply {
@ -358,8 +352,7 @@ pub mod drtio {
pub fn startup(_io: &Io, _aux_mutex: &Mutex, pub fn startup(_io: &Io, _aux_mutex: &Mutex,
_routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>, _routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {} _up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {}
pub fn init(_io: &Io, _aux_mutex: &Mutex) {} pub fn reset(_io: &Io, _aux_mutex: &Mutex) {}
pub fn link_up(_linkno: u8) -> bool { false }
} }
fn async_error_thread(io: Io) { fn async_error_thread(io: Io) {
@ -425,18 +418,17 @@ pub fn startup(io: &Io, aux_mutex: &Mutex,
} }
} }
} }
unsafe {
csr::rtio_core::reset_phy_write(1);
}
drtio::startup(io, aux_mutex, routing_table, up_destinations); drtio::startup(io, aux_mutex, routing_table, up_destinations);
init_core(io, aux_mutex, true);
io.spawn(4096, async_error_thread); io.spawn(4096, async_error_thread);
} }
pub fn init_core(io: &Io, aux_mutex: &Mutex, phy: bool) { pub fn reset(io: &Io, aux_mutex: &Mutex) {
unsafe { unsafe {
csr::rtio_core::reset_write(1); csr::rtio_core::reset_write(1);
if phy {
csr::rtio_core::reset_phy_write(1);
} }
} drtio::reset(io, aux_mutex)
drtio::init(io, aux_mutex)
} }

View File

@ -82,6 +82,7 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
drtiosat_reset_phy(false); drtiosat_reset_phy(false);
} else { } else {
drtiosat_reset(true); drtiosat_reset(true);
clock::spin_us(100);
drtiosat_reset(false); drtiosat_reset(false);
} }
for rep in _repeaters.iter() { for rep in _repeaters.iter() {

View File

@ -243,9 +243,17 @@ impl Repeater {
} }
pub fn rtio_reset(&self, phy: bool) -> Result<(), drtioaux::Error<!>> { pub fn rtio_reset(&self, phy: bool) -> Result<(), drtioaux::Error<!>> {
let repno = self.repno as usize;
if !phy {
unsafe { (csr::DRTIOREP[repno].reset_write)(1); }
clock::spin_us(100);
unsafe { (csr::DRTIOREP[repno].reset_write)(0); }
}
if self.state != RepeaterState::Up { if self.state != RepeaterState::Up {
return Ok(()); return Ok(());
} }
drtioaux::send(self.auxno, &drtioaux::Packet::ResetRequest { drtioaux::send(self.auxno, &drtioaux::Packet::ResetRequest {
phy: phy phy: phy
}).unwrap(); }).unwrap();

View File

@ -3,7 +3,6 @@
from migen import * from migen import *
from migen.genlib.cdc import MultiReg from migen.genlib.cdc import MultiReg
from migen.genlib.misc import WaitTimer from migen.genlib.misc import WaitTimer
from migen.genlib.resetsync import AsyncResetSynchronizer
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
@ -12,7 +11,7 @@ from artiq.gateware.rtio import cri
class _CSRs(AutoCSR): class _CSRs(AutoCSR):
def __init__(self): def __init__(self):
self.link_up = CSRStorage() self.reset = CSRStorage()
self.protocol_error = CSR(3) self.protocol_error = CSR(3)
@ -33,25 +32,12 @@ class RTController(Module):
self.csrs = _CSRs() self.csrs = _CSRs()
self.cri = cri.Interface() self.cri = cri.Interface()
# reset
local_reset = Signal(reset=1)
self.sync += local_reset.eq(~self.csrs.link_up.storage)
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 # protocol errors
err_unknown_packet_type = Signal() err_unknown_packet_type = Signal()
err_packet_truncated = Signal() err_packet_truncated = Signal()
signal_buffer_space_timeout = Signal() signal_buffer_space_timeout = Signal()
err_buffer_space_timeout = Signal() err_buffer_space_timeout = Signal()
self.sync.sys_with_rst += [ self.sync += [
If(self.csrs.protocol_error.re, If(self.csrs.protocol_error.re,
If(self.csrs.protocol_error.r[0], err_unknown_packet_type.eq(0)), If(self.csrs.protocol_error.r[0], err_unknown_packet_type.eq(0)),
If(self.csrs.protocol_error.r[1], err_packet_truncated.eq(0)), If(self.csrs.protocol_error.r[1], err_packet_truncated.eq(0)),
@ -106,7 +92,7 @@ class RTController(Module):
self.csrs.o_wait.status.eq(o_status_wait) self.csrs.o_wait.status.eq(o_status_wait)
] ]
o_underflow_set = Signal() o_underflow_set = Signal()
self.sync.sys_with_rst += [ self.sync += [
If(self.cri.cmd == cri.commands["write"], If(self.cri.cmd == cri.commands["write"],
o_status_underflow.eq(0) o_status_underflow.eq(0)
), ),
@ -145,7 +131,7 @@ class RTController(Module):
i_status_wait_event, i_status_overflow, i_status_wait_status)) i_status_wait_event, i_status_overflow, i_status_wait_status))
load_read_reply = Signal() load_read_reply = Signal()
self.sync.sys_with_rst += [ self.sync += [
If(load_read_reply, If(load_read_reply,
i_status_wait_event.eq(0), i_status_wait_event.eq(0),
i_status_overflow.eq(0), i_status_overflow.eq(0),
@ -162,7 +148,7 @@ class RTController(Module):
] ]
# FSM # FSM
fsm = ClockDomainsRenamer("sys_with_rst")(FSM()) fsm = FSM()
self.submodules += fsm self.submodules += fsm
fsm.act("IDLE", fsm.act("IDLE",
@ -226,7 +212,7 @@ class RTController(Module):
fsm.act("GET_READ_REPLY", fsm.act("GET_READ_REPLY",
i_status_wait_status.eq(1), i_status_wait_status.eq(1),
rt_packet.read_not_ack.eq(1), rt_packet.read_not_ack.eq(1),
If(rt_packet.read_not, If(self.csrs.reset.storage | rt_packet.read_not,
load_read_reply.eq(1), load_read_reply.eq(1),
NextState("IDLE") NextState("IDLE")
) )

View File

@ -1,4 +1,5 @@
from migen import * from migen import *
from migen.genlib.cdc import MultiReg
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
@ -8,12 +9,15 @@ from artiq.gateware.drtio.cdc import CrossDomainRequest
class RTController(Module, AutoCSR): class RTController(Module, AutoCSR):
def __init__(self, rt_packet): def __init__(self, rt_packet):
self.reset = CSRStorage()
self.set_time = CSR() self.set_time = CSR()
self.protocol_error = CSR(4) self.protocol_error = CSR(4)
self.command_missed_cmd = CSRStatus(2) self.command_missed_cmd = CSRStatus(2)
self.command_missed_chan_sel = CSRStatus(24) self.command_missed_chan_sel = CSRStatus(24)
self.buffer_space_timeout_dest = CSRStatus(8) self.buffer_space_timeout_dest = CSRStatus(8)
self.specials += MultiReg(self.reset.storage, rt_packet.reset, "rtio")
set_time_stb = Signal() set_time_stb = Signal()
set_time_ack = Signal() set_time_ack = Signal()
self.submodules += CrossDomainRequest("rtio", self.submodules += CrossDomainRequest("rtio",

View File

@ -84,7 +84,7 @@ class RTPacketMaster(Module):
self.submodules += rx_dp self.submodules += rx_dp
# Write FIFO and extra data count # Write FIFO and extra data count
sr_fifo = ClockDomainsRenamer({"write": "sys_with_rst", "read": "rtio_with_rst"})( sr_fifo = ClockDomainsRenamer({"write": "sys", "read": "rtio"})(
AsyncFIFO(1+64+24+16+512, sr_fifo_depth)) AsyncFIFO(1+64+24+16+512, sr_fifo_depth))
self.submodules += sr_fifo self.submodules += sr_fifo
sr_notwrite_d = Signal() sr_notwrite_d = Signal()

View File

@ -10,6 +10,9 @@ from artiq.gateware.drtio.rt_serializer import *
class RTPacketRepeater(Module): class RTPacketRepeater(Module):
def __init__(self, tsc, link_layer): def __init__(self, tsc, link_layer):
# in rtio domain
self.reset = Signal()
# CRI target interface in rtio domain # CRI target interface in rtio domain
self.cri = cri.Interface() self.cri = cri.Interface()
@ -58,11 +61,11 @@ class RTPacketRepeater(Module):
cb0_o_address = Signal(16) cb0_o_address = Signal(16)
cb0_o_data = Signal(512) cb0_o_data = Signal(512)
self.sync.rtio += [ self.sync.rtio += [
If(cb0_ack, If(self.reset | cb0_ack,
cb0_loaded.eq(0), cb0_loaded.eq(0),
cb0_cmd.eq(cri.commands["nop"]) cb0_cmd.eq(cri.commands["nop"])
), ),
If(~cb0_loaded & (self.cri.cmd != cri.commands["nop"]), If(~self.reset & ~cb0_loaded & (self.cri.cmd != cri.commands["nop"]),
cb0_loaded.eq(1), cb0_loaded.eq(1),
cb0_cmd.eq(self.cri.cmd), cb0_cmd.eq(self.cri.cmd),
cb0_timestamp.eq(self.cri.timestamp), cb0_timestamp.eq(self.cri.timestamp),
@ -85,11 +88,11 @@ class RTPacketRepeater(Module):
cb_o_address = Signal(16) cb_o_address = Signal(16)
cb_o_data = Signal(512) cb_o_data = Signal(512)
self.sync.rtio += [ self.sync.rtio += [
If(cb_ack, If(self.reset | cb_ack,
cb_loaded.eq(0), cb_loaded.eq(0),
cb_cmd.eq(cri.commands["nop"]) cb_cmd.eq(cri.commands["nop"])
), ),
If(~cb_loaded & cb0_loaded, If(~self.reset & ~cb_loaded & cb0_loaded,
cb_loaded.eq(1), cb_loaded.eq(1),
cb_cmd.eq(cb0_cmd), cb_cmd.eq(cb0_cmd),
cb_timestamp.eq(cb0_timestamp), cb_timestamp.eq(cb0_timestamp),
@ -277,7 +280,7 @@ class RTPacketRepeater(Module):
) )
tx_fsm.act("GET_READ_REPLY", tx_fsm.act("GET_READ_REPLY",
rtio_read_not_ack.eq(1), rtio_read_not_ack.eq(1),
If(rtio_read_not, If(self.reset | rtio_read_not,
load_read_reply.eq(1), load_read_reply.eq(1),
cb_ack.eq(1), cb_ack.eq(1),
NextState("READY") NextState("READY")

View File

@ -57,7 +57,6 @@ class DUT(Module):
self.transceivers.alice) self.transceivers.alice)
self.submodules.master_ki = rtio.KernelInitiator(self.tsc_master, self.submodules.master_ki = rtio.KernelInitiator(self.tsc_master,
self.master.cri) self.master.cri)
self.master.rt_controller.csrs.link_up.storage.reset = 1
rx_synchronizer = DummyRXSynchronizer() rx_synchronizer = DummyRXSynchronizer()
self.submodules.phy0 = ttl_simple.Output(self.ttl0) self.submodules.phy0 = ttl_simple.Output(self.ttl0)
@ -146,8 +145,7 @@ class OutputsTestbench:
class TestFullStack(unittest.TestCase): class TestFullStack(unittest.TestCase):
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5, clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
"rio": 5, "rio_phy": 5, "rio": 5, "rio_phy": 5}
"sys_with_rst": 8, "rtio_with_rst": 5}
def test_pulses(self): def test_pulses(self):
tb = OutputsTestbench() tb = OutputsTestbench()

View File

@ -43,7 +43,6 @@ class DUT(Module):
self.submodules.tsc_master = rtio.TSC("async") self.submodules.tsc_master = rtio.TSC("async")
self.submodules.master = DRTIOMaster(self.tsc_master, self.submodules.master = DRTIOMaster(self.tsc_master,
self.transceivers.alice) self.transceivers.alice)
self.master.rt_controller.csrs.link_up.storage.reset = 1
rx_synchronizer = DummyRXSynchronizer() rx_synchronizer = DummyRXSynchronizer()
self.submodules.tsc_satellite = rtio.TSC("sync") self.submodules.tsc_satellite = rtio.TSC("sync")
@ -132,8 +131,7 @@ class Testbench:
class TestSwitching(unittest.TestCase): class TestSwitching(unittest.TestCase):
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5, clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
"rio": 5, "rio_phy": 5, "rio": 5, "rio_phy": 5}
"sys_with_rst": 8, "rtio_with_rst": 5}
def test_outputs(self): def test_outputs(self):
tb = Testbench() tb = Testbench()