Merge branch 'master' into nac3

This commit is contained in:
Sebastien Bourdeauducq 2023-05-27 19:00:49 +08:00
commit caee570c48
21 changed files with 432 additions and 87 deletions

View File

@ -27,7 +27,22 @@ Highlights:
* Full Python 3.10 support. * Full Python 3.10 support.
* Distributed DMA is now supported, allowing DMA to be run directly on satellites for corresponding * Distributed DMA is now supported, allowing DMA to be run directly on satellites for corresponding
RTIO events, increasing bandwidth in scenarios with heavy satellite usage. RTIO events, increasing bandwidth in scenarios with heavy satellite usage.
* Persistent datasets are now stored in a LMDB database for improved performance. * Persistent datasets are now stored in a LMDB database for improved performance. PYON databases can
be converted with the script below.
::
from sipyco import pyon
import lmdb
old = pyon.load_file("dataset_db.pyon")
new = lmdb.open("dataset_db.mdb", subdir=False, map_size=2**30)
with new.begin(write=True) as txn:
for key, value in old.items():
txn.put(key.encode(), pyon.encode(value).encode())
new.close()
ARTIQ-7 ARTIQ-7
------- -------

View File

@ -352,6 +352,7 @@ dependencies = [
"board_misoc", "board_misoc",
"build_misoc", "build_misoc",
"log", "log",
"proto_artiq",
"riscv", "riscv",
] ]

View File

