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")
@syscall
def dma_retrieve(name: TStr) -> TTuple([TInt64, TInt32]):
def dma_retrieve(name: TStr) -> TTuple([TInt64, TInt32, TBool]):
raise NotImplementedError("syscall not simulated")
@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")
@ -101,24 +101,24 @@ class CoreDMA:
def playback(self, name):
"""Replays a previously recorded DMA trace. This function blocks until
the entire trace is submitted to the RTIO FIFOs."""
(advance_mu, ptr) = dma_retrieve(name)
dma_playback(now_mu(), ptr)
(advance_mu, ptr, uses_ddma) = dma_retrieve(name)
dma_playback(now_mu(), ptr, uses_ddma)
delay_mu(advance_mu)
@kernel
def get_handle(self, name):
"""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`."""
(advance_mu, ptr) = dma_retrieve(name)
return (self.epoch, advance_mu, ptr)
(advance_mu, ptr, uses_ddma) = dma_retrieve(name)
return (self.epoch, advance_mu, ptr, uses_ddma)
@kernel
def playback_handle(self, handle):
"""Replays a handle obtained with :meth:`get_handle`. Using this function
is much faster than :meth:`playback` for replaying a set of traces repeatedly,
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:
raise DMAError("Invalid handle")
dma_playback(now_mu(), ptr)
dma_playback(now_mu(), ptr, uses_ddma)
delay_mu(advance_mu)

View File

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

View File

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

View File

@ -17,6 +17,7 @@ pub mod remote_dma {
Loaded,
PlaybackEnded { error: u8, channel: u32, timestamp: u64 }
}
#[derive(Debug, Clone)]
struct RemoteTrace {
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>> {
match request {
&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) {
debug!("comm->kern DmaRetrieveReply {{ trace: ..., duration: {:?} }}", duration)
debug!("comm->kern DmaRetrieveReply {{ trace: ..., duration: {:?}, uses_ddma: {} }}", duration, uses_ddma)
} else {
debug!("comm->kern {:?}", request)
}
@ -400,9 +400,17 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
}
&kern::DmaRetrieveRequest { name } => {
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 {
trace: trace,
duration: duration
duration: duration,
uses_ddma: uses_ddma,
})
})
}