forked from M-Labs/artiq
1
0
Fork 0

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")
@syscall
def dma_record_stop(name: TStr) -> TNone:
def dma_record_stop(name: TStr, duration: TInt64) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
@ -51,7 +51,7 @@ class DMARecordContextManager:
@kernel
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)

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();
unsafe {
@ -272,7 +272,10 @@ extern fn dma_record_stop(name: CSlice<u8>) {
rtio::output_wide as *const () as u32).unwrap();
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>) {
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>) {
let name = str::from_utf8(name.as_ref()).unwrap();
send(&DmaPlaybackRequest(name));
let succeeded = recv!(&DmaPlaybackReply(data) => unsafe {
match data {
send(&DmaPlaybackRequest { name: name });
let (succeeded, now_advance) =
recv!(&DmaPlaybackReply { trace, duration } => unsafe {
match trace {
Some(bytes) => {
let ptr = bytes.as_ptr() as usize;
assert!(ptr % 64 == 0);
@ -319,9 +323,10 @@ extern fn dma_playback(timestamp: i64, name: CSlice<u8>) {
while csr::rtio_dma::enable_read() != 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}",
timestamp as i64, channel as i64, 0)
}
NOW += now_advance;
}
}

View File

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

View File

@ -9,7 +9,8 @@ const ALIGNMENT: usize = 64;
#[derive(Debug)]
struct Entry {
data: Vec<u8>,
padding: usize
padding: usize,
duration: u64
}
#[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();
mem::swap(&mut self.recording, &mut recorded);
recorded.push(0);
@ -83,6 +84,7 @@ impl Manager {
self.entries.insert(String::from(name), Entry {
data: recorded,
padding: padding,
duration: duration
});
}
@ -90,9 +92,11 @@ impl Manager {
self.entries.remove(name);
}
pub fn with_trace<F: FnOnce(Option<&[u8]>) -> R, R>(&self, name: &str, f: F) -> R {
f(self.entries
.get(name)
.map(|entry| &entry.data[entry.padding..]))
pub fn with_trace<F, R>(&self, name: &str, f: F) -> R
where F: FnOnce(Option<&[u8]>, u64) -> R {
match self.entries.get(name) {
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);
kern_acknowledge()
}
&kern::DmaRecordStop(name) => {
session.congress.dma_manager.record_stop(name);
&kern::DmaRecordStop { name, duration } => {
session.congress.dma_manager.record_stop(name, duration);
board::cache::flush_l2_cache();
kern_acknowledge()
}
&kern::DmaEraseRequest(name) => {
&kern::DmaEraseRequest { name } => {
session.congress.dma_manager.erase(name);
kern_acknowledge()
}
&kern::DmaPlaybackRequest(name) => {
session.congress.dma_manager.with_trace(name, |trace| {
kern_send(io, &kern::DmaPlaybackReply(trace))
&kern::DmaPlaybackRequest { name } => {
session.congress.dma_manager.with_trace(name, |trace, duration| {
kern_send(io, &kern::DmaPlaybackReply {
trace: trace,
duration: duration
})
})
}

View File

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