From 527189ab6afcfc51cbe0fe5c60ff740b7cb6c91f Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 12 Dec 2022 17:35:07 +0800 Subject: [PATCH] Support channel names in RTIO errors Signed-off-by: Egor Savkin --- src/runtime/src/comms.rs | 2 +- src/runtime/src/eh_artiq.rs | 3 ++- src/runtime/src/kernel/dma.rs | 5 ++-- src/runtime/src/main.rs | 13 ++++++----- src/runtime/src/rtio_acp.rs | 19 ++++++++-------- src/runtime/src/rtio_csr.rs | 19 ++++++++-------- src/runtime/src/rtio_mgt.rs | 43 ++++++++++++++++++++++++++++++++++- 7 files changed, 75 insertions(+), 29 deletions(-) diff --git a/src/runtime/src/comms.rs b/src/runtime/src/comms.rs index 504d637..e6aaa74 100644 --- a/src/runtime/src/comms.rs +++ b/src/runtime/src/comms.rs @@ -423,7 +423,7 @@ 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); + rtio_mgt::startup(&aux_mutex, &drtio_routing_table, &up_destinations, timer, &cfg); analyzer::start(); moninj::start(timer, aux_mutex, drtio_routing_table); diff --git a/src/runtime/src/eh_artiq.rs b/src/runtime/src/eh_artiq.rs index 4cd3ba4..9696201 100644 --- a/src/runtime/src/eh_artiq.rs +++ b/src/runtime/src/eh_artiq.rs @@ -434,6 +434,7 @@ macro_rules! artiq_raise { ($name:expr, $message:expr, $param0:expr, $param1:expr, $param2:expr) => ({ use cslice::AsCSlice; let name_id = $crate::eh_artiq::get_exception_id($name); + let message_cl = $message.clone(); let exn = $crate::eh_artiq::Exception { id: name_id, file: file!().as_c_slice(), @@ -441,7 +442,7 @@ macro_rules! artiq_raise { column: column!(), // https://github.com/rust-lang/rfcs/pull/1719 function: "(Rust function)".as_c_slice(), - message: $message.as_c_slice(), + message: message_cl.as_c_slice(), param: [$param0, $param1, $param2] }; #[allow(unused_unsafe)] diff --git a/src/runtime/src/kernel/dma.rs b/src/runtime/src/kernel/dma.rs index a19d95f..e39ac23 100644 --- a/src/runtime/src/kernel/dma.rs +++ b/src/runtime/src/kernel/dma.rs @@ -2,6 +2,7 @@ use crate::{ pl::csr, artiq_raise, rtio, + rtio_mgt::resolve_channel_name, }; use alloc::{vec::Vec, string::String, boxed::Box}; use cslice::CSlice; @@ -198,12 +199,12 @@ pub extern fn dma_playback(timestamp: i64, ptr: i32) { csr::rtio_dma::error_write(1); if error & 1 != 0 { artiq_raise!("RTIOUnderflow", - "RTIO underflow at {0} mu, channel {1}", + format!("RTIO underflow at channel {}:{}, {{0}} mu", channel, resolve_channel_name(channel as u32)), timestamp as i64, channel as i64, 0); } if error & 2 != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, output, at {0} mu, channel {1}", + format!("RTIO destination unreachable, output, at {{0}} mu, channel {}:{}", channel, resolve_channel_name(channel as u32)), timestamp as i64, channel as i64, 0); } } diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index f7bca21..6177cb9 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -9,6 +9,7 @@ #![feature(naked_functions)] #![feature(asm)] +#[macro_use] extern crate alloc; use log::{info, warn, error}; @@ -70,16 +71,16 @@ async fn report_async_rtio_errors() { unsafe { let errors = pl::csr::rtio_core::async_error_read(); if errors & ASYNC_ERROR_COLLISION != 0 { - error!("RTIO collision involving channel {}", - pl::csr::rtio_core::collision_channel_read()); + let channel = pl::csr::rtio_core::collision_channel_read(); + error!("RTIO collision involving channel {}:{}", channel, rtio_mgt::resolve_channel_name(channel as u32)); } if errors & ASYNC_ERROR_BUSY != 0 { - error!("RTIO busy error involving channel {}", - pl::csr::rtio_core::busy_channel_read()); + let channel = pl::csr::rtio_core::busy_channel_read(); + error!("RTIO busy error involving channel {}:{}", channel, rtio_mgt::resolve_channel_name(channel as u32)); } if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 { - error!("RTIO sequence error involving channel {}", - pl::csr::rtio_core::sequence_error_channel_read()); + let channel = pl::csr::rtio_core::sequence_error_channel_read(); + error!("RTIO sequence error involving channel {}:{}", channel, rtio_mgt::resolve_channel_name(channel as u32)); } SEEN_ASYNC_ERRORS = errors; pl::csr::rtio_core::async_error_write(errors); diff --git a/src/runtime/src/rtio_acp.rs b/src/runtime/src/rtio_acp.rs index 4c1f33b..2fff41d 100644 --- a/src/runtime/src/rtio_acp.rs +++ b/src/runtime/src/rtio_acp.rs @@ -5,6 +5,7 @@ use crate::artiq_raise; use core::sync::atomic::{fence, Ordering}; use crate::pl::csr; +use crate::rtio_mgt::resolve_channel_name; pub const RTIO_O_STATUS_WAIT: i32 = 1; pub const RTIO_O_STATUS_UNDERFLOW: i32 = 2; @@ -87,12 +88,12 @@ unsafe fn process_exceptional_status(channel: i32, status: i32) { } if status & RTIO_O_STATUS_UNDERFLOW != 0 { artiq_raise!("RTIOUnderflow", - "RTIO underflow at {0} mu, channel {1}, slack {2} mu", - timestamp, channel as i64, timestamp - get_counter()); + format!("RTIO underflow at channel {}:{}, {{1}} mu, slack {{2}} mu", channel, resolve_channel_name(channel as u32)), + channel as i64, timestamp, timestamp - get_counter()); } if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, output, at {0} mu, channel {1}", + format!("RTIO destination unreachable, output, at {{0}} mu, channel {}:{}", channel, resolve_channel_name(channel as u32)), timestamp, channel as i64, 0); } } @@ -176,7 +177,7 @@ pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_WAIT_EVENT != 0 { @@ -184,7 +185,7 @@ pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } @@ -214,12 +215,12 @@ pub extern fn input_data(channel: i32) -> i32 { if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } @@ -249,12 +250,12 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } diff --git a/src/runtime/src/rtio_csr.rs b/src/runtime/src/rtio_csr.rs index 761dcbe..df30106 100644 --- a/src/runtime/src/rtio_csr.rs +++ b/src/runtime/src/rtio_csr.rs @@ -4,6 +4,7 @@ use cslice::CSlice; use crate::artiq_raise; use crate::pl::csr; +use crate::rtio_mgt::resolve_channel_name; pub const RTIO_O_STATUS_WAIT: u8 = 1; pub const RTIO_O_STATUS_UNDERFLOW: u8 = 2; @@ -72,12 +73,12 @@ unsafe fn process_exceptional_status(channel: i32, status: u8) { } if status & RTIO_O_STATUS_UNDERFLOW != 0 { artiq_raise!("RTIOUnderflow", - "RTIO underflow at {0} mu, channel {1}, slack {2} mu", - timestamp, channel as i64, timestamp - get_counter()); + format!("RTIO underflow at channel {}:{}, {{1}} mu, slack {{2}} mu", channel, resolve_channel_name(channel as u32)), + channel as i64, timestamp, timestamp - get_counter()); } if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, output, at {0} mu, channel {1}", + format!("RTIO destination unreachable, output, at {{0}} mu, channel {}:{}", channel, resolve_channel_name(channel as u32)), timestamp, channel as i64, 0); } } @@ -120,7 +121,7 @@ pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_WAIT_EVENT != 0 { @@ -128,7 +129,7 @@ pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } @@ -148,12 +149,12 @@ pub extern fn input_data(channel: i32) -> i32 { if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } @@ -173,7 +174,7 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD if status & RTIO_I_STATUS_OVERFLOW != 0 { artiq_raise!("RTIOOverflow", - "RTIO input overflow on channel {0}", + format!("RTIO input overflow on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } if status & RTIO_I_STATUS_WAIT_EVENT != 0 { @@ -181,7 +182,7 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD } if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 { artiq_raise!("RTIODestinationUnreachable", - "RTIO destination unreachable, input, on channel {0}", + format!("RTIO destination unreachable, input, on channel {}:{}", channel, resolve_channel_name(channel as u32)), channel as i64, 0, 0); } diff --git a/src/runtime/src/rtio_mgt.rs b/src/runtime/src/rtio_mgt.rs index e6cb5b5..beea59e 100644 --- a/src/runtime/src/rtio_mgt.rs +++ b/src/runtime/src/rtio_mgt.rs @@ -1,8 +1,15 @@ use core::cell::RefCell; use alloc::rc::Rc; +use alloc::collections::BTreeMap; +use alloc::string::String; use libboard_zynq::timer::GlobalTimer; use libboard_artiq::{pl::csr, drtio_routing}; use libcortex_a9::mutex::Mutex; +use libconfig::Config; +use io::{Cursor, ProtoRead}; +use log::error; + +static mut RTIO_DEVICE_MAP: BTreeMap = BTreeMap::new(); #[cfg(has_drtio)] @@ -332,6 +339,38 @@ 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()) { + error!("conflicting entries for channel {}: `{}` and `{}`", + channel, old_entry, device_name); + } + } + Ok(()) + } ).or_else(|err| { + error!("read_device_map: error reading `device_map` from config: {}", 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::*; @@ -346,7 +385,9 @@ pub mod drtio { pub fn startup(aux_mutex: &Rc>, routing_table: &Rc>, up_destinations: &Rc>, - timer: GlobalTimer) { + 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);