forked from M-Labs/artiq-zynq
implement core device cache
This commit is contained in:
parent
673ad3fd8e
commit
7f983a453d
|
@ -12,6 +12,11 @@ device_db = {
|
||||||
"target": "cortexa9"
|
"target": "cortexa9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"core_cache": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.cache",
|
||||||
|
"class": "CoreCache"
|
||||||
|
},
|
||||||
"core_dma": {
|
"core_dma": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.dma",
|
"module": "artiq.coredevice.dma",
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::eh_artiq;
|
||||||
use crate::rtio;
|
use crate::rtio;
|
||||||
use super::rpc::{rpc_send, rpc_send_async, rpc_recv};
|
use super::rpc::{rpc_send, rpc_send_async, rpc_recv};
|
||||||
use super::dma;
|
use super::dma;
|
||||||
|
use super::cache;
|
||||||
|
|
||||||
macro_rules! api {
|
macro_rules! api {
|
||||||
($i:ident) => ({
|
($i:ident) => ({
|
||||||
|
@ -58,6 +59,10 @@ pub fn resolve(required: &[u8]) -> Option<u32> {
|
||||||
api!(dma_retrieve = dma::dma_retrieve),
|
api!(dma_retrieve = dma::dma_retrieve),
|
||||||
api!(dma_playback = dma::dma_playback),
|
api!(dma_playback = dma::dma_playback),
|
||||||
|
|
||||||
|
// cache
|
||||||
|
api!(cache_get = cache::get),
|
||||||
|
api!(cache_put = cache::put),
|
||||||
|
|
||||||
// Double-precision floating-point arithmetic helper functions
|
// Double-precision floating-point arithmetic helper functions
|
||||||
// RTABI chapter 4.1.2, Table 2
|
// RTABI chapter 4.1.2, Table 2
|
||||||
api!(__aeabi_dadd),
|
api!(__aeabi_dadd),
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ use super::{
|
||||||
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
||||||
KERNEL_IMAGE,
|
KERNEL_IMAGE,
|
||||||
Message,
|
Message,
|
||||||
|
cache
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
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_rx = core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), None).unwrap();
|
||||||
core1_tx = core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), None).unwrap();
|
core1_tx = core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), None).unwrap();
|
||||||
}
|
}
|
||||||
|
unsafe { cache::unborrow(); }
|
||||||
info!("kernel finished");
|
info!("kernel finished");
|
||||||
core1_tx.send(Message::KernelFinished);
|
core1_tx.send(Message::KernelFinished);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +182,8 @@ pub fn main_core1() {
|
||||||
|
|
||||||
/// Called by eh_artiq
|
/// Called by eh_artiq
|
||||||
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
||||||
|
unsafe { cache::unborrow(); }
|
||||||
|
|
||||||
let load_addr = unsafe {
|
let load_addr = unsafe {
|
||||||
KERNEL_IMAGE.as_ref().unwrap().get_load_addr()
|
KERNEL_IMAGE.as_ref().unwrap().get_load_addr()
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub mod core1;
|
||||||
mod api;
|
mod api;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod dma;
|
mod dma;
|
||||||
|
mod cache;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RPCException {
|
pub struct RPCException {
|
||||||
|
|
Loading…
Reference in New Issue