forked from M-Labs/artiq
add channel names to RTIO errors
This commit is contained in:
parent
c591e7e305
commit
1852491102
|
@ -15,6 +15,7 @@ Highlights:
|
||||||
* Sampler: adjusted ADC MU to Volt conversion base for Sampler since v2.2.
|
* Sampler: adjusted ADC MU to Volt conversion base for Sampler since v2.2.
|
||||||
For earlier version please explicitly define it as an argument in the device database file
|
For earlier version please explicitly define it as an argument in the device database file
|
||||||
(e.g. ``"hw_rev": "v2.1"``).
|
(e.g. ``"hw_rev": "v2.1"``).
|
||||||
|
* Added channel names to RTIO errors.
|
||||||
|
|
||||||
ARTIQ-7
|
ARTIQ-7
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -80,6 +80,10 @@ class AD9914:
|
||||||
self.set_x_duration_mu = 7 * self.write_duration_mu
|
self.set_x_duration_mu = 7 * self.write_duration_mu
|
||||||
self.exit_x_duration_mu = 3 * self.write_duration_mu
|
self.exit_x_duration_mu = 3 * self.write_duration_mu
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(bus_channel, **kwargs):
|
||||||
|
return [(bus_channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write(self, addr, data):
|
def write(self, addr, data):
|
||||||
rtio_output((self.bus_channel << 8) | addr, data)
|
rtio_output((self.bus_channel << 8) | addr, data)
|
||||||
|
|
|
@ -73,6 +73,10 @@ class ADF5356:
|
||||||
|
|
||||||
self._init_registers()
|
self._init_registers()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self, blind=False):
|
def init(self, blind=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -91,6 +91,10 @@ class EdgeCounter:
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.counter_max = (1 << (gateware_width - 1)) - 1
|
self.counter_max = (1 << (gateware_width - 1)) - 1
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def gate_rising(self, duration):
|
def gate_rising(self, duration):
|
||||||
"""Count rising edges for the given duration and request the total at
|
"""Count rising edges for the given duration and request the total at
|
||||||
|
|
|
@ -52,6 +52,10 @@ class Fastino:
|
||||||
assert self.core.ref_period == 1*ns
|
assert self.core.ref_period == 1*ns
|
||||||
self.t_frame = int64(14*7*4)
|
self.t_frame = int64(14*7*4)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self):
|
def init(self):
|
||||||
"""Initialize the device.
|
"""Initialize the device.
|
||||||
|
|
|
@ -25,6 +25,10 @@ class Grabber:
|
||||||
# ROI engine outputs for one video frame.
|
# ROI engine outputs for one video frame.
|
||||||
self.sentinel = int32(int64(2**count_width))
|
self.sentinel = int32(int64(2**count_width))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel_base, **kwargs):
|
||||||
|
return [(channel_base, "ROI coordinates"), (channel_base + 1, "ROI mask")]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def setup_roi(self, n, x0, y0, x1, y1):
|
def setup_roi(self, n, x0, y0, x1, y1):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -229,7 +229,7 @@ class Phaser:
|
||||||
"dac_mmap"}
|
"dac_mmap"}
|
||||||
|
|
||||||
def __init__(self, dmgr, channel_base, miso_delay=1, tune_fifo_offset=True,
|
def __init__(self, dmgr, channel_base, miso_delay=1, tune_fifo_offset=True,
|
||||||
clk_sel=0, sync_dly=0, dac=None, trf0=None, trf1=None,
|
clk_sel=0, sync_dly=0, dac=None, trf0=None, trf1=None, gw_rev=PHASER_GW_BASE,
|
||||||
core_device="core"):
|
core_device="core"):
|
||||||
self.channel_base = channel_base
|
self.channel_base = channel_base
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
|
@ -243,13 +243,25 @@ class Phaser:
|
||||||
self.clk_sel = clk_sel
|
self.clk_sel = clk_sel
|
||||||
self.tune_fifo_offset = tune_fifo_offset
|
self.tune_fifo_offset = tune_fifo_offset
|
||||||
self.sync_dly = sync_dly
|
self.sync_dly = sync_dly
|
||||||
self.gw_rev = -1 # discovered in init()
|
self.gw_rev = gw_rev # verified in init()
|
||||||
|
|
||||||
self.dac_mmap = DAC34H84(dac).get_mmap()
|
self.dac_mmap = DAC34H84(dac).get_mmap()
|
||||||
|
|
||||||
self.channel = [PhaserChannel(self, ch, trf)
|
self.channel = [PhaserChannel(self, ch, trf)
|
||||||
for ch, trf in enumerate([trf0, trf1])]
|
for ch, trf in enumerate([trf0, trf1])]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel_base, gw_rev=PHASER_GW_BASE, **kwargs):
|
||||||
|
if gw_rev == PHASER_GW_MIQRO:
|
||||||
|
return [(channel_base, "base"), (channel_base + 1, "ch0"), (channel_base + 2, "ch1")]
|
||||||
|
elif gw_rev == PHASER_GW_BASE:
|
||||||
|
return [(channel_base, "base"),
|
||||||
|
(channel_base + 1, "ch0 frequency"),
|
||||||
|
(channel_base + 2, "ch0 phase amplitude"),
|
||||||
|
(channel_base + 3, "ch1 frequency"),
|
||||||
|
(channel_base + 4, "ch1 phase amplitude")]
|
||||||
|
raise ValueError("invalid gw_rev `{}`".format(gw_rev))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self, debug=False):
|
def init(self, debug=False):
|
||||||
"""Initialize the board.
|
"""Initialize the board.
|
||||||
|
@ -267,10 +279,11 @@ class Phaser:
|
||||||
delay(.1*ms) # slack
|
delay(.1*ms) # slack
|
||||||
is_baseband = hw_rev & PHASER_HW_REV_VARIANT
|
is_baseband = hw_rev & PHASER_HW_REV_VARIANT
|
||||||
|
|
||||||
self.gw_rev = self.read8(PHASER_ADDR_GW_REV)
|
gw_rev = self.read8(PHASER_ADDR_GW_REV)
|
||||||
if debug:
|
if debug:
|
||||||
print("gw_rev:", self.gw_rev)
|
print("gw_rev:", self.gw_rev)
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
|
assert gw_rev == self.gw_rev
|
||||||
delay(.1*ms) # slack
|
delay(.1*ms) # slack
|
||||||
|
|
||||||
# allow a few errors during startup and alignment since boot
|
# allow a few errors during startup and alignment since boot
|
||||||
|
|
|
@ -334,6 +334,19 @@ class SAWG:
|
||||||
self.phase0 = Spline(width, time_width, channel_base + 9,
|
self.phase0 = Spline(width, time_width, channel_base + 9,
|
||||||
self.core, 1.)
|
self.core, 1.)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel_base, **kwargs):
|
||||||
|
return [(channel_base, "base"),
|
||||||
|
(channel_base+1, "offset"),
|
||||||
|
(channel_base+2, "amplitude 1"),
|
||||||
|
(channel_base+3, "frequency 1"),
|
||||||
|
(channel_base+4, "phase 1"),
|
||||||
|
(channel_base+5, "amplitude 2"),
|
||||||
|
(channel_base+6, "frequency 2"),
|
||||||
|
(channel_base+7, "phase 2"),
|
||||||
|
(channel_base+8, "frequency 0"),
|
||||||
|
(channel_base+9, "phase0")]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Re-establish initial conditions.
|
"""Re-establish initial conditions.
|
||||||
|
|
|
@ -72,6 +72,10 @@ class SPIMaster:
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.update_xfer_duration_mu(div, length)
|
self.update_xfer_duration_mu(div, length)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def frequency_to_div(self, f):
|
def frequency_to_div(self, f):
|
||||||
"""Convert a SPI clock frequency to the closest SPI clock divider."""
|
"""Convert a SPI clock frequency to the closest SPI clock divider."""
|
||||||
|
|
|
@ -41,6 +41,10 @@ class Spline:
|
||||||
self.time_scale = float((1 << time_width) *
|
self.time_scale = float((1 << time_width) *
|
||||||
core_device.coarse_ref_period)
|
core_device.coarse_ref_period)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@portable(flags={"fast-math"})
|
@portable(flags={"fast-math"})
|
||||||
def to_mu(self, value: TFloat) -> TInt32:
|
def to_mu(self, value: TFloat) -> TInt32:
|
||||||
"""Convert floating point ``value`` from physical units to 32 bit
|
"""Convert floating point ``value`` from physical units to 32 bit
|
||||||
|
|
|
@ -85,6 +85,10 @@ class SUServo:
|
||||||
self.corrected_fs = sampler.Sampler.use_corrected_fs(sampler_hw_rev)
|
self.corrected_fs = sampler.Sampler.use_corrected_fs(sampler_hw_rev)
|
||||||
assert self.ref_period_mu == self.core.ref_multiplier
|
assert self.ref_period_mu == self.core.ref_multiplier
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def init(self):
|
def init(self):
|
||||||
"""Initialize the servo, Sampler and both Urukuls.
|
"""Initialize the servo, Sampler and both Urukuls.
|
||||||
|
@ -257,6 +261,10 @@ class Channel:
|
||||||
self.servo.channel)
|
self.servo.channel)
|
||||||
self.dds = self.servo.ddses[self.servo_channel // 4]
|
self.dds = self.servo.ddses[self.servo_channel // 4]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set(self, en_out, en_iir=0, profile=0):
|
def set(self, en_out, en_iir=0, profile=0):
|
||||||
"""Operate channel.
|
"""Operate channel.
|
||||||
|
|
|
@ -36,6 +36,10 @@ class TTLOut:
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.target_o = channel << 8
|
self.target_o = channel << 8
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def output(self):
|
def output(self):
|
||||||
pass
|
pass
|
||||||
|
@ -128,6 +132,10 @@ class TTLInOut:
|
||||||
self.target_sens = (channel << 8) + 2
|
self.target_sens = (channel << 8) + 2
|
||||||
self.target_sample = (channel << 8) + 3
|
self.target_sample = (channel << 8) + 3
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_oe(self, oe):
|
def set_oe(self, oe):
|
||||||
rtio_output(self.target_oe, 1 if oe else 0)
|
rtio_output(self.target_oe, 1 if oe else 0)
|
||||||
|
@ -465,6 +473,10 @@ class TTLClockGen:
|
||||||
|
|
||||||
self.acc_width = numpy.int64(acc_width)
|
self.acc_width = numpy.int64(acc_width)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_rtio_channels(channel, **kwargs):
|
||||||
|
return [(channel, None)]
|
||||||
|
|
||||||
@portable
|
@portable
|
||||||
def frequency_to_ftw(self, frequency):
|
def frequency_to_ftw(self, frequency):
|
||||||
"""Returns the frequency tuning word corresponding to the given
|
"""Returns the frequency tuning word corresponding to the given
|
||||||
|
|
|
@ -414,13 +414,13 @@ extern fn dma_playback(timestamp: i64, ptr: i32) {
|
||||||
csr::rtio_dma::error_write(1);
|
csr::rtio_dma::error_write(1);
|
||||||
if error & 1 != 0 {
|
if error & 1 != 0 {
|
||||||
raise!("RTIOUnderflow",
|
raise!("RTIOUnderflow",
|
||||||
"RTIO underflow at {0} mu, channel {1}",
|
"RTIO underflow at channel {rtio_channel_info:0}, {1} mu",
|
||||||
timestamp as i64, channel as i64, 0);
|
channel as i64, timestamp as i64, 0);
|
||||||
}
|
}
|
||||||
if error & 2 != 0 {
|
if error & 2 != 0 {
|
||||||
raise!("RTIODestinationUnreachable",
|
raise!("RTIODestinationUnreachable",
|
||||||
"RTIO destination unreachable, output, at {0} mu, channel {1}",
|
"RTIO destination unreachable, output, at channel {rtio_channel_info:0}, {1} mu",
|
||||||
timestamp as i64, channel as i64, 0);
|
channel as i64, timestamp as i64, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,13 +67,13 @@ mod imp {
|
||||||
}
|
}
|
||||||
if status & RTIO_O_STATUS_UNDERFLOW != 0 {
|
if status & RTIO_O_STATUS_UNDERFLOW != 0 {
|
||||||
raise!("RTIOUnderflow",
|
raise!("RTIOUnderflow",
|
||||||
"RTIO underflow at {0} mu, channel {1}, slack {2} mu",
|
"RTIO underflow at channel {rtio_channel_info:0}, {1} mu, slack {2} mu",
|
||||||
timestamp, channel as i64, timestamp - get_counter());
|
channel as i64, timestamp, timestamp - get_counter());
|
||||||
}
|
}
|
||||||
if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 {
|
if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
raise!("RTIODestinationUnreachable",
|
raise!("RTIODestinationUnreachable",
|
||||||
"RTIO destination unreachable, output, at {0} mu, channel {1}",
|
"RTIO destination unreachable, output, at channel {rtio_channel_info:0}, {1} mu",
|
||||||
timestamp, channel as i64, 0);
|
channel as i64, timestamp, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ mod imp {
|
||||||
|
|
||||||
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
raise!("RTIOOverflow",
|
raise!("RTIOOverflow",
|
||||||
"RTIO input overflow on channel {0}",
|
"RTIO input overflow on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
||||||
|
@ -123,7 +123,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
raise!("RTIODestinationUnreachable",
|
raise!("RTIODestinationUnreachable",
|
||||||
"RTIO destination unreachable, input, on channel {0}",
|
"RTIO destination unreachable, input, on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,12 +143,12 @@ mod imp {
|
||||||
|
|
||||||
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
raise!("RTIOOverflow",
|
raise!("RTIOOverflow",
|
||||||
"RTIO input overflow on channel {0}",
|
"RTIO input overflow on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
raise!("RTIODestinationUnreachable",
|
raise!("RTIODestinationUnreachable",
|
||||||
"RTIO destination unreachable, input, on channel {0}",
|
"RTIO destination unreachable, input, on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ mod imp {
|
||||||
|
|
||||||
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
raise!("RTIOOverflow",
|
raise!("RTIOOverflow",
|
||||||
"RTIO input overflow on channel {0}",
|
"RTIO input overflow on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
||||||
|
@ -176,7 +176,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
raise!("RTIODestinationUnreachable",
|
raise!("RTIODestinationUnreachable",
|
||||||
"RTIO destination unreachable, input, on channel {0}",
|
"RTIO destination unreachable, input, on channel {rtio_channel_info:0}",
|
||||||
channel as i64, 0, 0);
|
channel as i64, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(lang_items, panic_info_message)]
|
#![feature(lang_items, panic_info_message, const_btree_new, iter_advance_by)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate eh;
|
extern crate eh;
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use urc::Urc;
|
use urc::Urc;
|
||||||
use board_misoc::csr;
|
use board_misoc::{csr, config};
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use board_misoc::clock;
|
use board_misoc::clock;
|
||||||
use board_artiq::drtio_routing;
|
use board_artiq::drtio_routing;
|
||||||
use sched::Io;
|
use sched::Io;
|
||||||
use sched::Mutex;
|
use sched::Mutex;
|
||||||
|
use io::{Cursor, ProtoRead};
|
||||||
const ASYNC_ERROR_COLLISION: u8 = 1 << 0;
|
const ASYNC_ERROR_COLLISION: u8 = 1 << 0;
|
||||||
const ASYNC_ERROR_BUSY: u8 = 1 << 1;
|
const ASYNC_ERROR_BUSY: u8 = 1 << 1;
|
||||||
const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2;
|
const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2;
|
||||||
|
|
||||||
|
static mut RTIO_DEVICE_MAP: BTreeMap<u32, String> = BTreeMap::new();
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
pub mod drtio {
|
pub mod drtio {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -215,15 +220,15 @@ pub mod drtio {
|
||||||
destination_set_up(routing_table, up_destinations, destination, false),
|
destination_set_up(routing_table, up_destinations, destination, false),
|
||||||
Ok(drtioaux::Packet::DestinationOkReply) => (),
|
Ok(drtioaux::Packet::DestinationOkReply) => (),
|
||||||
Ok(drtioaux::Packet::DestinationSequenceErrorReply { channel }) => {
|
Ok(drtioaux::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 as u32), channel);
|
||||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
|
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
|
||||||
}
|
}
|
||||||
Ok(drtioaux::Packet::DestinationCollisionReply { channel }) => {
|
Ok(drtioaux::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 as u32), channel);
|
||||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
|
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
|
||||||
}
|
}
|
||||||
Ok(drtioaux::Packet::DestinationBusyReply { channel }) => {
|
Ok(drtioaux::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 as u32), channel);
|
||||||
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
|
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
|
||||||
}
|
}
|
||||||
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
|
||||||
|
@ -349,16 +354,16 @@ fn async_error_thread(io: Io) {
|
||||||
io.until(|| csr::rtio_core::async_error_read() != 0).unwrap();
|
io.until(|| csr::rtio_core::async_error_read() != 0).unwrap();
|
||||||
let errors = csr::rtio_core::async_error_read();
|
let errors = csr::rtio_core::async_error_read();
|
||||||
if errors & ASYNC_ERROR_COLLISION != 0 {
|
if errors & ASYNC_ERROR_COLLISION != 0 {
|
||||||
error!("RTIO collision involving channel {}",
|
let channel = csr::rtio_core::collision_channel_read();
|
||||||
csr::rtio_core::collision_channel_read());
|
error!("RTIO collision involving channel {}:{}", channel, resolve_channel_name(channel as u32));
|
||||||
}
|
}
|
||||||
if errors & ASYNC_ERROR_BUSY != 0 {
|
if errors & ASYNC_ERROR_BUSY != 0 {
|
||||||
error!("RTIO busy error involving channel {}",
|
let channel = csr::rtio_core::busy_channel_read();
|
||||||
csr::rtio_core::busy_channel_read());
|
error!("RTIO busy error involving channel {}:{}", channel, resolve_channel_name(channel as u32));
|
||||||
}
|
}
|
||||||
if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 {
|
if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 {
|
||||||
error!("RTIO sequence error involving channel {}",
|
let channel = csr::rtio_core::sequence_error_channel_read();
|
||||||
csr::rtio_core::sequence_error_channel_read());
|
error!("RTIO sequence error involving channel {}:{}", channel, resolve_channel_name(channel as u32));
|
||||||
}
|
}
|
||||||
SEEN_ASYNC_ERRORS = errors;
|
SEEN_ASYNC_ERRORS = errors;
|
||||||
csr::rtio_core::async_error_write(errors);
|
csr::rtio_core::async_error_write(errors);
|
||||||
|
@ -366,9 +371,47 @@ fn async_error_thread(io: Io) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_device_map() -> BTreeMap<u32, String> {
|
||||||
|
let mut device_map: BTreeMap<u32, String> = BTreeMap::new();
|
||||||
|
config::read("device_map", |value: Result<&[u8], config::Error>| {
|
||||||
|
let mut bytes = match value {
|
||||||
|
Ok(val) => if val.len() > 0 { Cursor::new(val) } else {
|
||||||
|
error!("read_device_map: `device_map` was not found in the config");
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
error!("read_device_map: error reading `device_map` from config: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let size = bytes.read_u32().unwrap();
|
||||||
|
for _ in 0..size {
|
||||||
|
let channel = bytes.read_u32().unwrap();
|
||||||
|
let device_name= bytes.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn startup(io: &Io, aux_mutex: &Mutex,
|
pub fn startup(io: &Io, aux_mutex: &Mutex,
|
||||||
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
|
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
|
||||||
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
|
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
|
||||||
|
unsafe { RTIO_DEVICE_MAP = read_device_map(); }
|
||||||
drtio::startup(io, aux_mutex, routing_table, up_destinations);
|
drtio::startup(io, aux_mutex, routing_table, up_destinations);
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::rtio_core::reset_phy_write(1);
|
csr::rtio_core::reset_phy_write(1);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite};
|
use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite, slice};
|
||||||
use alloc::{vec::Vec, string::String};
|
use alloc::{vec::Vec, string::String};
|
||||||
use byteorder::{ByteOrder, NativeEndian};
|
use byteorder::{ByteOrder, NativeEndian};
|
||||||
use cslice::CSlice;
|
use cslice::CSlice;
|
||||||
|
@ -10,7 +10,7 @@ use urc::Urc;
|
||||||
use sched::{ThreadHandle, Io, Mutex, TcpListener, TcpStream, Error as SchedError};
|
use sched::{ThreadHandle, Io, Mutex, TcpListener, TcpStream, Error as SchedError};
|
||||||
use rtio_clocking;
|
use rtio_clocking;
|
||||||
use rtio_dma::Manager as DmaManager;
|
use rtio_dma::Manager as DmaManager;
|
||||||
use rtio_mgt::get_async_errors;
|
use rtio_mgt::{get_async_errors, resolve_channel_name};
|
||||||
use cache::Cache;
|
use cache::Cache;
|
||||||
use kern_hwreq;
|
use kern_hwreq;
|
||||||
use board_artiq::drtio_routing;
|
use board_artiq::drtio_routing;
|
||||||
|
@ -449,6 +449,25 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
|
||||||
session.kernel_state = KernelState::Absent;
|
session.kernel_state = KernelState::Absent;
|
||||||
unsafe { session.congress.cache.unborrow() }
|
unsafe { session.congress.cache.unborrow() }
|
||||||
|
|
||||||
|
let exceptions_with_channel: Vec<Option<eh::eh_artiq::Exception>> = exceptions.iter()
|
||||||
|
.map(|exception| {
|
||||||
|
if let Some(exn) = exception {
|
||||||
|
let msg = str::from_utf8(unsafe{slice::from_raw_parts(exn.message.as_ptr(), exn.message.len())})
|
||||||
|
.unwrap()
|
||||||
|
.replace("{rtio_channel_info:0}", &format!("{}:{}", exn.param[0], resolve_channel_name(exn.param[0] as u32)));
|
||||||
|
Some(eh::eh_artiq::Exception {
|
||||||
|
id: exn.id,
|
||||||
|
file: exn.file,
|
||||||
|
line: exn.line,
|
||||||
|
column: exn.column,
|
||||||
|
function: exn.function,
|
||||||
|
message: unsafe {CSlice::new(msg.as_ptr(), msg.len())},
|
||||||
|
param: exn.param
|
||||||
|
})
|
||||||
|
} else { None }
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
match stream {
|
match stream {
|
||||||
None => {
|
None => {
|
||||||
error!("exception in flash kernel");
|
error!("exception in flash kernel");
|
||||||
|
@ -459,7 +478,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
|
||||||
},
|
},
|
||||||
Some(ref mut stream) => {
|
Some(ref mut stream) => {
|
||||||
host_write(stream, host::Reply::KernelException {
|
host_write(stream, host::Reply::KernelException {
|
||||||
exceptions: exceptions,
|
exceptions: &exceptions_with_channel,
|
||||||
stack_pointers: stack_pointers,
|
stack_pointers: stack_pointers,
|
||||||
backtrace: backtrace,
|
backtrace: backtrace,
|
||||||
async_errors: unsafe { get_async_errors() }
|
async_errors: unsafe { get_async_errors() }
|
||||||
|
|
|
@ -8,6 +8,7 @@ from itertools import count
|
||||||
|
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
from artiq.coredevice import jsondesc
|
from artiq.coredevice import jsondesc
|
||||||
|
from artiq.coredevice.phaser import PHASER_GW_MIQRO, PHASER_GW_BASE
|
||||||
|
|
||||||
|
|
||||||
def process_header(output, description):
|
def process_header(output, description):
|
||||||
|
@ -566,10 +567,10 @@ class PeripheralManager:
|
||||||
def process_phaser(self, rtio_offset, peripheral):
|
def process_phaser(self, rtio_offset, peripheral):
|
||||||
mode = peripheral.get("mode", "base")
|
mode = peripheral.get("mode", "base")
|
||||||
if mode == "miqro":
|
if mode == "miqro":
|
||||||
dac = ', "dac": {"pll_m": 16, "pll_n": 3, "interpolation": 2}'
|
dac = f', "dac": {{"pll_m": 16, "pll_n": 3, "interpolation": 2}}, "gw_rev"={PHASER_GW_MIQRO}'
|
||||||
n_channels = 3
|
n_channels = 3
|
||||||
else:
|
else:
|
||||||
dac = ""
|
dac = f', "gw_rev"={PHASER_GW_BASE}'
|
||||||
n_channels = 5
|
n_channels = 5
|
||||||
self.gen("""
|
self.gen("""
|
||||||
device_db["{name}"] = {{
|
device_db["{name}"] = {{
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import importlib
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from sipyco import common_args
|
||||||
|
|
||||||
|
from artiq import __version__ as artiq_version
|
||||||
|
from artiq.master.databases import DeviceDB
|
||||||
|
|
||||||
|
|
||||||
|
def get_argparser():
|
||||||
|
parser = argparse.ArgumentParser(description="ARTIQ RTIO channel name map encoder tool")
|
||||||
|
|
||||||
|
parser.add_argument("--version", action="version",
|
||||||
|
version="ARTIQ v{}".format(artiq_version),
|
||||||
|
help="print the ARTIQ version number")
|
||||||
|
|
||||||
|
common_args.verbosity_args(parser)
|
||||||
|
parser.add_argument("--device-db", default="device_db.py",
|
||||||
|
help="device database file (default: '%(default)s')")
|
||||||
|
parser.add_argument("file", metavar="FILE", default=None,
|
||||||
|
help="write the result into the specified file, or read from it to show the map (see `--show`)")
|
||||||
|
parser.add_argument("--show", default=False, action="store_true",
|
||||||
|
help="show the channel mapping from the specified file, instead of writing to it")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def get_rtio_channels(desc):
|
||||||
|
if desc["type"] == "local":
|
||||||
|
module = importlib.import_module(desc["module"])
|
||||||
|
device_class = getattr(module, desc["class"])
|
||||||
|
return getattr(device_class, "get_rtio_channels", lambda **kwargs: [])(**desc.get("arguments", {}))
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def get_channel_map(device_db):
|
||||||
|
reversed_map = {}
|
||||||
|
for dev_name, device in device_db.items():
|
||||||
|
try:
|
||||||
|
channels = get_rtio_channels(device)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"failed to process the device `{dev_name}`") from e
|
||||||
|
for chan, suffix in channels:
|
||||||
|
assert chan not in reversed_map
|
||||||
|
reversed_map[chan] = dev_name + (" " + suffix if suffix is not None else "")
|
||||||
|
|
||||||
|
return reversed_map
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_device_map(channel_map, outfile):
|
||||||
|
outfile.write(struct.pack("<I", len(channel_map)))
|
||||||
|
for dev_num, dev_name in channel_map.items():
|
||||||
|
dev_name_bytes = dev_name.encode("utf-8")
|
||||||
|
outfile.write(struct.pack("<II{}s".format(len(dev_name_bytes)), dev_num, len(dev_name_bytes), dev_name_bytes))
|
||||||
|
|
||||||
|
|
||||||
|
def deserialize_device_map(infile):
|
||||||
|
result_map = dict()
|
||||||
|
ch_count, = struct.unpack_from("<I", infile.read(4))
|
||||||
|
for _ in range(ch_count):
|
||||||
|
dev_num, dev_name_len = struct.unpack_from("<II", infile.read(8))
|
||||||
|
dev_name = struct.unpack_from("<{}s".format(dev_name_len), infile.read(dev_name_len))[0].decode("utf-8")
|
||||||
|
assert dev_num not in result_map
|
||||||
|
result_map[dev_num] = dev_name
|
||||||
|
return result_map
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_argparser().parse_args()
|
||||||
|
common_args.init_logger_from_args(args)
|
||||||
|
|
||||||
|
if args.show:
|
||||||
|
with open(args.file, "rb") as infile:
|
||||||
|
chan_map = deserialize_device_map(infile)
|
||||||
|
for chan, device in sorted(chan_map.items(), key=lambda x: x[0]):
|
||||||
|
print(f"{chan} -> {device}")
|
||||||
|
else:
|
||||||
|
ddb = DeviceDB(args.device_db)
|
||||||
|
chan_map = get_channel_map(ddb.get_device_db())
|
||||||
|
|
||||||
|
with open(args.file, "wb") as outfile:
|
||||||
|
serialize_device_map(chan_map, outfile)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -13,7 +13,7 @@ class TestFrontends(unittest.TestCase):
|
||||||
],
|
],
|
||||||
"artiq": [
|
"artiq": [
|
||||||
"client", "compile", "coreanalyzer", "coremgmt",
|
"client", "compile", "coreanalyzer", "coremgmt",
|
||||||
"flash", "master", "mkfs", "route",
|
"flash", "master", "mkfs", "route", "rtiomap",
|
||||||
"rtiomon", "run", "session", "browser", "dashboard"
|
"rtiomon", "run", "session", "browser", "dashboard"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,3 +340,13 @@ Other options include:
|
||||||
- ``ext0_bypass_125`` and ``ext0_bypass_100`` - explicit aliases for ``ext0_bypass``.
|
- ``ext0_bypass_125`` and ``ext0_bypass_100`` - explicit aliases for ``ext0_bypass``.
|
||||||
|
|
||||||
Availability of these options depends on the board and their configuration - specific setting may or may not be supported.
|
Availability of these options depends on the board and their configuration - specific setting may or may not be supported.
|
||||||
|
|
||||||
|
* Setup resolving RTIO channels to their names
|
||||||
|
|
||||||
|
This feature allows you to print the channels' respective names alongside with their numbers in RTIO error messages. To enable it, run the ``artiq_rtiomap`` tool and write its result into the device config at the ``device_map`` key: ::
|
||||||
|
|
||||||
|
$ artiq_rtiomap dev_map.bin
|
||||||
|
$ artiq_coremgmt config write -f device_map dev_map.bin
|
||||||
|
|
||||||
|
.. note:: You can find more information about how to use the ``artiq_rtiomap`` utility on the :ref:`Utilities <rtiomap-tool>` page.
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,15 @@ Moninj proxy
|
||||||
:ref: artiq.frontend.aqctl_moninj_proxy.get_argparser
|
:ref: artiq.frontend.aqctl_moninj_proxy.get_argparser
|
||||||
:prog: aqctl_moninj_proxy
|
:prog: aqctl_moninj_proxy
|
||||||
|
|
||||||
|
.. _rtiomap-tool:
|
||||||
|
|
||||||
|
RTIO channel name map tool
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. argparse::
|
||||||
|
:ref: artiq.frontend.artiq_rtiomap.get_argparser
|
||||||
|
:prog: artiq_rtiomap
|
||||||
|
|
||||||
|
|
||||||
.. _core-device-rtio-analyzer-tool:
|
.. _core-device-rtio-analyzer-tool:
|
||||||
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -23,6 +23,7 @@ console_scripts = [
|
||||||
"artiq_compile = artiq.frontend.artiq_compile:main",
|
"artiq_compile = artiq.frontend.artiq_compile:main",
|
||||||
"artiq_coreanalyzer = artiq.frontend.artiq_coreanalyzer:main",
|
"artiq_coreanalyzer = artiq.frontend.artiq_coreanalyzer:main",
|
||||||
"artiq_coremgmt = artiq.frontend.artiq_coremgmt:main",
|
"artiq_coremgmt = artiq.frontend.artiq_coremgmt:main",
|
||||||
|
"artiq_rtiomap = artiq.frontend.artiq_rtiomap:main",
|
||||||
"artiq_ddb_template = artiq.frontend.artiq_ddb_template:main",
|
"artiq_ddb_template = artiq.frontend.artiq_ddb_template:main",
|
||||||
"artiq_master = artiq.frontend.artiq_master:main",
|
"artiq_master = artiq.frontend.artiq_master:main",
|
||||||
"artiq_mkfs = artiq.frontend.artiq_mkfs:main",
|
"artiq_mkfs = artiq.frontend.artiq_mkfs:main",
|
||||||
|
|
Loading…
Reference in New Issue