From f1ef0219c3499cf4d8d641d0940ccbdd1bb2d8a5 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Thu, 23 Mar 2023 17:13:34 +0800 Subject: [PATCH] rtio_mgt: implement ddma related functions add kernel messages --- src/runtime/src/kernel/dma.rs | 5 +- src/runtime/src/kernel/mod.rs | 16 ++++ src/runtime/src/rtio_mgt.rs | 139 +++++++++++++++++++--------------- 3 files changed, 99 insertions(+), 61 deletions(-) diff --git a/src/runtime/src/kernel/dma.rs b/src/runtime/src/kernel/dma.rs index ed3d492..63b8318 100644 --- a/src/runtime/src/kernel/dma.rs +++ b/src/runtime/src/kernel/dma.rs @@ -17,6 +17,7 @@ pub struct DmaRecorder { pub name: String, pub buffer: Vec, pub duration: i64, + pub enable_ddma: bool } static mut RECORDER: Option = None; @@ -50,11 +51,12 @@ pub extern "C" fn dma_record_start(name: CSlice) { name, buffer: Vec::new(), duration: 0, + enable_ddma: false }); } } -pub extern "C" fn dma_record_stop(duration: i64) { +pub extern "C" fn dma_record_stop(duration: i64, enable_ddma: bool) { unsafe { if RECORDER.is_none() { artiq_raise!("DMAError", "DMA is not recording") @@ -68,6 +70,7 @@ pub extern "C" fn dma_record_stop(duration: i64) { let mut recorder = RECORDER.take().unwrap(); recorder.duration = duration; + recorder.enable_ddma = enable_ddma; KERNEL_CHANNEL_1TO0 .as_mut() .unwrap() diff --git a/src/runtime/src/kernel/mod.rs b/src/runtime/src/kernel/mod.rs index 4e00888..883c615 100644 --- a/src/runtime/src/kernel/mod.rs +++ b/src/runtime/src/kernel/mod.rs @@ -53,6 +53,22 @@ pub enum Message { DmaEraseRequest(String), DmaGetRequest(String), DmaGetReply(Option<(i32, i64)>), + #[cfg(has_drtio)] + DmaStartRemoteRequest { + id: i32, + timestamp: i64 + }, + #[cfg(has_drtio)] + DmaAwaitRemoteRequest { + id: i32 + }, + #[cfg(has_drtio)] + DmaAwaitRemoteReply { + timeout: bool, + error: u8, + channel: u32, + timestamp: u64 + }, #[cfg(has_drtio)] UpDestinationsRequest(i32), diff --git a/src/runtime/src/rtio_mgt.rs b/src/runtime/src/rtio_mgt.rs index 315ab73..683b581 100644 --- a/src/runtime/src/rtio_mgt.rs +++ b/src/runtime/src/rtio_mgt.rs @@ -13,13 +13,16 @@ static mut RTIO_DEVICE_MAP: BTreeMap = BTreeMap::new(); #[cfg(has_drtio)] pub mod drtio { use embedded_hal::blocking::delay::DelayMs; + use alloc::vec::Vec; use libasync::{delay, task}; use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet}; + use libboard_artiq::drtioaux_proto::DMA_TRACE_MAX_SIZE; use libboard_zynq::time::Milliseconds; use log::{error, info, warn}; use super::*; use crate::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS}; + use crate::rtio_dma::remote_dma; pub fn startup( aux_mutex: &Rc>, @@ -390,69 +393,85 @@ pub mod drtio { } } - // pub fn ddma_upload_trace(aux_mutex: Rc>, - // routing_table: &drtio_routing::RoutingTable, - // id: u32, destination: u8, trace: &Vec) -> Result<(), &'static str> { - // let linkno = routing_table.0[destination as usize][0] - 1; - // let mut i = 0; - // while i < trace.len() { - // let mut trace_slice: [u8; DMA_TRACE_MAX_SIZE] = [0; DMA_TRACE_MAX_SIZE]; - // let len: usize = if i + DMA_TRACE_MAX_SIZE < trace.len() { DMA_TRACE_MAX_SIZE } else { trace.len() - i } as usize; - // let last = i + len == trace.len(); - // trace_slice[..len].clone_from_slice(&trace[i..i+len]); - // i += len; - // let reply = aux_transact(io, aux_mutex, linkno, - // &drtioaux::Packet::DmaAddTraceRequest { - // id: id, destination: destination, last: last, length: len as u16, trace: trace_slice}); - // match reply { - // Ok(drtioaux::Packet::DmaAddTraceReply { succeeded: true }) => (), - // Ok(drtioaux::Packet::DmaAddTraceReply { succeeded: false }) => { - // return Err("error adding trace on satellite"); }, - // Ok(_) => { return Err("adding DMA trace failed, unexpected aux packet"); }, - // Err(_) => { return Err("adding DMA trace failed, aux error"); } - // } - // } - // Ok(()) - // } + pub async fn ddma_upload_trace( + aux_mutex: &Rc>, + routing_table: &drtio_routing::RoutingTable, + timer: GlobalTimer, + id: u32, + destination: u8, + trace: &Vec + ) -> Result<(), &'static str> { + let linkno = routing_table.0[destination as usize][0] - 1; + let mut i = 0; + while i < trace.len() { + let mut trace_slice: [u8; DMA_TRACE_MAX_SIZE] = [0; DMA_TRACE_MAX_SIZE]; + let len: usize = if i + DMA_TRACE_MAX_SIZE < trace.len() { DMA_TRACE_MAX_SIZE } else { trace.len() - i } as usize; + let last = i + len == trace.len(); + trace_slice[..len].clone_from_slice(&trace[i..i+len]); + i += len; + let reply = aux_transact(aux_mutex, linkno, + &Packet::DmaAddTraceRequest { + id: id, destination: destination, last: last, length: len as u16, trace: trace_slice}, + timer).await; + match reply { + Ok(Packet::DmaAddTraceReply { succeeded: true }) => (), + Ok(Packet::DmaAddTraceReply { succeeded: false }) => { + return Err("error adding trace on satellite"); }, + Ok(_) => { return Err("adding DMA trace failed, unexpected aux packet"); }, + Err(_) => { return Err("adding DMA trace failed, aux error"); } + } + } + Ok(()) + } - // pub fn ddma_send_erase(io: &Io, aux_mutex: &Mutex, - // routing_table: &drtio_routing::RoutingTable, - // id: u32, destination: u8) -> Result<(), &'static str> { - // let linkno = routing_table.0[destination as usize][0] - 1; - // let reply = aux_transact(io, aux_mutex, linkno, - // &drtioaux::Packet::DmaRemoveTraceRequest { id: id, destination: destination }); - // match reply { - // Ok(drtioaux::Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()), - // Ok(drtioaux::Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"), - // Ok(_) => Err("adding trace failed, unexpected aux packet"), - // Err(_) => Err("erasing trace failed, aux error") - // } - // } + pub async fn ddma_send_erase( + aux_mutex: &Rc>, + routing_table: &drtio_routing::RoutingTable, + timer: GlobalTimer, + id: u32, + destination: u8 + ) -> Result<(), &'static str> { + let linkno = routing_table.0[destination as usize][0] - 1; + let reply = aux_transact(aux_mutex, linkno, + &Packet::DmaRemoveTraceRequest { id: id, destination: destination }, + timer).await; + match reply { + Ok(Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()), + Ok(Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"), + Ok(_) => Err("adding trace failed, unexpected aux packet"), + Err(_) => Err("erasing trace failed, aux error") + } + } - // pub fn ddma_send_playback(io: &Io, aux_mutex: &Mutex, - // routing_table: &drtio_routing::RoutingTable, - // ddma_mutex: &Mutex, id: u32, destination: u8, timestamp: u64) -> Result<(), &'static str> { - // let linkno = routing_table.0[destination as usize][0] - 1; - // let _lock = aux_mutex.lock(io).unwrap(); - // drtioaux::send(linkno, &drtioaux::Packet::DmaPlaybackRequest{ - // id: id, destination: destination, timestamp: timestamp }).unwrap(); - // loop { - // let reply = recv_aux_timeout(io, linkno, 200); - // match reply { - // Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: true }) => { return Ok(()) }, - // Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: false }) => { - // return Err("error on DMA playback request") }, - // // in case we received status from another destination - // // but we want to get DmaPlaybackReply anyway, thus the loop - // Ok(drtioaux::Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) => { - // remote_dma::playback_done(io, ddma_mutex, id, destination, error, channel, timestamp); - // }, - // Ok(_) => { return Err("received unexpected aux packet while DMA playback") }, - // Err(_) => { return Err("aux error on DMA playback") } - // } - // } - // } + pub async fn ddma_send_playback( + aux_mutex: &Rc>, + routing_table: &drtio_routing::RoutingTable, + timer: GlobalTimer, + id: u32, + destination: u8, + timestamp: u64 + ) -> Result<(), &'static str> { + let linkno = routing_table.0[destination as usize][0] - 1; + let _lock = aux_mutex.async_lock().await; + drtioaux_async::send(linkno, &Packet::DmaPlaybackRequest{ + id: id, destination: destination, timestamp: timestamp }).await.unwrap(); + loop { + let reply = recv_aux_timeout(linkno, 200, timer).await; + match reply { + Ok(Packet::DmaPlaybackReply { succeeded: true }) => { return Ok(()) }, + Ok(Packet::DmaPlaybackReply { succeeded: false }) => { + return Err("error on DMA playback request") }, + // in case we received status from another destination + // but we want to get DmaPlaybackReply anyway, thus the loop + Ok(Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) => { + remote_dma::playback_done(id, destination, error, channel, timestamp).await; + }, + Ok(_) => { return Err("received unexpected aux packet while DMA playback") }, + Err(_) => { return Err("aux error on DMA playback") } + } + } + } } fn read_device_map(cfg: &Config) -> BTreeMap {