forked from M-Labs/artiq-zynq
analyzer: implement firmware part
This commit is contained in:
parent
b62fbce826
commit
2e10922715
104
src/runtime/src/analyzer.rs
Normal file
104
src/runtime/src/analyzer.rs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -28,6 +28,7 @@ use crate::kernel;
|
|||||||
use crate::rpc;
|
use crate::rpc;
|
||||||
use crate::moninj;
|
use crate::moninj;
|
||||||
use crate::mgmt;
|
use crate::mgmt;
|
||||||
|
use crate::analyzer;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -331,6 +332,10 @@ pub fn main(timer: GlobalTimer, cfg: &config::Config) {
|
|||||||
|
|
||||||
Sockets::init(32);
|
Sockets::init(32);
|
||||||
|
|
||||||
|
mgmt::start();
|
||||||
|
analyzer::start();
|
||||||
|
moninj::start(timer);
|
||||||
|
|
||||||
let control: Rc<RefCell<kernel::Control>> = Rc::new(RefCell::new(kernel::Control::start()));
|
let control: Rc<RefCell<kernel::Control>> = Rc::new(RefCell::new(kernel::Control::start()));
|
||||||
if let Ok(buffer) = cfg.read("startup") {
|
if let Ok(buffer) = cfg.read("startup") {
|
||||||
info!("Loading startup kernel...");
|
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, || {
|
Sockets::run(&mut iface, || {
|
||||||
Instant::from_millis(timer.get_time().0 as i32)
|
Instant::from_millis(timer.get_time().0 as i32)
|
||||||
});
|
});
|
||||||
|
@ -35,6 +35,7 @@ mod eh_artiq;
|
|||||||
mod panic;
|
mod panic;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod mgmt;
|
mod mgmt;
|
||||||
|
mod analyzer;
|
||||||
|
|
||||||
fn init_gateware() {
|
fn init_gateware() {
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
|
Loading…
Reference in New Issue
Block a user