From b42816582ed7f6c7290f495f0c728f90daea8364 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Thu, 5 Oct 2023 14:39:19 +0800 Subject: [PATCH] ksupport: support subkernels --- artiq/build_soc.py | 1 - artiq/firmware/ksupport/api.rs | 5 ++ artiq/firmware/ksupport/eh_artiq.rs | 3 +- artiq/firmware/ksupport/lib.rs | 71 +++++++++++++++++-- artiq/firmware/libproto_artiq/kernel_proto.rs | 17 +++++ 5 files changed, 91 insertions(+), 6 deletions(-) diff --git a/artiq/build_soc.py b/artiq/build_soc.py index f51c8885a..0e6deb499 100644 --- a/artiq/build_soc.py +++ b/artiq/build_soc.py @@ -71,7 +71,6 @@ def build_artiq_soc(soc, argdict): if not soc.config["DRTIO_ROLE"] == "satellite": builder.add_software_package("runtime", os.path.join(firmware_dir, "runtime")) else: - # Assume DRTIO satellite. builder.add_software_package("satman", os.path.join(firmware_dir, "satman")) try: builder.build() diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 1682f818b..e4d7b2482 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -157,6 +157,11 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(dma_retrieve = ::dma_retrieve), api!(dma_playback = ::dma_playback), + api!(subkernel_load_run = ::subkernel_load_run), + api!(subkernel_send_message = ::subkernel_send_message), + api!(subkernel_await_message = ::subkernel_await_message), + api!(subkernel_await_finish = ::subkernel_await_finish), + api!(i2c_start = ::nrt_bus::i2c::start), api!(i2c_restart = ::nrt_bus::i2c::restart), api!(i2c_stop = ::nrt_bus::i2c::stop), diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index 19470fe70..80d999304 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -333,7 +333,7 @@ extern fn stop_fn(_version: c_int, } } -static EXCEPTION_ID_LOOKUP: [(&str, u32); 11] = [ +static EXCEPTION_ID_LOOKUP: [(&str, u32); 12] = [ ("RuntimeError", 0), ("RTIOUnderflow", 1), ("RTIOOverflow", 2), @@ -345,6 +345,7 @@ static EXCEPTION_ID_LOOKUP: [(&str, u32); 11] = [ ("ZeroDivisionError", 8), ("IndexError", 9), ("UnwrapNoneError", 10), + ("SubkernelError", 11) ]; pub fn get_exception_id(name: &str) -> u32 { diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 685516e2b..53ea4574d 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -21,7 +21,6 @@ use dyld::Library; use board_artiq::{mailbox, rpc_queue}; use proto_artiq::{kernel_proto, rpc_proto}; use kernel_proto::*; -#[cfg(has_rtio_dma)] use board_misoc::csr; use riscv::register::{mcause, mepc, mtval}; @@ -396,7 +395,7 @@ extern fn dma_retrieve(name: &CSlice) -> DmaTrace { }) } -#[cfg(has_rtio_dma)] +#[cfg(kernel_has_rtio_dma)] #[unwind(allowed)] extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) { assert!(ptr % 64 == 0); @@ -454,10 +453,74 @@ extern fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) { } } -#[cfg(not(has_rtio_dma))] +#[cfg(not(kernel_has_rtio_dma))] #[unwind(allowed)] extern fn dma_playback(_timestamp: i64, _ptr: i32, _uses_ddma: bool) { - unimplemented!("not(has_rtio_dma)") + unimplemented!("not(kernel_has_rtio_dma)") +} + +#[unwind(allowed)] +extern fn subkernel_load_run(id: u32, run: bool) { + send(&SubkernelLoadRunRequest { id: id, run: run }); + recv!(&SubkernelLoadRunReply { succeeded } => { + if !succeeded { + raise!("SubkernelError", + "Error loading or running the subkernel"); + } + }); +} + +#[unwind(allowed)] +extern fn subkernel_await_finish(id: u32, timeout: u64) { + send(&SubkernelAwaitFinishRequest { id: id, timeout: timeout }); + recv!(SubkernelAwaitFinishReply { status } => { + match status { + SubkernelStatus::NoError => (), + SubkernelStatus::IncorrectState => raise!("SubkernelError", + "Subkernel not running"), + SubkernelStatus::Timeout => raise!("SubkernelError", + "Subkernel timed out"), + SubkernelStatus::CommLost => raise!("SubkernelError", + "Lost communication with satellite"), + SubkernelStatus::OtherError => raise!("SubkernelError", + "An error occurred during subkernel operation") + } + }) +} + +#[unwind(aborts)] +extern fn subkernel_send_message(id: u32, count: u8, tag: &CSlice, data: *const *const ()) { + send(&SubkernelMsgSend { + id: id, + count: count, + tag: tag.as_ref(), + data: data + }); +} + +#[unwind(allowed)] +extern fn subkernel_await_message(id: u32, timeout: u64, min: u8, max: u8) -> u8 { + send(&SubkernelMsgRecvRequest { id: id, timeout: timeout }); + recv!(SubkernelMsgRecvReply { status, count } => { + match status { + SubkernelStatus::NoError => { + if count < &min || count > &max { + raise!("SubkernelError", + "Received less or more arguments than expected"); + } + *count + } + SubkernelStatus::IncorrectState => raise!("SubkernelError", + "Subkernel not running"), + SubkernelStatus::Timeout => raise!("SubkernelError", + "Subkernel timed out"), + SubkernelStatus::CommLost => raise!("SubkernelError", + "Lost communication with satellite"), + SubkernelStatus::OtherError => raise!("SubkernelError", + "An error occurred during subkernel operation") + } + }) + // RpcRecvRequest should be called `count` times after this to receive message data } unsafe fn attribute_writeback(typeinfo: *const ()) { diff --git a/artiq/firmware/libproto_artiq/kernel_proto.rs b/artiq/firmware/libproto_artiq/kernel_proto.rs index 2ecb39c3b..51e619974 100644 --- a/artiq/firmware/libproto_artiq/kernel_proto.rs +++ b/artiq/firmware/libproto_artiq/kernel_proto.rs @@ -10,6 +10,15 @@ pub const KERNELCPU_LAST_ADDRESS: usize = 0x4fffffff; // section in ksupport.elf. pub const KSUPPORT_HEADER_SIZE: usize = 0x74; +#[derive(Debug)] +pub enum SubkernelStatus { + NoError, + Timeout, + IncorrectState, + CommLost, + OtherError +} + #[derive(Debug)] pub enum Message<'a> { LoadRequest(&'a [u8]), @@ -94,6 +103,14 @@ pub enum Message<'a> { SpiReadReply { succeeded: bool, data: u32 }, SpiBasicReply { succeeded: bool }, + SubkernelLoadRunRequest { id: u32, run: bool }, + SubkernelLoadRunReply { succeeded: bool }, + SubkernelAwaitFinishRequest { id: u32, timeout: u64 }, + SubkernelAwaitFinishReply { status: SubkernelStatus }, + SubkernelMsgSend { id: u32, count: u8, tag: &'a [u8], data: *const *const () }, + SubkernelMsgRecvRequest { id: u32, timeout: u64 }, + SubkernelMsgRecvReply { status: SubkernelStatus, count: u8 }, + Log(fmt::Arguments<'a>), LogSlice(&'a str) }