dma: pass "uses_ddma" for non-remote recordings

This commit is contained in:
mwojcik 2023-04-14 14:41:34 +08:00 committed by Sébastien Bourdeauducq
parent b5d9062ba9
commit 918d30b900
5 changed files with 37 additions and 21 deletions

View File

@ -25,11 +25,11 @@ def dma_erase(name: TStr) -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall @syscall
def dma_retrieve(name: TStr) -> TTuple([TInt64, TInt32]): def dma_retrieve(name: TStr) -> TTuple([TInt64, TInt32, TBool]):
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall @syscall
def dma_playback(timestamp: TInt64, ptr: TInt32) -> TNone: def dma_playback(timestamp: TInt64, ptr: TInt32, enable_ddma: TBool) -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@ -101,24 +101,24 @@ class CoreDMA:
def playback(self, name): def playback(self, name):
"""Replays a previously recorded DMA trace. This function blocks until """Replays a previously recorded DMA trace. This function blocks until
the entire trace is submitted to the RTIO FIFOs.""" the entire trace is submitted to the RTIO FIFOs."""
(advance_mu, ptr) = dma_retrieve(name) (advance_mu, ptr, uses_ddma) = dma_retrieve(name)
dma_playback(now_mu(), ptr) dma_playback(now_mu(), ptr, uses_ddma)
delay_mu(advance_mu) delay_mu(advance_mu)
@kernel @kernel
def get_handle(self, name): def get_handle(self, name):
"""Returns a handle to a previously recorded DMA trace. The returned handle """Returns a handle to a previously recorded DMA trace. The returned handle
is only valid until the next call to :meth:`record` or :meth:`erase`.""" is only valid until the next call to :meth:`record` or :meth:`erase`."""
(advance_mu, ptr) = dma_retrieve(name) (advance_mu, ptr, uses_ddma) = dma_retrieve(name)
return (self.epoch, advance_mu, ptr) return (self.epoch, advance_mu, ptr, uses_ddma)
@kernel @kernel
def playback_handle(self, handle): def playback_handle(self, handle):
"""Replays a handle obtained with :meth:`get_handle`. Using this function """Replays a handle obtained with :meth:`get_handle`. Using this function
is much faster than :meth:`playback` for replaying a set of traces repeatedly, is much faster than :meth:`playback` for replaying a set of traces repeatedly,
but incurs the overhead of managing the handles onto the programmer.""" but incurs the overhead of managing the handles onto the programmer."""
(epoch, advance_mu, ptr) = handle (epoch, advance_mu, ptr, uses_ddma) = handle
if self.epoch != epoch: if self.epoch != epoch:
raise DMAError("Invalid handle") raise DMAError("Invalid handle")
dma_playback(now_mu(), ptr) dma_playback(now_mu(), ptr, uses_ddma)
delay_mu(advance_mu) delay_mu(advance_mu)

View File