@ -26,7 +26,7 @@ $(RUSTOUT)/libksupport.a:
ksupport.elf: $(RUSTOUT)/libksupport.a glue.o ksupport.elf: $(RUSTOUT)/libksupport.a glue.o
$(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \ $(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \
-lunwind-$(CPU)-elf -lprintf-float -lm -lunwind-$(CPU)-libc -lprintf-float -lm
%.o: $(KSUPPORT_DIRECTORY)/%.c %.o: $(KSUPPORT_DIRECTORY)/%.c
$(compile) $(compile)

View File

@ -343,7 +343,7 @@ extern fn dma_record_output(target: i32, word: i32) {
} }
#[unwind(aborts)] #[unwind(aborts)]
extern fn dma_record_output_wide(target: i32, words: CSlice<i32>) { extern fn dma_record_output_wide(target: i32, words: &CSlice<i32>) {
assert!(words.len() <= 16); // enforce the hardware limit assert!(words.len() <= 16); // enforce the hardware limit
unsafe { unsafe {

View File

@ -89,7 +89,7 @@ mod imp {
} }
} }
pub extern fn output_wide(target: i32, data: CSlice<i32>) { pub extern fn output_wide(target: i32, data: &CSlice<i32>) {
unsafe { unsafe {
csr::rtio::target_write(target as u32); csr::rtio::target_write(target as u32);
// writing target clears o_data // writing target clears o_data
@ -235,7 +235,7 @@ mod imp {
unimplemented!("not(has_rtio)") unimplemented!("not(has_rtio)")
} }
pub extern fn output_wide(_target: i32, _data: CSlice<i32>) { pub extern fn output_wide(_target: i32, _data: &CSlice<i32>) {
unimplemented!("not(has_rtio)") unimplemented!("not(has_rtio)")
} }

View File

@ -14,8 +14,8 @@ impl<T> From<IoError<T>> for Error<T> {
} }
} }
/* 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(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum Packet { pub enum Packet {
@ -58,6 +58,11 @@ pub enum Packet {
SpiReadReply { succeeded: bool, data: u32 }, SpiReadReply { succeeded: bool, data: u32 },
SpiBasicReply { succeeded: bool }, SpiBasicReply { 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 { destination: u8, id: u32, last: bool, length: u16, trace: [u8; DMA_TRACE_MAX_SIZE] }, DmaAddTraceRequest { destination: u8, id: u32, last: bool, length: u16, trace: [u8; DMA_TRACE_MAX_SIZE] },
DmaAddTraceReply { succeeded: bool }, DmaAddTraceReply { succeeded: bool },
DmaRemoveTraceRequest { destination: u8, id: u32 }, DmaRemoveTraceRequest { destination: u8, id: u32 },
@ -65,7 +70,6 @@ pub enum Packet {
DmaPlaybackRequest { destination: u8, id: u32, timestamp: u64 }, DmaPlaybackRequest { destination: u8, id: u32, timestamp: u64 },
DmaPlaybackReply { succeeded: bool }, DmaPlaybackReply { succeeded: bool },
DmaPlaybackStatus { destination: u8, id: u32, error: u8, channel: u32, timestamp: u64 } DmaPlaybackStatus { destination: u8, id: u32, error: u8, channel: u32, timestamp: u64 }
} }
impl Packet { impl Packet {
@ -197,6 +201,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()?;
@ -397,6 +424,27 @@ 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 { destination, id, last, trace, length } => { Packet::DmaAddTraceRequest { destination, id, last, trace, length } => {
writer.write_u8(0xb0)?; writer.write_u8(0xb0)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;

View File

@ -22,7 +22,7 @@ $(RUSTOUT)/libruntime.a:
runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o
$(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \ $(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \
-lunwind-bare -m elf32lriscv -lunwind-vexriscv-bare -m elf32lriscv
ksupport_data.o: ../ksupport/ksupport.elf ksupport_data.o: ../ksupport/ksupport.elf
$(LD) -r -m elf32lriscv -b binary -o $@ $< $(LD) -r -m elf32lriscv -b binary -o $@ $<

View File

@ -1,7 +1,10 @@
use io::{Write, Error as IoError}; use io::{Write, Error as IoError};
use board_misoc::{csr, cache}; use board_misoc::{csr, cache};
use sched::{Io, TcpListener, TcpStream, Error as SchedError}; use sched::{Io, Mutex, TcpListener, TcpStream, Error as SchedError};
use analyzer_proto::*; use analyzer_proto::*;
use urc::Urc;
use board_artiq::drtio_routing;
use core::cell::RefCell;
const BUFFER_SIZE: usize = 512 * 1024; const BUFFER_SIZE: usize = 512 * 1024;
@ -35,17 +38,92 @@ fn disarm() {
} }
} }
fn worker(stream: &mut TcpStream) -> Result<(), IoError<SchedError>> { #[cfg(has_drtio)]
let data = unsafe { &BUFFER.data[..] }; pub mod remote_analyzer {
let overflow_occurred = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 }; use super::*;
let total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() }; use rtio_mgt::drtio;
let pointer = (total_byte_count % BUFFER_SIZE as u64) as usize; use alloc::vec::Vec;
let wraparound = total_byte_count >= BUFFER_SIZE as u64;
pub struct RemoteBuffer {
pub total_byte_count: u64,
pub sent_bytes: u32,
pub overflow_occurred: bool,
pub data: Vec<u8>
}
pub fn get_data(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) -> Result<RemoteBuffer, &'static str> {
// gets data from satellites and returns consolidated data
let mut remote_data: Vec<u8> = Vec::new();
let mut remote_overflow = false;
let mut remote_sent_bytes = 0;
let mut remote_total_bytes = 0;
let data_vec = match drtio::analyzer_query(io, aux_mutex, ddma_mutex, routing_table, up_destinations) {
Ok(data_vec) => data_vec,
Err(e) => return Err(e)
};
for data in data_vec {
remote_total_bytes += data.total_byte_count;
remote_sent_bytes += data.sent_bytes;
remote_overflow |= data.overflow_occurred;
remote_data.extend(data.data);
}
Ok(RemoteBuffer {
total_byte_count: remote_total_bytes,
sent_bytes: remote_sent_bytes,
overflow_occurred: remote_overflow,
data: remote_data
})
}
}
fn worker(stream: &mut TcpStream, _io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex,
_routing_table: &drtio_routing::RoutingTable,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>
) -> Result<(), IoError<SchedError>> {
let local_data = unsafe { &BUFFER.data[..] };
let local_overflow_occurred = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 };
let local_total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() };
let wraparound = local_total_byte_count >= BUFFER_SIZE as u64;
let local_sent_bytes = if wraparound { BUFFER_SIZE as u32 } else { local_total_byte_count as u32 };
let pointer = (local_total_byte_count % BUFFER_SIZE as u64) as usize;
#[cfg(has_drtio)]
let remote = remote_analyzer::get_data(
_io, _aux_mutex, _ddma_mutex, _routing_table, _up_destinations);
#[cfg(has_drtio)]
let (header, remote_data) = match remote {
Ok(remote) => (Header {
total_byte_count: local_total_byte_count + remote.total_byte_count,
sent_bytes: local_sent_bytes + remote.sent_bytes,
overflow_occurred: local_overflow_occurred | remote.overflow_occurred,
log_channel: csr::CONFIG_RTIO_LOG_CHANNEL as u8,
dds_onehot_sel: true
}, remote.data),
Err(e) => {
error!("Error getting remote analyzer data: {}", e);
(Header {
total_byte_count: local_total_byte_count,
sent_bytes: local_sent_bytes,
overflow_occurred: true,
log_channel: csr::CONFIG_RTIO_LOG_CHANNEL as u8,
dds_onehot_sel: true
},
Vec::new())
}
};
#[cfg(not(has_drtio))]
let header = Header { let header = Header {
total_byte_count: total_byte_count, total_byte_count: local_total_byte_count,
sent_bytes: if wraparound { BUFFER_SIZE as u32 } else { total_byte_count as u32 }, sent_bytes: local_sent_bytes,
overflow_occurred: overflow_occurred, overflow_occurred: local_overflow_occurred,
log_channel: csr::CONFIG_RTIO_LOG_CHANNEL as u8, log_channel: csr::CONFIG_RTIO_LOG_CHANNEL as u8,
dds_onehot_sel: true // kept for backward compatibility of analyzer dumps dds_onehot_sel: true // kept for backward compatibility of analyzer dumps
}; };
@ -54,16 +132,20 @@ fn worker(stream: &mut TcpStream) -> Result<(), IoError<SchedError>> {
stream.write_all("e".as_bytes())?; stream.write_all("e".as_bytes())?;
header.write_to(stream)?; header.write_to(stream)?;
if wraparound { if wraparound {
stream.write_all(&data[pointer..])?; stream.write_all(&local_data[pointer..])?;
stream.write_all(&data[..pointer])?; stream.write_all(&local_data[..pointer])?;
} else { } else {
stream.write_all(&data[..pointer])?; stream.write_all(&local_data[..pointer])?;
} }
#[cfg(has_drtio)]
stream.write_all(&remote_data)?;
Ok(()) Ok(())
} }
pub fn thread(io: Io) { pub fn thread(io: Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
let listener = TcpListener::new(&io, 65535); let listener = TcpListener::new(&io, 65535);
listener.listen(1382).expect("analyzer: cannot listen"); listener.listen(1382).expect("analyzer: cannot listen");
@ -75,7 +157,8 @@ pub fn thread(io: Io) {
disarm(); disarm();
match worker(&mut stream) { let routing_table = routing_table.borrow();
match worker(&mut stream, &io, aux_mutex, ddma_mutex, &routing_table, up_destinations) {
Ok(()) => (), Ok(()) => (),
Err(err) => error!("analyzer aborted: {}", err) Err(err) => error!("analyzer aborted: {}", err)
} }

View File

@ -209,7 +209,13 @@ fn startup() {
io.spawn(4096, move |io| { moninj::thread(io, &aux_mutex, &ddma_mutex, &drtio_routing_table) }); io.spawn(4096, move |io| { moninj::thread(io, &aux_mutex, &ddma_mutex, &drtio_routing_table) });
} }
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
io.spawn(4096, analyzer::thread); {
let aux_mutex = aux_mutex.clone();
let drtio_routing_table = drtio_routing_table.clone();
let up_destinations = up_destinations.clone();
let ddma_mutex = ddma_mutex.clone();
io.spawn(8192, move |io| { analyzer::thread(io, &aux_mutex, &ddma_mutex, &drtio_routing_table, &up_destinations) });
}
#[cfg(has_grabber)] #[cfg(has_grabber)]
io.spawn(4096, grabber_thread); io.spawn(4096, grabber_thread);

View File

@ -19,6 +19,8 @@ pub mod drtio {
use drtioaux; use drtioaux;
use proto_artiq::drtioaux_proto::DMA_TRACE_MAX_SIZE; use proto_artiq::drtioaux_proto::DMA_TRACE_MAX_SIZE;
use rtio_dma::remote_dma; use rtio_dma::remote_dma;
#[cfg(has_rtio_analyzer)]
use analyzer::remote_analyzer::RemoteBuffer;
pub fn startup(io: &Io, aux_mutex: &Mutex, pub fn startup(io: &Io, aux_mutex: &Mutex,
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
@ -404,6 +406,60 @@ pub mod drtio {
} }
} }
#[cfg(has_rtio_analyzer)]
fn analyzer_get_data(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable, destination: u8
) -> Result<RemoteBuffer, &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno,
&drtioaux::Packet::AnalyzerHeaderRequest { destination: destination });
let (sent, total, overflow) = match reply {
Ok(drtioaux::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)
};
let mut remote_data: Vec<u8> = Vec::new();
if sent > 0 {
let mut last_packet = false;
while !last_packet {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno,
&drtioaux::Packet::AnalyzerDataRequest { destination: destination });
match reply {
Ok(drtioaux::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)
}
}
}
Ok(RemoteBuffer {
sent_bytes: sent,
total_byte_count: total,
overflow_occurred: overflow,
data: remote_data
})
}
#[cfg(has_rtio_analyzer)]
pub fn analyzer_query(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>
) -> Result<Vec<RemoteBuffer>, &'static str> {
let mut remote_buffers: Vec<RemoteBuffer> = Vec::new();
for i in 1..drtio_routing::DEST_COUNT {
if destination_up(up_destinations, i as u8) {
remote_buffers.push(analyzer_get_data(io, aux_mutex, ddma_mutex, routing_table, i as u8)?);
}
}
Ok(remote_buffers)
}
} }
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]

View File

@ -18,3 +18,4 @@ board_misoc = { path = "../libboard_misoc", features = ["uart_console", "log"] }
board_artiq = { path = "../libboard_artiq" } board_artiq = { path = "../libboard_artiq" }
alloc_list = { path = "../liballoc_list" } alloc_list = { path = "../liballoc_list" }
riscv = { version = "0.6.0", features = ["inline-asm"] } riscv = { version = "0.6.0", features = ["inline-asm"] }
proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] }

View File

@ -0,0 +1,105 @@
use board_misoc::{csr, cache};
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]
};
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);
}
}
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 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 overflow: 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 total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() };
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,
overflow: overflow
}
}
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

@ -8,6 +8,7 @@ extern crate board_misoc;
extern crate board_artiq; extern crate board_artiq;
extern crate riscv; extern crate riscv;
extern crate alloc; extern crate alloc;
extern crate proto_artiq;
use core::convert::TryFrom; use core::convert::TryFrom;
use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp};
@ -15,14 +16,17 @@ use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp};
use board_artiq::si5324; use board_artiq::si5324;
use board_artiq::{spi, drtioaux}; use board_artiq::{spi, drtioaux};
use board_artiq::drtio_routing; use board_artiq::drtio_routing;
use proto_artiq::drtioaux_proto::ANALYZER_MAX_SIZE;
use riscv::register::{mcause, mepc, mtval}; use riscv::register::{mcause, mepc, mtval};
use dma::Manager as DmaManager; use dma::Manager as DmaManager;
use analyzer::Analyzer;
#[global_allocator] #[global_allocator]
static mut ALLOC: alloc_list::ListAlloc = alloc_list::EMPTY; static mut ALLOC: alloc_list::ListAlloc = alloc_list::EMPTY;
mod repeater; mod repeater;
mod dma; mod dma;
mod analyzer;
fn drtiosat_reset(reset: bool) { fn drtiosat_reset(reset: bool) {
unsafe { unsafe {
@ -73,7 +77,7 @@ macro_rules! forward {
($routing_table:expr, $destination:expr, $rank:expr, $repeaters:expr, $packet:expr) => {} ($routing_table:expr, $destination:expr, $rank:expr, $repeaters:expr, $packet:expr) => {}
} }
fn process_aux_packet(_manager: &mut DmaManager, _repeaters: &mut [repeater::Repeater], fn process_aux_packet(_manager: &mut DmaManager, analyzer: &mut Analyzer, _repeaters: &mut [repeater::Repeater],
_routing_table: &mut drtio_routing::RoutingTable, _rank: &mut u8, _routing_table: &mut drtio_routing::RoutingTable, _rank: &mut u8,
packet: drtioaux::Packet) -> Result<(), drtioaux::Error<!>> { packet: drtioaux::Packet) -> 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,
@ -300,6 +304,28 @@ fn process_aux_packet(_manager: &mut DmaManager, _repeaters: &mut [repeater::Rep
&drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 }) &drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 })
} }
} }
drtioaux::Packet::AnalyzerHeaderRequest { destination: _destination } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet);
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);
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,
})
}
#[cfg(has_rtio_dma)] #[cfg(has_rtio_dma)]
drtioaux::Packet::DmaAddTraceRequest { destination: _destination, id, last, length, trace } => { drtioaux::Packet::DmaAddTraceRequest { destination: _destination, id, last, length, trace } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet); forward!(_routing_table, _destination, *_rank, _repeaters, &packet);
@ -329,12 +355,13 @@ fn process_aux_packet(_manager: &mut DmaManager, _repeaters: &mut [repeater::Rep
} }
} }
fn process_aux_packets(dma_manager: &mut DmaManager, repeaters: &mut [repeater::Repeater], fn process_aux_packets(dma_manager: &mut DmaManager, analyzer: &mut Analyzer,
repeaters: &mut [repeater::Repeater],
routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8) { routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8) {
let result = let result =
drtioaux::recv(0).and_then(|packet| { drtioaux::recv(0).and_then(|packet| {
if let Some(packet) = packet { if let Some(packet) = packet {
process_aux_packet(dma_manager, repeaters, routing_table, rank, packet) process_aux_packet(dma_manager, analyzer, repeaters, routing_table, rank, packet)
} else { } else {
Ok(()) Ok(())
} }
@ -546,13 +573,16 @@ pub extern fn main() -> i32 {
// without a manual intervention. // without a manual intervention.
let mut dma_manager = DmaManager::new(); let mut dma_manager = DmaManager::new();
// Reset the analyzer as well.
let mut analyzer = Analyzer::new();
drtioaux::reset(0); drtioaux::reset(0);
drtiosat_reset(false); drtiosat_reset(false);
drtiosat_reset_phy(false); drtiosat_reset_phy(false);
while drtiosat_link_rx_up() { while drtiosat_link_rx_up() {
drtiosat_process_errors(); drtiosat_process_errors();
process_aux_packets(&mut dma_manager, &mut repeaters, &mut routing_table, &mut rank); process_aux_packets(&mut dma_manager, &mut analyzer, &mut repeaters, &mut routing_table, &mut rank);
for rep in repeaters.iter_mut() { for rep in repeaters.iter_mut() {
rep.service(&routing_table, rank); rep.service(&routing_table, rank);
} }

View File

@ -122,7 +122,7 @@ class RawSlicer(Module):
for i in range(out_size)})), for i in range(out_size)})),
If(shift_buf, Case(self.source_consume, If(shift_buf, Case(self.source_consume,
{i: buf.eq(buf[i*g:]) {i: buf.eq(buf[i*g:])
for i in range(out_size)})), for i in range(out_size + 1)})),
] ]
fsm = FSM(reset_state="FETCH") fsm = FSM(reset_state="FETCH")

View File

@ -360,7 +360,7 @@ class MasterBase(MiniSoC, AMPSoC):
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
self.csr_devices.append("routing_table") self.csr_devices.append("routing_table")
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.cri_con.switch.slave, self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri,
self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
self.csr_devices.append("rtio_analyzer") self.csr_devices.append("rtio_analyzer")
@ -576,6 +576,10 @@ class SatelliteBase(BaseSoC):
self.csr_devices.append("cri_con") self.csr_devices.append("cri_con")
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
self.csr_devices.append("routing_table") self.csr_devices.append("routing_table")
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")
class Master(MasterBase): class Master(MasterBase):

View File

@ -2,7 +2,7 @@
import argparse import argparse
import logging import logging
from packaging import version from packaging.version import Version
from misoc.integration.builder import builder_args, builder_argdict from misoc.integration.builder import builder_args, builder_argdict
from misoc.targets.kasli import soc_kasli_args, soc_kasli_argdict from misoc.targets.kasli import soc_kasli_args, soc_kasli_argdict
@ -150,7 +150,7 @@ def main():
description = jsondesc.load(args.description) description = jsondesc.load(args.description)
min_artiq_version = description.get("min_artiq_version", "0") min_artiq_version = description.get("min_artiq_version", "0")
if version.parse(artiq_version) < version.parse(min_artiq_version): if Version(artiq_version) < Version(min_artiq_version):
logger.warning("ARTIQ version mismatch: current %s < %s minimum", logger.warning("ARTIQ version mismatch: current %s < %s minimum",
artiq_version, min_artiq_version) artiq_version, min_artiq_version)

View File

@ -308,6 +308,10 @@ class _MasterBase(MiniSoC, AMPSoC):
self.register_kernel_cpu_csrdevice("cri_con") self.register_kernel_cpu_csrdevice("cri_con")
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
self.csr_devices.append("routing_table") self.csr_devices.append("routing_table")
self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri,
self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
self.csr_devices.append("rtio_analyzer")
class _SatelliteBase(BaseSoC): class _SatelliteBase(BaseSoC):
@ -460,6 +464,9 @@ class _SatelliteBase(BaseSoC):
self.csr_devices.append("cri_con") self.csr_devices.append("cri_con")
self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con)
self.csr_devices.append("routing_table") self.csr_devices.append("routing_table")
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")
class _NIST_CLOCK_RTIO: class _NIST_CLOCK_RTIO:

View File

@ -68,6 +68,7 @@ def do_dma(dut, address):
test_writes1 = [ test_writes1 = [
(0x01, 0x23, 0x12, 0x33), (0x01, 0x23, 0x12, 0x33),
(0x901, 0x902, 0x11, 0xeeeeeeeeeeeeeefffffffffffffffffffffffffffffff28888177772736646717738388488), (0x901, 0x902, 0x11, 0xeeeeeeeeeeeeeefffffffffffffffffffffffffffffff28888177772736646717738388488),
(0x82, 0x289, 0x99, int.from_bytes(b"\xf0" * 64, "little")),
(0x81, 0x288, 0x88, 0x8888) (0x81, 0x288, 0x88, 0x8888)
] ]

View File

@ -320,12 +320,13 @@ def main():
elif action == "analyze": elif action == "analyze":
try: try:
exp_inst.analyze() exp_inst.analyze()
put_completed()
finally: finally:
# browser's analyze shouldn't write results, # browser's analyze shouldn't write results,
# since it doesn't run the experiment and cannot have rid # since it doesn't run the experiment and cannot have rid
if rid is not None: if rid is not None:
write_results() write_results()
put_completed()
elif action == "examine": elif action == "examine":
examine(ExamineDeviceMgr, ExamineDatasetMgr, obj["file"]) examine(ExamineDeviceMgr, ExamineDatasetMgr, obj["file"])
put_completed() put_completed()

View File

@ -43,11 +43,11 @@
"mozilla-overlay": { "mozilla-overlay": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1677493379, "lastModified": 1684487559,
"narHash": "sha256-A1gO8zlWLv3+tZ3cGVB1WYvvoN9pbFyv0xIJHcTsckw=", "narHash": "sha256-SZcJEM+NnLr8ctzeQf1BGAqBHzJ3jn+tdSeO7lszIJc=",
"owner": "mozilla", "owner": "mozilla",
"repo": "nixpkgs-mozilla", "repo": "nixpkgs-mozilla",
"rev": "78e723925daf5c9e8d0a1837ec27059e61649cb6", "rev": "e6ca26fe8b9df914d4567604e426fbc185d9ef3e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -61,11 +61,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1682845907, "lastModified": 1685184981,
"narHash": "sha256-nQmDWeglDUVJH/Rhdg6uvE7Rdt8sEgC2J21Vs61BTDI=", "narHash": "sha256-cl+mFQIUdxhlgetiGMkiSu1o9ffSwcni9592HV3uS1s=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "5b53be0311d67eedad5bec98b8abe2603e29850c", "rev": "b8d637f5c4340d12b747b7f1bfd1ef2b14540297",
"revCount": 807, "revCount": 809,
"type": "git", "type": "git",
"url": "https://git.m-labs.hk/m-labs/nac3.git" "url": "https://git.m-labs.hk/m-labs/nac3.git"
}, },
@ -76,16 +76,16 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1682669017, "lastModified": 1685004253,
"narHash": "sha256-Vi+p4y3wnl0/4gcwTdmCO398kKlDaUrNROtf3GOD2NY=", "narHash": "sha256-AbVL1nN/TDicUQ5wXZ8xdLERxz/eJr7+o8lqkIOVuaE=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7449971a3ecf857b4a554cf79b1d9dcc1a4647d8", "rev": "3e01645c40b92d29f3ae76344a6d654986a91a91",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-22.11", "ref": "nixos-23.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -108,11 +108,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1681290481, "lastModified": 1685094262,
"narHash": "sha256-VEZcGhbtJGonRrrWi31evNDVSerlLjEPL0MZGm9VlB8=", "narHash": "sha256-7DvbdTUYP7PbhZClT/tob66iMV95v7124RynMpPc5VA=",
"owner": "m-labs", "owner": "m-labs",
"repo": "sipyco", "repo": "sipyco",
"rev": "727631ada6e59dc6ef0ad50bfcc376d2ffe805aa", "rev": "f1f0fc1d3071c5a6ba6dd613b54bb4176ad1e8dc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -140,11 +140,11 @@
"src-misoc": { "src-misoc": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1679903508, "lastModified": 1685174995,
"narHash": "sha256-TI0agjSSMJtH4mgAMpSO128zxcwSo/AjY1B6AW7zBQQ=", "narHash": "sha256-90UwWt9/TAaFAoYDpiIzHXqMWYfftlps8sodv/Gf07c=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "0cf0ebb7d4f56cc6d44a3dea3e386efab9d82419", "rev": "d83499b318e8ef021b12e2df261707a165eb3afa",
"revCount": 2437, "revCount": 2439,
"submodules": true, "submodules": true,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/misoc.git" "url": "https://github.com/m-labs/misoc.git"

View File

@ -43,7 +43,7 @@
}); });
vivadoDeps = pkgs: with pkgs; [ vivadoDeps = pkgs: with pkgs; [
libxcrypt libxcrypt-legacy
ncurses5 ncurses5
zlib zlib
libuuid libuuid
@ -60,18 +60,16 @@
qasync = pkgs.python3Packages.buildPythonPackage rec { qasync = pkgs.python3Packages.buildPythonPackage rec {
pname = "qasync"; pname = "qasync";
version = "0.19.0"; version = "0.24.1";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "CabbageDevelopment"; owner = "CabbageDevelopment";
repo = "qasync"; repo = "qasync";
rev = "v${version}"; rev = "v${version}";
sha256 = "sha256-xGAUAyOq+ELwzMGbLLmXijxLG8pv4a6tPvfAVOt1YwU="; sha256 = "sha256-DAzmobw+c29Pt/URGO3bWXHBxgu9bDHhdTUBE9QJDe4=";
}; };
propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ]; propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ];
checkInputs = [ pkgs.python3Packages.pytest ]; nativeCheckInputs = [ pkgs.python3Packages.pytest-runner pkgs.python3Packages.pytestCheckHook ];
checkPhase = '' disabledTestPaths = [ "tests/test_qeventloop.py" ];
pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio
'';
}; };
artiq-upstream = pkgs.python3Packages.buildPythonPackage rec { artiq-upstream = pkgs.python3Packages.buildPythonPackage rec {
@ -98,8 +96,14 @@
wrapQtApp "$out/bin/artiq_session" wrapQtApp "$out/bin/artiq_session"
''; '';
# Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. preFixup =
# Allows subprocesses using python to find all packages you have installed ''
# Ensure that wrapProgram uses makeShellWrapper rather than makeBinaryWrapper
# brought in by wrapQtAppsHook. Only makeShellWrapper supports --run.
wrapProgram() { wrapProgramShell "$@"; }
'';
## Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses.
## Allows subprocesses using python to find all packages you have installed
makeWrapperArgs = [ makeWrapperArgs = [
''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' ''
"--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf" "--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf"
@ -108,7 +112,7 @@
# FIXME: automatically propagate llvm_x dependency # FIXME: automatically propagate llvm_x dependency
# cacert is required in the check stage only, as certificates are to be # cacert is required in the check stage only, as certificates are to be
# obtained from system elsewhere # obtained from system elsewhere
checkInputs = [ pkgs.llvm_14 pkgs.cacert ]; nativeCheckInputs = [ pkgs.llvm_14 pkgs.cacert ];
checkPhase = '' checkPhase = ''
python -m unittest discover -v artiq.test python -m unittest discover -v artiq.test
''; '';
@ -155,12 +159,12 @@
propagatedBuildInputs = with pkgs.python3Packages; [ pyserial prettytable msgpack migen ]; propagatedBuildInputs = with pkgs.python3Packages; [ pyserial prettytable msgpack migen ];
}; };
vivadoEnv = pkgs.buildFHSUserEnv { vivadoEnv = pkgs.buildFHSEnv {
name = "vivado-env"; name = "vivado-env";
targetPkgs = vivadoDeps; targetPkgs = vivadoDeps;
}; };
vivado = pkgs.buildFHSUserEnv { vivado = pkgs.buildFHSEnv {
name = "vivado"; name = "vivado";
targetPkgs = vivadoDeps; targetPkgs = vivadoDeps;
profile = "set -e; source /opt/Xilinx/Vivado/2022.2/settings64.sh"; profile = "set -e; source /opt/Xilinx/Vivado/2022.2/settings64.sh";
@ -179,8 +183,7 @@
}; };
nativeBuildInputs = [ nativeBuildInputs = [
(pkgs.python3.withPackages(ps: [ ps.jsonschema migen misoc (artiq.withExperimentalFeatures experimentalFeatures) ])) (pkgs.python3.withPackages(ps: [ ps.jsonschema migen misoc (artiq.withExperimentalFeatures experimentalFeatures) ]))
rustPlatform.rust.rustc rust
rustPlatform.rust.cargo
pkgs.cargo-xbuild pkgs.cargo-xbuild
pkgs.llvmPackages_14.clang-unwrapped pkgs.llvmPackages_14.clang-unwrapped
pkgs.llvm_14 pkgs.llvm_14
@ -262,21 +265,6 @@
paths = [ openocd-fixed bscan_spi_bitstreams-pkg ]; paths = [ openocd-fixed bscan_spi_bitstreams-pkg ];
}; };
# https://github.com/ashb/sphinx-argparse/issues/5
sphinx-argparse = pkgs.python3Packages.buildPythonPackage rec {
pname = "sphinx-argparse";
version = "0.3.1";
src = pkgs.python3Packages.fetchPypi {
inherit pname version;
sha256 = "82151cbd43ccec94a1530155f4ad34f251aaca6a0ffd5516d7fadf952d32dc1e";
};
checkInputs = [ pkgs.python3Packages.pytest ];
checkPhase =
''
pytest -vv -k "not test_parse_nested and not test_parse_nested_with_alias and not test_parse_groups and not test_action_groups_with_subcommands"
'';
propagatedBuildInputs = [ pkgs.python3Packages.sphinx ];
};
sphinxcontrib-wavedrom = pkgs.python3Packages.buildPythonPackage rec { sphinxcontrib-wavedrom = pkgs.python3Packages.buildPythonPackage rec {
pname = "sphinxcontrib-wavedrom"; pname = "sphinxcontrib-wavedrom";
version = "3.0.2"; version = "3.0.2";
@ -303,14 +291,14 @@
target = "kc705"; target = "kc705";
variant = "nist_clock"; variant = "nist_clock";
}; };
inherit sphinx-argparse sphinxcontrib-wavedrom latex-artiq-manual; inherit sphinxcontrib-wavedrom latex-artiq-manual;
artiq-manual-html = pkgs.stdenvNoCC.mkDerivation rec { artiq-manual-html = pkgs.stdenvNoCC.mkDerivation rec {
name = "artiq-manual-html-${version}"; name = "artiq-manual-html-${version}";
version = artiqVersion; version = artiqVersion;
src = self; src = self;
buildInputs = [ buildInputs = [
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
sphinx-argparse sphinxcontrib-wavedrom pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom
]; ];
buildPhase = '' buildPhase = ''
export VERSIONEER_OVERRIDE=${artiqVersion} export VERSIONEER_OVERRIDE=${artiqVersion}
@ -330,7 +318,7 @@
src = self; src = self;
buildInputs = [ buildInputs = [
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
sphinx-argparse sphinxcontrib-wavedrom pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom
latex-artiq-manual latex-artiq-manual
]; ];
buildPhase = '' buildPhase = ''
@ -358,8 +346,7 @@
name = "artiq-dev-shell"; name = "artiq-dev-shell";
buildInputs = [ buildInputs = [
(packages.x86_64-linux.python3-mimalloc.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema microscope ])) (packages.x86_64-linux.python3-mimalloc.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema microscope ]))
rustPlatform.rust.rustc rust
rustPlatform.rust.cargo
pkgs.cargo-xbuild pkgs.cargo-xbuild
pkgs.llvmPackages_14.clang-unwrapped pkgs.llvmPackages_14.clang-unwrapped
pkgs.llvm_14 pkgs.llvm_14
@ -369,7 +356,7 @@
packages.x86_64-linux.vivado packages.x86_64-linux.vivado
packages.x86_64-linux.openocd-bscanspi packages.x86_64-linux.openocd-bscanspi
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
sphinx-argparse sphinxcontrib-wavedrom latex-artiq-manual pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom latex-artiq-manual
]; ];
shellHook = '' shellHook = ''
export QT_PLUGIN_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtPluginPrefix} export QT_PLUGIN_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtPluginPrefix}