implement core device cache

This commit is contained in:
Sebastien Bourdeauducq 2020-07-25 17:04:40 +08:00
parent 673ad3fd8e
commit 7f983a453d
5 changed files with 94 additions and 0 deletions

View File

@ -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",

View File

@ -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<u32> {
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),

View File

@ -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<i32>,
borrowed: bool
}
#[derive(Debug)]
struct Cache {
entries: BTreeMap<String, Entry>
}
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<Cache> = Mutex::new(Cache::new());
pub extern fn get(key: CSlice<u8>) -> 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<u8>, list: CSlice<i32>) {
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();
}

View File

@ -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()
};

View File

@ -10,6 +10,7 @@ pub mod core1;
mod api;
mod rpc;
mod dma;
mod cache;
#[derive(Debug)]
pub struct RPCException {