mirror of https://github.com/m-labs/artiq.git
parent
674bf82f3a
commit
14ae1cc100
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue