diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index c77d93a21..aac2ad298 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -104,13 +104,13 @@ pub fn cricon_read() -> RtioMaster { #[cfg(has_drtio_routing)] macro_rules! forward { - ($routing_table:expr, $destination:expr, $rank:expr, $repeaters:expr, $packet:expr) => {{ + ($router:expr, $routing_table:expr, $destination:expr, $rank:expr, $self_destination:expr, $repeaters:expr, $packet:expr) => {{ let hop = $routing_table.0[$destination as usize][$rank as usize]; if hop != 0 { let repno = (hop - 1) as usize; if repno < $repeaters.len() { if $packet.expects_response() { - return $repeaters[repno].aux_forward($packet); + return $repeaters[repno].aux_forward($packet, $router, $routing_table, $rank, $self_destination); } else { let res = $repeaters[repno].aux_send($packet); // allow the satellite to parse the packet before next @@ -126,7 +126,7 @@ macro_rules! forward { #[cfg(not(has_drtio_routing))] macro_rules! forward { - ($routing_table:expr, $destination:expr, $rank:expr, $repeaters:expr, $packet:expr) => {} + ($router:expr, $routing_table:expr, $destination:expr, $rank:expr, $self_destination:expr, $repeaters:expr, $packet:expr) => {} } fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmgr: &mut KernelManager, @@ -201,7 +201,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg let repno = hop - 1; match _repeaters[repno].aux_forward(&drtioaux::Packet::DestinationStatusRequest { destination: destination - }) { + }, router, _routing_table, *rank, *self_destination) { Ok(()) => (), Err(drtioaux::Error::LinkDown) => drtioaux::send(0, &drtioaux::Packet::DestinationDownReply)?, Err(e) => { @@ -255,7 +255,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } drtioaux::Packet::MonitorRequest { destination: _destination, channel, probe } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let value; #[cfg(has_rtio_moninj)] unsafe { @@ -272,7 +272,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg drtioaux::send(0, &reply) }, drtioaux::Packet::InjectionRequest { destination: _destination, channel, overrd, value } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); #[cfg(has_rtio_moninj)] unsafe { csr::rtio_moninj::inj_chan_sel_write(channel as _); @@ -282,7 +282,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg Ok(()) }, drtioaux::Packet::InjectionStatusRequest { destination: _destination, channel, overrd } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let value; #[cfg(has_rtio_moninj)] unsafe { @@ -298,22 +298,22 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg }, drtioaux::Packet::I2cStartRequest { destination: _destination, busno } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = i2c::start(busno).is_ok(); drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }) } drtioaux::Packet::I2cRestartRequest { destination: _destination, busno } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = i2c::restart(busno).is_ok(); drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }) } drtioaux::Packet::I2cStopRequest { destination: _destination, busno } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = i2c::stop(busno).is_ok(); drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }) } drtioaux::Packet::I2cWriteRequest { destination: _destination, busno, data } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); match i2c::write(busno, data) { Ok(ack) => drtioaux::send(0, &drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }), @@ -322,7 +322,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } } drtioaux::Packet::I2cReadRequest { destination: _destination, busno, ack } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); match i2c::read(busno, ack) { Ok(data) => drtioaux::send(0, &drtioaux::Packet::I2cReadReply { succeeded: true, data: data }), @@ -331,25 +331,25 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } } drtioaux::Packet::I2cSwitchSelectRequest { destination: _destination, busno, address, mask } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = i2c::switch_select(busno, address, mask).is_ok(); drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded }) } drtioaux::Packet::SpiSetConfigRequest { destination: _destination, busno, flags, length, div, cs } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = spi::set_config(busno, flags, length, div, cs).is_ok(); drtioaux::send(0, &drtioaux::Packet::SpiBasicReply { succeeded: succeeded }) }, drtioaux::Packet::SpiWriteRequest { destination: _destination, busno, data } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = spi::write(busno, data).is_ok(); drtioaux::send(0, &drtioaux::Packet::SpiBasicReply { succeeded: succeeded }) } drtioaux::Packet::SpiReadRequest { destination: _destination, busno } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); match spi::read(busno) { Ok(data) => drtioaux::send(0, &drtioaux::Packet::SpiReadReply { succeeded: true, data: data }), @@ -359,7 +359,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } drtioaux::Packet::AnalyzerHeaderRequest { destination: _destination } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let header = analyzer.get_header(); drtioaux::send(0, &drtioaux::Packet::AnalyzerHeader { total_byte_count: header.total_byte_count, @@ -369,7 +369,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } drtioaux::Packet::AnalyzerDataRequest { destination: _destination } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let mut data_slice: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let meta = analyzer.get_data(&mut data_slice); drtioaux::send(0, &drtioaux::Packet::AnalyzerData { @@ -380,7 +380,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } drtioaux::Packet::DmaAddTraceRequest { source, destination, id, status, length, trace } => { - forward!(_routing_table, destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, destination, *rank, *self_destination, _repeaters, &packet); *self_destination = destination; let succeeded = dmamgr.add(source, id, status, &trace, length as usize).is_ok(); router.send(drtioaux::Packet::DmaAddTraceReply { @@ -388,19 +388,19 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg }, _routing_table, *rank, *self_destination) } drtioaux::Packet::DmaAddTraceReply { source, destination: _destination, id, succeeded } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); dmamgr.ack_upload(kernelmgr, source, id, succeeded, router, *rank, *self_destination, _routing_table); Ok(()) } drtioaux::Packet::DmaRemoveTraceRequest { source, destination: _destination, id } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let succeeded = dmamgr.erase(source, id).is_ok(); router.send(drtioaux::Packet::DmaRemoveTraceReply { destination: source, succeeded: succeeded }, _routing_table, *rank, *self_destination) } drtioaux::Packet::DmaPlaybackRequest { source, destination: _destination, id, timestamp } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); // no DMA with a running kernel let succeeded = !kernelmgr.is_running() && dmamgr.playback(source, id, timestamp).is_ok(); router.send(drtioaux::Packet::DmaPlaybackReply { @@ -408,27 +408,27 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg }, _routing_table, *rank, *self_destination) } drtioaux::Packet::DmaPlaybackReply { destination: _destination, succeeded } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); if !succeeded { kernelmgr.ddma_nack(); } Ok(()) } drtioaux::Packet::DmaPlaybackStatus { source: _, destination: _destination, id, error, channel, timestamp } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); dmamgr.remote_finished(kernelmgr, id, error, channel, timestamp); Ok(()) } drtioaux::Packet::SubkernelAddDataRequest { destination, id, status, length, data } => { - forward!(_routing_table, destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, destination, *rank, *self_destination, _repeaters, &packet); *self_destination = destination; let succeeded = kernelmgr.add(id, status, &data, length as usize).is_ok(); drtioaux::send(0, &drtioaux::Packet::SubkernelAddDataReply { succeeded: succeeded }) } drtioaux::Packet::SubkernelLoadRunRequest { source, destination: _destination, id, run } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let mut succeeded = kernelmgr.load(id).is_ok(); // allow preloading a kernel with delayed run if run { @@ -445,18 +445,18 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg _routing_table, *rank, *self_destination) } drtioaux::Packet::SubkernelLoadRunReply { destination: _destination, succeeded } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); // received if local subkernel started another, remote subkernel kernelmgr.subkernel_load_run_reply(succeeded, *self_destination); Ok(()) } drtioaux::Packet::SubkernelFinished { destination: _destination, id, with_exception, exception_src } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); kernelmgr.remote_subkernel_finished(id, with_exception, exception_src); Ok(()) } drtioaux::Packet::SubkernelExceptionRequest { destination: _destination } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let mut data_slice: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let meta = kernelmgr.exception_get_slice(&mut data_slice); drtioaux::send(0, &drtioaux::Packet::SubkernelException { @@ -466,14 +466,14 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg }) } drtioaux::Packet::SubkernelMessage { source, destination: _destination, id, status, length, data } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); kernelmgr.message_handle_incoming(status, length as usize, id, &data); router.send(drtioaux::Packet::SubkernelMessageAck { destination: source }, _routing_table, *rank, *self_destination) } drtioaux::Packet::SubkernelMessageAck { destination: _destination } => { - forward!(_routing_table, _destination, *rank, _repeaters, &packet); + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); if kernelmgr.message_ack_slice() { let mut data_slice: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; if let Some(meta) = kernelmgr.message_get_slice(&mut data_slice) { diff --git a/artiq/firmware/satman/repeater.rs b/artiq/firmware/satman/repeater.rs index 7617e0e98..68407abca 100644 --- a/artiq/firmware/satman/repeater.rs +++ b/artiq/firmware/satman/repeater.rs @@ -186,10 +186,31 @@ impl Repeater { } } - pub fn aux_forward(&self, request: &drtioaux::Packet) -> Result<(), drtioaux::Error> { + pub fn aux_forward(&self, request: &drtioaux::Packet, router: &mut Router, + routing_table: &drtio_routing::RoutingTable, rank: u8, + self_destination: u8) -> Result<(), drtioaux::Error> { self.aux_send(request)?; - let reply = self.recv_aux_timeout(200)?; - drtioaux::send(0, &reply).unwrap(); + loop { + let reply = self.recv_aux_timeout(200)?; + match reply { + // async/locally requested packets to be consumed or routed + // these may come while a packet would be forwarded + drtioaux::Packet::DmaPlaybackStatus { .. } | + drtioaux::Packet::SubkernelFinished { .. } | + drtioaux::Packet::SubkernelMessage { .. } | + drtioaux::Packet::SubkernelMessageAck { .. } | + drtioaux::Packet::SubkernelLoadRunReply { .. } | + drtioaux::Packet::SubkernelException { .. } | + drtioaux::Packet::DmaAddTraceReply { .. } | + drtioaux::Packet::DmaPlaybackReply { .. } => { + router.route(reply, routing_table, rank, self_destination); + } + _ => { + drtioaux::send(0, &reply).unwrap(); + break; + } + } + } Ok(()) }