pub(crate) mod backend;
pub(crate) mod op_prep;
mod emulation;
pub mod npu;
mod simulation;
mod typecheck;
use cfg_if::cfg_if;
pub use backend::Backend;
pub use emulation::Emulation;
pub use simulation::Simulation;
pub use typecheck::Typecheck;
pub use npu::Npu;
cfg_if! {
if #[cfg(backend = "simulation")] {
pub type CurrentBackend = Simulation;
} else if #[cfg(backend = "emulation")] {
pub type CurrentBackend = Emulation;
} else if #[cfg(backend = "npu")] {
pub type CurrentBackend = Npu;
} else if #[cfg(backend = "typecheck")] {
pub type CurrentBackend = Typecheck;
} else {
compile_error!("wrong backend cfg: expected one of \"simulation\", \"emulation\", \"npu\", or \"typecheck\"");
}
}
pub trait TupleApply<Args> {
type Output;
fn apply(self, args: Args) -> Self::Output;
}
impl<F, A, R> TupleApply<&mut A> for F
where
F: FnOnce(&mut A) -> R,
{
type Output = R;
fn apply(self, a: &mut A) -> R {
self(a)
}
}
impl<F, A, R> TupleApply<&A> for F
where
F: FnOnce(&A) -> R,
{
type Output = R;
fn apply(self, a: &A) -> R {
self(a)
}
}
macro_rules! impl_tuple_apply {
($($T:ident),+) => {
#[expect(non_snake_case, reason = "type parameters A..Z used as destructuring variable names")]
impl<Func, $($T,)+ Ret> TupleApply<($($T,)+)> for Func
where
Func: FnOnce($($T,)+) -> Ret,
{
type Output = Ret;
fn apply(self, ($($T,)+): ($($T,)+)) -> Ret {
self($($T,)+)
}
}
};
}
impl_tuple_apply!(A, B);
impl_tuple_apply!(A, B, C);
impl_tuple_apply!(A, B, C, D);
impl_tuple_apply!(A, B, C, D, E);
impl_tuple_apply!(A, B, C, D, E, G);
impl_tuple_apply!(A, B, C, D, E, G, H);
impl_tuple_apply!(A, B, C, D, E, G, H, I);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
impl_tuple_apply!(A, B, C, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
pub trait DeviceSend {}
impl DeviceSend for () {}
impl DeviceSend for bool {}
impl DeviceSend for i8 {}
impl DeviceSend for i16 {}
impl DeviceSend for i32 {}
impl DeviceSend for i64 {}
impl DeviceSend for isize {}
impl DeviceSend for u8 {}
impl DeviceSend for u16 {}
impl DeviceSend for u32 {}
impl DeviceSend for u64 {}
impl DeviceSend for usize {}
impl DeviceSend for f32 {}
impl DeviceSend for f64 {}
macro_rules! impl_device_send_tuple {
($($T:ident),+) => {
impl<$($T: DeviceSend),+> DeviceSend for ($($T,)+) {}
};
}
impl_device_send_tuple!(A);
impl_device_send_tuple!(A, B);
impl_device_send_tuple!(A, B, C);
impl_device_send_tuple!(A, B, C, D);
impl_device_send_tuple!(A, B, C, D, E);
impl_device_send_tuple!(A, B, C, D, E, F);
impl_device_send_tuple!(A, B, C, D, E, F, G);
impl_device_send_tuple!(A, B, C, D, E, F, G, H);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
impl_device_send_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
impl<T> DeviceSend for std::marker::PhantomData<T> {}
pub trait DeviceFn<Args: DeviceSend> {
type Output: DeviceSend;
fn execute(args: Args) -> impl std::future::Future<Output = Self::Output>;
}
pub async fn launch<F, P>(_f: F, args: P) -> F::Output
where
F: DeviceFn<P>,
P: DeviceSend,
{
F::execute(args).await
}