From 7f983a453d06dc46efa348f94f42b1682abcf278 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 25 Jul 2020 17:04:40 +0800 Subject: [PATCH] implement core device cache --- examples/device_db.py | 5 +++ src/runtime/src/kernel/api.rs | 5 +++ src/runtime/src/kernel/cache.rs | 79 +++++++++++++++++++++++++++++++++ src/runtime/src/kernel/core1.rs | 4 ++ src/runtime/src/kernel/mod.rs | 1 + 5 files changed, 94 insertions(+) create mode 100644 src/runtime/src/kernel/cache.rs diff --git a/examples/device_db.py b/examples/device_db.py index 9110390..105d50f 100644 --- a/examples/device_db.py +++ b/examples/device_db.py @@ -12,6 +12,11 @@ device_db = { "target": "cortexa9" } }, + "core_cache": { + "type": "local", + "module": "artiq.coredevice.cache", + "class": "CoreCache" + }, "core_dma": { "type": "local", "module": "artiq.coredevice.dma", diff --git a/src/runtime/src/kernel/api.rs b/src/runtime/src/kernel/api.rs index ae68fc5..f798d84 100644 --- a/src/runtime/src/kernel/api.rs +++ b/src/runtime/src/kernel/api.rs @@ -4,6 +4,7 @@ use crate::eh_artiq; use crate::rtio; use super::rpc::{rpc_send, rpc_send_async, rpc_recv}; use super::dma; +use super::cache; macro_rules! api { ($i:ident) => ({ @@ -58,6 +59,10 @@ pub fn resolve(required: &[u8]) -> Option { api!(dma_retrieve = dma::dma_retrieve), api!(dma_playback = dma::dma_playback), + // cache + api!(cache_get = cache::get), + api!(cache_put = cache::put), + // Double-precision floating-point arithmetic helper functions // RTABI chapter 4.1.2, Table 2 api!(__aeabi_dadd), diff --git a/src/runtime/src/kernel/cache.rs b/src/runtime/src/kernel/cache.rs new file mode 100644 index 0000000..1d2b1c5 --- /dev/null +++ b/src/runtime/src/kernel/cache.rs @@ -0,0 +1,79 @@ +use alloc::{string::String, vec::Vec, collections::BTreeMap}; +use libcortex_a9::mutex::Mutex; +use cslice::{CSlice, AsCSlice}; +use core::mem::transmute; +use core::str; +use log::debug; + +use crate::artiq_raise; + + +#[derive(Debug)] +struct Entry { + data: Vec, + borrowed: bool +} + +#[derive(Debug)] +struct Cache { + entries: BTreeMap +} + +impl Cache { + pub const fn new() -> Cache { + Cache { entries: BTreeMap::new() } + } + + pub fn get(&mut self, key: &str) -> *const [i32] { + match self.entries.get_mut(key) { + None => &[], + Some(ref mut entry) => { + entry.borrowed = true; + &entry.data[..] + } + } + } + + pub fn put(&mut self, key: &str, data: &[i32]) -> Result<(), ()> { + match self.entries.get_mut(key) { + None => (), + Some(ref mut entry) => { + if entry.borrowed { return Err(()) } + entry.data = Vec::from(data); + return Ok(()) + } + } + + self.entries.insert(String::from(key), Entry { + data: Vec::from(data), + borrowed: false + }); + Ok(()) + } + + pub unsafe fn unborrow(&mut self) { + for (_key, entry) in self.entries.iter_mut() { + entry.borrowed = false; + } + } +} + +static CACHE: Mutex = Mutex::new(Cache::new()); + +pub extern fn get(key: CSlice) -> CSlice<'static, i32> { + let value = CACHE.lock().get(str::from_utf8(key.as_ref()).unwrap()); + unsafe { + transmute::<*const [i32], &'static [i32]>(value).as_c_slice() + } +} + +pub extern fn put(key: CSlice, list: CSlice) { + let result = CACHE.lock().put(str::from_utf8(key.as_ref()).unwrap(), list.as_ref()); + if result.is_err() { + artiq_raise!("CacheError", "cannot put into a busy cache row"); + } +} + +pub unsafe fn unborrow() { + CACHE.lock().unborrow(); +} diff --git a/src/runtime/src/kernel/core1.rs b/src/runtime/src/kernel/core1.rs index 000306f..b5c619c 100644 --- a/src/runtime/src/kernel/core1.rs +++ b/src/runtime/src/kernel/core1.rs @@ -19,6 +19,7 @@ use super::{ KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE, Message, + cache }; unsafe fn attribute_writeback(typeinfo: *const ()) { @@ -170,6 +171,7 @@ pub fn main_core1() { core1_rx = core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), None).unwrap(); core1_tx = core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), None).unwrap(); } + unsafe { cache::unborrow(); } info!("kernel finished"); core1_tx.send(Message::KernelFinished); } @@ -180,6 +182,8 @@ pub fn main_core1() { /// Called by eh_artiq pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! { + unsafe { cache::unborrow(); } + let load_addr = unsafe { KERNEL_IMAGE.as_ref().unwrap().get_load_addr() }; diff --git a/src/runtime/src/kernel/mod.rs b/src/runtime/src/kernel/mod.rs index 10451a7..b3d94fb 100644 --- a/src/runtime/src/kernel/mod.rs +++ b/src/runtime/src/kernel/mod.rs @@ -10,6 +10,7 @@ pub mod core1; mod api; mod rpc; mod dma; +mod cache; #[derive(Debug)] pub struct RPCException {