forked from M-Labs/artiq
rtio: cleanup resets
This commit is contained in:
parent
251d90c3d5
commit
53a979e74d
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue