From bae41253e488b947415babedde3ac96be1ccea61 Mon Sep 17 00:00:00 2001 From: abdul124 Date: Wed, 21 Aug 2024 16:34:25 +0800 Subject: [PATCH 1/2] firmware: sync exception names and ids --- src/libksupport/src/eh_artiq.rs | 36 ++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libksupport/src/eh_artiq.rs b/src/libksupport/src/eh_artiq.rs index b42b880..1587e47 100644 --- a/src/libksupport/src/eh_artiq.rs +++ b/src/libksupport/src/eh_artiq.rs @@ -477,20 +477,28 @@ extern "C" fn stop_fn( } } -// Must be kept in sync with preallocate_runtime_exception_names() in artiq/language/embedding_map.py -static EXCEPTION_ID_LOOKUP: [(&str, u32); 12] = [ - ("RuntimeError", 0), - ("RTIOUnderflow", 1), - ("RTIOOverflow", 2), - ("RTIODestinationUnreachable", 3), - ("DMAError", 4), - ("I2CError", 5), - ("CacheError", 6), - ("SPIError", 7), - ("ZeroDivisionError", 8), - ("IndexError", 9), - ("UnwrapNoneError", 10), - ("SubkernelError", 11), +// Must be kept in sync with preallocate_runtime_exception_names() in `artiq.compiler.embedding` +static EXCEPTION_ID_LOOKUP: [(&str, u32); 20] = [ + ("RTIOUnderflow", 0), + ("RTIOOverflow", 1), + ("RTIODestinationUnreachable", 2), + ("DMAError", 3), + ("I2CError", 4), + ("CacheError", 5), + ("SPIError", 6), + ("SubkernelError", 7), + ("AssertionError", 8), + ("AttributeError", 9), + ("IndexError", 10), + ("IOError", 11), + ("KeyError", 12), + ("NotImplementedError", 13), + ("OverflowError", 14), + ("RuntimeError", 15), + ("TimeoutError", 16), + ("TypeError", 17), + ("ValueError", 18), + ("ZeroDivisionError", 19), ]; pub fn get_exception_id(name: &str) -> u32 { -- 2.44.1 From d508c5c6f81b7877b77bf80ac5a911d365599d38 Mon Sep 17 00:00:00 2001 From: abdul124 Date: Wed, 21 Aug 2024 16:35:03 +0800 Subject: [PATCH 2/2] firmware: add unit tests for exception sync --- src/libksupport/src/eh_artiq.rs | 30 +++++++++++++++++++++++++++--- src/libksupport/src/kernel/api.rs | 7 +++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/libksupport/src/eh_artiq.rs b/src/libksupport/src/eh_artiq.rs index 1587e47..a0f0519 100644 --- a/src/libksupport/src/eh_artiq.rs +++ b/src/libksupport/src/eh_artiq.rs @@ -15,7 +15,7 @@ use core::mem; use core_io::Error as ReadError; -use cslice::CSlice; +use cslice::{AsCSlice, CSlice}; use dwarf::eh::{self, EHAction, EHContext}; use io::{Cursor, ProtoRead}; use libc::{c_int, c_void, uintptr_t}; @@ -222,8 +222,6 @@ pub unsafe fn artiq_personality( } pub unsafe extern "C" fn raise(exception: *const Exception) -> ! { - use cslice::AsCSlice; - let count = EXCEPTION_BUFFER.exception_count; let stack = &mut EXCEPTION_BUFFER.exception_stack; let diff = exception as isize - EXCEPTION_BUFFER.exceptions.as_ptr() as isize; @@ -533,3 +531,29 @@ macro_rules! artiq_raise { }}; ($name:expr, $message:expr) => {{ artiq_raise!($name, $message, 0, 0, 0) }}; } + +/// Takes as input exception id from host +/// Generates a new exception with: +/// * `id` set to `exn_id` +/// * `message` set to corresponding exception name from `EXCEPTION_ID_LOOKUP` +/// +/// The message is matched on host to ensure correct exception is being referred +/// This test checks the synchronization of exception ids for runtime errors +#[no_mangle] +pub extern "C" fn test_exception_id_sync(exn_id: u32) { + let message = EXCEPTION_ID_LOOKUP + .iter() + .find_map(|&(name, id)| if id == exn_id { Some(name) } else { None }) + .unwrap_or("unallocated internal exception id"); + + let exn = Exception { + id: exn_id, + file: file!().as_c_slice(), + line: 0, + column: 0, + function: "test_exception_id_sync".as_c_slice(), + message: message.as_c_slice(), + param: [0, 0, 0], + }; + unsafe { raise(&exn) }; +} diff --git a/src/libksupport/src/kernel/api.rs b/src/libksupport/src/kernel/api.rs index 106024f..ef77e43 100644 --- a/src/libksupport/src/kernel/api.rs +++ b/src/libksupport/src/kernel/api.rs @@ -332,6 +332,13 @@ pub fn resolve(required: &[u8]) -> Option { api!(sp_linalg_schur = linalg::sp_linalg_schur), api!(sp_linalg_hessenberg = linalg::sp_linalg_hessenberg), + /* + * syscall for unit tests + * Used in `artiq.tests.coredevice.test_exceptions.ExceptionTest.test_raise_exceptions_kernel` + * This syscall checks that the exception IDs used in the Python `EmbeddingMap` (in `artiq.language.embedding`) + * match the `EXCEPTION_ID_LOOKUP` defined in the firmware (`libksupport::src::eh_artiq`) + */ + api!(test_exception_id_sync = eh_artiq::test_exception_id_sync) ]; api.iter() .find(|&&(exported, _)| exported.as_bytes() == required) -- 2.44.1