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 {
&kern::RtioInitRequest => {
info!("resetting RTIO");
rtio_mgt::init_core(io, aux_mutex, false);
rtio_mgt::reset(io, aux_mutex);
kern_acknowledge()
}

View File

@ -1,5 +1,6 @@
#![feature(lang_items, alloc, try_from, nonzero, asm,
panic_implementation, panic_info_message)]
panic_implementation, panic_info_message,
const_slice_len)]
#![no_std]
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> {
let max_time = clock::get_ms() + timeout as u64;
loop {
@ -238,6 +218,7 @@ pub mod drtio {
}
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]>>) {
for destination in 0..drtio_routing::DEST_COUNT {
let hop = routing_table.0[destination][0];
@ -251,7 +232,7 @@ pub mod drtio {
} else if hop as usize <= csr::DRTIO.len() {
let linkno = hop - 1;
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 {
destination: destination
});
@ -272,7 +253,7 @@ pub mod drtio {
destination_set_up(routing_table, up_destinations, destination, false);
}
} else {
if link_up(linkno) {
if up_links[linkno as usize] {
let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest {
destination: destination
});
@ -294,17 +275,18 @@ pub mod drtio {
pub fn link_thread(io: Io, aux_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
let mut up_links = [false; csr::DRTIO.len()];
loop {
for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8;
if link_up(linkno) {
if up_links[linkno as usize] {
/* link was previously up */
if link_rx_up(linkno) {
process_unsolicited_aux(&io, aux_mutex, linkno);
process_local_errors(linkno);
} else {
info!("[LINK#{}] link is down", linkno);
set_link_up(linkno, false);
up_links[linkno as usize] = false;
}
} else {
/* link was previously down */
@ -313,7 +295,7 @@ pub mod drtio {
let ping_count = ping_remote(&io, aux_mutex, linkno);
if ping_count > 0 {
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) {
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();
}
}
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() {
let linkno = linkno as u8;
if link_up(linkno) {
if link_rx_up(linkno) {
let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::ResetRequest { phy: false });
match reply {
@ -358,8 +352,7 @@ pub mod drtio {
pub fn startup(_io: &Io, _aux_mutex: &Mutex,
_routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {}
pub fn init(_io: &Io, _aux_mutex: &Mutex) {}
pub fn link_up(_linkno: u8) -> bool { false }
pub fn reset(_io: &Io, _aux_mutex: &Mutex) {}
}
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);
init_core(io, aux_mutex, true);
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 {
csr::rtio_core::reset_write(1);
if phy {
csr::rtio_core::reset_phy_write(1);
}
}
drtio::init(io, aux_mutex)
drtio::reset(io, aux_mutex)
}

View File

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

View File

@ -243,9 +243,17 @@ impl Repeater {
}
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 {
return Ok(());
}
drtioaux::send(self.auxno, &drtioaux::Packet::ResetRequest {
phy: phy
}).unwrap();

View File

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

View File

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

View File

@ -84,7 +84,7 @@ class RTPacketMaster(Module):
self.submodules += rx_dp
# 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))
self.submodules += sr_fifo
sr_notwrite_d = Signal()

View File

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

View File

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

View File

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