From 14ae1cc100a771d8e70bb8c49244d8962b16e66f Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Apr 2017 18:34:08 +0000 Subject: [PATCH] runtime: advance now on DMA replay. Fixes #700. --- artiq/coredevice/dma.py | 4 ++-- artiq/firmware/ksupport/lib.rs | 23 +++++++++++++++-------- artiq/firmware/libproto/kernel_proto.rs | 18 ++++++++++++++---- artiq/firmware/runtime/rtio_dma.rs | 16 ++++++++++------ artiq/firmware/runtime/session.rs | 15 +++++++++------ artiq/test/coredevice/test_rtio.py | 16 ++++++++++++++++ 6 files changed, 66 insertions(+), 26 deletions(-) diff --git a/artiq/coredevice/dma.py b/artiq/coredevice/dma.py index e4dc6d52c..070f2c2d8 100644 --- a/artiq/coredevice/dma.py +++ b/artiq/coredevice/dma.py @@ -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) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 84471c136..bddbe3651 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -257,7 +257,7 @@ extern fn dma_record_start() { } } -extern fn dma_record_stop(name: CSlice) { +extern fn dma_record_stop(name: CSlice, duration: i64) { let name = str::from_utf8(name.as_ref()).unwrap(); unsafe { @@ -272,7 +272,10 @@ extern fn dma_record_stop(name: CSlice) { 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) { let name = str::from_utf8(name.as_ref()).unwrap(); - send(&DmaEraseRequest(name)); + send(&DmaEraseRequest { name: name }); } extern fn dma_playback(timestamp: i64, name: CSlice) { 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) { 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) { "RTIO sequence error at {0} mu, channel {1}", timestamp as i64, channel as i64, 0) } + + NOW += now_advance; } } diff --git a/artiq/firmware/libproto/kernel_proto.rs b/artiq/firmware/libproto/kernel_proto.rs index ede5cedd5..36adc462d 100644 --- a/artiq/firmware/libproto/kernel_proto.rs +++ b/artiq/firmware/libproto/kernel_proto.rs @@ -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 }, diff --git a/artiq/firmware/runtime/rtio_dma.rs b/artiq/firmware/runtime/rtio_dma.rs index a8d624462..118048ec2 100644 --- a/artiq/firmware/runtime/rtio_dma.rs +++ b/artiq/firmware/runtime/rtio_dma.rs @@ -9,7 +9,8 @@ const ALIGNMENT: usize = 64; #[derive(Debug)] struct Entry { data: Vec, - 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) -> R, R>(&self, name: &str, f: F) -> R { - f(self.entries - .get(name) - .map(|entry| &entry.data[entry.padding..])) + pub fn with_trace(&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) + } } } diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index b2218bce1..871cd15e4 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -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 + }) }) } diff --git a/artiq/test/coredevice/test_rtio.py b/artiq/test/coredevice/test_rtio.py index 9ceb01129..f4da5b3b9 100644 --- a/artiq/test/coredevice/test_rtio.py +++ b/artiq/test/coredevice/test_rtio.py @@ -2,6 +2,7 @@ # Copyright (C) 2014, 2015 Robert Jordens 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)