runtime: advance now on DMA replay.

Fixes #700.
This commit is contained in:
whitequark 2017-04-05 18:34:08 +00:00
parent 674bf82f3a
commit 14ae1cc100
6 changed files with 66 additions and 26 deletions

View File

@ -16,7 +16,7 @@ def dma_record_start() -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall @syscall
def dma_record_stop(name: TStr) -> TNone: def dma_record_stop(name: TStr, duration: TInt64) -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall @syscall
@ -51,7 +51,7 @@ class DMARecordContextManager:
@kernel @kernel
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
dma_record_stop(self.name) # see above dma_record_stop(self.name, now_mu()) # see above
at_mu(self.saved_now_mu) at_mu(self.saved_now_mu)

View File

@ -257,7 +257,7 @@ extern fn dma_record_start() {
} }
} }
extern fn dma_record_stop(name: CSlice<u8>) { extern fn dma_record_stop(name: CSlice<u8>, duration: i64) {
let name = str::from_utf8(name.as_ref()).unwrap(); let name = str::from_utf8(name.as_ref()).unwrap();
unsafe { unsafe {
@ -272,7 +272,10 @@ extern fn dma_record_stop(name: CSlice<u8>) {
rtio::output_wide as *const () as u32).unwrap(); rtio::output_wide as *const () as u32).unwrap();
DMA_RECORDING = false; DMA_RECORDING = false;
send(&DmaRecordStop(name)); send(&DmaRecordStop {
name: name,
duration: duration as u64
});
} }
} }
@ -298,15 +301,16 @@ extern fn dma_record_output_wide(timestamp: i64, channel: i32, address: i32, dat
extern fn dma_erase(name: CSlice<u8>) { extern fn dma_erase(name: CSlice<u8>) {
let name = str::from_utf8(name.as_ref()).unwrap(); let name = str::from_utf8(name.as_ref()).unwrap();
send(&DmaEraseRequest(name)); send(&DmaEraseRequest { name: name });
} }
extern fn dma_playback(timestamp: i64, name: CSlice<u8>) { extern fn dma_playback(timestamp: i64, name: CSlice<u8>) {
let name = str::from_utf8(name.as_ref()).unwrap(); let name = str::from_utf8(name.as_ref()).unwrap();
send(&DmaPlaybackRequest(name)); send(&DmaPlaybackRequest { name: name });
let succeeded = recv!(&DmaPlaybackReply(data) => unsafe { let (succeeded, now_advance) =
match data { recv!(&DmaPlaybackReply { trace, duration } => unsafe {
match trace {
Some(bytes) => { Some(bytes) => {
let ptr = bytes.as_ptr() as usize; let ptr = bytes.as_ptr() as usize;
assert!(ptr % 64 == 0); assert!(ptr % 64 == 0);
@ -319,9 +323,10 @@ extern fn dma_playback(timestamp: i64, name: CSlice<u8>) {
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);
true (true, duration)
} }
None => false None =>
(false, 0)
} }
}); });
@ -347,6 +352,8 @@ extern fn dma_playback(timestamp: i64, name: CSlice<u8>) {
"RTIO sequence error at {0} mu, channel {1}", "RTIO sequence error at {0} mu, channel {1}",
timestamp as i64, channel as i64, 0) timestamp as i64, channel as i64, 0)
} }
NOW += now_advance;
} }
} }

View File

@ -36,12 +36,22 @@ pub enum Message<'a> {
address: u32, address: u32,
data: &'a [u32] data: &'a [u32]
}, },
DmaRecordStop(&'a str), DmaRecordStop {
name: &'a str,
duration: u64
},
DmaEraseRequest(&'a str), DmaEraseRequest {
name: &'a str
},
DmaPlaybackRequest(&'a str), DmaPlaybackRequest {
DmaPlaybackReply(Option<&'a [u8]>), name: &'a str
},
DmaPlaybackReply {
trace: Option<&'a [u8]>,
duration: u64
},
DrtioChannelStateRequest { channel: u32 }, DrtioChannelStateRequest { channel: u32 },
DrtioChannelStateReply { fifo_space: u16, last_timestamp: u64 }, DrtioChannelStateReply { fifo_space: u16, last_timestamp: u64 },

View File

@ -9,7 +9,8 @@ const ALIGNMENT: usize = 64;
#[derive(Debug)] #[derive(Debug)]
struct Entry { struct Entry {
data: Vec<u8>, data: Vec<u8>,
padding: usize padding: usize,
duration: u64
} }
#[derive(Debug)] #[derive(Debug)]
@ -62,7 +63,7 @@ impl Manager {
} }
} }
pub fn record_stop(&mut self, name: &str) { pub fn record_stop(&mut self, name: &str, duration: u64) {
let mut recorded = Vec::new(); let mut recorded = Vec::new();
mem::swap(&mut self.recording, &mut recorded); mem::swap(&mut self.recording, &mut recorded);
recorded.push(0); recorded.push(0);
@ -83,6 +84,7 @@ impl Manager {
self.entries.insert(String::from(name), Entry { self.entries.insert(String::from(name), Entry {
data: recorded, data: recorded,
padding: padding, padding: padding,
duration: duration
}); });
} }
@ -90,9 +92,11 @@ impl Manager {
self.entries.remove(name); self.entries.remove(name);
} }
pub fn with_trace<F: FnOnce(Option<&[u8]>) -> R, R>(&self, name: &str, f: F) -> R { pub fn with_trace<F, R>(&self, name: &str, f: F) -> R
f(self.entries where F: FnOnce(Option<&[u8]>, u64) -> R {
.get(name) match self.entries.get(name) {
.map(|entry| &entry.data[entry.padding..])) Some(entry) => f(Some(&entry.data[entry.padding..]), entry.duration),
None => f(None, 0)
}
} }
} }

View File

@ -388,18 +388,21 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
session.congress.dma_manager.record_append(timestamp, channel, address, data); session.congress.dma_manager.record_append(timestamp, channel, address, data);
kern_acknowledge() kern_acknowledge()
} }
&kern::DmaRecordStop(name) => { &kern::DmaRecordStop { name, duration } => {
session.congress.dma_manager.record_stop(name); session.congress.dma_manager.record_stop(name, duration);
board::cache::flush_l2_cache(); board::cache::flush_l2_cache();
kern_acknowledge() kern_acknowledge()
} }
&kern::DmaEraseRequest(name) => { &kern::DmaEraseRequest { name } => {
session.congress.dma_manager.erase(name); session.congress.dma_manager.erase(name);
kern_acknowledge() kern_acknowledge()
} }
&kern::DmaPlaybackRequest(name) => { &kern::DmaPlaybackRequest { name } => {
session.congress.dma_manager.with_trace(name, |trace| { session.congress.dma_manager.with_trace(name, |trace, duration| {
kern_send(io, &kern::DmaPlaybackReply(trace)) kern_send(io, &kern::DmaPlaybackReply {
trace: trace,
duration: duration
})
}) })
} }

View File

@ -2,6 +2,7 @@
# Copyright (C) 2014, 2015 Robert Jordens <jordens@gmail.com> # Copyright (C) 2014, 2015 Robert Jordens <jordens@gmail.com>
import os, unittest import os, unittest
import numpy as np
from math import sqrt from math import sqrt
@ -477,6 +478,7 @@ class _DMA(EnvExperiment):
self.setattr_device("core_dma") self.setattr_device("core_dma")
self.setattr_device("ttl1") self.setattr_device("ttl1")
self.trace_name = trace_name self.trace_name = trace_name
self.delta = np.int64(0)
@kernel @kernel
def record(self): def record(self):
@ -492,6 +494,14 @@ class _DMA(EnvExperiment):
delay(100*ms) delay(100*ms)
self.core_dma.replay(self.trace_name) self.core_dma.replay(self.trace_name)
@kernel
def replay_delta(self):
self.core.break_realtime()
delay(100*ms)
start = now_mu()
self.core_dma.replay(self.trace_name)
self.delta = now_mu() - start
@kernel @kernel
def erase(self): def erase(self):
self.core_dma.erase(self.trace_name) self.core_dma.erase(self.trace_name)
@ -539,3 +549,9 @@ class DMATest(ExperimentCase):
self.assertEqual(dump.messages[1].data, 0) self.assertEqual(dump.messages[1].data, 0)
self.assertEqual(dump.messages[1].timestamp - self.assertEqual(dump.messages[1].timestamp -
dump.messages[0].timestamp, 100) dump.messages[0].timestamp, 100)
def test_dma_delta(self):
exp = self.create(_DMA)
exp.record()
exp.replay_delta()
self.assertEqual(exp.delta, 200)