From 2e1092271524a66133170e2a47e9b18ccce2e5f2 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 16 Jul 2020 11:47:55 +0800 Subject: [PATCH] analyzer: implement firmware part --- src/runtime/src/analyzer.rs | 104 ++++++++++++++++++++++++++++++++++++ src/runtime/src/comms.rs | 8 +-- src/runtime/src/main.rs | 1 + 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 src/runtime/src/analyzer.rs diff --git a/src/runtime/src/analyzer.rs b/src/runtime/src/analyzer.rs new file mode 100644 index 00000000..9e96116f --- /dev/null +++ b/src/runtime/src/analyzer.rs @@ -0,0 +1,104 @@ +use libasync::{smoltcp::TcpStream, task}; +use libboard_zynq::smoltcp::Error; +use libcortex_a9::cache; +use log::{debug, info, warn}; + +use crate::proto_async::*; +use crate::pl; + +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() { + debug!("arming RTIO analyzer"); + 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; + pl::csr::rtio_analyzer::message_encoder_overflow_reset_write(1); + pl::csr::rtio_analyzer::dma_base_address_write(base_addr as u32); + pl::csr::rtio_analyzer::dma_last_address_write(last_addr as u32); + pl::csr::rtio_analyzer::dma_reset_write(1); + pl::csr::rtio_analyzer::enable_write(1); + } +} + +fn disarm() { + debug!("disarming RTIO analyzer"); + unsafe { + pl::csr::rtio_analyzer::enable_write(0); + while pl::csr::rtio_analyzer::busy_read() != 0 {} + cache::dcci_slice(&BUFFER.data); + } + debug!("RTIO analyzer disarmed"); +} + +#[derive(Debug)] +struct Header { + sent_bytes: u32, + total_byte_count: u64, + overflow_occurred: bool, + log_channel: u8, + dds_onehot_sel: bool +} + +async fn write_header(stream: &mut TcpStream, header: &Header) -> Result<(), Error> { + write_i32(stream, header.sent_bytes as i32).await?; + write_i64(stream, header.total_byte_count as i64).await?; + write_i8(stream, header.overflow_occurred as i8).await?; + write_i8(stream, header.log_channel as i8).await?; + write_i8(stream, header.dds_onehot_sel as i8).await?; + Ok(()) +} + +async fn handle_connection(stream: &mut TcpStream) -> Result<(), Error> { + info!("received connection"); + + let data = unsafe { &BUFFER.data[..] }; + let overflow_occurred = unsafe { pl::csr::rtio_analyzer::message_encoder_overflow_read() != 0 }; + let total_byte_count = unsafe { pl::csr::rtio_analyzer::dma_byte_count_read() as u64 }; + let pointer = (total_byte_count % BUFFER_SIZE as u64) as usize; + let wraparound = total_byte_count >= BUFFER_SIZE as u64; + + let header = Header { + total_byte_count: total_byte_count, + sent_bytes: if wraparound { BUFFER_SIZE as u32 } else { total_byte_count as u32 }, + overflow_occurred: overflow_occurred, + log_channel: 255, + dds_onehot_sel: true // kept for backward compatibility of analyzer dumps + }; + debug!("{:?}", header); + debug!("{:?}", &data[..256]); + + write_header(stream, &header).await?; + if wraparound { + stream.send(data[pointer..].iter().copied()).await?; + stream.send(data[..pointer].iter().copied()).await?; + } else { + stream.send(data[..pointer].iter().copied()).await?; + } + + Ok(()) +} + +pub fn start() { + task::spawn(async move { + loop { + arm(); + let mut stream = TcpStream::accept(1382, 2048, 2048).await.unwrap(); + disarm(); + let _ = handle_connection(&mut stream) + .await + .map_err(|e| warn!("connection terminated: {:?}", e)); + let _ = stream.flush().await; + let _ = stream.abort().await; + } + }); +} diff --git a/src/runtime/src/comms.rs b/src/runtime/src/comms.rs index 65a83f1e..db9b7e02 100644 --- a/src/runtime/src/comms.rs +++ b/src/runtime/src/comms.rs @@ -28,6 +28,7 @@ use crate::kernel; use crate::rpc; use crate::moninj; use crate::mgmt; +use crate::analyzer; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -331,6 +332,10 @@ pub fn main(timer: GlobalTimer, cfg: &config::Config) { Sockets::init(32); + mgmt::start(); + analyzer::start(); + moninj::start(timer); + let control: Rc> = Rc::new(RefCell::new(kernel::Control::start())); if let Ok(buffer) = cfg.read("startup") { info!("Loading startup kernel..."); @@ -357,9 +362,6 @@ pub fn main(timer: GlobalTimer, cfg: &config::Config) { } }); - mgmt::start(); - moninj::start(timer); - Sockets::run(&mut iface, || { Instant::from_millis(timer.get_time().0 as i32) }); diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index a9e1a41a..ecd09705 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -35,6 +35,7 @@ mod eh_artiq; mod panic; mod logger; mod mgmt; +mod analyzer; fn init_gateware() { // Set up PS->PL clocks