Compare commits

...

5 Commits

12 changed files with 305 additions and 316 deletions

View File

@ -11,11 +11,11 @@
"src-pythonparser": "src-pythonparser"
},
"locked": {
"lastModified": 1710303235,
"narHash": "sha256-0rIfVoL8RInAQSDVfjpLdMqIYdnVsA8DdMk2+aqvwrM=",
"ref": "refs/heads/master",
"rev": "c4323e1179aa0b9c9b4c135f894f267715cf2391",
"revCount": 8727,
"lastModified": 1714013217,
"narHash": "sha256-P0pVHTSgAkTYWFPjddcPhufe5oH8mjJAsxG8x8mo4NA=",
"ref": "master",
"rev": "7204feae1f504e4a1dcd54b95c59e8f36c62b701",
"revCount": 8776,
"type": "git",
"url": "https://github.com/m-labs/artiq.git"
},
@ -118,11 +118,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1707347730,
"narHash": "sha256-0etC/exQIaqC9vliKhc3eZE2Mm2wgLa0tj93ZF/egvM=",
"lastModified": 1711668574,
"narHash": "sha256-u1dfs0ASQIEr1icTVrsKwg2xToIpn7ZXxW3RHfHxshg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6832d0d99649db3d65a0e15fa51471537b2c56a6",
"rev": "219951b495fc2eac67b1456824cc1ec1fd2ee659",
"type": "github"
},
"original": {
@ -147,11 +147,11 @@
]
},
"locked": {
"lastModified": 1701572254,
"narHash": "sha256-ixq8dlpyOytDr+d/OmW8v1Ioy9V2G2ibOlNj8GFDSq4=",
"lastModified": 1708937641,
"narHash": "sha256-Hkb9VYFzFgkYxfbh4kYcDSn7DbMUYehoQDeTALrxo2Q=",
"owner": "m-labs",
"repo": "sipyco",
"rev": "cceac0df537887135f99aa6b1bdd82853f16b4d6",
"rev": "4a28b311ce0069454b4e8fe1e6049db11b9f1296",
"type": "github"
},
"original": {
@ -234,11 +234,11 @@
]
},
"locked": {
"lastModified": 1709785588,
"narHash": "sha256-2Pik/AP05ZKOrCfsXVZfdRijAWSyya9mrNTXzljFskM=",
"ref": "refs/heads/master",
"rev": "7c58c0cf434f37504c62caa03c2c0d6b863da9bf",
"revCount": 641,
"lastModified": 1711358419,
"narHash": "sha256-LzetYaLsnov9pHVWSCTSowXUAXkxemAa61CIMY98xsc=",
"ref": "master",
"rev": "195a21fe78e4dde1fd705cb2899ab5d2763ae037",
"revCount": 643,
"type": "git",
"url": "https://git.m-labs.hk/m-labs/zynq-rs"
},

View File

@ -1,12 +1,12 @@
"""Auxiliary controller, common to satellite and master"""
from artiq.gateware.drtio.aux_controller import Transmitter, Receiver
from artiq.gateware.drtio.aux_controller import (max_packet, aux_buffer_count,
Transmitter, Receiver)
from migen.fhdl.simplify import FullMemoryWE
from misoc.interconnect.csr import *
from migen_axi.interconnect.sram import SRAM
from migen_axi.interconnect import axi
max_packet = 1024
class _DRTIOAuxControllerBase(Module):
def __init__(self, link_layer):
@ -27,12 +27,12 @@ class DRTIOAuxControllerAxi(_DRTIOAuxControllerBase):
tx_sdram_if = SRAM(self.transmitter.mem, read_only=False)
rx_sdram_if = SRAM(self.receiver.mem, read_only=True)
aw_decoder = axi.AddressDecoder(self.bus.aw,
[(lambda a: a[log2_int(max_packet)] == 0, tx_sdram_if.bus.aw),
(lambda a: a[log2_int(max_packet)] == 1, rx_sdram_if.bus.aw)],
[(lambda a: a[log2_int(max_packet*aux_buffer_count)] == 0, tx_sdram_if.bus.aw),
(lambda a: a[log2_int(max_packet*aux_buffer_count)] == 1, rx_sdram_if.bus.aw)],
register=True)
ar_decoder = axi.AddressDecoder(self.bus.ar,
[(lambda a: a[log2_int(max_packet)] == 0, tx_sdram_if.bus.ar),
(lambda a: a[log2_int(max_packet)] == 1, rx_sdram_if.bus.ar)],
[(lambda a: a[log2_int(max_packet*aux_buffer_count)] == 0, tx_sdram_if.bus.ar),
(lambda a: a[log2_int(max_packet*aux_buffer_count)] == 1, rx_sdram_if.bus.ar)],
register=True)
# unlike wb, axi address decoder only connects ar/aw lanes,
# the rest must also be connected!
@ -82,4 +82,4 @@ class DRTIOAuxControllerBare(_DRTIOAuxControllerBase):
return self.receiver.mem.get_port(write_capable=False)
def get_mem_size(self):
return max_packet
return max_packet*aux_buffer_count

View File

@ -74,12 +74,15 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
let linkidx = linkno as usize;
unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2) as *mut u32;
let len = (DRTIOAUX[linkidx].aux_rx_length_read)() as usize;
let read_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize;
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + read_ptr * 0x400) as *mut u32;
// work buffer to accomodate axi burst reads
let mut buf: [u8; 1024] = [0; 1024];
copy_work_buffer(ptr, buf.as_mut_ptr() as *mut u32, len as isize);
let result = f(&buf[0..len]);
// buffer at maximum proto packet size, not maximum gateware supported size
// to minimize copying time
const LEN: usize = 512;
let mut buf: [u8; LEN] = [0; LEN];
copy_work_buffer(ptr, buf.as_mut_ptr() as *mut u32, LEN as isize);
let result = f(&buf);
(DRTIOAUX[linkidx].aux_rx_present_write)(1);
Ok(Some(result?))
} else {
@ -100,15 +103,15 @@ pub fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
let mut reader = Cursor::new(buffer);
let checksum_at = buffer.len() - 4;
let packet = Packet::read_from(&mut reader)?;
let padding = (12 - (reader.position() % 8)) % 8;
let checksum_at = reader.position() + padding;
let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]);
reader.set_position(checksum_at);
if reader.read_u32()? != checksum {
return Err(Error::CorruptedPacket);
}
reader.set_position(0);
Ok(Packet::read_from(&mut reader)?)
Ok(packet)
})
}
@ -130,10 +133,9 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
unsafe {
while (DRTIOAUX[linkno].aux_tx_read)() != 0 {}
let ptr = DRTIOAUX_MEM[linkno].base as *mut u32;
let len = DRTIOAUX_MEM[linkno].size / 2;
// work buffer, works with unaligned mem access
let mut buf: [u8; 1024] = [0; 1024];
let len = f(&mut buf[0..len])?;
let len = f(&mut buf)?;
copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize);
(DRTIOAUX[linkno].aux_tx_length_write)(len as u16);
(DRTIOAUX[linkno].aux_tx_write)(1);

View File

@ -38,12 +38,15 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
let linkidx = linkno as usize;
unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2) as *mut u32;
let len = (DRTIOAUX[linkidx].aux_rx_length_read)() as usize;
let read_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize;
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + read_ptr * 0x400) as *mut u32;
// work buffer to accomodate axi burst reads
let mut buf: [u8; 1024] = [0; 1024];
copy_work_buffer(ptr, buf.as_mut_ptr() as *mut u32, len as isize);
let result = f(&buf[0..len]);
// buffer at maximum proto packet size, not maximum gateware supported size
// to minimize required copying time
const LEN: usize = 512;
let mut buf: [u8; LEN] = [0; LEN];
copy_work_buffer(ptr, buf.as_mut_ptr() as *mut u32, LEN as isize);
let result = f(&buf);
(DRTIOAUX[linkidx].aux_rx_present_write)(1);
Ok(Some(result?))
} else {
@ -64,15 +67,15 @@ pub async fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
let mut reader = Cursor::new(buffer);
let checksum_at = buffer.len() - 4;
let packet = Packet::read_from(&mut reader)?;
let padding = (12 - (reader.position() % 8)) % 8;
let checksum_at = reader.position() + padding;
let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]);
reader.set_position(checksum_at);
if reader.read_u32()? != checksum {
return Err(Error::CorruptedPacket);
}
reader.set_position(0);
Ok(Packet::read_from(&mut reader)?)
Ok(packet)
})
.await
}
@ -103,10 +106,9 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
unsafe {
let _ = block_async!(tx_ready(linkno)).await;
let ptr = DRTIOAUX_MEM[linkno].base as *mut u32;
let len = DRTIOAUX_MEM[linkno].size / 2;
// work buffer, works with unaligned mem access
let mut buf: [u8; 1024] = [0; 1024];
let len = f(&mut buf[0..len])?;
let len = f(&mut buf)?;
copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize);
(DRTIOAUX[linkno].aux_tx_length_write)(len as u16);
(DRTIOAUX[linkno].aux_tx_write)(1);

View File

@ -89,8 +89,6 @@ pub enum Packet {
RoutingSetRank {
rank: u8,
},
RoutingRetrievePackets,
RoutingNoPackets,
RoutingAck,
MonitorRequest {
@ -325,8 +323,6 @@ impl Packet {
rank: reader.read_u8()?,
},
0x32 => Packet::RoutingAck,
0x33 => Packet::RoutingRetrievePackets,
0x34 => Packet::RoutingNoPackets,
0x40 => Packet::MonitorRequest {
destination: reader.read_u8()?,
@ -602,8 +598,6 @@ impl Packet {
writer.write_u8(rank)?;
}
Packet::RoutingAck => writer.write_u8(0x32)?,
Packet::RoutingRetrievePackets => writer.write_u8(0x33)?,
Packet::RoutingNoPackets => writer.write_u8(0x34)?,
Packet::MonitorRequest {
destination,

View File

@ -60,7 +60,7 @@ pub mod remote_analyzer {
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
) -> Result<RemoteBuffer, &'static str> {
) -> Result<RemoteBuffer, drtio::Error> {
// gets data from satellites and returns consolidated data
let mut remote_data: Vec<u8> = Vec::new();
let mut remote_error = false;

View File

@ -58,10 +58,11 @@ mod remote_moninj {
use log::error;
use super::*;
use crate::rtio_mgt::drtio;
use crate::rtio_mgt::{drtio, drtio::Error as DrtioError};
pub async fn read_probe(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer,
linkno: u8,
destination: u8,
@ -71,6 +72,7 @@ mod remote_moninj {
let reply = drtio::aux_transact(
aux_mutex,
linkno,
routing_table,
&drtioaux_async::Packet::MonitorRequest {
destination: destination,
channel: channel as _,
@ -82,8 +84,8 @@ mod remote_moninj {
match reply {
Ok(drtioaux_async::Packet::MonitorReply { value }) => return value as i64,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
Err("link went down") => {
debug!("link is down");
Err(DrtioError::LinkDown) => {
warn!("link is down");
}
Err(e) => error!("aux packet error ({})", e),
}
@ -92,6 +94,7 @@ mod remote_moninj {
pub async fn inject(
aux_mutex: &Rc<Mutex<bool>>,
_routing_table: &drtio_routing::RoutingTable,
_timer: GlobalTimer,
linkno: u8,
destination: u8,
@ -115,6 +118,7 @@ mod remote_moninj {
pub async fn read_injection_status(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer,
linkno: u8,
destination: u8,
@ -124,6 +128,7 @@ mod remote_moninj {
let reply = drtio::aux_transact(
aux_mutex,
linkno,
routing_table,
&drtioaux_async::Packet::InjectionStatusRequest {
destination: destination,
channel: channel as _,
@ -135,8 +140,8 @@ mod remote_moninj {
match reply {
Ok(drtioaux_async::Packet::InjectionStatusReply { value }) => return value as i8,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
Err("link went down") => {
debug!("link is down");
Err(DrtioError::LinkDown) => {
warn!("link is down");
}
Err(e) => error!("aux packet error ({})", e),
}
@ -183,7 +188,7 @@ macro_rules! dispatch {
local_moninj::$func(channel.into(), $($param, )*)
} else {
let linkno = hop - 1 as u8;
remote_moninj::$func($aux_mutex, $timer, linkno, destination, channel, $($param, )*).await
remote_moninj::$func($aux_mutex, $routing_table, $timer, linkno, destination, channel, $($param, )*).await
}
}}
}

View File

@ -1,19 +1,20 @@
use alloc::rc::Rc;
use core::cell::RefCell;
use libboard_artiq::{drtio_routing, pl::csr};
use libboard_artiq::{drtio_routing, drtio_routing::RoutingTable, pl::csr};
use libboard_zynq::timer::GlobalTimer;
use libcortex_a9::mutex::Mutex;
#[cfg(has_drtio)]
pub mod drtio {
use alloc::vec::Vec;
use core::fmt;
use embedded_hal::blocking::delay::DelayMs;
use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
SEEN_ASYNC_ERRORS};
use libasync::{delay, task};
use libboard_artiq::{drtioaux::Error,
use libboard_artiq::{drtioaux::Error as DrtioError,
drtioaux_async,
drtioaux_async::Packet,
drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE}};
@ -23,9 +24,44 @@ pub mod drtio {
use super::*;
use crate::{analyzer::remote_analyzer::RemoteBuffer, rtio_dma::remote_dma, subkernel};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Error {
Timeout,
AuxError,
LinkDown,
UnexpectedReply,
DmaAddTraceFail(u8),
DmaEraseFail(u8),
DmaPlaybackFail(u8),
SubkernelAddFail(u8),
SubkernelRunFail(u8),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Timeout => write!(f, "timed out"),
Error::AuxError => write!(f, "aux packet error"),
Error::LinkDown => write!(f, "link down"),
Error::UnexpectedReply => write!(f, "unexpected reply"),
Error::DmaAddTraceFail(dest) => write!(f, "error adding DMA trace on satellite #{}", dest),
Error::DmaEraseFail(dest) => write!(f, "error erasing DMA trace on satellite #{}", dest),
Error::DmaPlaybackFail(dest) => write!(f, "error playing back DMA trace on satellite #{}", dest),
Error::SubkernelAddFail(dest) => write!(f, "error adding subkernel on satellite #{}", dest),
Error::SubkernelRunFail(dest) => write!(f, "error on subkernel run request on satellite #{}", dest),
}
}
}
impl From<DrtioError> for Error {
fn from(_error: DrtioError) -> Self {
Error::AuxError
}
}
pub fn startup(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
routing_table: &Rc<RefCell<RoutingTable>>,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
) {
@ -43,128 +79,104 @@ pub mod drtio {
unsafe { (csr::DRTIO[linkno].rx_up_read)() == 1 }
}
async fn link_has_async_ready(linkno: u8) -> bool {
let linkno = linkno as usize;
let async_ready;
unsafe {
async_ready = (csr::DRTIO[linkno].async_messages_ready_read)() == 1;
(csr::DRTIO[linkno].async_messages_ready_write)(1);
}
async_ready
}
async fn process_async_packets(
aux_mutex: &Mutex<bool>,
linkno: u8,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer,
) {
if link_has_async_ready(linkno).await {
loop {
let reply = aux_transact(aux_mutex, linkno, &Packet::RoutingRetrievePackets, timer).await;
if let Ok(packet) = reply {
match packet {
Packet::DmaPlaybackStatus {
id,
source,
destination: 0,
error,
channel,
timestamp,
} => {
remote_dma::playback_done(id, source, error, channel, timestamp).await;
}
Packet::SubkernelFinished {
id,
destination: 0,
with_exception,
exception_src,
} => {
subkernel::subkernel_finished(id, with_exception, exception_src).await;
}
Packet::SubkernelMessage {
id,
source,
destination: 0,
status,
length,
data,
} => {
subkernel::message_handle_incoming(id, status, length as usize, &data).await;
// acknowledge receiving part of the message
let _lock = aux_mutex.async_lock().await;
drtioaux_async::send(linkno, &Packet::SubkernelMessageAck { destination: source })
.await
.unwrap();
let mut countdown = timer.countdown();
// give the satellites some time to process
delay(&mut countdown, Milliseconds(10)).await;
}
// routable packets
Packet::DmaAddTraceRequest { destination, .. }
| Packet::DmaAddTraceReply { destination, .. }
| Packet::DmaRemoveTraceRequest { destination, .. }
| Packet::DmaRemoveTraceReply { destination, .. }
| Packet::DmaPlaybackRequest { destination, .. }
| Packet::DmaPlaybackReply { destination, .. }
| Packet::SubkernelLoadRunRequest { destination, .. }
| Packet::SubkernelLoadRunReply { destination, .. }
| Packet::SubkernelMessage { destination, .. }
| Packet::SubkernelMessageAck { destination, .. }
| Packet::DmaPlaybackStatus { destination, .. }
| Packet::SubkernelFinished { destination, .. } => {
let dest_link = routing_table.0[destination as usize][0] - 1;
if dest_link == linkno {
warn!(
"[LINK#{}] Re-routed packet would return to the same link, dropping: {:?}",
linkno, packet
);
} else if destination == 0 {
warn!("[LINK#{}] Received invalid routable packet: {:?}", linkno, packet)
} else {
drtioaux_async::send(dest_link, &packet).await.unwrap();
}
}
Packet::RoutingNoPackets => break,
other => warn!("[LINK#{}] Received an unroutable packet: {:?}", linkno, other),
}
async fn process_async_packets(linkno: u8, routing_table: &RoutingTable, packet: Packet) -> Option<Packet> {
match packet {
Packet::DmaPlaybackStatus {
id,
source,
destination: 0,
error,
channel,
timestamp,
} => {
remote_dma::playback_done(id, source, error, channel, timestamp).await;
None
}
Packet::SubkernelFinished {
id,
destination: 0,
with_exception,
exception_src,
} => {
subkernel::subkernel_finished(id, with_exception, exception_src).await;
None
}
Packet::SubkernelMessage {
id,
source,
destination: 0,
status,
length,
data,
} => {
subkernel::message_handle_incoming(id, status, length as usize, &data).await;
// acknowledge receiving part of the message
drtioaux_async::send(linkno, &Packet::SubkernelMessageAck { destination: source })
.await
.unwrap();
None
}
// routable packets
Packet::DmaAddTraceRequest { destination, .. }
| Packet::DmaAddTraceReply { destination, .. }
| Packet::DmaRemoveTraceRequest { destination, .. }
| Packet::DmaRemoveTraceReply { destination, .. }
| Packet::DmaPlaybackRequest { destination, .. }
| Packet::DmaPlaybackReply { destination, .. }
| Packet::SubkernelLoadRunRequest { destination, .. }
| Packet::SubkernelLoadRunReply { destination, .. }
| Packet::SubkernelMessage { destination, .. }
| Packet::SubkernelMessageAck { destination, .. }
| Packet::DmaPlaybackStatus { destination, .. }
| Packet::SubkernelFinished { destination, .. } => {
if destination == 0 {
Some(packet)
} else {
warn!(
"[LINK#{}] Error handling async packets ({})",
linkno,
reply.unwrap_err()
);
return;
let dest_link = routing_table.0[destination as usize][0] - 1;
if dest_link == linkno {
warn!(
"[LINK#{}] Re-routed packet would return to the same link, dropping: {:?}",
linkno, packet
);
} else {
drtioaux_async::send(dest_link, &packet).await.unwrap();
}
None
}
}
other => Some(other),
}
}
async fn recv_aux_timeout(linkno: u8, timeout: u64, timer: GlobalTimer) -> Result<Packet, &'static str> {
async fn recv_aux_timeout(linkno: u8, timeout: u64, timer: GlobalTimer) -> Result<Packet, Error> {
if !link_rx_up(linkno).await {
return Err("link went down");
return Err(Error::LinkDown);
}
match drtioaux_async::recv_timeout(linkno, Some(timeout), timer).await {
Ok(packet) => return Ok(packet),
Err(Error::TimedOut) => return Err("timed out"),
Err(_) => return Err("aux packet error"),
Err(DrtioError::TimedOut) => return Err(Error::Timeout),
Err(_) => return Err(Error::AuxError),
}
}
pub async fn aux_transact(
aux_mutex: &Mutex<bool>,
linkno: u8,
routing_table: &RoutingTable,
request: &Packet,
timer: GlobalTimer,
) -> Result<Packet, &'static str> {
) -> Result<Packet, Error> {
if !link_rx_up(linkno).await {
return Err("link went down");
return Err(Error::LinkDown);
}
let _lock = aux_mutex.async_lock().await;
drtioaux_async::send(linkno, request).await.unwrap();
Ok(recv_aux_timeout(linkno, 200, timer).await?)
loop {
let packet = recv_aux_timeout(linkno, 200, timer).await?;
if let Some(packet) = process_async_packets(linkno, routing_table, packet).await {
return Ok(packet);
}
}
}
async fn drain_buffer(linkno: u8, draining_time: Milliseconds, timer: GlobalTimer) {
@ -172,12 +184,17 @@ pub mod drtio {
loop {
if timer.get_time() > max_time {
return;
} //could this be cut short?
}
let _ = drtioaux_async::recv(linkno).await;
}
}
async fn ping_remote(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> u32 {
async fn ping_remote(
aux_mutex: &Rc<Mutex<bool>>,
linkno: u8,
routing_table: &RoutingTable,
timer: GlobalTimer,
) -> u32 {
let mut count = 0;
loop {
if !link_rx_up(linkno).await {
@ -187,7 +204,7 @@ pub mod drtio {
if count > 100 {
return 0;
}
let reply = aux_transact(aux_mutex, linkno, &Packet::EchoRequest, timer).await;
let reply = aux_transact(aux_mutex, linkno, routing_table, &Packet::EchoRequest, timer).await;
match reply {
Ok(Packet::EchoReply) => {
// make sure receive buffer is drained
@ -200,7 +217,7 @@ pub mod drtio {
}
}
async fn sync_tsc(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> Result<(), &'static str> {
async fn sync_tsc(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> Result<(), Error> {
let _lock = aux_mutex.async_lock().await;
unsafe {
@ -211,22 +228,23 @@ pub mod drtio {
// by the satellite, in response to a TSC set on the RT link.
let reply = recv_aux_timeout(linkno, 10000, timer).await?;
if reply == Packet::TSCAck {
return Ok(());
Ok(())
} else {
return Err("unexpected reply");
Err(Error::UnexpectedReply)
}
}
async fn load_routing_table(
aux_mutex: &Rc<Mutex<bool>>,
linkno: u8,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
for i in 0..drtio_routing::DEST_COUNT {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::RoutingSetPath {
destination: i as u8,
hops: routing_table.0[i],
@ -235,7 +253,7 @@ pub mod drtio {
)
.await?;
if reply != Packet::RoutingAck {
return Err("unexpected reply");
return Err(Error::UnexpectedReply);
}
}
Ok(())
@ -245,13 +263,21 @@ pub mod drtio {
aux_mutex: &Rc<Mutex<bool>>,
linkno: u8,
rank: u8,
routing_table: &RoutingTable,
timer: GlobalTimer,
) -> Result<(), &'static str> {
let reply = aux_transact(aux_mutex, linkno, &Packet::RoutingSetRank { rank: rank }, timer).await?;
if reply != Packet::RoutingAck {
return Err("unexpected reply");
) -> Result<(), Error> {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::RoutingSetRank { rank: rank },
timer,
)
.await?;
match reply {
Packet::RoutingAck => Ok(()),
_ => Err(Error::UnexpectedReply),
}
Ok(())
}
async fn init_buffer_space(destination: u8, linkno: u8) {
@ -270,10 +296,14 @@ pub mod drtio {
}
}
async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) {
async fn process_unsolicited_aux(aux_mutex: &Mutex<bool>, linkno: u8, routing_table: &RoutingTable) {
let _lock = aux_mutex.async_lock().await;
match drtioaux_async::recv(linkno).await {
Ok(Some(packet)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet),
Ok(Some(packet)) => {
if let Some(packet) = process_async_packets(linkno, routing_table, packet).await {
warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet);
}
}
Ok(None) => (),
Err(_) => warn!("[LINK#{}] aux packet error", linkno),
}
@ -301,7 +331,7 @@ pub mod drtio {
}
async fn destination_set_up(
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
destination: u8,
up: bool,
@ -324,7 +354,7 @@ pub mod drtio {
async fn destination_survey(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
up_links: &[bool],
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
@ -345,6 +375,7 @@ pub mod drtio {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::DestinationStatusRequest {
destination: destination,
},
@ -400,6 +431,7 @@ pub mod drtio {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::DestinationStatusRequest {
destination: destination,
},
@ -427,7 +459,7 @@ pub mod drtio {
pub async fn link_task(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
) {
@ -438,8 +470,7 @@ pub mod drtio {
if up_links[linkno as usize] {
/* link was previously up */
if link_rx_up(linkno).await {
process_async_packets(aux_mutex, linkno, routing_table, timer).await;
process_unsolicited_aux(aux_mutex, linkno).await;
process_unsolicited_aux(aux_mutex, linkno, routing_table).await;
process_local_errors(linkno).await;
} else {
info!("[LINK#{}] link is down", linkno);
@ -449,7 +480,7 @@ pub mod drtio {
/* link was previously down */
if link_rx_up(linkno).await {
info!("[LINK#{}] link RX became up, pinging", linkno);
let ping_count = ping_remote(aux_mutex, linkno, timer).await;
let ping_count = ping_remote(aux_mutex, linkno, routing_table, timer).await;
if ping_count > 0 {
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
up_links[linkno as usize] = true;
@ -459,7 +490,7 @@ pub mod drtio {
if let Err(e) = load_routing_table(aux_mutex, linkno, routing_table, timer).await {
error!("[LINK#{}] failed to load routing table ({})", linkno, e);
}
if let Err(e) = set_rank(aux_mutex, linkno, 1 as u8, timer).await {
if let Err(e) = set_rank(aux_mutex, linkno, 1 as u8, routing_table, timer).await {
error!("[LINK#{}] failed to set rank ({})", linkno, e);
}
info!("[LINK#{}] link initialization completed", linkno);
@ -476,7 +507,7 @@ pub mod drtio {
}
#[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, mut timer: GlobalTimer) {
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
for linkno in 0..csr::DRTIO.len() {
unsafe {
(csr::DRTIO[linkno].reset_write)(1);
@ -492,7 +523,13 @@ pub mod drtio {
for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8;
if task::block_on(link_rx_up(linkno)) {
let reply = task::block_on(aux_transact(&aux_mutex, linkno, &Packet::ResetRequest, timer));
let reply = task::block_on(aux_transact(
&aux_mutex,
linkno,
routing_table,
&Packet::ResetRequest,
timer,
));
match reply {
Ok(Packet::ResetAck) => (),
Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno),
@ -505,14 +542,15 @@ pub mod drtio {
async fn partition_data<PacketF, HandlerF>(
linkno: u8,
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
data: &[u8],
packet_f: PacketF,
reply_handler_f: HandlerF,
) -> Result<(), &'static str>
) -> Result<(), Error>
where
PacketF: Fn(&[u8; MASTER_PAYLOAD_MAX_SIZE], PayloadStatus, usize) -> Packet,
HandlerF: Fn(&Packet) -> Result<(), &'static str>,
HandlerF: Fn(&Packet) -> Result<(), Error>,
{
let mut i = 0;
while i < data.len() {
@ -528,7 +566,7 @@ pub mod drtio {
i += len;
let status = PayloadStatus::from_status(first, last);
let packet = packet_f(&slice, status, len);
let reply = aux_transact(aux_mutex, linkno, &packet, timer).await?;
let reply = aux_transact(aux_mutex, linkno, routing_table, &packet, timer).await?;
reply_handler_f(&reply)?;
}
Ok(())
@ -536,16 +574,17 @@ pub mod drtio {
pub async fn ddma_upload_trace(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
trace: &Vec<u8>,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
partition_data(
linkno,
aux_mutex,
routing_table,
timer,
trace,
|slice, status, len| Packet::DmaAddTraceRequest {
@ -566,8 +605,8 @@ pub mod drtio {
destination: 0,
succeeded: false,
..
} => Err("error adding trace on satellite"),
_ => Err("adding DMA trace failed, unexpected aux packet"),
} => Err(Error::DmaAddTraceFail(destination)),
_ => Err(Error::UnexpectedReply),
},
)
.await
@ -575,15 +614,16 @@ pub mod drtio {
pub async fn ddma_send_erase(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::DmaRemoveTraceRequest {
id: id,
source: 0,
@ -591,33 +631,33 @@ pub mod drtio {
},
timer,
)
.await;
.await?;
match reply {
Ok(Packet::DmaRemoveTraceReply {
Packet::DmaRemoveTraceReply {
destination: 0,
succeeded: true,
}) => Ok(()),
Ok(Packet::DmaRemoveTraceReply {
} => Ok(()),
Packet::DmaRemoveTraceReply {
destination: 0,
succeeded: false,
}) => Err("satellite DMA erase error"),
Ok(_) => Err("adding trace failed, unexpected aux packet"),
Err(_) => Err("erasing trace failed, aux error"),
} => Err(Error::DmaEraseFail(destination)),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn ddma_send_playback(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
timestamp: u64,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::DmaPlaybackRequest {
id: id,
source: 0,
@ -626,45 +666,44 @@ pub mod drtio {
},
timer,
)
.await;
.await?;
match reply {
Ok(Packet::DmaPlaybackReply {
Packet::DmaPlaybackReply {
destination: 0,
succeeded: true,
}) => Ok(()),
Ok(Packet::DmaPlaybackReply {
} => Ok(()),
Packet::DmaPlaybackReply {
destination: 0,
succeeded: false,
}) => Err("error on DMA playback request"),
Ok(_) => Err("received unexpected aux packet during DMA playback"),
Err(_) => Err("aux error on DMA playback"),
} => Err(Error::DmaPlaybackFail(destination)),
_ => Err(Error::UnexpectedReply),
}
}
async fn analyzer_get_data(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
destination: u8,
) -> Result<RemoteBuffer, &'static str> {
) -> Result<RemoteBuffer, Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::AnalyzerHeaderRequest {
destination: destination,
},
timer,
)
.await;
.await?;
let (sent, total, overflow) = match reply {
Ok(Packet::AnalyzerHeader {
Packet::AnalyzerHeader {
sent_bytes,
total_byte_count,
overflow_occurred,
}) => (sent_bytes, total_byte_count, overflow_occurred),
Ok(_) => return Err("received unexpected aux packet during remote analyzer header request"),
Err(e) => return Err(e),
} => (sent_bytes, total_byte_count, overflow_occurred),
_ => return Err(Error::UnexpectedReply),
};
let mut remote_data: Vec<u8> = Vec::new();
@ -674,19 +713,19 @@ pub mod drtio {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::AnalyzerDataRequest {
destination: destination,
},
timer,
)
.await;
.await?;
match reply {
Ok(Packet::AnalyzerData { last, length, data }) => {
Packet::AnalyzerData { last, length, data } => {
last_packet = last;
remote_data.extend(&data[0..length as usize]);
}
Ok(_) => return Err("received unexpected aux packet during remote analyzer data request"),
Err(e) => return Err(e),
_ => return Err(Error::UnexpectedReply),
}
}
}
@ -701,10 +740,10 @@ pub mod drtio {
pub async fn analyzer_query(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
) -> Result<Vec<RemoteBuffer>, &'static str> {
) -> Result<Vec<RemoteBuffer>, Error> {
let mut remote_buffers: Vec<RemoteBuffer> = Vec::new();
for i in 1..drtio_routing::DEST_COUNT {
if destination_up(up_destinations, i as u8).await {
@ -716,16 +755,17 @@ pub mod drtio {
pub async fn subkernel_upload(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
data: &Vec<u8>,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
partition_data(
linkno,
aux_mutex,
routing_table,
timer,
data,
|slice, status, len| Packet::SubkernelAddDataRequest {
@ -737,8 +777,8 @@ pub mod drtio {
},
|reply| match reply {
Packet::SubkernelAddDataReply { succeeded: true } => Ok(()),
Packet::SubkernelAddDataReply { succeeded: false } => Err("error adding subkernel on satellite"),
_ => Err("adding subkernel failed, unexpected aux packet"),
Packet::SubkernelAddDataReply { succeeded: false } => Err(Error::SubkernelAddFail(destination)),
_ => Err(Error::UnexpectedReply),
},
)
.await
@ -746,16 +786,17 @@ pub mod drtio {
pub async fn subkernel_load(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
run: bool,
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::SubkernelLoadRunRequest {
id: id,
source: 0,
@ -773,23 +814,24 @@ pub mod drtio {
Packet::SubkernelLoadRunReply {
destination: 0,
succeeded: false,
} => return Err("error on subkernel run request"),
_ => return Err("received unexpected aux packet during subkernel run"),
} => return Err(Error::SubkernelRunFail(destination)),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn subkernel_retrieve_exception(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
destination: u8,
) -> Result<Vec<u8>, &'static str> {
) -> Result<Vec<u8>, Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let mut remote_data: Vec<u8> = Vec::new();
loop {
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::SubkernelExceptionRequest {
destination: destination,
},
@ -803,23 +845,24 @@ pub mod drtio {
return Ok(remote_data);
}
}
_ => return Err("received unexpected aux packet during subkernel exception request"),
_ => return Err(Error::UnexpectedReply),
}
}
}
pub async fn subkernel_send_message(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32,
destination: u8,
message: &[u8],
) -> Result<(), &'static str> {
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
partition_data(
linkno,
aux_mutex,
routing_table,
timer,
message,
|slice, status, len| Packet::SubkernelMessage {
@ -832,7 +875,7 @@ pub mod drtio {
},
|reply| match reply {
Packet::SubkernelMessageAck { .. } => Ok(()),
_ => Err("sending message to subkernel failed, unexpected aux packet"),
_ => Err(Error::UnexpectedReply),
},
)
.await
@ -845,19 +888,19 @@ pub mod drtio {
pub fn startup(
_aux_mutex: &Rc<Mutex<bool>>,
_routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
_routing_table: &Rc<RefCell<RoutingTable>>,
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
_timer: GlobalTimer,
) {
}
#[allow(dead_code)]
pub fn reset(_aux_mutex: Rc<Mutex<bool>>, mut _timer: GlobalTimer) {}
pub fn reset(_aux_mutex: Rc<Mutex<bool>>, _routing_table: &RoutingTable, mut _timer: GlobalTimer) {}
}
pub fn startup(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
routing_table: &Rc<RefCell<RoutingTable>>,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer,
) {
@ -868,9 +911,9 @@ pub fn startup(
}
#[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, timer: GlobalTimer) {
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
unsafe {
csr::rtio_core::reset_write(1);
}
drtio::reset(aux_mutex, timer)
drtio::reset(aux_mutex, routing_table, timer)
}

View File

@ -7,7 +7,7 @@ use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use libcortex_a9::mutex::Mutex;
use log::{error, warn};
use crate::rtio_mgt::drtio;
use crate::rtio_mgt::{drtio, drtio::Error as DrtioError};
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum FinishStatus {
@ -31,11 +31,11 @@ pub enum Error {
SubkernelNotFound,
SubkernelException,
CommLost,
DrtioError(&'static str),
DrtioError(DrtioError),
}
impl From<&'static str> for Error {
fn from(value: &'static str) -> Error {
impl From<DrtioError> for Error {
fn from(value: DrtioError) -> Error {
Error::DrtioError(value)
}
}

View File

@ -81,12 +81,6 @@ fn drtiosat_tsc_loaded() -> bool {
}
}
fn drtiosat_async_ready() {
unsafe {
csr::drtiosat::async_messages_ready_write(1);
}
}
#[cfg(has_drtio_routing)]
macro_rules! forward {
($routing_table:expr, $destination:expr, $rank:expr, $repeaters:expr, $packet:expr, $timer:expr) => {{
@ -245,14 +239,6 @@ fn process_aux_packet(
#[cfg(not(has_drtio_routing))]
drtioaux::Packet::RoutingSetRank { rank: _ } => drtioaux::send(0, &drtioaux::Packet::RoutingAck),
drtioaux::Packet::RoutingRetrievePackets => {
let packet = router
.get_upstream_packet()
.or(Some(drtioaux::Packet::RoutingNoPackets))
.unwrap();
drtioaux::send(0, &packet)
}
drtioaux::Packet::MonitorRequest {
destination: _destination,
channel,
@ -1067,8 +1053,8 @@ pub extern "C" fn main_core0() -> i32 {
}
}
if router.any_upstream_waiting() {
drtiosat_async_ready();
if let Some(packet) = router.get_upstream_packet() {
drtioaux::send(0, &packet).unwrap();
}
}

View File

@ -119,16 +119,11 @@ impl Repeater {
}
}
RepeaterState::Up => {
self.process_unsolicited_aux();
self.process_unsolicited_aux(routing_table, rank, destination, router);
if !rep_link_rx_up(self.repno) {
info!("[REP#{}] link is down", self.repno);
self.state = RepeaterState::Down;
}
if self.async_messages_ready() {
if let Err(e) = self.handle_async(routing_table, rank, destination, router, timer) {
warn!("[REP#{}] Error handling async messages ({:?})", self.repno, e);
}
}
}
RepeaterState::Failed => {
if !rep_link_rx_up(self.repno) {
@ -139,9 +134,15 @@ impl Repeater {
}
}
fn process_unsolicited_aux(&self) {
fn process_unsolicited_aux(
&self,
routing_table: &drtio_routing::RoutingTable,
rank: u8,
destination: u8,
router: &mut Router,
) {
match drtioaux::recv(self.auxno) {
Ok(Some(packet)) => warn!("[REP#{}] unsolicited aux packet: {:?}", self.repno, packet),
Ok(Some(packet)) => router.route(packet, routing_table, rank, destination),
Ok(None) => (),
Err(_) => warn!("[REP#{}] aux packet error", self.repno),
}
@ -186,34 +187,6 @@ impl Repeater {
}
}
fn async_messages_ready(&self) -> bool {
let async_rdy;
unsafe {
async_rdy = (csr::DRTIOREP[self.repno as usize].async_messages_ready_read)();
(csr::DRTIOREP[self.repno as usize].async_messages_ready_write)(0);
}
async_rdy == 1
}
fn handle_async(
&self,
routing_table: &drtio_routing::RoutingTable,
rank: u8,
self_destination: u8,
router: &mut Router,
timer: &mut GlobalTimer,
) -> Result<(), drtioaux::Error> {
loop {
drtioaux::send(self.auxno, &drtioaux::Packet::RoutingRetrievePackets).unwrap();
let reply = self.recv_aux_timeout(200, timer)?;
match reply {
drtioaux::Packet::RoutingNoPackets => break,
packet => router.route(packet, routing_table, rank, self_destination),
}
}
Ok(())
}
fn recv_aux_timeout(&self, timeout: u32, timer: &mut GlobalTimer) -> Result<drtioaux::Packet, drtioaux::Error> {
let max_time = timer.get_time() + Milliseconds(timeout.into());
loop {

View File

@ -75,7 +75,6 @@ pub struct Router {
local_queue: VecDeque<drtioaux::Packet>,
#[cfg(has_drtio_routing)]
downstream_queue: VecDeque<(usize, drtioaux::Packet)>,
upstream_notified: bool,
}
impl Router {
@ -85,7 +84,6 @@ impl Router {
local_queue: VecDeque::new(),
#[cfg(has_drtio_routing)]
downstream_queue: VecDeque::new(),
upstream_notified: false,
}
}
@ -161,22 +159,8 @@ impl Router {
}
}
pub fn any_upstream_waiting(&mut self) -> bool {
let empty = self.upstream_queue.is_empty();
if !empty && !self.upstream_notified {
self.upstream_notified = true; // so upstream will not get spammed with notifications
true
} else {
false
}
}
pub fn get_upstream_packet(&mut self) -> Option<drtioaux::Packet> {
let packet = self.upstream_queue.pop_front();
if packet.is_none() {
self.upstream_notified = false;
}
packet
self.upstream_queue.pop_front()
}
#[cfg(has_drtio_routing)]