use cubecl::ir::Scope;
use cubecl::prelude::*;
use cubecl::unexpanded;
use super::payload::base::{Payload, PayloadExpand};
use super::payload::pair::OperandPair;
use crate::*;
pub(crate) const FIRST_SLOT: usize = 0;
#[derive(CubeType)]
pub struct Slot<T: CubeType> {
pub(crate) data: T,
pub(crate) pipeline: Meeting,
#[cube(comptime)]
pub(crate) refills: Vec<Refill>,
}
#[cube]
impl<T: CubeType> Slot<T> {
pub(crate) fn wrap(data: T, pipeline: Meeting, #[comptime] refills: Vec<Refill>) -> Slot<T> {
Slot::<T> {
data,
pipeline,
refills,
}
}
#[allow(dead_code)] pub(crate) fn has_fixed(&self) -> comptime_type!(bool) {
comptime!(self.refills.contains(&Refill::Once))
}
#[allow(dead_code)] pub(crate) fn acquire_write(&self) {
match &self.pipeline {
Meeting::Barrier { empty, writes, .. } => empty.wait_parity(*writes ^ 1),
Meeting::Cube => sync_cube(),
Meeting::Plane => sync_plane(),
}
}
#[allow(dead_code)] pub(crate) fn release_write(&mut self) {
match &mut self.pipeline {
Meeting::Barrier {
full,
all_publish,
commits,
elected,
writes,
..
} => {
if *all_publish || UNIT_POS == *elected {
if *commits {
full.commit_copy_async();
}
full.arrive();
}
*writes ^= 1;
}
Meeting::Cube | Meeting::Plane => {}
}
}
#[allow(dead_code)] pub(crate) fn acquire_read(&self) {
match &self.pipeline {
Meeting::Barrier { full, reads, .. } => full.wait_parity(*reads),
Meeting::Cube | Meeting::Plane => {}
}
}
#[allow(dead_code)] pub(crate) fn release_read(&mut self) {
match &mut self.pipeline {
Meeting::Barrier { empty, reads, .. } => {
empty.arrive();
*reads ^= 1;
}
Meeting::Cube | Meeting::Plane => {}
}
}
pub fn publish(&self) {
match &self.pipeline {
Meeting::Cube => sync_cube(),
Meeting::Plane => sync_plane(),
Meeting::Barrier { .. } => {}
}
}
}
#[cube]
impl<P: Payload<P> + CubeType<ExpandType: Clone>> Slot<P> {
pub(crate) fn refill(&mut self, src: &P, region: &Region, #[comptime] only: Refill) {
let refills = comptime!(self.refills.clone());
let writes = comptime!(refills.contains(&only));
if comptime!(writes || only == Refill::EveryRegion) {
self.acquire_write();
self.data
.bring(src, &self.pipeline, region, comptime!(refills), only);
self.release_write();
}
}
}
impl Slot<OperandPair> {
pub fn consume(&mut self, _compute: impl FnOnce(&Tile, &Tile)) {
unexpanded!()
}
}
impl SlotExpand<OperandPair> {
pub fn __expand_consume_method<F>(&mut self, scope: &Scope, compute: F)
where
F: FnOnce(&Scope, &TileExpand, &TileExpand),
{
self.__expand_acquire_read_method(scope);
compute(scope, &self.data.lhs, &self.data.rhs);
self.__expand_release_read_method(scope);
}
}
impl Slot<Tile> {
pub fn consume(&mut self, _compute: impl FnOnce(&Tile)) {
unexpanded!()
}
}
impl SlotExpand<Tile> {
pub fn __expand_consume_method<F>(&mut self, scope: &Scope, compute: F)
where
F: FnOnce(&Scope, &TileExpand),
{
self.__expand_acquire_read_method(scope);
compute(scope, &self.data);
self.__expand_release_read_method(scope);
}
}