forked from M-Labs/artiq-zynq
add RTIO syscalls
This commit is contained in:
parent
986c4e9327
commit
ce6c89e343
|
@ -30,6 +30,12 @@ version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "036b035e9ebcd705affece16319223d19f229e2358be6e3b7b094e57193312e6"
|
checksum = "036b035e9ebcd705affece16319223d19f229e2358be6e3b7b094e57193312e6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cslice"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dyld"
|
name = "dyld"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -154,6 +160,7 @@ checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||||
name = "runtime"
|
name = "runtime"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cslice",
|
||||||
"dyld",
|
"dyld",
|
||||||
"libasync",
|
"libasync",
|
||||||
"libboard_zynq",
|
"libboard_zynq",
|
||||||
|
|
|
@ -12,6 +12,7 @@ default = ["target_zc706"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = { version = "0.2", default-features = false }
|
num-traits = { version = "0.2", default-features = false }
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
|
cslice = "0.3"
|
||||||
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
|
|
|
@ -13,6 +13,7 @@ use libsupport_zynq::ram;
|
||||||
|
|
||||||
|
|
||||||
mod pl;
|
mod pl;
|
||||||
|
mod rtio;
|
||||||
mod network;
|
mod network;
|
||||||
|
|
||||||
fn identifier_read(buf: &mut [u8]) -> &str {
|
fn identifier_read(buf: &mut [u8]) -> &str {
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
use core::ptr::{read_volatile, write_volatile};
|
||||||
|
use cslice::CSlice;
|
||||||
|
|
||||||
|
use libboard_zynq::println;
|
||||||
|
|
||||||
|
use crate::pl::csr;
|
||||||
|
|
||||||
|
pub const RTIO_O_STATUS_WAIT: u8 = 1;
|
||||||
|
pub const RTIO_O_STATUS_UNDERFLOW: u8 = 2;
|
||||||
|
pub const RTIO_O_STATUS_DESTINATION_UNREACHABLE: u8 = 4;
|
||||||
|
pub const RTIO_I_STATUS_WAIT_EVENT: u8 = 1;
|
||||||
|
pub const RTIO_I_STATUS_OVERFLOW: u8 = 2;
|
||||||
|
pub const RTIO_I_STATUS_WAIT_STATUS: u8 = 4;
|
||||||
|
pub const RTIO_I_STATUS_DESTINATION_UNREACHABLE: u8 = 8;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TimestampedData {
|
||||||
|
timestamp: i64,
|
||||||
|
data: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn init() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn get_destination_status(destination: i32) -> bool {
|
||||||
|
// TODO
|
||||||
|
destination == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn get_counter() -> i64 {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::counter_update_write(1);
|
||||||
|
csr::rtio::counter_read() as i64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writing the LSB of o_data (offset=0) triggers the RTIO write
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn rtio_o_data_write(offset: usize, data: u32) {
|
||||||
|
write_volatile(
|
||||||
|
csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - offset) as isize),
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn rtio_i_data_read(offset: usize) -> u32 {
|
||||||
|
read_volatile(
|
||||||
|
csr::rtio::I_DATA_ADDR.offset((csr::rtio::I_DATA_SIZE - 1 - offset) as isize))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
unsafe fn process_exceptional_status(channel: i32, status: u8) {
|
||||||
|
let timestamp = *(csr::rtio::NOW_HI_ADDR as *const i64);
|
||||||
|
if status & RTIO_O_STATUS_WAIT != 0 {
|
||||||
|
while csr::rtio::o_status_read() & RTIO_O_STATUS_WAIT != 0 {}
|
||||||
|
}
|
||||||
|
if status & RTIO_O_STATUS_UNDERFLOW != 0 {
|
||||||
|
println!("RTIO underflow at {0} mu, channel {1}, slack {2} mu",
|
||||||
|
timestamp, channel as i64, timestamp - get_counter());
|
||||||
|
}
|
||||||
|
if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
|
println!("RTIO destination unreachable, output, at {0} mu, channel {1}",
|
||||||
|
timestamp, channel as i64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn output(target: i32, data: i32) {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::target_write(target as u32);
|
||||||
|
// writing target clears o_data
|
||||||
|
rtio_o_data_write(0, data as _);
|
||||||
|
let status = csr::rtio::o_status_read();
|
||||||
|
if status != 0 {
|
||||||
|
process_exceptional_status(target >> 8, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn output_wide(target: i32, data: CSlice<i32>) {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::target_write(target as u32);
|
||||||
|
// writing target clears o_data
|
||||||
|
for i in (0..data.len()).rev() {
|
||||||
|
rtio_o_data_write(i, data[i] as _)
|
||||||
|
}
|
||||||
|
let status = csr::rtio::o_status_read();
|
||||||
|
if status != 0 {
|
||||||
|
process_exceptional_status(target >> 8, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::target_write((channel as u32) << 8);
|
||||||
|
csr::rtio::i_timeout_write(timeout as u64);
|
||||||
|
|
||||||
|
let mut status = RTIO_I_STATUS_WAIT_STATUS;
|
||||||
|
while status & RTIO_I_STATUS_WAIT_STATUS != 0 {
|
||||||
|
status = csr::rtio::i_status_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
|
csr::rtio::i_overflow_reset_write(1);
|
||||||
|
println!("RTIO input overflow on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
|
println!("RTIO destination unreachable, input, on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
|
||||||
|
csr::rtio::i_timestamp_read() as i64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn input_data(channel: i32) -> i32 {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::target_write((channel as u32) << 8);
|
||||||
|
csr::rtio::i_timeout_write(0xffffffff_ffffffff);
|
||||||
|
|
||||||
|
let mut status = RTIO_I_STATUS_WAIT_STATUS;
|
||||||
|
while status & RTIO_I_STATUS_WAIT_STATUS != 0 {
|
||||||
|
status = csr::rtio::i_status_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
|
csr::rtio::i_overflow_reset_write(1);
|
||||||
|
println!("RTIO input overflow on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
|
println!("RTIO destination unreachable, input, on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtio_i_data_read(0) as i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedData {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio::target_write((channel as u32) << 8);
|
||||||
|
csr::rtio::i_timeout_write(timeout as u64);
|
||||||
|
|
||||||
|
let mut status = RTIO_I_STATUS_WAIT_STATUS;
|
||||||
|
while status & RTIO_I_STATUS_WAIT_STATUS != 0 {
|
||||||
|
status = csr::rtio::i_status_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
if status & RTIO_I_STATUS_OVERFLOW != 0 {
|
||||||
|
csr::rtio::i_overflow_reset_write(1);
|
||||||
|
println!("RTIO input overflow on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
if status & RTIO_I_STATUS_WAIT_EVENT != 0 {
|
||||||
|
return TimestampedData { timestamp: -1, data: 0 }
|
||||||
|
}
|
||||||
|
if status & RTIO_I_STATUS_DESTINATION_UNREACHABLE != 0 {
|
||||||
|
println!("RTIO destination unreachable, input, on channel {0}",
|
||||||
|
channel as i64);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimestampedData {
|
||||||
|
timestamp: csr::rtio::i_timestamp_read() as i64,
|
||||||
|
data: rtio_i_data_read(0) as i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue