forked from M-Labs/nac3
1
0
Fork 0

satellite: port analyzer, drtio packets

This commit is contained in:
mwojcik 2023-05-19 12:53:33 +08:00 committed by spaqin
parent c5aac198f2
commit 259b0ba1b7
3 changed files with 205 additions and 3 deletions

View File

@ -1,8 +1,8 @@
use core_io::{Error as IoError, Read, Write}; use core_io::{Error as IoError, Read, Write};
use io::proto::{ProtoRead, ProtoWrite}; use io::proto::{ProtoRead, ProtoWrite};
/* 512 (max size) - 4 (CRC) - 1 (packet ID) - 1 (destination) - 4 (trace ID) - 1 (last) - 2 (length) */ pub const DMA_TRACE_MAX_SIZE: usize = /*max size*/512 - /*CRC*/4 - /*packet ID*/1 - /*trace ID*/4 - /*last*/1 -/*length*/2;
pub const DMA_TRACE_MAX_SIZE: usize = 499; pub const ANALYZER_MAX_SIZE: usize = /*max size*/512 - /*CRC*/4 - /*packet ID*/1 - /*last*/1 - /*length*/2;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -136,6 +136,23 @@ pub enum Packet {
succeeded: bool, succeeded: bool,
}, },
AnalyzerHeaderRequest {
destination: u8
},
AnalyzerHeader {
sent_bytes: u32,
total_byte_count: u64,
overflow_occurred: bool,
},
AnalyzerDataRequest {
destination: u8,
},
AnalyzerData {
last: bool,
length: u16,
data: [u8; ANALYZER_MAX_SIZE],
},
DmaAddTraceRequest { DmaAddTraceRequest {
destination: u8, destination: u8,
id: u32, id: u32,
@ -298,6 +315,29 @@ impl Packet {
succeeded: reader.read_bool()?, succeeded: reader.read_bool()?,
}, },
0xa0 => Packet::AnalyzerHeaderRequest {
destination: reader.read_u8()?
},
0xa1 => Packet::AnalyzerHeader {
sent_bytes: reader.read_u32()?,
total_byte_count: reader.read_u64()?,
overflow_occurred: reader.read_bool()?,
},
0xa2 => Packet::AnalyzerDataRequest {
destination: reader.read_u8()?
},
0xa3 => {
let last = reader.read_bool()?;
let length = reader.read_u16()?;
let mut data: [u8; ANALYZER_MAX_SIZE] = [0; ANALYZER_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?;
Packet::AnalyzerData {
last: last,
length: length,
data: data
}
},
0xb0 => { 0xb0 => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let id = reader.read_u32()?; let id = reader.read_u32()?;
@ -526,6 +566,35 @@ impl Packet {
writer.write_bool(succeeded)?; writer.write_bool(succeeded)?;
} }
Packet::AnalyzerHeaderRequest { destination } => {
writer.write_u8(0xa0)?;
writer.write_u8(destination)?;
}
Packet::AnalyzerHeader {
sent_bytes,
total_byte_count,
overflow_occurred
} => {
writer.write_u8(0xa1)?;
writer.write_u32(sent_bytes)?;
writer.write_u64(total_byte_count)?;
writer.write_bool(overflow_occurred)?;
}
Packet::AnalyzerDataRequest { destination } => {
writer.write_u8(0xa2)?;
writer.write_u8(destination)?;
}
Packet::AnalyzerData {
last,
length,
data
} => {
writer.write_u8(0xa3)?;
writer.write_bool(last)?;
writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?;
}
Packet::DmaAddTraceRequest { Packet::DmaAddTraceRequest {
destination, destination,
id, id,

106
src/satman/src/analyzer.rs Normal file
View File

@ -0,0 +1,106 @@
use libboard_artiq::pl::csr;
use libcortex_a9::cache;
use libboard_artiq::drtioaux_proto::ANALYZER_MAX_SIZE;
const BUFFER_SIZE: usize = 512 * 1024;
#[repr(align(64))]
struct Buffer {
data: [u8; BUFFER_SIZE],
}
static mut BUFFER: Buffer = Buffer {
data: [0; BUFFER_SIZE]
};
fn arm() {
unsafe {
let base_addr = &mut BUFFER.data[0] as *mut _ as usize;
let last_addr = &mut BUFFER.data[BUFFER_SIZE - 1] as *mut _ as usize;
csr::rtio_analyzer::dma_base_address_write(base_addr as u32);
csr::rtio_analyzer::message_encoder_overflow_reset_write(1);
csr::rtio_analyzer::dma_last_address_write(last_addr as u32);
csr::rtio_analyzer::dma_reset_write(1);
csr::rtio_analyzer::enable_write(1);
}
}
fn disarm() {
unsafe {
csr::rtio_analyzer::enable_write(0);
while csr::rtio_analyzer::busy_read() != 0 {}
cache::dcci_slice(&BUFFER.data);
}
}
pub struct Analyzer {
// necessary for keeping track of sent data
sent_bytes: usize,
data_iter: usize
}
pub struct Header {
pub total_byte_count: u64,
pub sent_bytes: u32,
pub error: bool
}
pub struct AnalyzerSliceMeta {
pub len: u16,
pub last: bool
}
impl Analyzer {
pub fn new() -> Analyzer {
// create and arm new Analyzer
arm();
Analyzer {
sent_bytes: 0,
data_iter: 0
}
}
fn drop(&mut self) {
disarm();
}
pub fn get_header(&mut self) -> Header {
disarm();
let overflow = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 };
let bus_err = unsafe { csr::rtio_analyzer::dma_bus_error_read() != 0 };
let total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() as u64 };
let wraparound = total_byte_count >= BUFFER_SIZE as u64;
self.sent_bytes = if wraparound { BUFFER_SIZE } else { total_byte_count as usize };
self.data_iter = if wraparound { (total_byte_count % BUFFER_SIZE as u64) as usize } else { 0 };
Header {
total_byte_count: total_byte_count,
sent_bytes: self.sent_bytes as u32,
error: overflow | bus_err
}
}
pub fn get_data(&mut self, data_slice: &mut [u8; ANALYZER_MAX_SIZE]) -> AnalyzerSliceMeta {
let data = unsafe { &BUFFER.data[..] };
let i = self.data_iter;
let len = if i + ANALYZER_MAX_SIZE < self.sent_bytes { ANALYZER_MAX_SIZE } else { self.sent_bytes - i };
let last = i + len == self.sent_bytes;
if i + len >= BUFFER_SIZE {
data_slice[..len].clone_from_slice(&data[i..BUFFER_SIZE]);
data_slice[..len].clone_from_slice(&data[..(i+len) % BUFFER_SIZE]);
} else {
data_slice[..len].clone_from_slice(&data[i..i+len]);
}
self.data_iter += len;
if last {
arm();
}
AnalyzerSliceMeta {
len: len as u16,
last: last
}
}
}

View File

@ -20,6 +20,7 @@ extern crate alloc;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use analyzer::Analyzer as Analyzer;
use dma::Manager as DmaManager; use dma::Manager as DmaManager;
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
@ -40,6 +41,7 @@ use libsupport_zynq::ram;
mod dma; mod dma;
mod repeater; mod repeater;
mod analyzer;
fn drtiosat_reset(reset: bool) { fn drtiosat_reset(reset: bool) {
unsafe { unsafe {
@ -95,6 +97,7 @@ fn process_aux_packet(
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
i2c: &mut I2c, i2c: &mut I2c,
dma_manager: &mut DmaManager, dma_manager: &mut DmaManager,
analyzer: &mut Analyzer,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error> {
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
// and u16 otherwise; hence the `as _` conversion. // and u16 otherwise; hence the `as _` conversion.
@ -412,6 +415,26 @@ fn process_aux_packet(
) )
} }
drtioaux::Packet::AnalyzerHeaderRequest { destination: _destination } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
let header = analyzer.get_header();
drtioaux::send(0, &drtioaux::Packet::AnalyzerHeader {
total_byte_count: header.total_byte_count,
sent_bytes: header.sent_bytes,
overflow_occurred: header.overflow,
})
}
drtioaux::Packet::AnalyzerDataRequest { destination: _destination } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
let mut data_slice: [u8; ANALYZER_MAX_SIZE] = [0; ANALYZER_MAX_SIZE];
let meta = analyzer.get_data(&mut data_slice);
drtioaux::send(0, &drtioaux::Packet::AnalyzerData {
last: meta.last,
length: meta.len,
data: data_slice,
})
}
drtioaux::Packet::DmaAddTraceRequest { drtioaux::Packet::DmaAddTraceRequest {
destination: _destination, destination: _destination,
id, id,
@ -455,10 +478,11 @@ fn process_aux_packets(
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
i2c: &mut I2c, i2c: &mut I2c,
dma_manager: &mut DmaManager, dma_manager: &mut DmaManager,
analyzer: &mut Analyzer,
) { ) {
let result = drtioaux::recv(0).and_then(|packet| { let result = drtioaux::recv(0).and_then(|packet| {
if let Some(packet) = packet { if let Some(packet) = packet {
process_aux_packet(repeaters, routing_table, rank, packet, timer, i2c, dma_manager) process_aux_packet(repeaters, routing_table, rank, packet, timer, i2c, dma_manager, analyzer)
} else { } else {
Ok(()) Ok(())
} }
@ -635,6 +659,8 @@ pub extern "C" fn main_core0() -> i32 {
// are cleared out for a clean slate on subsequent connections, // are cleared out for a clean slate on subsequent connections,
// without a manual intervention. // without a manual intervention.
let mut dma_manager = DmaManager::new(); let mut dma_manager = DmaManager::new();
// same for RTIO Analyzer
let mut analyzer = Analyzer::new();
drtioaux::reset(0); drtioaux::reset(0);
drtiosat_reset(false); drtiosat_reset(false);
@ -649,6 +675,7 @@ pub extern "C" fn main_core0() -> i32 {
&mut timer, &mut timer,
&mut i2c, &mut i2c,
&mut dma_manager, &mut dma_manager,
&mut analyzer,
); );
#[allow(unused_mut)] #[allow(unused_mut)]
for mut rep in repeaters.iter_mut() { for mut rep in repeaters.iter_mut() {