forked from M-Labs/artiq-zynq
add channel names to RTIO errors
Co-authored-by: Egor Savkin <es@m-labs.hk> Co-committed-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
4a522ecb3b
commit
6b3fa98d70
|
@ -1,4 +1,4 @@
|
|||
use core::fmt;
|
||||
use core::{fmt, slice, str};
|
||||
use core::cell::RefCell;
|
||||
use alloc::{vec, vec::Vec, string::String, collections::BTreeMap, rc::Rc};
|
||||
use log::{info, warn, error};
|
||||
|
@ -31,7 +31,7 @@ use crate::rpc;
|
|||
use crate::moninj;
|
||||
use crate::mgmt;
|
||||
use crate::analyzer;
|
||||
use crate::rtio_mgt;
|
||||
use crate::rtio_mgt::{self, resolve_channel_name};
|
||||
#[cfg(has_drtio)]
|
||||
use crate::pl;
|
||||
|
||||
|
@ -246,7 +246,16 @@ async fn handle_run_kernel(stream: Option<&TcpStream>, control: &Rc<RefCell<kern
|
|||
for exception in exceptions.iter() {
|
||||
let exception = exception.as_ref().unwrap();
|
||||
write_i32(stream, exception.id as i32).await?;
|
||||
|
||||
if exception.message.len() == usize::MAX { // exception with host string
|
||||
write_exception_string(stream, exception.message).await?;
|
||||
} else {
|
||||
let msg = str::from_utf8(unsafe { slice::from_raw_parts(exception.message.as_ptr(), exception.message.len()) })
|
||||
.unwrap()
|
||||
.replace("{rtio_channel_info:0}", &format!("{}:{}", exception.param[0], resolve_channel_name(exception.param[0] as u32)));
|
||||
write_exception_string(stream, unsafe { CSlice::new(msg.as_ptr(), msg.len()) }).await?;
|
||||
}
|
||||
|
||||
write_i64(stream, exception.param[0] as i64).await?;
|
||||
write_i64(stream, exception.param[1] as i64).await?;
|
||||
write_i64(stream, exception.param[2] as i64).await?;
|
||||
|
@ -423,7 +432,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);
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -198,13 +198,13 @@ 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}",
|
||||
timestamp as i64, channel as i64, 0);
|
||||
"RTIO underflow at {1} mu, channel {rtio_channel_info:0}",
|
||||
channel as i64, timestamp as i64, 0);
|
||||
}
|
||||
if error & 2 != 0 {
|
||||
artiq_raise!("RTIODestinationUnreachable",
|
||||
"RTIO destination unreachable, output, at {0} mu, channel {1}",
|
||||
timestamp as i64, channel as i64, 0);
|
||||
"RTIO destination unreachable, output, at {1} mu, channel {rtio_channel_info:0}",
|
||||
channel as i64, timestamp as i64, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {{1}} mu, channel {}:{}, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {{1}} mu, channel {}:{}, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u32, String> = BTreeMap::new();
|
||||
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
|
@ -219,15 +226,15 @@ pub mod drtio {
|
|||
destination_set_up(routing_table, up_destinations, destination, false).await,
|
||||
Ok(Packet::DestinationOkReply) => (),
|
||||
Ok(Packet::DestinationSequenceErrorReply { channel }) =>{
|
||||
error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}", destination, channel);
|
||||
error!("[DEST#{}] RTIO sequence error involving channel {} 0x{:04x}", destination, resolve_channel_name(channel), channel);
|
||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
|
||||
}
|
||||
Ok(Packet::DestinationCollisionReply { channel }) =>{
|
||||
error!("[DEST#{}] RTIO collision involving channel 0x{:04x}", destination, channel);
|
||||
error!("[DEST#{}] RTIO collision involving channel {} 0x{:04x}", destination, resolve_channel_name(channel), channel);
|
||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
|
||||
}
|
||||
Ok(Packet::DestinationBusyReply { channel }) =>{
|
||||
error!("[DEST#{}] RTIO busy error involving channel 0x{:04x}", destination, channel);
|
||||
error!("[DEST#{}] RTIO busy error involving channel {} 0x{:04x}", destination, resolve_channel_name(channel), channel);
|
||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
|
||||
}
|
||||
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
||||
|
@ -332,6 +339,38 @@ pub mod drtio {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
|
||||
let mut device_map: BTreeMap<u32, String> = 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!("read_device_map: 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<u32, String>) -> 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<Mutex<bool>>,
|
||||
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
|
||||
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue