I've been toying with the idea of using Rust as an alternative language for writing ARTIQ kernels. Here's a proof-of-concept for a few basic things (on ARTIQ-5):
#![crate_name = "rustkernel"]
#![crate_type = "lib"]
#![no_std]
use core::ptr::write_volatile;
// RTIO channel numbers
const LED0: i32 = 25;
const LED1: i32 = 26;
extern "C" {
#[no_mangle]
pub static mut now: i64;
fn rtio_get_counter() -> i64;
fn rtio_init();
fn rtio_output(target: i32, data: i32);
}
fn at_mu(t: i64) {
unsafe {
write_volatile(((&mut now as *mut i64) as usize) as *mut i32, (t >> 32) as i32);
write_volatile(((&mut now as *mut i64) as usize + 4) as *mut i32, t as i32);
}
}
fn now_mu() -> i64 {
unsafe { now }
}
fn delay_mu(d: i64) {
at_mu(now_mu() + d);
}
macro_rules! parallel {
($($v:stmt),*) => (
let origin = now_mu();
let mut finalt = origin;
$(at_mu(origin); $v; if now_mu() > finalt { finalt = now_mu()})*
at_mu(finalt);
)
}
#[export_name = "__modinit__"]
pub extern fn run() {
unsafe {
rtio_init();
at_mu(rtio_get_counter() + 1250000);
loop {
parallel!(
{
rtio_output(LED0 << 8, 1);
delay_mu(1_000_000_000);
rtio_output(LED0 << 8, 0);
delay_mu(1_000_000_000);
},
{
rtio_output(LED1 << 8, 1);
delay_mu(250_000_000);
rtio_output(LED1 << 8, 0);
delay_mu(250_000_000);
}
);
}
}
}
Compile and run with:
rustc --target or1k-unknown-none -g -C target-feature=+mul,+div,+ffl1,+cmov,+addc rustkernel.rs -Z force-overflow-checks=off
rm *.o
or1k-linux-ar x librustkernel.rlib
or1k-linux-ld -shared --eh-frame-hdr *.o -o rustkernel.elf
artiq_run rustkernel.elf
If there is interest, this could be developed further. One of the main areas is obviously interaction with Python and ARTIQ-Python.
Other languages such as C++ may also be supported.