diff --git a/artiq/runtime.rs/libksupport/api.rs b/artiq/runtime.rs/libksupport/api.rs index dbfbd759b..57b6302d8 100644 --- a/artiq/runtime.rs/libksupport/api.rs +++ b/artiq/runtime.rs/libksupport/api.rs @@ -102,6 +102,7 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(rtio_get_counter = ::rtio::get_counter), api!(rtio_log), api!(rtio_output = ::rtio::output), + api!(rtio_output_list = ::rtio::output_list), api!(rtio_input_timestamp = ::rtio::input_timestamp), api!(rtio_input_data = ::rtio::input_data), diff --git a/artiq/runtime.rs/libksupport/rtio.rs b/artiq/runtime.rs/libksupport/rtio.rs index 4363b255d..eaeb4d01c 100644 --- a/artiq/runtime.rs/libksupport/rtio.rs +++ b/artiq/runtime.rs/libksupport/rtio.rs @@ -1,4 +1,6 @@ use board::csr; +use core::ptr::{read_volatile, write_volatile}; +use core::slice; const RTIO_O_STATUS_FULL: u32 = 1; const RTIO_O_STATUS_UNDERFLOW: u32 = 2; @@ -23,6 +25,21 @@ pub extern fn get_counter() -> i64 { } } +#[inline(always)] +pub unsafe fn rtio_o_data_write(w: u32) { + write_volatile( + csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1) as isize), + w); +} + +#[inline(always)] +pub unsafe fn rtio_i_data_read() -> u32 { + read_volatile( + csr::rtio::I_DATA_ADDR.offset((csr::rtio::I_DATA_SIZE - 1) as isize) + ) +} + + #[inline(never)] unsafe fn process_exceptional_status(timestamp: i64, channel: u32, status: u32) { if status & RTIO_O_STATUS_FULL != 0 { @@ -59,7 +76,27 @@ pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { csr::rtio::chan_sel_write(channel); csr::rtio::o_timestamp_write(timestamp as u64); csr::rtio::o_address_write(addr); - csr::rtio::o_data_write(data); + rtio_o_data_write(data); + csr::rtio::o_we_write(1); + let status = csr::rtio::o_status_read(); + if status != 0 { + process_exceptional_status(timestamp, channel, status); + } + } +} + +pub extern fn output_list(timestamp: i64, channel: u32, addr: u32, + &(len, ptr): &(usize, *const u32)) { + unsafe { + csr::rtio::chan_sel_write(channel); + csr::rtio::o_timestamp_write(timestamp as u64); + csr::rtio::o_address_write(addr); + let data = slice::from_raw_parts(ptr, len); + for i in 0..data.len() { + write_volatile( + csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - i) as isize), + data[i]); + } csr::rtio::o_we_write(1); let status = csr::rtio::o_status_read(); if status != 0 { @@ -119,7 +156,7 @@ pub extern fn input_data(channel: u32) -> u32 { } } - let data = csr::rtio::i_data_read(); + let data = rtio_i_data_read(); csr::rtio::i_re_write(1); data } @@ -136,14 +173,14 @@ pub fn log(timestamp: i64, data: &[u8]) { word <<= 8; word |= data[i] as u32; if i % 4 == 0 { - csr::rtio::o_data_write(word); + rtio_o_data_write(word); csr::rtio::o_we_write(1); word = 0; } } word <<= 8; - csr::rtio::o_data_write(word); + rtio_o_data_write(word); csr::rtio::o_we_write(1); } }