@ -371,7 +371,8 @@ extern fn dma_erase(name: &CSlice<u8>) {
#[repr(C)] #[repr(C)]
struct DmaTrace { struct DmaTrace {
duration: i64, duration: i64,
address: i32 address: i32,
uses_ddma: bool,
} }
#[unwind(allowed)] #[unwind(allowed)]
@ -379,11 +380,12 @@ extern fn dma_retrieve(name: &CSlice<u8>) -> DmaTrace {
let name = str::from_utf8(name.as_ref()).unwrap(); let name = str::from_utf8(name.as_ref()).unwrap();
send(&DmaRetrieveRequest { name: name }); send(&DmaRetrieveRequest { name: name });
recv!(&DmaRetrieveReply { trace, duration } => { recv!(&DmaRetrieveReply { trace, duration, uses_ddma } => {
match trace { match trace {
Some(bytes) => Ok(DmaTrace { Some(bytes) => Ok(DmaTrace {
address: bytes.as_ptr() as i32, address: bytes.as_ptr() as i32,
duration: duration as i64 duration: duration as i64,
uses_ddma: uses_ddma,
}), }),
None => Err(()) None => Err(())
} }
@ -396,7 +398,7 @@ extern fn dma_retrieve(name: &CSlice<u8>) -> DmaTrace {
#[cfg(has_rtio_dma)] #[cfg(has_rtio_dma)]
#[unwind(allowed)] #[unwind(allowed)]
extern fn dma_playback(timestamp: i64, ptr: i32) { extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) {
assert!(ptr % 64 == 0); assert!(ptr % 64 == 0);
unsafe { unsafe {
@ -406,7 +408,9 @@ extern 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)]
if _uses_ddma {
send(&DmaStartRemoteRequest { id: ptr as i32, timestamp: timestamp }); send(&DmaStartRemoteRequest { id: ptr as i32, 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);
@ -429,22 +433,19 @@ extern fn dma_playback(timestamp: i64, ptr: i32) {
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
{ if _uses_ddma {
send(&DmaAwaitRemoteRequest { id: ptr as i32 }); send(&DmaAwaitRemoteRequest { id: ptr as i32 });
recv!(&DmaAwaitRemoteReply { timeout, error, channel, timestamp } => { recv!(&DmaAwaitRemoteReply { timeout, error, channel, timestamp } => {
if timeout { if timeout {
println!("timeout\n");
raise!("DMAError", raise!("DMAError",
"Error running DMA on satellite device, timed out waiting for results"); "Error running DMA on satellite device, timed out waiting for results");
} }
if error & 1 != 0 { if error & 1 != 0 {
println!("rtio underflow from ddma\n");
raise!("RTIOUnderflow", raise!("RTIOUnderflow",
"RTIO underflow at channel {rtio_channel_info:0}, {1} mu", "RTIO underflow at channel {rtio_channel_info:0}, {1} mu",
channel as i64, timestamp as i64, 0); channel as i64, timestamp as i64, 0);
} }
if error & 2 != 0 { if error & 2 != 0 {
println!("rtio destun from ddma\n");
raise!("RTIODestinationUnreachable", raise!("RTIODestinationUnreachable",
"RTIO destination unreachable, output, at channel {rtio_channel_info:0}, {1} mu", "RTIO destination unreachable, output, at channel {rtio_channel_info:0}, {1} mu",
channel as i64, timestamp as i64, 0); channel as i64, timestamp as i64, 0);
@ -455,7 +456,7 @@ extern fn dma_playback(timestamp: i64, ptr: i32) {
#[cfg(not(has_rtio_dma))] #[cfg(not(has_rtio_dma))]
#[unwind(allowed)] #[unwind(allowed)]
extern fn dma_playback(_timestamp: i64, _ptr: i32) { extern fn dma_playback(_timestamp: i64, _ptr: i32, _uses_ddma: bool) {
unimplemented!("not(has_rtio_dma)") unimplemented!("not(has_rtio_dma)")
} }

View File

@ -34,6 +34,7 @@ pub enum Message<'a> {
DmaRetrieveReply { DmaRetrieveReply {
trace: Option<&'a [u8]>, trace: Option<&'a [u8]>,
duration: u64, duration: u64,
uses_ddma: bool,
}, },
DmaStartRemoteRequest { DmaStartRemoteRequest {

View File

@ -17,6 +17,7 @@ pub mod remote_dma {
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>,
@ -169,7 +170,12 @@ pub mod remote_dma {
} }
} }
} }
}
pub fn has_remote_traces(io: &Io, ddma_mutex: &Mutex, id: u32) -> bool {
let _lock = ddma_mutex.lock(io).unwrap();
let trace_list = unsafe { TRACES.get(&id).unwrap() };
!trace_list.is_empty()
} }
} }

View File

@ -146,9 +146,9 @@ fn host_write<W>(writer: &mut W, reply: host::Reply) -> Result<(), IoError<W::Wr
pub fn kern_send(io: &Io, request: &kern::Message) -> Result<(), Error<SchedError>> { pub fn kern_send(io: &Io, request: &kern::Message) -> Result<(), Error<SchedError>> {
match request { match request {
&kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"), &kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"),
&kern::DmaRetrieveReply { trace, duration } => { &kern::DmaRetrieveReply { trace, duration, uses_ddma } => {
if trace.map(|data| data.len() > 100).unwrap_or(false) { if trace.map(|data| data.len() > 100).unwrap_or(false) {
debug!("comm->kern DmaRetrieveReply {{ trace: ..., duration: {:?} }}", duration) debug!("comm->kern DmaRetrieveReply {{ trace: ..., duration: {:?}, uses_ddma: {} }}", duration, uses_ddma)
} else { } else {
debug!("comm->kern {:?}", request) debug!("comm->kern {:?}", request)
} }
@ -400,9 +400,17 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
} }
&kern::DmaRetrieveRequest { name } => { &kern::DmaRetrieveRequest { name } => {
session.congress.dma_manager.with_trace(name, |trace, duration| { session.congress.dma_manager.with_trace(name, |trace, duration| {
#[cfg(has_drtio)]
let uses_ddma = match trace {
Some(trace) => remote_dma::has_remote_traces(io, aux_mutex, trace.as_ptr() as u32),
None => false
};
#[cfg(not(has_drtio))]
let uses_ddma = false;
kern_send(io, &kern::DmaRetrieveReply { kern_send(io, &kern::DmaRetrieveReply {
trace: trace, trace: trace,
duration: duration duration: duration,
uses_ddma: uses_ddma,
}) })
}) })
} }