diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 71d4a3af5..23ded9aa2 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -352,6 +352,7 @@ dependencies = [ "board_misoc", "build_misoc", "log", + "proto_artiq", "riscv", ] diff --git a/artiq/firmware/libproto_artiq/drtioaux_proto.rs b/artiq/firmware/libproto_artiq/drtioaux_proto.rs index 6f50b1b9d..d09be2745 100644 --- a/artiq/firmware/libproto_artiq/drtioaux_proto.rs +++ b/artiq/firmware/libproto_artiq/drtioaux_proto.rs @@ -59,6 +59,7 @@ pub enum Packet { SpiBasicReply { succeeded: bool }, AnalyzerRequest { destination: u8 }, + AnalyzerHeader { sent_bytes: u32, total_byte_count: u64, overflow_occurred: bool }, AnalyzerData { last: bool, length: u16, data: [u8; ANALYZER_MAX_SIZE]}, DmaAddTraceRequest { destination: u8, id: u32, last: bool, length: u16, trace: [u8; DMA_TRACE_MAX_SIZE] }, @@ -202,18 +203,22 @@ impl Packet { 0xa0 => Packet::AnalyzerRequest { destination: reader.read_u8()? }, - - 0xa1 => { + 0xa1 => Packet::AnalyzerHeader { + sent_bytes: reader.read_u32()?, + total_byte_count: reader.read_u64()?, + overflow_occurred: reader.read_bool()?, + }, + 0xa2 => { 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 trace[0..length as usize])?; + reader.read_exact(&mut data[0..length as usize])?; Packet::AnalyzerData { last: last, length: length, data: data } - } + }, 0xb0 => { let destination = reader.read_u8()?; @@ -419,8 +424,14 @@ impl Packet { writer.write_u8(0xa0)?; writer.write_u8(destination)?; }, - Packet::AnalyzerData { last, length, data } => { + 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::AnalyzerData { last, length, data } => { + writer.write_u8(0xa2)?; writer.write_bool(last)?; writer.write_u16(length)?; writer.write_all(&data[0..length as usize])?; diff --git a/artiq/firmware/satman/Cargo.toml b/artiq/firmware/satman/Cargo.toml index 53b08d7b5..0b219c15f 100644 --- a/artiq/firmware/satman/Cargo.toml +++ b/artiq/firmware/satman/Cargo.toml @@ -18,3 +18,4 @@ board_misoc = { path = "../libboard_misoc", features = ["uart_console", "log"] } board_artiq = { path = "../libboard_artiq" } alloc_list = { path = "../liballoc_list" } riscv = { version = "0.6.0", features = ["inline-asm"] } +proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] } diff --git a/artiq/firmware/satman/analyzer.rs b/artiq/firmware/satman/analyzer.rs new file mode 100644 index 000000000..4378d1deb --- /dev/null +++ b/artiq/firmware/satman/analyzer.rs @@ -0,0 +1,71 @@ +use board_misoc::{csr, cache}; +use board_artiq::drtioaux; +use proto_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] +}; + +pub 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::message_encoder_overflow_reset_write(1); + csr::rtio_analyzer::dma_base_address_write(base_addr as u64); + csr::rtio_analyzer::dma_last_address_write(last_addr as u64); + csr::rtio_analyzer::dma_reset_write(1); + csr::rtio_analyzer::enable_write(1); + } +} + +pub fn disarm() { + unsafe { + csr::rtio_analyzer::enable_write(0); + while csr::rtio_analyzer::busy_read() != 0 {} + cache::flush_cpu_dcache(); + cache::flush_l2_cache(); + } +} + +pub fn send() -> Result<(), drtioaux::Error> { + let data = unsafe { &BUFFER.data[..] }; + let overflow_occurred = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 }; + let total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() }; + let pointer = (total_byte_count % BUFFER_SIZE as u64) as usize; + let wraparound = total_byte_count >= BUFFER_SIZE as u64; + let sent_bytes = if wraparound { BUFFER_SIZE } else { total_byte_count as usize }; + + drtioaux::send(0, &drtioaux::Packet::AnalyzerHeader { + total_byte_count: total_byte_count, + sent_bytes: sent_bytes as u32, + overflow_occurred: overflow_occurred, + })?; + + let mut i = if wraparound { pointer } else { 0 }; + while i < sent_bytes { + let mut data_slice: [u8; ANALYZER_MAX_SIZE] = [0; ANALYZER_MAX_SIZE]; + let len: usize = if i + ANALYZER_MAX_SIZE < sent_bytes { ANALYZER_MAX_SIZE } else { sent_bytes - i } as usize; + let last = i + len == 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]); + } + i += len; + drtioaux::send(0, &drtioaux::Packet::AnalyzerData { + last: last, + length: len as u16, + data: data_slice, + })?; + } + + Ok(()) +} diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 3b770a2c0..65282701e 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -8,6 +8,7 @@ extern crate board_misoc; extern crate board_artiq; extern crate riscv; extern crate alloc; +extern crate proto_artiq; use core::convert::TryFrom; use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; @@ -23,6 +24,7 @@ static mut ALLOC: alloc_list::ListAlloc = alloc_list::EMPTY; mod repeater; mod dma; +mod analyzer; fn drtiosat_reset(reset: bool) { unsafe { @@ -300,6 +302,15 @@ fn process_aux_packet(_manager: &mut DmaManager, _repeaters: &mut [repeater::Rep &drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 }) } } + + drtioaux::Packet::AnalyzerRequest { destination: _destination } => { + forward!(_routing_table, _destination, *_rank, _repeaters, &packet); + analyzer::disarm(); + let res = analyzer::send(); + analyzer::arm(); + res + } + #[cfg(has_rtio_dma)] drtioaux::Packet::DmaAddTraceRequest { destination: _destination, id, last, length, trace } => { forward!(_routing_table, _destination, *_rank, _repeaters, &packet); @@ -546,6 +557,9 @@ pub extern fn main() -> i32 { // without a manual intervention. let mut dma_manager = DmaManager::new(); + // Reset the analyzer as well. + analyzer::arm(); + drtioaux::reset(0); drtiosat_reset(false); drtiosat_reset_phy(false); diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 98bf6c990..c09615e9c 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -577,7 +577,7 @@ class SatelliteBase(BaseSoC): self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.csr_devices.append("routing_table") - self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, + self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.local_io.cri, self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 70733dfe3..ed2e70ac4 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -464,7 +464,7 @@ class _SatelliteBase(BaseSoC): self.csr_devices.append("cri_con") self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.csr_devices.append("routing_table") - self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, + self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.local_io.cri, self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer")