From 6885c618b5bbc760fa377ec92fb1e6dac06e633e Mon Sep 17 00:00:00 2001 From: mwojcik Date: Mon, 4 Sep 2023 16:04:42 +0800 Subject: [PATCH] move kernel-related code to separate library --- src/Cargo.lock | 30 ++- src/libkernel/Cargo.toml | 33 +++ src/libkernel/build.rs | 5 + src/{runtime => libkernel}/src/eh_artiq.rs | 0 src/{runtime => libkernel}/src/i2c.rs | 0 src/{runtime => libkernel}/src/irq.rs | 0 src/{runtime => libkernel}/src/kernel/api.rs | 2 + .../src/kernel/cache.rs | 0 .../src/kernel/control.rs | 4 +- .../src/kernel/core1.rs | 0 src/{runtime => libkernel}/src/kernel/dma.rs | 0 src/libkernel/src/kernel/mod.rs | 27 ++ src/{runtime => libkernel}/src/kernel/rpc.rs | 0 .../src/kernel/subkernel.rs | 4 +- src/libkernel/src/lib.rs | 243 ++++++++++++++++++ src/{runtime => libkernel}/src/rpc.rs | 128 ++++----- src/{runtime => libkernel}/src/rtio_acp.rs | 2 +- src/{runtime => libkernel}/src/rtio_csr.rs | 2 +- src/runtime/Cargo.toml | 3 +- src/runtime/src/comms.rs | 41 ++- src/runtime/src/kernel/mod.rs | 132 ---------- src/runtime/src/main.rs | 89 +------ src/runtime/src/rpc_async.rs | 197 ++++++++++++++ src/runtime/src/rtio_clocking.rs | 5 +- src/runtime/src/rtio_dma.rs | 3 +- src/runtime/src/rtio_mgt.rs | 55 +--- 26 files changed, 621 insertions(+), 384 deletions(-) create mode 100644 src/libkernel/Cargo.toml create mode 100644 src/libkernel/build.rs rename src/{runtime => libkernel}/src/eh_artiq.rs (100%) rename src/{runtime => libkernel}/src/i2c.rs (100%) rename src/{runtime => libkernel}/src/irq.rs (100%) rename src/{runtime => libkernel}/src/kernel/api.rs (99%) rename src/{runtime => libkernel}/src/kernel/cache.rs (100%) rename src/{runtime => libkernel}/src/kernel/control.rs (92%) rename src/{runtime => libkernel}/src/kernel/core1.rs (100%) rename src/{runtime => libkernel}/src/kernel/dma.rs (100%) create mode 100644 src/libkernel/src/kernel/mod.rs rename src/{runtime => libkernel}/src/kernel/rpc.rs (100%) rename src/{runtime => libkernel}/src/kernel/subkernel.rs (96%) create mode 100644 src/libkernel/src/lib.rs rename src/{runtime => libkernel}/src/rpc.rs (84%) rename src/{runtime => libkernel}/src/rtio_acp.rs (99%) rename src/{runtime => libkernel}/src/rtio_csr.rs (99%) delete mode 100644 src/runtime/src/kernel/mod.rs create mode 100644 src/runtime/src/rpc_async.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index c56fdb5..57906b5 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -218,6 +218,33 @@ dependencies = [ "libsupport_zynq", ] +[[package]] +name = "kernel" +version = "0.1.0" +dependencies = [ + "build_zynq", + "byteorder", + "core_io", + "cslice", + "dwarf", + "dyld", + "io", + "libasync", + "libboard_artiq", + "libboard_zynq", + "libc", + "libconfig", + "libcortex_a9", + "libm", + "libregister", + "libsupport_zynq", + "log", + "log_buffer", + "nb 0.1.3", + "unwind", + "void", +] + [[package]] name = "libasync" version = "0.0.0" @@ -438,18 +465,17 @@ dependencies = [ "embedded-hal", "futures", "io", + "kernel", "libasync", "libboard_artiq", "libboard_zynq", "libc", "libconfig", "libcortex_a9", - "libm", "libregister", "libsupport_zynq", "log", "log_buffer", - "nb 0.1.3", "num-derive", "num-traits", "unwind", diff --git a/src/libkernel/Cargo.toml b/src/libkernel/Cargo.toml new file mode 100644 index 0000000..0d63344 --- /dev/null +++ b/src/libkernel/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "kernel" +description = "Kernel support for Zynq-based platforms" +version = "0.1.0" +authors = ["M-Labs"] +edition = "2018" + +[build-dependencies] +build_zynq = { path = "../libbuild_zynq" } + +[dependencies] +cslice = "0.3" +log = "0.4" +nb = "0.1" +core_io = { version = "0.1", features = ["collections"] } +byteorder = { version = "1.3", default-features = false } +void = { version = "1", default-features = false } +log_buffer = { version = "1.2" } +libm = { version = "0.2", features = ["unstable"] } + +libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["ipv6"]} +libsupport_zynq = { default-features = false, features = ["alloc_core"], git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libasync = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libregister = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libconfig = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["fat_lfn", "ipv6"] } + +dyld = { path = "../libdyld" } +dwarf = { path = "../libdwarf" } +unwind = { path = "../libunwind" } +libc = { path = "../libc" } +io = { path = "../libio" } +libboard_artiq = { path = "../libboard_artiq" } \ No newline at end of file diff --git a/src/libkernel/build.rs b/src/libkernel/build.rs new file mode 100644 index 0000000..ba3b31b --- /dev/null +++ b/src/libkernel/build.rs @@ -0,0 +1,5 @@ +extern crate build_zynq; + +fn main() { + build_zynq::cfg(); +} diff --git a/src/runtime/src/eh_artiq.rs b/src/libkernel/src/eh_artiq.rs similarity index 100% rename from src/runtime/src/eh_artiq.rs rename to src/libkernel/src/eh_artiq.rs diff --git a/src/runtime/src/i2c.rs b/src/libkernel/src/i2c.rs similarity index 100% rename from src/runtime/src/i2c.rs rename to src/libkernel/src/i2c.rs diff --git a/src/runtime/src/irq.rs b/src/libkernel/src/irq.rs similarity index 100% rename from src/runtime/src/irq.rs rename to src/libkernel/src/irq.rs diff --git a/src/runtime/src/kernel/api.rs b/src/libkernel/src/kernel/api.rs similarity index 99% rename from src/runtime/src/kernel/api.rs rename to src/libkernel/src/kernel/api.rs index 87b57ae..479525e 100644 --- a/src/runtime/src/kernel/api.rs +++ b/src/libkernel/src/kernel/api.rs @@ -5,6 +5,8 @@ use libc::{c_char, c_int, size_t}; use libm; use log::{info, warn}; +#[cfg(has_drtio)] +use super::subkernel; use super::{cache, core1::rtio_get_destination_status, dma, diff --git a/src/runtime/src/kernel/cache.rs b/src/libkernel/src/kernel/cache.rs similarity index 100% rename from src/runtime/src/kernel/cache.rs rename to src/libkernel/src/kernel/cache.rs diff --git a/src/runtime/src/kernel/control.rs b/src/libkernel/src/kernel/control.rs similarity index 92% rename from src/runtime/src/kernel/control.rs rename to src/libkernel/src/kernel/control.rs index fcd35dc..7d03236 100644 --- a/src/runtime/src/kernel/control.rs +++ b/src/libkernel/src/kernel/control.rs @@ -3,8 +3,8 @@ use core::mem::{forget, replace}; use libcortex_a9::sync_channel::{Receiver, Sender}; use libsupport_zynq::boot::Core1; -use super::{Message, CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK}; -use crate::irq::restart_core1; +use super::{CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK}; +use crate::{irq::restart_core1, Message}; pub struct Control { pub tx: Sender<'static, Message>, diff --git a/src/runtime/src/kernel/core1.rs b/src/libkernel/src/kernel/core1.rs similarity index 100% rename from src/runtime/src/kernel/core1.rs rename to src/libkernel/src/kernel/core1.rs diff --git a/src/runtime/src/kernel/dma.rs b/src/libkernel/src/kernel/dma.rs similarity index 100% rename from src/runtime/src/kernel/dma.rs rename to src/libkernel/src/kernel/dma.rs diff --git a/src/libkernel/src/kernel/mod.rs b/src/libkernel/src/kernel/mod.rs new file mode 100644 index 0000000..6e02c60 --- /dev/null +++ b/src/libkernel/src/kernel/mod.rs @@ -0,0 +1,27 @@ +use core::ptr; + +use libcortex_a9::{mutex::Mutex, semaphore::Semaphore, sync_channel}; + +use crate::Message; + +mod control; +pub use control::Control; +mod api; +pub mod core1; +mod dma; +mod rpc; +pub use dma::DmaRecorder; +mod cache; +#[cfg(has_drtio)] +mod subkernel; + +static CHANNEL_0TO1: Mutex>> = Mutex::new(None); +static CHANNEL_1TO0: Mutex>> = Mutex::new(None); +static CHANNEL_SEM: Semaphore = Semaphore::new(0, 1); + +static mut KERNEL_CHANNEL_0TO1: Option> = None; +static mut KERNEL_CHANNEL_1TO0: Option> = None; + +pub static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null(); + +static INIT_LOCK: Mutex<()> = Mutex::new(()); diff --git a/src/runtime/src/kernel/rpc.rs b/src/libkernel/src/kernel/rpc.rs similarity index 100% rename from src/runtime/src/kernel/rpc.rs rename to src/libkernel/src/kernel/rpc.rs diff --git a/src/runtime/src/kernel/subkernel.rs b/src/libkernel/src/kernel/subkernel.rs similarity index 96% rename from src/runtime/src/kernel/subkernel.rs rename to src/libkernel/src/kernel/subkernel.rs index f5fbf49..870070e 100644 --- a/src/runtime/src/kernel/subkernel.rs +++ b/src/libkernel/src/kernel/subkernel.rs @@ -2,8 +2,8 @@ use alloc::vec::Vec; use cslice::CSlice; -use super::{Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0}; -use crate::{artiq_raise, rpc::send_args}; +use super::{KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0}; +use crate::{artiq_raise, rpc::send_args, Message, SubkernelStatus}; pub extern "C" fn load_run(id: u32, run: bool) { unsafe { diff --git a/src/libkernel/src/lib.rs b/src/libkernel/src/lib.rs new file mode 100644 index 0000000..8074ebc --- /dev/null +++ b/src/libkernel/src/lib.rs @@ -0,0 +1,243 @@ +#![no_std] +#![feature(c_variadic)] +#![feature(const_btree_new)] +#![feature(const_in_array_repeat_expressions)] +#![feature(naked_functions)] +#![feature(asm)] + +#[macro_use] +extern crate alloc; + +use alloc::{collections::BTreeMap, string::String, vec::Vec}; + +use io::{Cursor, ProtoRead}; +pub use kernel::{Control, DmaRecorder}; +use libasync::block_async; +use libconfig::Config; +use log::{error, warn}; +use void::Void; + +pub mod eh_artiq; +pub mod i2c; +pub mod irq; +pub mod kernel; +pub mod rpc; +#[cfg(ki_impl = "csr")] +#[path = "rtio_csr.rs"] +pub mod rtio; +#[cfg(ki_impl = "acp")] +#[path = "rtio_acp.rs"] +pub mod rtio; +#[rustfmt::skip] +#[path = "../../../build/pl.rs"] +pub mod pl; + + +#[derive(Debug, Clone)] +pub struct RPCException { + pub id: u32, + pub message: u32, + pub param: [i64; 3], + pub file: u32, + pub line: i32, + pub column: i32, + pub function: u32, +} + +#[cfg(has_drtio)] +#[derive(Debug, Clone)] +pub enum SubkernelStatus { + NoError, + Timeout, + IncorrectState, + CommLost, + OtherError, +} + +#[derive(Debug, Clone)] +pub enum Message { + LoadRequest(Vec), + LoadCompleted, + LoadFailed, + StartRequest, + KernelFinished(u8), + KernelException( + &'static [Option>], + &'static [eh_artiq::StackPointerBacktrace], + &'static [(usize, usize)], + u8, + ), + RpcSend { + is_async: bool, + data: Vec, + }, + RpcRecvRequest(*mut ()), + RpcRecvReply(Result), + + CacheGetRequest(String), + CacheGetReply(Vec), + CachePutRequest(String, Vec), + + DmaPutRequest(DmaRecorder), + DmaEraseRequest(String), + DmaGetRequest(String), + DmaGetReply(Option<(i32, i64, bool)>), + #[cfg(has_drtio)] + DmaStartRemoteRequest { + id: i32, + timestamp: i64, + }, + #[cfg(has_drtio)] + DmaAwaitRemoteRequest(i32), + #[cfg(has_drtio)] + DmaAwaitRemoteReply { + timeout: bool, + error: u8, + channel: u32, + timestamp: u64, + }, + + #[cfg(has_drtio)] + UpDestinationsRequest(i32), + #[cfg(has_drtio)] + UpDestinationsReply(bool), + + #[cfg(has_drtio)] + SubkernelLoadRunRequest { + id: u32, + run: bool, + }, + #[cfg(has_drtio)] + SubkernelLoadRunReply { + succeeded: bool, + }, + #[cfg(has_drtio)] + SubkernelAwaitFinishRequest { + id: u32, + timeout: u64, + }, + #[cfg(has_drtio)] + SubkernelAwaitFinishReply { + status: SubkernelStatus, + }, + #[cfg(has_drtio)] + SubkernelMsgSend { + id: u32, + data: Vec, + }, + #[cfg(has_drtio)] + SubkernelMsgRecvRequest { + id: u32, + timeout: u64, + }, + #[cfg(has_drtio)] + SubkernelMsgRecvReply { + status: SubkernelStatus, + count: u8, + }, +} + +pub static mut SEEN_ASYNC_ERRORS: u8 = 0; + +pub const ASYNC_ERROR_COLLISION: u8 = 1 << 0; +pub const ASYNC_ERROR_BUSY: u8 = 1 << 1; +pub const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2; + +pub unsafe fn get_async_errors() -> u8 { + let errors = SEEN_ASYNC_ERRORS; + SEEN_ASYNC_ERRORS = 0; + errors +} + +fn wait_for_async_rtio_error() -> nb::Result<(), Void> { + unsafe { + if pl::csr::rtio_core::async_error_read() != 0 { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } +} + +pub async fn report_async_rtio_errors() { + loop { + let _ = block_async!(wait_for_async_rtio_error()).await; + unsafe { + let errors = pl::csr::rtio_core::async_error_read(); + if errors & ASYNC_ERROR_COLLISION != 0 { + let channel = pl::csr::rtio_core::collision_channel_read(); + error!( + "RTIO collision involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + if errors & ASYNC_ERROR_BUSY != 0 { + let channel = pl::csr::rtio_core::busy_channel_read(); + error!( + "RTIO busy error involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 { + let channel = pl::csr::rtio_core::sequence_error_channel_read(); + error!( + "RTIO sequence error involving channel 0x{:04x}:{}", + channel, + resolve_channel_name(channel as u32) + ); + } + SEEN_ASYNC_ERRORS = errors; + pl::csr::rtio_core::async_error_write(errors); + } + } +} + +static mut RTIO_DEVICE_MAP: BTreeMap = BTreeMap::new(); + +fn read_device_map(cfg: &Config) -> BTreeMap { + let mut device_map: BTreeMap = BTreeMap::new(); + let _ = cfg + .read("device_map") + .and_then(|raw_bytes| { + let mut bytes_cr = Cursor::new(raw_bytes); + let size = bytes_cr.read_u32().unwrap(); + for _ in 0..size { + let channel = bytes_cr.read_u32().unwrap(); + let device_name = bytes_cr.read_string().unwrap(); + if let Some(old_entry) = device_map.insert(channel, device_name.clone()) { + warn!( + "conflicting device map entries for RTIO channel {}: '{}' and '{}'", + channel, old_entry, device_name + ); + } + } + Ok(()) + }) + .or_else(|err| { + warn!( + "error reading device map ({}), device names will not be available in RTIO error messages", + err + ); + Err(err) + }); + device_map +} + +fn _resolve_channel_name(channel: u32, device_map: &BTreeMap) -> String { + match device_map.get(&channel) { + Some(val) => val.clone(), + None => String::from("unknown"), + } +} + +pub fn resolve_channel_name(channel: u32) -> String { + _resolve_channel_name(channel, unsafe { &RTIO_DEVICE_MAP }) +} + +pub fn setup_device_map(cfg: &Config) { + unsafe { + RTIO_DEVICE_MAP = read_device_map(cfg); + } +} diff --git a/src/runtime/src/rpc.rs b/src/libkernel/src/rpc.rs similarity index 84% rename from src/runtime/src/rpc.rs rename to src/libkernel/src/rpc.rs index 6ca5d02..cdcd302 100644 --- a/src/runtime/src/rpc.rs +++ b/src/libkernel/src/rpc.rs @@ -1,75 +1,62 @@ -use alloc::boxed::Box; -#[cfg(has_drtio)] -use alloc::vec::Vec; -use core::{future::Future, str}; +use core::str; -use async_recursion::async_recursion; use byteorder::{ByteOrder, NativeEndian}; -use core_io::{Error, Write}; +use core_io::{Error, Read, Write}; use cslice::{CMutSlice, CSlice}; -#[cfg(has_drtio)] -use io::{Cursor, ProtoRead}; -use io::ProtoWrite; -use libasync::smoltcp::TcpStream; -use libboard_zynq::smoltcp; +use io::{ProtoRead, ProtoWrite}; use log::trace; use self::tag::{split_tag, Tag, TagIterator}; -use crate::proto_async; #[inline] -fn round_up(val: usize, power_of_two: usize) -> usize { +pub fn round_up(val: usize, power_of_two: usize) -> usize { assert!(power_of_two.is_power_of_two()); let max_rem = power_of_two - 1; (val + max_rem) & (!max_rem) } #[inline] -unsafe fn round_up_mut(ptr: *mut T, power_of_two: usize) -> *mut T { +pub unsafe fn round_up_mut(ptr: *mut T, power_of_two: usize) -> *mut T { round_up(ptr as usize, power_of_two) as *mut T } #[inline] -unsafe fn round_up_const(ptr: *const T, power_of_two: usize) -> *const T { +pub unsafe fn round_up_const(ptr: *const T, power_of_two: usize) -> *const T { round_up(ptr as usize, power_of_two) as *const T } #[inline] -unsafe fn align_ptr(ptr: *const ()) -> *const T { +pub unsafe fn align_ptr(ptr: *const ()) -> *const T { round_up_const(ptr, core::mem::align_of::()) as *const T } #[inline] -unsafe fn align_ptr_mut(ptr: *mut ()) -> *mut T { +pub unsafe fn align_ptr_mut(ptr: *mut ()) -> *mut T { round_up_mut(ptr, core::mem::align_of::()) as *mut T } -/// Reads (deserializes) `length` array or list elements of type `tag` from `stream`, -/// writing them into the buffer given by `storage`. -/// -/// `alloc` is used for nested allocations (if elements themselves contain -/// lists/arrays), see [recv_value]. -#[async_recursion(?Send)] -async unsafe fn recv_elements( - stream: &TcpStream, - elt_tag: Tag<'async_recursion>, +// versions for reader rather than TcpStream +// they will be made into sync for satellite subkernels later +unsafe fn recv_elements( + reader: &mut R, + elt_tag: Tag, length: usize, storage: *mut (), - alloc: &(impl Fn(usize) -> F + 'async_recursion), -) -> Result<(), smoltcp::Error> + alloc: &F, +) -> Result<(), Error> where - F: Future, + F: Fn(usize) -> *mut (), + R: Read + ?Sized, { - // List of simple types are special-cased in the protocol for performance. match elt_tag { Tag::Bool => { let dest = core::slice::from_raw_parts_mut(storage as *mut u8, length); - proto_async::read_chunk(stream, dest).await?; + reader.read_exact(dest)?; } Tag::Int32 => { let ptr = storage as *mut u32; let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4); - proto_async::read_chunk(stream, dest).await?; + reader.read_exact(dest)?; drop(dest); let dest = core::slice::from_raw_parts_mut(ptr, length); NativeEndian::from_slice_u32(dest); @@ -77,7 +64,7 @@ where Tag::Int64 | Tag::Float64 => { let ptr = storage as *mut u64; let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8); - proto_async::read_chunk(stream, dest).await?; + reader.read_exact(dest)?; drop(dest); let dest = core::slice::from_raw_parts_mut(ptr, length); NativeEndian::from_slice_u64(dest); @@ -85,27 +72,17 @@ where _ => { let mut data = storage; for _ in 0..length { - recv_value(stream, elt_tag, &mut data, alloc).await? + recv_value(reader, elt_tag, &mut data, alloc)? } } } Ok(()) } -/// Reads (deserializes) a value of type `tag` from `stream`, writing the results to -/// the kernel-side buffer `data` (the passed pointer to which is incremented to point -/// past the just-received data). For nested allocations (lists/arrays), `alloc` is -/// invoked any number of times with the size of the required allocation as a parameter -/// (which is assumed to be correctly aligned for all payload types). -#[async_recursion(?Send)] -async unsafe fn recv_value( - stream: &TcpStream, - tag: Tag<'async_recursion>, - data: &mut *mut (), - alloc: &(impl Fn(usize) -> F + 'async_recursion), -) -> Result<(), smoltcp::Error> +unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), alloc: &F) -> Result<(), Error> where - F: Future, + F: Fn(usize) -> *mut (), + R: Read + ?Sized, { macro_rules! consume_value { ($ty:ty, | $ptr:ident | $map:expr) => {{ @@ -118,22 +95,22 @@ where match tag { Tag::None => Ok(()), Tag::Bool => consume_value!(i8, |ptr| { - *ptr = proto_async::read_i8(stream).await?; + *ptr = reader.read_u8()? as i8; Ok(()) }), Tag::Int32 => consume_value!(i32, |ptr| { - *ptr = proto_async::read_i32(stream).await?; + *ptr = reader.read_u32()? as i32; Ok(()) }), Tag::Int64 | Tag::Float64 => consume_value!(i64, |ptr| { - *ptr = proto_async::read_i64(stream).await?; + *ptr = reader.read_u64()? as i64; Ok(()) }), Tag::String | Tag::Bytes | Tag::ByteArray => { consume_value!(CMutSlice, |ptr| { - let length = proto_async::read_i32(stream).await? as usize; - *ptr = CMutSlice::new(alloc(length).await as *mut u8, length); - proto_async::read_chunk(stream, (*ptr).as_mut()).await?; + let length = reader.read_u32()? as usize; + *ptr = CMutSlice::new(alloc(length) as *mut u8, length); + reader.read_exact((*ptr).as_mut())?; Ok(()) }) } @@ -143,10 +120,8 @@ where let mut it = it.clone(); for _ in 0..arity { let tag = it.next().expect("truncated tag"); - recv_value(stream, tag, data, alloc).await? + recv_value(reader, tag, data, alloc)? } - // Take into account any tail padding (if element(s) with largest alignment - // are not at the end). *data = round_up_mut(*data, alignment); Ok(()) } @@ -158,50 +133,41 @@ where } consume_value!(*mut List, |ptr_to_list| { let tag = it.clone().next().expect("truncated tag"); - let length = proto_async::read_i32(stream).await? as usize; + let length = reader.read_u32()? as usize; - // To avoid multiple kernel CPU roundtrips, use a single allocation for - // both the pointer/length List (slice) and the backing storage for the - // elements. We can assume that alloc() is aligned suitably, so just - // need to take into account any extra padding required. - // (Note: At the time of writing, there will never actually be any types - // with alignment larger than 8 bytes, so storage_offset == 0 always.) let list_size = 4 + 4; let storage_offset = round_up(list_size, tag.alignment()); let storage_size = tag.size() * length; - let allocation = alloc(storage_offset + storage_size).await as *mut u8; + let allocation = alloc(storage_offset + storage_size) as *mut u8; *ptr_to_list = allocation as *mut List; let storage = allocation.offset(storage_offset as isize) as *mut (); (**ptr_to_list).length = length; (**ptr_to_list).elements = storage; - recv_elements(stream, tag, length, storage, alloc).await + recv_elements(reader, tag, length, storage, alloc) }) } Tag::Array(it, num_dims) => { consume_value!(*mut (), |buffer| { - // Deserialize length along each dimension and compute total number of - // elements. let mut total_len: usize = 1; for _ in 0..num_dims { - let len = proto_async::read_i32(stream).await? as usize; + let len = reader.read_u32()? as usize; total_len *= len; consume_value!(usize, |ptr| *ptr = len) } - // Allocate backing storage for elements; deserialize them. let elt_tag = it.clone().next().expect("truncated tag"); - *buffer = alloc(elt_tag.size() * total_len).await; - recv_elements(stream, elt_tag, total_len, *buffer, alloc).await + *buffer = alloc(elt_tag.size() * total_len); + recv_elements(reader, elt_tag, total_len, *buffer, alloc) }) } Tag::Range(it) => { *data = round_up_mut(*data, tag.alignment()); let tag = it.clone().next().expect("truncated tag"); - recv_value(stream, tag, data, alloc).await?; - recv_value(stream, tag, data, alloc).await?; - recv_value(stream, tag, data, alloc).await?; + recv_value(reader, tag, data, alloc)?; + recv_value(reader, tag, data, alloc)?; + recv_value(reader, tag, data, alloc)?; Ok(()) } Tag::Keyword(_) => unreachable!(), @@ -209,21 +175,17 @@ where } } -pub async fn recv_return( - stream: &TcpStream, - tag_bytes: &[u8], - data: *mut (), - alloc: &impl Fn(usize) -> F, -) -> Result<(), smoltcp::Error> +pub fn recv_return(reader: &mut R, tag_bytes: &[u8], data: *mut (), alloc: &F) -> Result<(), Error> where - F: Future, + F: Fn(usize) -> *mut (), + R: Read + ?Sized, { let mut it = TagIterator::new(tag_bytes); trace!("recv ...->{}", it); let tag = it.next().expect("truncated tag"); let mut data = data; - unsafe { recv_value(stream, tag, &mut data, alloc).await? }; + unsafe { recv_value(reader, tag, &mut data, alloc)? }; Ok(()) } @@ -538,7 +500,7 @@ where W: Write + ?Sized { Ok(()) } -mod tag { +pub mod tag { use core::fmt; pub fn split_tag(tag_bytes: &[u8]) -> (&[u8], &[u8]) { diff --git a/src/runtime/src/rtio_acp.rs b/src/libkernel/src/rtio_acp.rs similarity index 99% rename from src/runtime/src/rtio_acp.rs rename to src/libkernel/src/rtio_acp.rs index 1b71590..e820db9 100644 --- a/src/runtime/src/rtio_acp.rs +++ b/src/libkernel/src/rtio_acp.rs @@ -4,7 +4,7 @@ use cslice::CSlice; use libcortex_a9::asm; use vcell::VolatileCell; -use crate::{artiq_raise, pl::csr, rtio_mgt::resolve_channel_name}; +use crate::{artiq_raise, pl::csr, resolve_channel_name}; pub const RTIO_O_STATUS_WAIT: i32 = 1; pub const RTIO_O_STATUS_UNDERFLOW: i32 = 2; diff --git a/src/runtime/src/rtio_csr.rs b/src/libkernel/src/rtio_csr.rs similarity index 99% rename from src/runtime/src/rtio_csr.rs rename to src/libkernel/src/rtio_csr.rs index ca710c0..bb983c4 100644 --- a/src/runtime/src/rtio_csr.rs +++ b/src/libkernel/src/rtio_csr.rs @@ -2,7 +2,7 @@ use core::ptr::{read_volatile, write_volatile}; use cslice::CSlice; -use crate::{artiq_raise, pl::csr, rtio_mgt::resolve_channel_name}; +use crate::{artiq_raise, pl::csr, resolve_channel_name}; pub const RTIO_O_STATUS_WAIT: u8 = 1; pub const RTIO_O_STATUS_UNDERFLOW: u8 = 2; diff --git a/src/runtime/Cargo.toml b/src/runtime/Cargo.toml index b5c5e69..0903d7b 100644 --- a/src/runtime/Cargo.toml +++ b/src/runtime/Cargo.toml @@ -18,7 +18,6 @@ num-traits = { version = "0.2", default-features = false } num-derive = "0.3" cslice = "0.3" log = "0.4" -nb = "0.1" embedded-hal = "0.2" core_io = { version = "0.1", features = ["collections"] } byteorder = { version = "1.3", default-features = false } @@ -26,7 +25,6 @@ void = { version = "1", default-features = false } futures = { version = "0.3", default-features = false, features = ["async-await"] } async-recursion = "0.3" log_buffer = { version = "1.2" } -libm = { version = "0.2", features = ["unstable"] } vcell = "0.1" libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["ipv6"]} @@ -41,4 +39,5 @@ dwarf = { path = "../libdwarf" } unwind = { path = "../libunwind" } libc = { path = "../libc" } io = { path = "../libio" } +kernel = { path = "../libkernel" } libboard_artiq = { path = "../libboard_artiq" } \ No newline at end of file diff --git a/src/runtime/src/comms.rs b/src/runtime/src/comms.rs index b081821..e43ab1f 100644 --- a/src/runtime/src/comms.rs +++ b/src/runtime/src/comms.rs @@ -6,6 +6,9 @@ use cslice::CSlice; use futures::{future::FutureExt, select_biased}; #[cfg(has_drtio)] use io::{Cursor, ProtoRead}; +use kernel::resolve_channel_name; +#[cfg(has_drtio)] +use kernel::rpc; use libasync::{smoltcp::{Sockets, TcpStream}, task}; use libboard_artiq::drtio_routing; @@ -27,10 +30,7 @@ use num_traits::{FromPrimitive, ToPrimitive}; #[cfg(has_drtio)] use crate::pl; -use crate::{analyzer, kernel, mgmt, moninj, - proto_async::*, - rpc, rtio_dma, - rtio_mgt::{self, resolve_channel_name}}; +use crate::{analyzer, mgmt, moninj, proto_async::*, rpc_async, rtio_dma, rtio_mgt}; #[cfg(has_drtio)] use crate::{subkernel, subkernel::Error as SubkernelError}; @@ -207,7 +207,7 @@ async fn handle_run_kernel( kernel::Message::RpcRecvRequest(slot) => slot, other => panic!("expected root value slot from core1, not {:?}", other), }; - rpc::recv_return(stream, &tag, slot, &|size| { + rpc_async::recv_return(stream, &tag, slot, &|size| { let control = control.clone(); async move { if size == 0 { @@ -471,24 +471,20 @@ async fn handle_run_kernel( kernel::Message::RpcRecvRequest(slot) => slot, other => panic!("expected root value slot from core1, not {:?}", other), }; - rpc::recv_return_cursor(&mut reader, &tag, slot, &|size| { - let control = control.clone(); - async move { - if size == 0 { - 0 as *mut () - } else { - let mut control = control.borrow_mut(); - fast_send(&mut control.tx, kernel::Message::RpcRecvReply(Ok(size))).await; - match fast_recv(&mut control.rx).await { - kernel::Message::RpcRecvRequest(slot) => slot, - other => { - panic!("expected nested value slot from kernel CPU, not {:?}", other) - } + rpc::recv_return(&mut reader, &tag, slot, &|size| { + if size == 0 { + 0 as *mut () + } else { + let mut control = control.borrow_mut(); + control.tx.send(kernel::Message::RpcRecvReply(Ok(size))); + match control.rx.recv() { + kernel::Message::RpcRecvRequest(slot) => slot, + other => { + panic!("expected nested value slot from kernel CPU, not {:?}", other) } } } - }) - .await?; + })?; control .borrow_mut() .tx @@ -619,7 +615,7 @@ async fn handle_connection( } } } - #[cfg(not(has_drtio))] + #[cfg(not(has_drtio))] { write_header(stream, Reply::LoadFailed).await?; write_chunk(stream, b"No DRTIO on this system, subkernels are not supported").await?; @@ -688,7 +684,8 @@ pub fn main(timer: GlobalTimer, cfg: Config) { #[cfg(has_drtio_routing)] drtio_routing::interconnect_disable_all(); - rtio_mgt::startup(&aux_mutex, &drtio_routing_table, &up_destinations, timer, &cfg); + rtio_mgt::startup(&aux_mutex, &drtio_routing_table, &up_destinations, timer); + kernel::setup_device_map(&cfg); analyzer::start(&aux_mutex, &drtio_routing_table, &up_destinations, timer); moninj::start(timer, &aux_mutex, &drtio_routing_table); diff --git a/src/runtime/src/kernel/mod.rs b/src/runtime/src/kernel/mod.rs deleted file mode 100644 index 258e0f5..0000000 --- a/src/runtime/src/kernel/mod.rs +++ /dev/null @@ -1,132 +0,0 @@ -use alloc::{string::String, vec::Vec}; -use core::ptr; - -use libcortex_a9::{mutex::Mutex, semaphore::Semaphore, sync_channel}; - -use crate::eh_artiq; - -mod control; -pub use control::Control; -mod api; -pub mod core1; -mod dma; -mod rpc; -pub use dma::DmaRecorder; -mod cache; -#[cfg(has_drtio)] -mod subkernel; - -#[derive(Debug, Clone)] -pub struct RPCException { - pub id: u32, - pub message: u32, - pub param: [i64; 3], - pub file: u32, - pub line: i32, - pub column: i32, - pub function: u32, -} - -#[cfg(has_drtio)] -#[derive(Debug, Clone)] -pub enum SubkernelStatus { - NoError, - Timeout, - IncorrectState, - CommLost, - OtherError, -} - -#[derive(Debug, Clone)] -pub enum Message { - LoadRequest(Vec), - LoadCompleted, - LoadFailed, - StartRequest, - KernelFinished(u8), - KernelException( - &'static [Option>], - &'static [eh_artiq::StackPointerBacktrace], - &'static [(usize, usize)], - u8, - ), - RpcSend { - is_async: bool, - data: Vec, - }, - RpcRecvRequest(*mut ()), - RpcRecvReply(Result), - - CacheGetRequest(String), - CacheGetReply(Vec), - CachePutRequest(String, Vec), - - DmaPutRequest(DmaRecorder), - DmaEraseRequest(String), - DmaGetRequest(String), - DmaGetReply(Option<(i32, i64, bool)>), - #[cfg(has_drtio)] - DmaStartRemoteRequest { - id: i32, - timestamp: i64, - }, - #[cfg(has_drtio)] - DmaAwaitRemoteRequest(i32), - #[cfg(has_drtio)] - DmaAwaitRemoteReply { - timeout: bool, - error: u8, - channel: u32, - timestamp: u64, - }, - - #[cfg(has_drtio)] - UpDestinationsRequest(i32), - #[cfg(has_drtio)] - UpDestinationsReply(bool), - - #[cfg(has_drtio)] - SubkernelLoadRunRequest { - id: u32, - run: bool, - }, - #[cfg(has_drtio)] - SubkernelLoadRunReply { - succeeded: bool, - }, - #[cfg(has_drtio)] - SubkernelAwaitFinishRequest { - id: u32, - timeout: u64, - }, - #[cfg(has_drtio)] - SubkernelAwaitFinishReply { - status: SubkernelStatus, - }, - #[cfg(has_drtio)] - SubkernelMsgSend { - id: u32, - data: Vec, - }, - #[cfg(has_drtio)] - SubkernelMsgRecvRequest { - id: u32, - timeout: u64, - }, - #[cfg(has_drtio)] - SubkernelMsgRecvReply { - status: SubkernelStatus, - count: u8, - }, -} - -static CHANNEL_0TO1: Mutex>> = Mutex::new(None); -static CHANNEL_1TO0: Mutex>> = Mutex::new(None); -static CHANNEL_SEM: Semaphore = Semaphore::new(0, 1); - -static mut KERNEL_CHANNEL_0TO1: Option> = None; -static mut KERNEL_CHANNEL_1TO0: Option> = None; - -pub static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null(); - -static INIT_LOCK: Mutex<()> = Mutex::new(()); diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 826b76a..d7799b4 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -2,12 +2,8 @@ #![no_main] #![recursion_limit = "1024"] // for futures_util::select! #![feature(alloc_error_handler)] -#![feature(panic_info_message)] -#![feature(c_variadic)] #![feature(const_btree_new)] -#![feature(const_in_array_repeat_expressions)] -#![feature(naked_functions)] -#![feature(asm)] +#![feature(panic_info_message)] #[macro_use] extern crate alloc; @@ -15,7 +11,8 @@ extern crate alloc; #[cfg(feature = "target_kasli_soc")] use core::cell::RefCell; -use libasync::{block_async, task}; +use kernel; +use libasync::task; #[cfg(feature = "target_kasli_soc")] use libboard_artiq::io_expander; use libboard_artiq::{identifier_read, logger, pl}; @@ -23,90 +20,22 @@ use libboard_zynq::{gic, mpcore, timer::GlobalTimer}; use libconfig::Config; use libcortex_a9::l2c::enable_l2_cache; use libsupport_zynq::ram; -use log::{error, info, warn}; -use nb; -use void::Void; - -const ASYNC_ERROR_COLLISION: u8 = 1 << 0; -const ASYNC_ERROR_BUSY: u8 = 1 << 1; -const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2; +use log::{info, warn}; mod analyzer; mod comms; -mod eh_artiq; -mod i2c; -mod irq; -mod kernel; + mod mgmt; mod moninj; mod panic; mod proto_async; -mod rpc; -#[cfg(ki_impl = "csr")] -#[path = "rtio_csr.rs"] -mod rtio; -#[cfg(ki_impl = "acp")] -#[path = "rtio_acp.rs"] -mod rtio; +mod rpc_async; mod rtio_clocking; mod rtio_dma; mod rtio_mgt; #[cfg(has_drtio)] mod subkernel; -static mut SEEN_ASYNC_ERRORS: u8 = 0; - -pub unsafe fn get_async_errors() -> u8 { - let errors = SEEN_ASYNC_ERRORS; - SEEN_ASYNC_ERRORS = 0; - errors -} - -fn wait_for_async_rtio_error() -> nb::Result<(), Void> { - unsafe { - if pl::csr::rtio_core::async_error_read() != 0 { - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } -} - -async fn report_async_rtio_errors() { - loop { - let _ = block_async!(wait_for_async_rtio_error()).await; - unsafe { - let errors = pl::csr::rtio_core::async_error_read(); - if errors & ASYNC_ERROR_COLLISION != 0 { - let channel = pl::csr::rtio_core::collision_channel_read(); - error!( - "RTIO collision involving channel 0x{:04x}:{}", - channel, - rtio_mgt::resolve_channel_name(channel as u32) - ); - } - if errors & ASYNC_ERROR_BUSY != 0 { - let channel = pl::csr::rtio_core::busy_channel_read(); - error!( - "RTIO busy error involving channel 0x{:04x}:{}", - channel, - rtio_mgt::resolve_channel_name(channel as u32) - ); - } - if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 { - let channel = pl::csr::rtio_core::sequence_error_channel_read(); - error!( - "RTIO sequence error involving channel 0x{:04x}:{}", - channel, - rtio_mgt::resolve_channel_name(channel as u32) - ); - } - SEEN_ASYNC_ERRORS = errors; - pl::csr::rtio_core::async_error_write(errors); - } - } -} - #[cfg(feature = "target_kasli_soc")] async fn io_expanders_service( i2c_bus: RefCell<&mut libboard_zynq::i2c::I2c>, @@ -145,9 +74,9 @@ pub fn main_core0() { info!("gateware ident: {}", identifier_read(&mut [0; 64])); - i2c::init(); + kernel::i2c::init(); #[cfg(feature = "target_kasli_soc")] - let i2c_bus = unsafe { (i2c::I2C_BUS).as_mut().unwrap() }; + let i2c_bus = unsafe { (kernel::i2c::I2C_BUS).as_mut().unwrap() }; #[cfg(feature = "target_kasli_soc")] let (mut io_expander0, mut io_expander1); @@ -180,7 +109,7 @@ pub fn main_core0() { rtio_clocking::init(&mut timer, &cfg); - task::spawn(report_async_rtio_errors()); + task::spawn(kernel::report_async_rtio_errors()); #[cfg(feature = "target_kasli_soc")] task::spawn(io_expanders_service( diff --git a/src/runtime/src/rpc_async.rs b/src/runtime/src/rpc_async.rs new file mode 100644 index 0000000..226ba91 --- /dev/null +++ b/src/runtime/src/rpc_async.rs @@ -0,0 +1,197 @@ +use alloc::boxed::Box; +use core::future::Future; + +use async_recursion::async_recursion; +use byteorder::{ByteOrder, NativeEndian}; +use cslice::CMutSlice; +use kernel::rpc::{tag::{Tag, TagIterator}, + *}; +use libasync::smoltcp::TcpStream; +use libboard_zynq::smoltcp; +use log::trace; + +use crate::proto_async; + +/// Reads (deserializes) `length` array or list elements of type `tag` from `stream`, +/// writing them into the buffer given by `storage`. +/// +/// `alloc` is used for nested allocations (if elements themselves contain +/// lists/arrays), see [recv_value]. +#[async_recursion(?Send)] +async unsafe fn recv_elements( + stream: &TcpStream, + elt_tag: Tag<'async_recursion>, + length: usize, + storage: *mut (), + alloc: &(impl Fn(usize) -> F + 'async_recursion), +) -> Result<(), smoltcp::Error> +where + F: Future, +{ + // List of simple types are special-cased in the protocol for performance. + match elt_tag { + Tag::Bool => { + let dest = core::slice::from_raw_parts_mut(storage as *mut u8, length); + proto_async::read_chunk(stream, dest).await?; + } + Tag::Int32 => { + let ptr = storage as *mut u32; + let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4); + proto_async::read_chunk(stream, dest).await?; + drop(dest); + let dest = core::slice::from_raw_parts_mut(ptr, length); + NativeEndian::from_slice_u32(dest); + } + Tag::Int64 | Tag::Float64 => { + let ptr = storage as *mut u64; + let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8); + proto_async::read_chunk(stream, dest).await?; + drop(dest); + let dest = core::slice::from_raw_parts_mut(ptr, length); + NativeEndian::from_slice_u64(dest); + } + _ => { + let mut data = storage; + for _ in 0..length { + recv_value(stream, elt_tag, &mut data, alloc).await? + } + } + } + Ok(()) +} + +/// Reads (deserializes) a value of type `tag` from `stream`, writing the results to +/// the kernel-side buffer `data` (the passed pointer to which is incremented to point +/// past the just-received data). For nested allocations (lists/arrays), `alloc` is +/// invoked any number of times with the size of the required allocation as a parameter +/// (which is assumed to be correctly aligned for all payload types). +#[async_recursion(?Send)] +async unsafe fn recv_value( + stream: &TcpStream, + tag: Tag<'async_recursion>, + data: &mut *mut (), + alloc: &(impl Fn(usize) -> F + 'async_recursion), +) -> Result<(), smoltcp::Error> +where + F: Future, +{ + macro_rules! consume_value { + ($ty:ty, | $ptr:ident | $map:expr) => {{ + let $ptr = align_ptr_mut::<$ty>(*data); + *data = $ptr.offset(1) as *mut (); + $map + }}; + } + + match tag { + Tag::None => Ok(()), + Tag::Bool => consume_value!(i8, |ptr| { + *ptr = proto_async::read_i8(stream).await?; + Ok(()) + }), + Tag::Int32 => consume_value!(i32, |ptr| { + *ptr = proto_async::read_i32(stream).await?; + Ok(()) + }), + Tag::Int64 | Tag::Float64 => consume_value!(i64, |ptr| { + *ptr = proto_async::read_i64(stream).await?; + Ok(()) + }), + Tag::String | Tag::Bytes | Tag::ByteArray => { + consume_value!(CMutSlice, |ptr| { + let length = proto_async::read_i32(stream).await? as usize; + *ptr = CMutSlice::new(alloc(length).await as *mut u8, length); + proto_async::read_chunk(stream, (*ptr).as_mut()).await?; + Ok(()) + }) + } + Tag::Tuple(it, arity) => { + let alignment = tag.alignment(); + *data = round_up_mut(*data, alignment); + let mut it = it.clone(); + for _ in 0..arity { + let tag = it.next().expect("truncated tag"); + recv_value(stream, tag, data, alloc).await? + } + // Take into account any tail padding (if element(s) with largest alignment + // are not at the end). + *data = round_up_mut(*data, alignment); + Ok(()) + } + Tag::List(it) => { + #[repr(C)] + struct List { + elements: *mut (), + length: usize, + } + consume_value!(*mut List, |ptr_to_list| { + let tag = it.clone().next().expect("truncated tag"); + let length = proto_async::read_i32(stream).await? as usize; + + // To avoid multiple kernel CPU roundtrips, use a single allocation for + // both the pointer/length List (slice) and the backing storage for the + // elements. We can assume that alloc() is aligned suitably, so just + // need to take into account any extra padding required. + // (Note: At the time of writing, there will never actually be any types + // with alignment larger than 8 bytes, so storage_offset == 0 always.) + let list_size = 4 + 4; + let storage_offset = round_up(list_size, tag.alignment()); + let storage_size = tag.size() * length; + + let allocation = alloc(storage_offset + storage_size).await as *mut u8; + *ptr_to_list = allocation as *mut List; + let storage = allocation.offset(storage_offset as isize) as *mut (); + + (**ptr_to_list).length = length; + (**ptr_to_list).elements = storage; + recv_elements(stream, tag, length, storage, alloc).await + }) + } + Tag::Array(it, num_dims) => { + consume_value!(*mut (), |buffer| { + // Deserialize length along each dimension and compute total number of + // elements. + let mut total_len: usize = 1; + for _ in 0..num_dims { + let len = proto_async::read_i32(stream).await? as usize; + total_len *= len; + consume_value!(usize, |ptr| *ptr = len) + } + + // Allocate backing storage for elements; deserialize them. + let elt_tag = it.clone().next().expect("truncated tag"); + *buffer = alloc(elt_tag.size() * total_len).await; + recv_elements(stream, elt_tag, total_len, *buffer, alloc).await + }) + } + Tag::Range(it) => { + *data = round_up_mut(*data, tag.alignment()); + let tag = it.clone().next().expect("truncated tag"); + recv_value(stream, tag, data, alloc).await?; + recv_value(stream, tag, data, alloc).await?; + recv_value(stream, tag, data, alloc).await?; + Ok(()) + } + Tag::Keyword(_) => unreachable!(), + Tag::Object => unreachable!(), + } +} + +pub async fn recv_return( + stream: &TcpStream, + tag_bytes: &[u8], + data: *mut (), + alloc: &impl Fn(usize) -> F, +) -> Result<(), smoltcp::Error> +where + F: Future, +{ + let mut it = TagIterator::new(tag_bytes); + trace!("recv ...->{}", it); + + let tag = it.next().expect("truncated tag"); + let mut data = data; + unsafe { recv_value(stream, tag, &mut data, alloc).await? }; + + Ok(()) +} diff --git a/src/runtime/src/rtio_clocking.rs b/src/runtime/src/rtio_clocking.rs index 000acaa..736e2b3 100644 --- a/src/runtime/src/rtio_clocking.rs +++ b/src/runtime/src/rtio_clocking.rs @@ -1,4 +1,6 @@ use embedded_hal::blocking::delay::DelayMs; +#[cfg(has_si5324)] +use kernel::i2c; use libboard_artiq::pl; #[cfg(has_si5324)] use libboard_artiq::si5324; @@ -8,9 +10,6 @@ use libboard_zynq::timer::GlobalTimer; use libconfig::Config; use log::{info, warn}; -#[cfg(has_si5324)] -use crate::i2c; - #[derive(Debug, PartialEq, Copy, Clone)] #[allow(non_camel_case_types)] pub enum RtioClock { diff --git a/src/runtime/src/rtio_dma.rs b/src/runtime/src/rtio_dma.rs index d39e7de..dc6011b 100644 --- a/src/runtime/src/rtio_dma.rs +++ b/src/runtime/src/rtio_dma.rs @@ -2,14 +2,13 @@ use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec}; #[cfg(has_drtio)] use core::mem; +use kernel::DmaRecorder; #[cfg(has_drtio)] use libasync::task; use libboard_artiq::drtio_routing::RoutingTable; use libboard_zynq::timer::GlobalTimer; use libcortex_a9::{cache::dcci_slice, mutex::Mutex}; -use crate::kernel::DmaRecorder; - const ALIGNMENT: usize = 16 * 8; static DMA_RECORD_STORE: Mutex, i64)>> = Mutex::new(BTreeMap::new()); diff --git a/src/runtime/src/rtio_mgt.rs b/src/runtime/src/rtio_mgt.rs index ee8d79c..70c7d7a 100644 --- a/src/runtime/src/rtio_mgt.rs +++ b/src/runtime/src/rtio_mgt.rs @@ -1,20 +1,16 @@ -use alloc::{collections::BTreeMap, rc::Rc, string::String}; +use alloc::rc::Rc; use core::cell::RefCell; -use io::{Cursor, ProtoRead}; use libboard_artiq::{drtio_routing, pl::csr}; use libboard_zynq::timer::GlobalTimer; -use libconfig::Config; use libcortex_a9::mutex::Mutex; -use log::warn; - -static mut RTIO_DEVICE_MAP: BTreeMap = BTreeMap::new(); #[cfg(has_drtio)] pub mod drtio { use alloc::vec::Vec; use embedded_hal::blocking::delay::DelayMs; + use kernel::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS}; use libasync::{delay, task}; use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet, drtioaux_proto::MASTER_PAYLOAD_MAX_SIZE}; @@ -22,8 +18,7 @@ pub mod drtio { use log::{error, info, warn}; use super::*; - use crate::{analyzer::remote_analyzer::RemoteBuffer, rtio_dma::remote_dma, subkernel, ASYNC_ERROR_BUSY, - ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS}; + use crate::{analyzer::remote_analyzer::RemoteBuffer, rtio_dma::remote_dma, subkernel}; pub fn startup( aux_mutex: &Rc>, @@ -756,46 +751,6 @@ pub mod drtio { } } -fn read_device_map(cfg: &Config) -> BTreeMap { - let mut device_map: BTreeMap = BTreeMap::new(); - let _ = cfg - .read("device_map") - .and_then(|raw_bytes| { - let mut bytes_cr = Cursor::new(raw_bytes); - let size = bytes_cr.read_u32().unwrap(); - for _ in 0..size { - let channel = bytes_cr.read_u32().unwrap(); - let device_name = bytes_cr.read_string().unwrap(); - if let Some(old_entry) = device_map.insert(channel, device_name.clone()) { - warn!( - "conflicting device map entries for RTIO channel {}: '{}' and '{}'", - channel, old_entry, device_name - ); - } - } - Ok(()) - }) - .or_else(|err| { - warn!( - "error reading device map ({}), device names will not be available in RTIO error messages", - err - ); - Err(err) - }); - device_map -} - -fn _resolve_channel_name(channel: u32, device_map: &BTreeMap) -> String { - match device_map.get(&channel) { - Some(val) => val.clone(), - None => String::from("unknown"), - } -} - -pub fn resolve_channel_name(channel: u32) -> String { - _resolve_channel_name(channel, unsafe { &RTIO_DEVICE_MAP }) -} - #[cfg(not(has_drtio))] pub mod drtio { use super::*; @@ -817,11 +772,7 @@ pub fn startup( routing_table: &Rc>, up_destinations: &Rc>, timer: GlobalTimer, - cfg: &Config, ) { - unsafe { - RTIO_DEVICE_MAP = read_device_map(cfg); - } drtio::startup(aux_mutex, routing_table, up_destinations, timer); unsafe { csr::rtio_core::reset_phy_write(1);