use cubecl::prelude::*;
use crate::{
Bound, Output, OutputArgs, Partitioning, Refusal, Tile, TileArg, TileArgLaunch, TmaOperand,
kind::Write, launch::Unbound,
};
#[cube]
pub trait Destination: Send + Sync + 'static {
type Arg<E: Numeric>: LaunchArg + CubeType;
fn tile<E: Numeric, V: Size>(arg: &Self::Arg<E>, partitioning: &Partitioning) -> Tile;
}
pub trait DestinationLaunch: Destination {
type Operand;
fn arg<E: Numeric>(operand: Self::Operand) -> <Self::Arg<E> as LaunchArg>::RuntimeArg;
}
pub trait SinkLaunch {
fn width(&self) -> usize;
fn elements(&self) -> usize;
fn launch<O: DestinationLaunch>(self, sink: impl FnOnce(Unbound) -> O::Operand);
}
pub trait SinkLaunchVisitor {
type Output;
fn visit<L: SinkLaunch>(self, prepared: Result<L, Refusal>) -> Self::Output;
}
pub struct Buffered;
#[cube]
impl Destination for Buffered {
type Arg<E: Numeric> = Output<'static, E>;
fn tile<E: Numeric, V: Size>(arg: &Self::Arg<E>, partitioning: &Partitioning) -> Tile {
arg.tile(partitioning)
}
}
impl DestinationLaunch for Buffered {
type Operand = (Bound, Write);
fn arg<E: Numeric>((bound, write): (Bound, Write)) -> OutputArgs<'static, E> {
match write {
Write::Replace => bound.output(),
Write::Accumulate => bound.atomic(),
Write::Exclusive(_) => panic!(
"Buffered: a relayed output is opened in the kernel with `TileArg::relay`, which \
takes its turn counters beside it; bind the carry as a plain `TileArg`"
),
}
}
}
pub struct TmaStored;
#[cube]
impl Destination for TmaStored {
type Arg<E: Numeric> = TileArg<'static>;
fn tile<E: Numeric, V: Size>(arg: &Self::Arg<E>, partitioning: &Partitioning) -> Tile {
arg.tile(partitioning)
}
}
impl DestinationLaunch for TmaStored {
type Operand = TmaOperand;
fn arg<E: Numeric>(operand: TmaOperand) -> TileArgLaunch {
operand.arg()
}
}