diff --git a/artiq/firmware/runtime/kern_hwreq.rs b/artiq/firmware/runtime/kern_hwreq.rs index aa4d21bcf..008a3e9ec 100644 --- a/artiq/firmware/runtime/kern_hwreq.rs +++ b/artiq/firmware/runtime/kern_hwreq.rs @@ -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() } diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index d79de3b83..b3e2bbb94 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -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; diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 69233dd60..cedfb8686 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -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 { 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>) { 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>) { + 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>, _up_destinations: &Urc>) {} - 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) } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 1e69111b2..bc12bccfd 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -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() { diff --git a/artiq/firmware/satman/repeater.rs b/artiq/firmware/satman/repeater.rs index d5b04a94f..ca0531ac5 100644 --- a/artiq/firmware/satman/repeater.rs +++ b/artiq/firmware/satman/repeater.rs @@ -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(); diff --git a/artiq/gateware/drtio/rt_controller_master.py b/artiq/gateware/drtio/rt_controller_master.py index 40014dce0..0126184c6 100644 --- a/artiq/gateware/drtio/rt_controller_master.py +++ b/artiq/gateware/drtio/rt_controller_master.py @@ -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") ) diff --git a/artiq/gateware/drtio/rt_controller_repeater.py b/artiq/gateware/drtio/rt_controller_repeater.py index b877700b1..4cd192054 100644 --- a/artiq/gateware/drtio/rt_controller_repeater.py +++ b/artiq/gateware/drtio/rt_controller_repeater.py @@ -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", diff --git a/artiq/gateware/drtio/rt_packet_master.py b/artiq/gateware/drtio/rt_packet_master.py index 42370a09d..f91ac7667 100644 --- a/artiq/gateware/drtio/rt_packet_master.py +++ b/artiq/gateware/drtio/rt_packet_master.py @@ -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() diff --git a/artiq/gateware/drtio/rt_packet_repeater.py b/artiq/gateware/drtio/rt_packet_repeater.py index 1cbd45750..4788283f9 100644 --- a/artiq/gateware/drtio/rt_packet_repeater.py +++ b/artiq/gateware/drtio/rt_packet_repeater.py @@ -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") diff --git a/artiq/gateware/test/drtio/test_full_stack.py b/artiq/gateware/test/drtio/test_full_stack.py index 579d78f9b..e9bc6160a 100644 --- a/artiq/gateware/test/drtio/test_full_stack.py +++ b/artiq/gateware/test/drtio/test_full_stack.py @@ -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() diff --git a/artiq/gateware/test/drtio/test_switching.py b/artiq/gateware/test/drtio/test_switching.py index 2d3330484..eb691fcf7 100644 --- a/artiq/gateware/test/drtio/test_switching.py +++ b/artiq/gateware/test/drtio/test_switching.py @@ -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()