forked from M-Labs/nac3
apply rustfmt policies to ddma code
This commit is contained in:
parent
90071f7620
commit
48721ca9cb
|
@ -141,32 +141,32 @@ pub enum Packet {
|
||||||
id: u32,
|
id: u32,
|
||||||
last: bool,
|
last: bool,
|
||||||
length: u16,
|
length: u16,
|
||||||
trace: [u8; DMA_TRACE_MAX_SIZE]
|
trace: [u8; DMA_TRACE_MAX_SIZE],
|
||||||
},
|
},
|
||||||
DmaAddTraceReply {
|
DmaAddTraceReply {
|
||||||
succeeded: bool
|
succeeded: bool,
|
||||||
},
|
},
|
||||||
DmaRemoveTraceRequest {
|
DmaRemoveTraceRequest {
|
||||||
destination: u8,
|
destination: u8,
|
||||||
id: u32
|
id: u32,
|
||||||
},
|
},
|
||||||
DmaRemoveTraceReply {
|
DmaRemoveTraceReply {
|
||||||
succeeded: bool
|
succeeded: bool,
|
||||||
},
|
},
|
||||||
DmaPlaybackRequest {
|
DmaPlaybackRequest {
|
||||||
destination: u8,
|
destination: u8,
|
||||||
id: u32,
|
id: u32,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
},
|
},
|
||||||
DmaPlaybackReply {
|
DmaPlaybackReply {
|
||||||
succeeded: bool
|
succeeded: bool,
|
||||||
},
|
},
|
||||||
DmaPlaybackStatus {
|
DmaPlaybackStatus {
|
||||||
destination: u8,
|
destination: u8,
|
||||||
id: u32,
|
id: u32,
|
||||||
error: u8,
|
error: u8,
|
||||||
channel: u32,
|
channel: u32,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,31 +312,31 @@ impl Packet {
|
||||||
length: length as u16,
|
length: length as u16,
|
||||||
trace: trace,
|
trace: trace,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
0xb1 => Packet::DmaAddTraceReply {
|
0xb1 => Packet::DmaAddTraceReply {
|
||||||
succeeded: reader.read_bool()?
|
succeeded: reader.read_bool()?,
|
||||||
},
|
},
|
||||||
0xb2 => Packet::DmaRemoveTraceRequest {
|
0xb2 => Packet::DmaRemoveTraceRequest {
|
||||||
destination: reader.read_u8()?,
|
destination: reader.read_u8()?,
|
||||||
id: reader.read_u32()?
|
id: reader.read_u32()?,
|
||||||
},
|
},
|
||||||
0xb3 => Packet::DmaRemoveTraceReply {
|
0xb3 => Packet::DmaRemoveTraceReply {
|
||||||
succeeded: reader.read_bool()?
|
succeeded: reader.read_bool()?,
|
||||||
},
|
},
|
||||||
0xb4 => Packet::DmaPlaybackRequest {
|
0xb4 => Packet::DmaPlaybackRequest {
|
||||||
destination: reader.read_u8()?,
|
destination: reader.read_u8()?,
|
||||||
id: reader.read_u32()?,
|
id: reader.read_u32()?,
|
||||||
timestamp: reader.read_u64()?
|
timestamp: reader.read_u64()?,
|
||||||
},
|
},
|
||||||
0xb5 => Packet::DmaPlaybackReply {
|
0xb5 => Packet::DmaPlaybackReply {
|
||||||
succeeded: reader.read_bool()?
|
succeeded: reader.read_bool()?,
|
||||||
},
|
},
|
||||||
0xb6 => Packet::DmaPlaybackStatus {
|
0xb6 => Packet::DmaPlaybackStatus {
|
||||||
destination: reader.read_u8()?,
|
destination: reader.read_u8()?,
|
||||||
id: reader.read_u32()?,
|
id: reader.read_u32()?,
|
||||||
error: reader.read_u8()?,
|
error: reader.read_u8()?,
|
||||||
channel: reader.read_u32()?,
|
channel: reader.read_u32()?,
|
||||||
timestamp: reader.read_u64()?
|
timestamp: reader.read_u64()?,
|
||||||
},
|
},
|
||||||
|
|
||||||
ty => return Err(Error::UnknownPacket(ty)),
|
ty => return Err(Error::UnknownPacket(ty)),
|
||||||
|
@ -531,7 +531,7 @@ impl Packet {
|
||||||
id,
|
id,
|
||||||
last,
|
last,
|
||||||
trace,
|
trace,
|
||||||
length
|
length,
|
||||||
} => {
|
} => {
|
||||||
writer.write_u8(0xb0)?;
|
writer.write_u8(0xb0)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
|
@ -558,7 +558,7 @@ impl Packet {
|
||||||
Packet::DmaPlaybackRequest {
|
Packet::DmaPlaybackRequest {
|
||||||
destination,
|
destination,
|
||||||
id,
|
id,
|
||||||
timestamp
|
timestamp,
|
||||||
} => {
|
} => {
|
||||||
writer.write_u8(0xb4)?;
|
writer.write_u8(0xb4)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
|
@ -574,7 +574,7 @@ impl Packet {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
channel,
|
channel,
|
||||||
timestamp
|
timestamp,
|
||||||
} => {
|
} => {
|
||||||
writer.write_u8(0xb6)?;
|
writer.write_u8(0xb6)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
|
|
|
@ -26,9 +26,8 @@ use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
use crate::pl;
|
use crate::pl;
|
||||||
use crate::{analyzer, kernel, mgmt, moninj,
|
use crate::{analyzer, kernel, mgmt, moninj,
|
||||||
proto_async::*,
|
proto_async::*,
|
||||||
rpc,
|
rpc, rtio_dma,
|
||||||
rtio_mgt::{self, resolve_channel_name},
|
rtio_mgt::{self, resolve_channel_name}};
|
||||||
rtio_dma};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -81,7 +80,6 @@ enum Reply {
|
||||||
|
|
||||||
static CACHE_STORE: Mutex<BTreeMap<String, Vec<i32>>> = Mutex::new(BTreeMap::new());
|
static CACHE_STORE: Mutex<BTreeMap<String, Vec<i32>>> = Mutex::new(BTreeMap::new());
|
||||||
|
|
||||||
|
|
||||||
async fn write_header(stream: &TcpStream, reply: Reply) -> Result<()> {
|
async fn write_header(stream: &TcpStream, reply: Reply) -> Result<()> {
|
||||||
stream
|
stream
|
||||||
.send_slice(&[0x5a, 0x5a, 0x5a, 0x5a, reply.to_u8().unwrap()])
|
.send_slice(&[0x5a, 0x5a, 0x5a, 0x5a, reply.to_u8().unwrap()])
|
||||||
|
@ -160,7 +158,7 @@ async fn handle_run_kernel(
|
||||||
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &drtio_routing::RoutingTable,
|
routing_table: &drtio_routing::RoutingTable,
|
||||||
timer: GlobalTimer
|
timer: GlobalTimer,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await;
|
control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await;
|
||||||
loop {
|
loop {
|
||||||
|
@ -350,19 +348,19 @@ async fn handle_run_kernel(
|
||||||
Ok(rtio_dma::remote_dma::RemoteState::PlaybackEnded {
|
Ok(rtio_dma::remote_dma::RemoteState::PlaybackEnded {
|
||||||
error,
|
error,
|
||||||
channel,
|
channel,
|
||||||
timestamp
|
timestamp,
|
||||||
}) => kernel::Message::DmaAwaitRemoteReply {
|
}) => kernel::Message::DmaAwaitRemoteReply {
|
||||||
timeout: false,
|
timeout: false,
|
||||||
error: error,
|
error: error,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
timestamp: timestamp
|
timestamp: timestamp,
|
||||||
},
|
},
|
||||||
_ => kernel::Message::DmaAwaitRemoteReply {
|
_ => kernel::Message::DmaAwaitRemoteReply {
|
||||||
timeout: true,
|
timeout: true,
|
||||||
error: 0,
|
error: 0,
|
||||||
channel: 0,
|
channel: 0,
|
||||||
timestamp: 0
|
timestamp: 0,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
control.borrow_mut().tx.async_send(reply).await;
|
control.borrow_mut().tx.async_send(reply).await;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +426,7 @@ async fn handle_connection(
|
||||||
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &drtio_routing::RoutingTable,
|
routing_table: &drtio_routing::RoutingTable,
|
||||||
timer: GlobalTimer
|
timer: GlobalTimer,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
stream.set_ack_delay(None);
|
stream.set_ack_delay(None);
|
||||||
|
|
||||||
|
@ -452,7 +450,15 @@ async fn handle_connection(
|
||||||
load_kernel(&buffer, &control, Some(stream)).await?;
|
load_kernel(&buffer, &control, Some(stream)).await?;
|
||||||
}
|
}
|
||||||
Request::RunKernel => {
|
Request::RunKernel => {
|
||||||
handle_run_kernel(Some(stream), &control, &up_destinations, aux_mutex, routing_table, timer).await?;
|
handle_run_kernel(
|
||||||
|
Some(stream),
|
||||||
|
&control,
|
||||||
|
&up_destinations,
|
||||||
|
aux_mutex,
|
||||||
|
routing_table,
|
||||||
|
timer,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error!("unexpected request from host: {:?}", request);
|
error!("unexpected request from host: {:?}", request);
|
||||||
|
@ -528,7 +534,14 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||||
if let Ok(()) = task::block_on(load_kernel(&buffer, &control, None)) {
|
if let Ok(()) = task::block_on(load_kernel(&buffer, &control, None)) {
|
||||||
info!("Starting startup kernel...");
|
info!("Starting startup kernel...");
|
||||||
let routing_table = drtio_routing_table.borrow();
|
let routing_table = drtio_routing_table.borrow();
|
||||||
let _ = task::block_on(handle_run_kernel(None, &control, &up_destinations, &aux_mutex, &routing_table, timer));
|
let _ = task::block_on(handle_run_kernel(
|
||||||
|
None,
|
||||||
|
&control,
|
||||||
|
&up_destinations,
|
||||||
|
&aux_mutex,
|
||||||
|
&routing_table,
|
||||||
|
timer,
|
||||||
|
));
|
||||||
info!("Startup kernel finished!");
|
info!("Startup kernel finished!");
|
||||||
} else {
|
} else {
|
||||||
error!("Error loading startup kernel!");
|
error!("Error loading startup kernel!");
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct DmaRecorder {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub buffer: Vec<u8>,
|
pub buffer: Vec<u8>,
|
||||||
pub duration: i64,
|
pub duration: i64,
|
||||||
pub enable_ddma: bool
|
pub enable_ddma: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut RECORDER: Option<DmaRecorder> = None;
|
static mut RECORDER: Option<DmaRecorder> = None;
|
||||||
|
@ -51,7 +51,7 @@ pub extern "C" fn dma_record_start(name: CSlice<u8>) {
|
||||||
name,
|
name,
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
enable_ddma: false
|
enable_ddma: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,8 +168,13 @@ pub extern "C" fn dma_playback(timestamp: i64, ptr: i32) {
|
||||||
csr::cri_con::selected_write(1);
|
csr::cri_con::selected_write(1);
|
||||||
csr::rtio_dma::enable_write(1);
|
csr::rtio_dma::enable_write(1);
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(
|
KERNEL_CHANNEL_1TO0
|
||||||
Message::DmaStartRemoteRequest{ id: ptr, timestamp: timestamp });
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.send(Message::DmaStartRemoteRequest {
|
||||||
|
id: ptr,
|
||||||
|
timestamp: timestamp,
|
||||||
|
});
|
||||||
while csr::rtio_dma::enable_read() != 0 {}
|
while csr::rtio_dma::enable_read() != 0 {}
|
||||||
csr::cri_con::selected_write(0);
|
csr::cri_con::selected_write(0);
|
||||||
|
|
||||||
|
@ -199,10 +204,17 @@ pub extern "C" fn dma_playback(timestamp: i64, ptr: i32) {
|
||||||
}
|
}
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
{
|
{
|
||||||
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(
|
KERNEL_CHANNEL_1TO0
|
||||||
Message::DmaAwaitRemoteRequest(ptr));
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.send(Message::DmaAwaitRemoteRequest(ptr));
|
||||||
match KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv() {
|
match KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv() {
|
||||||
Message::DmaAwaitRemoteReply { timeout, error, channel, timestamp } => {
|
Message::DmaAwaitRemoteReply {
|
||||||
|
timeout,
|
||||||
|
error,
|
||||||
|
channel,
|
||||||
|
timestamp,
|
||||||
|
} => {
|
||||||
if timeout {
|
if timeout {
|
||||||
artiq_raise!(
|
artiq_raise!(
|
||||||
"DMAError",
|
"DMAError",
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub enum Message {
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
DmaStartRemoteRequest {
|
DmaStartRemoteRequest {
|
||||||
id: i32,
|
id: i32,
|
||||||
timestamp: i64
|
timestamp: i64,
|
||||||
},
|
},
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
DmaAwaitRemoteRequest(i32),
|
DmaAwaitRemoteRequest(i32),
|
||||||
|
@ -65,7 +65,7 @@ pub enum Message {
|
||||||
timeout: bool,
|
timeout: bool,
|
||||||
error: u8,
|
error: u8,
|
||||||
channel: u32,
|
channel: u32,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
|
|
|
@ -46,8 +46,8 @@ mod rtio;
|
||||||
#[path = "rtio_acp.rs"]
|
#[path = "rtio_acp.rs"]
|
||||||
mod rtio;
|
mod rtio;
|
||||||
mod rtio_clocking;
|
mod rtio_clocking;
|
||||||
mod rtio_mgt;
|
|
||||||
mod rtio_dma;
|
mod rtio_dma;
|
||||||
|
mod rtio_mgt;
|
||||||
|
|
||||||
static mut SEEN_ASYNC_ERRORS: u8 = 0;
|
static mut SEEN_ASYNC_ERRORS: u8 = 0;
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,11 @@ async fn handle_connection(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(timer: GlobalTimer, aux_mutex: &Rc<Mutex<bool>>, routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>) {
|
pub fn start(
|
||||||
|
timer: GlobalTimer,
|
||||||
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
|
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
|
||||||
|
) {
|
||||||
let aux_mutex = aux_mutex.clone();
|
let aux_mutex = aux_mutex.clone();
|
||||||
let routing_table = routing_table.clone();
|
let routing_table = routing_table.clone();
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec};
|
||||||
use alloc::{collections::BTreeMap, string::String, vec::Vec, rc::Rc};
|
|
||||||
use libcortex_a9::{mutex::Mutex, cache::dcci_slice};
|
|
||||||
use libboard_zynq::timer::GlobalTimer;
|
|
||||||
use libboard_artiq::drtio_routing::RoutingTable;
|
|
||||||
#[cfg(has_drtio)]
|
|
||||||
use libasync::task;
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
use libasync::task;
|
||||||
|
use libboard_artiq::drtio_routing::RoutingTable;
|
||||||
|
use libboard_zynq::timer::GlobalTimer;
|
||||||
|
use libcortex_a9::{cache::dcci_slice, mutex::Mutex};
|
||||||
|
|
||||||
use crate::kernel::DmaRecorder;
|
use crate::kernel::DmaRecorder;
|
||||||
|
|
||||||
const ALIGNMENT: usize = 16 * 8;
|
const ALIGNMENT: usize = 16 * 8;
|
||||||
|
@ -15,28 +16,29 @@ static DMA_RECORD_STORE: Mutex<BTreeMap<String, (u32, Vec<u8>, i64)>> = Mutex::n
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
pub mod remote_dma {
|
pub mod remote_dma {
|
||||||
use super::*;
|
|
||||||
use libboard_zynq::time::Milliseconds;
|
use libboard_zynq::time::Milliseconds;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::rtio_mgt::drtio;
|
use crate::rtio_mgt::drtio;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum RemoteState {
|
pub enum RemoteState {
|
||||||
NotLoaded,
|
NotLoaded,
|
||||||
Loaded,
|
Loaded,
|
||||||
PlaybackEnded { error: u8, channel: u32, timestamp: u64 }
|
PlaybackEnded { error: u8, channel: u32, timestamp: u64 },
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct RemoteTrace {
|
struct RemoteTrace {
|
||||||
trace: Vec<u8>,
|
trace: Vec<u8>,
|
||||||
pub state: RemoteState
|
pub state: RemoteState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for RemoteTrace {
|
impl From<Vec<u8>> for RemoteTrace {
|
||||||
fn from(trace: Vec<u8>) -> Self {
|
fn from(trace: Vec<u8>) -> Self {
|
||||||
RemoteTrace {
|
RemoteTrace {
|
||||||
trace: trace,
|
trace: trace,
|
||||||
state: RemoteState::NotLoaded
|
state: RemoteState::NotLoaded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +53,7 @@ pub mod remote_dma {
|
||||||
struct TraceSet {
|
struct TraceSet {
|
||||||
id: u32,
|
id: u32,
|
||||||
done_count: Mutex<usize>,
|
done_count: Mutex<usize>,
|
||||||
traces: Mutex<BTreeMap<u8, RemoteTrace>>
|
traces: Mutex<BTreeMap<u8, RemoteTrace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraceSet {
|
impl TraceSet {
|
||||||
|
@ -63,26 +65,27 @@ pub mod remote_dma {
|
||||||
TraceSet {
|
TraceSet {
|
||||||
id: id,
|
id: id,
|
||||||
done_count: Mutex::new(0),
|
done_count: Mutex::new(0),
|
||||||
traces: Mutex::new(trace_map)
|
traces: Mutex::new(trace_map),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn await_done(
|
pub async fn await_done(&self, timeout: Option<u64>, timer: GlobalTimer) -> Result<RemoteState, &'static str> {
|
||||||
&self,
|
|
||||||
timeout: Option<u64>,
|
|
||||||
timer: GlobalTimer
|
|
||||||
) -> Result<RemoteState, &'static str> {
|
|
||||||
let timeout_ms = Milliseconds(timeout.unwrap_or(10_000));
|
let timeout_ms = Milliseconds(timeout.unwrap_or(10_000));
|
||||||
let limit = timer.get_time() + timeout_ms;
|
let limit = timer.get_time() + timeout_ms;
|
||||||
while (timer.get_time() < limit) &
|
while (timer.get_time() < limit)
|
||||||
(*(self.done_count.async_lock().await) < self.traces.async_lock().await.len()) {
|
& (*(self.done_count.async_lock().await) < self.traces.async_lock().await.len())
|
||||||
|
{
|
||||||
task::r#yield().await;
|
task::r#yield().await;
|
||||||
}
|
}
|
||||||
if timer.get_time() >= limit {
|
if timer.get_time() >= limit {
|
||||||
error!("Remote DMA await done timed out");
|
error!("Remote DMA await done timed out");
|
||||||
return Err("Timed out waiting for results.");
|
return Err("Timed out waiting for results.");
|
||||||
}
|
}
|
||||||
let mut playback_state: RemoteState = RemoteState::PlaybackEnded { error: 0, channel: 0, timestamp: 0 };
|
let mut playback_state: RemoteState = RemoteState::PlaybackEnded {
|
||||||
|
error: 0,
|
||||||
|
channel: 0,
|
||||||
|
timestamp: 0,
|
||||||
|
};
|
||||||
let mut lock = self.traces.async_lock().await;
|
let mut lock = self.traces.async_lock().await;
|
||||||
let trace_iter = lock.iter_mut();
|
let trace_iter = lock.iter_mut();
|
||||||
for (_dest, trace) in trace_iter {
|
for (_dest, trace) in trace_iter {
|
||||||
|
@ -90,8 +93,12 @@ pub mod remote_dma {
|
||||||
RemoteState::PlaybackEnded {
|
RemoteState::PlaybackEnded {
|
||||||
error: e,
|
error: e,
|
||||||
channel: _c,
|
channel: _c,
|
||||||
timestamp: _ts
|
timestamp: _ts,
|
||||||
} => if e != 0 { playback_state = trace.state.clone(); },
|
} => {
|
||||||
|
if e != 0 {
|
||||||
|
playback_state = trace.state.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
trace.state = RemoteState::Loaded;
|
trace.state = RemoteState::Loaded;
|
||||||
|
@ -103,44 +110,35 @@ pub mod remote_dma {
|
||||||
&mut self,
|
&mut self,
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer
|
timer: GlobalTimer,
|
||||||
) {
|
) {
|
||||||
let mut lock = self.traces.async_lock().await;
|
let mut lock = self.traces.async_lock().await;
|
||||||
let trace_iter = lock.iter_mut();
|
let trace_iter = lock.iter_mut();
|
||||||
for (destination, trace) in trace_iter {
|
for (destination, trace) in trace_iter {
|
||||||
match drtio::ddma_upload_trace(
|
match drtio::ddma_upload_trace(
|
||||||
aux_mutex,
|
aux_mutex,
|
||||||
routing_table,
|
routing_table,
|
||||||
timer,
|
timer,
|
||||||
self.id,
|
self.id,
|
||||||
*destination,
|
*destination,
|
||||||
trace.get_trace()
|
trace.get_trace(),
|
||||||
).await {
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(_) => trace.state = RemoteState::Loaded,
|
Ok(_) => trace.state = RemoteState::Loaded,
|
||||||
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e)
|
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(self.done_count.async_lock().await) = 0;
|
*(self.done_count.async_lock().await) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn erase(
|
pub async fn erase(&mut self, aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
|
||||||
&mut self,
|
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
|
||||||
routing_table: &RoutingTable,
|
|
||||||
timer: GlobalTimer
|
|
||||||
) {
|
|
||||||
let lock = self.traces.async_lock().await;
|
let lock = self.traces.async_lock().await;
|
||||||
let trace_iter = lock.keys();
|
let trace_iter = lock.keys();
|
||||||
for destination in trace_iter {
|
for destination in trace_iter {
|
||||||
match drtio::ddma_send_erase(
|
match drtio::ddma_send_erase(aux_mutex, routing_table, timer, self.id, *destination).await {
|
||||||
aux_mutex,
|
|
||||||
routing_table,
|
|
||||||
timer,
|
|
||||||
self.id,
|
|
||||||
*destination
|
|
||||||
).await {
|
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e)
|
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +149,7 @@ pub mod remote_dma {
|
||||||
trace.state = RemoteState::PlaybackEnded {
|
trace.state = RemoteState::PlaybackEnded {
|
||||||
error: error,
|
error: error,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
timestamp: timestamp
|
timestamp: timestamp,
|
||||||
};
|
};
|
||||||
*(self.done_count.async_lock().await) += 1;
|
*(self.done_count.async_lock().await) += 1;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +159,7 @@ pub mod remote_dma {
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
) {
|
) {
|
||||||
let mut dest_list: Vec<u8> = Vec::new();
|
let mut dest_list: Vec<u8> = Vec::new();
|
||||||
{
|
{
|
||||||
|
@ -178,16 +176,10 @@ pub mod remote_dma {
|
||||||
// mutex lock must be dropped before sending a playback request to avoid a deadlock,
|
// mutex lock must be dropped before sending a playback request to avoid a deadlock,
|
||||||
// if PlaybackStatus is sent from another satellite and the state must be updated.
|
// if PlaybackStatus is sent from another satellite and the state must be updated.
|
||||||
for destination in dest_list {
|
for destination in dest_list {
|
||||||
match drtio::ddma_send_playback(
|
match drtio::ddma_send_playback(aux_mutex, routing_table, timer, self.id, destination, timestamp).await
|
||||||
aux_mutex,
|
{
|
||||||
routing_table,
|
|
||||||
timer,
|
|
||||||
self.id,
|
|
||||||
destination,
|
|
||||||
timestamp
|
|
||||||
).await {
|
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => error!("Error during remote DMA playback: {}", e)
|
Err(e) => error!("Error during remote DMA playback: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +189,8 @@ pub mod remote_dma {
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
destination: u8, up: bool
|
destination: u8,
|
||||||
|
up: bool,
|
||||||
) {
|
) {
|
||||||
// update state of the destination, resend traces if it's up
|
// update state of the destination, resend traces if it's up
|
||||||
if let Some(trace) = self.traces.lock().get_mut(&destination) {
|
if let Some(trace) = self.traces.lock().get_mut(&destination) {
|
||||||
|
@ -208,10 +201,12 @@ pub mod remote_dma {
|
||||||
timer,
|
timer,
|
||||||
self.id,
|
self.id,
|
||||||
destination,
|
destination,
|
||||||
trace.get_trace()
|
trace.get_trace(),
|
||||||
).await {
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(_) => trace.state = RemoteState::Loaded,
|
Ok(_) => trace.state = RemoteState::Loaded,
|
||||||
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e)
|
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trace.state = RemoteState::NotLoaded;
|
trace.state = RemoteState::NotLoaded;
|
||||||
|
@ -226,32 +221,20 @@ pub mod remote_dma {
|
||||||
unsafe { TRACES.insert(id, TraceSet::new(id, traces)) };
|
unsafe { TRACES.insert(id, TraceSet::new(id, traces)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn await_done(
|
pub async fn await_done(id: u32, timeout: Option<u64>, timer: GlobalTimer) -> Result<RemoteState, &'static str> {
|
||||||
id: u32,
|
|
||||||
timeout: Option<u64>,
|
|
||||||
timer: GlobalTimer
|
|
||||||
) -> Result<RemoteState, &'static str> {
|
|
||||||
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
||||||
trace_set.await_done(timeout, timer).await
|
trace_set.await_done(timeout, timer).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn erase(
|
pub async fn erase(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer, id: u32) {
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
|
||||||
routing_table: &RoutingTable,
|
|
||||||
timer: GlobalTimer,
|
|
||||||
id: u32
|
|
||||||
) {
|
|
||||||
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
||||||
trace_set.erase(aux_mutex, routing_table, timer).await;
|
trace_set.erase(aux_mutex, routing_table, timer).await;
|
||||||
unsafe { TRACES.remove(&id); }
|
unsafe {
|
||||||
|
TRACES.remove(&id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upload_traces(
|
pub async fn upload_traces(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer, id: u32) {
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
|
||||||
routing_table: &RoutingTable,
|
|
||||||
timer: GlobalTimer,
|
|
||||||
id: u32
|
|
||||||
) {
|
|
||||||
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
||||||
trace_set.upload_traces(aux_mutex, routing_table, timer).await;
|
trace_set.upload_traces(aux_mutex, routing_table, timer).await;
|
||||||
}
|
}
|
||||||
|
@ -261,19 +244,13 @@ pub mod remote_dma {
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
id: u32,
|
id: u32,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
) {
|
) {
|
||||||
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
||||||
trace_set.playback(aux_mutex, routing_table, timer, timestamp).await;
|
trace_set.playback(aux_mutex, routing_table, timer, timestamp).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn playback_done(
|
pub async fn playback_done(id: u32, destination: u8, error: u8, channel: u32, timestamp: u64) {
|
||||||
id: u32,
|
|
||||||
destination: u8,
|
|
||||||
error: u8,
|
|
||||||
channel: u32,
|
|
||||||
timestamp: u64
|
|
||||||
) {
|
|
||||||
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
|
||||||
trace_set.playback_done(destination, error, channel, timestamp).await;
|
trace_set.playback_done(destination, error, channel, timestamp).await;
|
||||||
}
|
}
|
||||||
|
@ -283,17 +260,19 @@ pub mod remote_dma {
|
||||||
routing_table: &RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
up: bool
|
up: bool,
|
||||||
) {
|
) {
|
||||||
let trace_iter = unsafe { TRACES.values_mut() };
|
let trace_iter = unsafe { TRACES.values_mut() };
|
||||||
for trace_set in trace_iter {
|
for trace_set in trace_iter {
|
||||||
trace_set.destination_changed(aux_mutex, routing_table, timer, destination, up).await;
|
trace_set
|
||||||
|
.destination_changed(aux_mutex, routing_table, timer, destination, up)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn put_record(
|
||||||
pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
|
_aux_mutex: &Rc<Mutex<bool>>,
|
||||||
_routing_table: &RoutingTable,
|
_routing_table: &RoutingTable,
|
||||||
_timer: GlobalTimer,
|
_timer: GlobalTimer,
|
||||||
mut recorder: DmaRecorder,
|
mut recorder: DmaRecorder,
|
||||||
|
@ -312,15 +291,14 @@ pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
|
||||||
while recorder.buffer[ptr] != 0 {
|
while recorder.buffer[ptr] != 0 {
|
||||||
// ptr + 3 = tgt >> 24 (destination)
|
// ptr + 3 = tgt >> 24 (destination)
|
||||||
let len = recorder.buffer[ptr] as usize;
|
let len = recorder.buffer[ptr] as usize;
|
||||||
let destination = recorder.buffer[ptr+3];
|
let destination = recorder.buffer[ptr + 3];
|
||||||
if destination == 0 {
|
if destination == 0 {
|
||||||
local_trace.extend(&recorder.buffer[ptr..ptr+len]);
|
local_trace.extend(&recorder.buffer[ptr..ptr + len]);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if let Some(remote_trace) = remote_traces.get_mut(&destination) {
|
if let Some(remote_trace) = remote_traces.get_mut(&destination) {
|
||||||
remote_trace.extend(&recorder.buffer[ptr..ptr+len]);
|
remote_trace.extend(&recorder.buffer[ptr..ptr + len]);
|
||||||
} else {
|
} else {
|
||||||
remote_traces.insert(destination, recorder.buffer[ptr..ptr+len].to_vec());
|
remote_traces.insert(destination, recorder.buffer[ptr..ptr + len].to_vec());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// and jump to the next event
|
// and jump to the next event
|
||||||
|
@ -343,8 +321,8 @@ pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
|
||||||
let ptr = recorder.buffer[padding..].as_ptr() as u32;
|
let ptr = recorder.buffer[padding..].as_ptr() as u32;
|
||||||
|
|
||||||
let _old_record = DMA_RECORD_STORE
|
let _old_record = DMA_RECORD_STORE
|
||||||
.lock()
|
.lock()
|
||||||
.insert(recorder.name, (ptr, recorder.buffer, recorder.duration));
|
.insert(recorder.name, (ptr, recorder.buffer, recorder.duration));
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
{
|
{
|
||||||
|
@ -357,9 +335,7 @@ pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
|
||||||
ptr
|
ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn erase(name: String, _aux_mutex: &Rc<Mutex<bool>>,
|
pub async fn erase(name: String, _aux_mutex: &Rc<Mutex<bool>>, _routing_table: &RoutingTable, _timer: GlobalTimer) {
|
||||||
_routing_table: &RoutingTable, _timer: GlobalTimer
|
|
||||||
) {
|
|
||||||
let _entry = DMA_RECORD_STORE.lock().remove(&name);
|
let _entry = DMA_RECORD_STORE.lock().remove(&name);
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
if let Some((id, _v, _d)) = _entry {
|
if let Some((id, _v, _d)) = _entry {
|
||||||
|
|
|
@ -12,17 +12,17 @@ static mut RTIO_DEVICE_MAP: BTreeMap<u32, String> = BTreeMap::new();
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
pub mod drtio {
|
pub mod drtio {
|
||||||
use embedded_hal::blocking::delay::DelayMs;
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use embedded_hal::blocking::delay::DelayMs;
|
||||||
use libasync::{delay, task};
|
use libasync::{delay, task};
|
||||||
use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet};
|
use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet, drtioaux_proto::DMA_TRACE_MAX_SIZE};
|
||||||
use libboard_artiq::drtioaux_proto::DMA_TRACE_MAX_SIZE;
|
|
||||||
use libboard_zynq::time::Milliseconds;
|
use libboard_zynq::time::Milliseconds;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS};
|
use crate::{rtio_dma::remote_dma, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
|
||||||
use crate::rtio_dma::remote_dma;
|
SEEN_ASYNC_ERRORS};
|
||||||
|
|
||||||
pub fn startup(
|
pub fn startup(
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
|
@ -69,11 +69,17 @@ pub mod drtio {
|
||||||
loop {
|
loop {
|
||||||
let reply = recv_aux_timeout(linkno, 200, timer).await;
|
let reply = recv_aux_timeout(linkno, 200, timer).await;
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) => {
|
Ok(Packet::DmaPlaybackStatus {
|
||||||
|
id,
|
||||||
|
destination,
|
||||||
|
error,
|
||||||
|
channel,
|
||||||
|
timestamp,
|
||||||
|
}) => {
|
||||||
remote_dma::playback_done(id, destination, error, channel, timestamp).await;
|
remote_dma::playback_done(id, destination, error, channel, timestamp).await;
|
||||||
},
|
}
|
||||||
Ok(packet) => return Ok(packet),
|
Ok(packet) => return Ok(packet),
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,8 +190,13 @@ pub mod drtio {
|
||||||
async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) {
|
async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) {
|
||||||
let _lock = aux_mutex.async_lock().await;
|
let _lock = aux_mutex.async_lock().await;
|
||||||
match drtioaux_async::recv(linkno).await {
|
match drtioaux_async::recv(linkno).await {
|
||||||
Ok(Some(Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp })
|
Ok(Some(Packet::DmaPlaybackStatus {
|
||||||
) => remote_dma::playback_done(id, destination, error, channel, timestamp).await,
|
id,
|
||||||
|
destination,
|
||||||
|
error,
|
||||||
|
channel,
|
||||||
|
timestamp,
|
||||||
|
})) => remote_dma::playback_done(id, destination, error, channel, timestamp).await,
|
||||||
Ok(Some(packet)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet),
|
Ok(Some(packet)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet),
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Err(_) => warn!("[LINK#{}] aux packet error", linkno),
|
Err(_) => warn!("[LINK#{}] aux packet error", linkno),
|
||||||
|
@ -267,7 +278,8 @@ pub mod drtio {
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::DestinationDownReply) => {
|
Ok(Packet::DestinationDownReply) => {
|
||||||
destination_set_up(routing_table, up_destinations, destination, false).await;
|
destination_set_up(routing_table, up_destinations, destination, false).await;
|
||||||
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, false).await;
|
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, false)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
Ok(Packet::DestinationOkReply) => (),
|
Ok(Packet::DestinationOkReply) => (),
|
||||||
Ok(Packet::DestinationSequenceErrorReply { channel }) => {
|
Ok(Packet::DestinationSequenceErrorReply { channel }) => {
|
||||||
|
@ -320,7 +332,8 @@ pub mod drtio {
|
||||||
Ok(Packet::DestinationOkReply) => {
|
Ok(Packet::DestinationOkReply) => {
|
||||||
destination_set_up(routing_table, up_destinations, destination, true).await;
|
destination_set_up(routing_table, up_destinations, destination, true).await;
|
||||||
init_buffer_space(destination as u8, linkno).await;
|
init_buffer_space(destination as u8, linkno).await;
|
||||||
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, true).await;
|
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, true)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
||||||
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e),
|
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e),
|
||||||
|
@ -413,48 +426,72 @@ pub mod drtio {
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
id: u32,
|
id: u32,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
trace: &Vec<u8>
|
trace: &Vec<u8>,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
let linkno = routing_table.0[destination as usize][0] - 1;
|
let linkno = routing_table.0[destination as usize][0] - 1;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < trace.len() {
|
while i < trace.len() {
|
||||||
let mut trace_slice: [u8; DMA_TRACE_MAX_SIZE] = [0; DMA_TRACE_MAX_SIZE];
|
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 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();
|
let last = i + len == trace.len();
|
||||||
trace_slice[..len].clone_from_slice(&trace[i..i+len]);
|
trace_slice[..len].clone_from_slice(&trace[i..i + len]);
|
||||||
i += len;
|
i += len;
|
||||||
let reply = aux_transact(aux_mutex, linkno,
|
let reply = aux_transact(
|
||||||
|
aux_mutex,
|
||||||
|
linkno,
|
||||||
&Packet::DmaAddTraceRequest {
|
&Packet::DmaAddTraceRequest {
|
||||||
id: id, destination: destination, last: last, length: len as u16, trace: trace_slice},
|
id: id,
|
||||||
timer).await;
|
destination: destination,
|
||||||
|
last: last,
|
||||||
|
length: len as u16,
|
||||||
|
trace: trace_slice,
|
||||||
|
},
|
||||||
|
timer,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::DmaAddTraceReply { succeeded: true }) => (),
|
Ok(Packet::DmaAddTraceReply { succeeded: true }) => (),
|
||||||
Ok(Packet::DmaAddTraceReply { succeeded: false }) => {
|
Ok(Packet::DmaAddTraceReply { succeeded: false }) => {
|
||||||
return Err("error adding trace on satellite"); },
|
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(_) => {
|
||||||
|
return Err("adding DMA trace failed, unexpected aux packet");
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err("adding DMA trace failed, aux error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn ddma_send_erase(
|
pub async fn ddma_send_erase(
|
||||||
aux_mutex: &Rc<Mutex<bool>>,
|
aux_mutex: &Rc<Mutex<bool>>,
|
||||||
routing_table: &drtio_routing::RoutingTable,
|
routing_table: &drtio_routing::RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
id: u32,
|
id: u32,
|
||||||
destination: u8
|
destination: u8,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
let linkno = routing_table.0[destination as usize][0] - 1;
|
let linkno = routing_table.0[destination as usize][0] - 1;
|
||||||
let reply = aux_transact(aux_mutex, linkno,
|
let reply = aux_transact(
|
||||||
&Packet::DmaRemoveTraceRequest { id: id, destination: destination },
|
aux_mutex,
|
||||||
timer).await;
|
linkno,
|
||||||
|
&Packet::DmaRemoveTraceRequest {
|
||||||
|
id: id,
|
||||||
|
destination: destination,
|
||||||
|
},
|
||||||
|
timer,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()),
|
Ok(Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()),
|
||||||
Ok(Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"),
|
Ok(Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"),
|
||||||
Ok(_) => Err("adding trace failed, unexpected aux packet"),
|
Ok(_) => Err("adding trace failed, unexpected aux packet"),
|
||||||
Err(_) => Err("erasing trace failed, aux error")
|
Err(_) => Err("erasing trace failed, aux error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,19 +501,27 @@ pub mod drtio {
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
id: u32,
|
id: u32,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
timestamp: u64
|
timestamp: u64,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
let linkno = routing_table.0[destination as usize][0] - 1;
|
let linkno = routing_table.0[destination as usize][0] - 1;
|
||||||
let reply = aux_transact(aux_mutex, linkno, &Packet::DmaPlaybackRequest{
|
let reply = aux_transact(
|
||||||
id: id, destination: destination, timestamp: timestamp }, timer).await;
|
aux_mutex,
|
||||||
|
linkno,
|
||||||
|
&Packet::DmaPlaybackRequest {
|
||||||
|
id: id,
|
||||||
|
destination: destination,
|
||||||
|
timestamp: timestamp,
|
||||||
|
},
|
||||||
|
timer,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::DmaPlaybackReply { succeeded: true }) => Ok(()),
|
Ok(Packet::DmaPlaybackReply { succeeded: true }) => Ok(()),
|
||||||
Ok(Packet::DmaPlaybackReply { succeeded: false }) => Err("error on DMA playback request"),
|
Ok(Packet::DmaPlaybackReply { succeeded: false }) => Err("error on DMA playback request"),
|
||||||
Ok(_) => Err("received unexpected aux packet during DMA playback"),
|
Ok(_) => Err("received unexpected aux packet during DMA playback"),
|
||||||
Err(_) => Err("aux error on DMA playback")
|
Err(_) => Err("aux error on DMA playback"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
|
fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
|
||||||
|
|
|
@ -1,49 +1,48 @@
|
||||||
use libcortex_a9::cache::dcci_slice;
|
use alloc::{collections::btree_map::BTreeMap, vec::Vec};
|
||||||
|
|
||||||
use libboard_artiq::pl::csr;
|
use libboard_artiq::pl::csr;
|
||||||
use alloc::{vec::Vec, collections::btree_map::BTreeMap};
|
use libcortex_a9::cache::dcci_slice;
|
||||||
|
|
||||||
const ALIGNMENT: usize = 64;
|
const ALIGNMENT: usize = 64;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum ManagerState {
|
enum ManagerState {
|
||||||
Idle,
|
Idle,
|
||||||
Playback
|
Playback,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RtioStatus {
|
pub struct RtioStatus {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
pub error: u8,
|
pub error: u8,
|
||||||
pub channel: u32,
|
pub channel: u32,
|
||||||
pub timestamp: u64
|
pub timestamp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
IdNotFound,
|
IdNotFound,
|
||||||
PlaybackInProgress,
|
PlaybackInProgress,
|
||||||
EntryNotComplete
|
EntryNotComplete,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Entry {
|
struct Entry {
|
||||||
trace: Vec<u8>,
|
trace: Vec<u8>,
|
||||||
padding_len: usize,
|
padding_len: usize,
|
||||||
complete: bool
|
complete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Manager {
|
pub struct Manager {
|
||||||
entries: BTreeMap<u32, Entry>,
|
entries: BTreeMap<u32, Entry>,
|
||||||
state: ManagerState,
|
state: ManagerState,
|
||||||
currentid: u32
|
currentid: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn new() -> Manager {
|
pub fn new() -> Manager {
|
||||||
// in case Manager is created during a DMA in progress
|
// in case Manager is created during a DMA in progress
|
||||||
// wait for it to end
|
// wait for it to end
|
||||||
unsafe {
|
unsafe { while csr::rtio_dma::enable_read() != 0 {} }
|
||||||
while csr::rtio_dma::enable_read() != 0 {}
|
|
||||||
}
|
|
||||||
Manager {
|
Manager {
|
||||||
entries: BTreeMap::new(),
|
entries: BTreeMap::new(),
|
||||||
currentid: 0,
|
currentid: 0,
|
||||||
|
@ -57,22 +56,30 @@ impl Manager {
|
||||||
if entry.complete {
|
if entry.complete {
|
||||||
// replace entry
|
// replace entry
|
||||||
self.entries.remove(&id);
|
self.entries.remove(&id);
|
||||||
self.entries.insert(id, Entry {
|
self.entries.insert(
|
||||||
trace: Vec::new(),
|
id,
|
||||||
padding_len: 0,
|
Entry {
|
||||||
complete: false });
|
trace: Vec::new(),
|
||||||
|
padding_len: 0,
|
||||||
|
complete: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
self.entries.get_mut(&id).unwrap()
|
self.entries.get_mut(&id).unwrap()
|
||||||
} else {
|
} else {
|
||||||
entry
|
entry
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
self.entries.insert(id, Entry {
|
self.entries.insert(
|
||||||
trace: Vec::new(),
|
id,
|
||||||
padding_len: 0,
|
Entry {
|
||||||
complete: false });
|
trace: Vec::new(),
|
||||||
|
padding_len: 0,
|
||||||
|
complete: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
self.entries.get_mut(&id).unwrap()
|
self.entries.get_mut(&id).unwrap()
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
entry.trace.extend(&trace[0..trace_len]);
|
entry.trace.extend(&trace[0..trace_len]);
|
||||||
|
|
||||||
|
@ -101,7 +108,7 @@ impl Manager {
|
||||||
pub fn erase(&mut self, id: u32) -> Result<(), Error> {
|
pub fn erase(&mut self, id: u32) -> Result<(), Error> {
|
||||||
match self.entries.remove(&id) {
|
match self.entries.remove(&id) {
|
||||||
Some(_) => Ok(()),
|
Some(_) => Ok(()),
|
||||||
None => Err(Error::IdNotFound)
|
None => Err(Error::IdNotFound),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,9 +117,11 @@ impl Manager {
|
||||||
return Err(Error::PlaybackInProgress);
|
return Err(Error::PlaybackInProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry = match self.entries.get(&id){
|
let entry = match self.entries.get(&id) {
|
||||||
Some(entry) => entry,
|
Some(entry) => entry,
|
||||||
None => { return Err(Error::IdNotFound); }
|
None => {
|
||||||
|
return Err(Error::IdNotFound);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if !entry.complete {
|
if !entry.complete {
|
||||||
return Err(Error::EntryNotComplete);
|
return Err(Error::EntryNotComplete);
|
||||||
|
@ -146,7 +155,7 @@ impl Manager {
|
||||||
self.state = ManagerState::Idle;
|
self.state = ManagerState::Idle;
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::cri_con::selected_write(0);
|
csr::cri_con::selected_write(0);
|
||||||
let error = csr::rtio_dma::error_read();
|
let error = csr::rtio_dma::error_read();
|
||||||
let channel = csr::rtio_dma::error_channel_read();
|
let channel = csr::rtio_dma::error_channel_read();
|
||||||
let timestamp = csr::rtio_dma::error_timestamp_read();
|
let timestamp = csr::rtio_dma::error_timestamp_read();
|
||||||
if error != 0 {
|
if error != 0 {
|
||||||
|
@ -156,9 +165,9 @@ impl Manager {
|
||||||
id: self.currentid,
|
id: self.currentid,
|
||||||
error: error,
|
error: error,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
timestamp: timestamp });
|
timestamp: timestamp,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ extern crate alloc;
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use dma::Manager as DmaManager;
|
||||||
use embedded_hal::blocking::delay::DelayUs;
|
use embedded_hal::blocking::delay::DelayUs;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
use libboard_artiq::io_expander;
|
use libboard_artiq::io_expander;
|
||||||
|
@ -36,10 +37,9 @@ use libcortex_a9::{asm, interrupt_handler,
|
||||||
spin_lock_yield};
|
spin_lock_yield};
|
||||||
use libregister::{RegisterR, RegisterW};
|
use libregister::{RegisterR, RegisterW};
|
||||||
use libsupport_zynq::ram;
|
use libsupport_zynq::ram;
|
||||||
use dma::Manager as DmaManager;
|
|
||||||
|
|
||||||
mod repeater;
|
|
||||||
mod dma;
|
mod dma;
|
||||||
|
mod repeater;
|
||||||
|
|
||||||
fn drtiosat_reset(reset: bool) {
|
fn drtiosat_reset(reset: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -94,7 +94,7 @@ fn process_aux_packet(
|
||||||
packet: drtioaux::Packet,
|
packet: drtioaux::Packet,
|
||||||
timer: &mut GlobalTimer,
|
timer: &mut GlobalTimer,
|
||||||
i2c: &mut I2c,
|
i2c: &mut I2c,
|
||||||
dma_manager: &mut DmaManager
|
dma_manager: &mut DmaManager,
|
||||||
) -> Result<(), drtioaux::Error> {
|
) -> Result<(), drtioaux::Error> {
|
||||||
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
|
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
|
||||||
// and u16 otherwise; hence the `as _` conversion.
|
// and u16 otherwise; hence the `as _` conversion.
|
||||||
|
@ -417,31 +417,28 @@ fn process_aux_packet(
|
||||||
id,
|
id,
|
||||||
last,
|
last,
|
||||||
length,
|
length,
|
||||||
trace
|
trace,
|
||||||
} => {
|
} => {
|
||||||
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
||||||
let succeeded = dma_manager.add(id, last, &trace, length as usize).is_ok();
|
let succeeded = dma_manager.add(id, last, &trace, length as usize).is_ok();
|
||||||
drtioaux::send(0,
|
drtioaux::send(0, &drtioaux::Packet::DmaAddTraceReply { succeeded: succeeded })
|
||||||
&drtioaux::Packet::DmaAddTraceReply { succeeded: succeeded })
|
|
||||||
}
|
}
|
||||||
drtioaux::Packet::DmaRemoveTraceRequest {
|
drtioaux::Packet::DmaRemoveTraceRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
id
|
id,
|
||||||
} => {
|
} => {
|
||||||
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
||||||
let succeeded = dma_manager.erase(id).is_ok();
|
let succeeded = dma_manager.erase(id).is_ok();
|
||||||
drtioaux::send(0,
|
drtioaux::send(0, &drtioaux::Packet::DmaRemoveTraceReply { succeeded: succeeded })
|
||||||
&drtioaux::Packet::DmaRemoveTraceReply { succeeded: succeeded })
|
|
||||||
}
|
}
|
||||||
drtioaux::Packet::DmaPlaybackRequest {
|
drtioaux::Packet::DmaPlaybackRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
id,
|
id,
|
||||||
timestamp
|
timestamp,
|
||||||
} => {
|
} => {
|
||||||
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
|
||||||
let succeeded = dma_manager.playback(id, timestamp).is_ok();
|
let succeeded = dma_manager.playback(id, timestamp).is_ok();
|
||||||
drtioaux::send(0,
|
drtioaux::send(0, &drtioaux::Packet::DmaPlaybackReply { succeeded: succeeded })
|
||||||
&drtioaux::Packet::DmaPlaybackReply { succeeded: succeeded })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -457,7 +454,7 @@ fn process_aux_packets(
|
||||||
rank: &mut u8,
|
rank: &mut u8,
|
||||||
timer: &mut GlobalTimer,
|
timer: &mut GlobalTimer,
|
||||||
i2c: &mut I2c,
|
i2c: &mut I2c,
|
||||||
dma_manager: &mut DmaManager
|
dma_manager: &mut DmaManager,
|
||||||
) {
|
) {
|
||||||
let result = drtioaux::recv(0).and_then(|packet| {
|
let result = drtioaux::recv(0).and_then(|packet| {
|
||||||
if let Some(packet) = packet {
|
if let Some(packet) = packet {
|
||||||
|
@ -645,7 +642,14 @@ pub extern "C" fn main_core0() -> i32 {
|
||||||
|
|
||||||
while drtiosat_link_rx_up() {
|
while drtiosat_link_rx_up() {
|
||||||
drtiosat_process_errors();
|
drtiosat_process_errors();
|
||||||
process_aux_packets(&mut repeaters, &mut routing_table, &mut rank, &mut timer, &mut i2c, &mut dma_manager);
|
process_aux_packets(
|
||||||
|
&mut repeaters,
|
||||||
|
&mut routing_table,
|
||||||
|
&mut rank,
|
||||||
|
&mut timer,
|
||||||
|
&mut i2c,
|
||||||
|
&mut dma_manager,
|
||||||
|
);
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
for mut rep in repeaters.iter_mut() {
|
for mut rep in repeaters.iter_mut() {
|
||||||
rep.service(&routing_table, rank, &mut timer);
|
rep.service(&routing_table, rank, &mut timer);
|
||||||
|
@ -663,14 +667,20 @@ pub extern "C" fn main_core0() -> i32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(status) = dma_manager.check_state() {
|
if let Some(status) = dma_manager.check_state() {
|
||||||
info!("playback done, error: {}, channel: {}, timestamp: {}", status.error, status.channel, status.timestamp);
|
info!(
|
||||||
if let Err(e) = drtioaux::send(0, &drtioaux::Packet::DmaPlaybackStatus {
|
"playback done, error: {}, channel: {}, timestamp: {}",
|
||||||
destination: rank,
|
status.error, status.channel, status.timestamp
|
||||||
id: status.id,
|
);
|
||||||
error: status.error,
|
if let Err(e) = drtioaux::send(
|
||||||
channel: status.channel,
|
0,
|
||||||
timestamp: status.timestamp
|
&drtioaux::Packet::DmaPlaybackStatus {
|
||||||
}) {
|
destination: rank,
|
||||||
|
id: status.id,
|
||||||
|
error: status.error,
|
||||||
|
channel: status.channel,
|
||||||
|
timestamp: status.timestamp,
|
||||||
|
},
|
||||||
|
) {
|
||||||
error!("error sending DMA playback status: {:?}", e);
|
error!("error sending DMA playback status: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue