use std::marker::PhantomData;
use crate::{
ir::{self, Instruction, Operation},
unexpanded,
};
use super::{
CubeContext, CubePrimitive, CubeType, ExpandElement, ExpandElementTyped, Init, IntoRuntime,
Slice, SliceMut,
};
pub use ir::{MatrixIdent, MatrixLayout};
#[derive(Copy, Clone)]
pub struct Matrix<C: CubeType> {
_c: PhantomData<C>,
}
pub struct MatrixExpand<C: CubeType> {
elem: ExpandElement,
ident: MatrixIdent,
_c: PhantomData<C>,
}
impl<C: CubeType> Clone for MatrixExpand<C> {
fn clone(&self) -> Self {
Self {
elem: self.elem.clone(),
ident: self.ident,
_c: self._c,
}
}
}
impl<C: CubeType> CubeType for Matrix<C> {
type ExpandType = MatrixExpand<C>;
}
impl<C: CubeType> IntoRuntime for Matrix<C> {
fn __expand_runtime_method(self, _context: &mut CubeContext) -> MatrixExpand<C> {
unimplemented!("Matrices can't exist at compile time")
}
}
impl<C: CubeType> Init for MatrixExpand<C> {
fn init(self, _context: &mut CubeContext) -> Self {
self
}
}
impl<C: CubePrimitive> Matrix<C> {
#[allow(unused_variables)]
pub unsafe fn uninitialized(
ident: MatrixIdent,
m: u32,
n: u32,
k: u32,
layout: MatrixLayout,
) -> Self {
Matrix { _c: PhantomData }
}
#[allow(unused_variables)]
pub fn from_value(
ident: MatrixIdent,
m: u32,
n: u32,
k: u32,
layout: MatrixLayout,
value: C,
) -> Self {
Matrix { _c: PhantomData }
}
#[allow(unused_variables)]
pub fn from_slice(
ident: MatrixIdent,
m: u32,
n: u32,
k: u32,
layout: MatrixLayout,
value: &Slice<C>,
stride: u32,
) -> Self {
Matrix { _c: PhantomData }
}
pub fn __expand_uninitialized(
context: &mut CubeContext,
ident: MatrixIdent,
m: ExpandElementTyped<u32>,
n: ExpandElementTyped<u32>,
k: ExpandElementTyped<u32>,
layout: MatrixLayout,
) -> MatrixExpand<C> {
let elem = C::as_elem(context);
let elem = context.create_matrix(ir::Matrix {
ident,
m: m.constant().unwrap().as_u32() as u8,
n: n.constant().unwrap().as_u32() as u8,
k: k.constant().unwrap().as_u32() as u8,
elem,
layout,
});
MatrixExpand {
elem,
ident,
_c: PhantomData,
}
}
pub fn __expand_from_value(
context: &mut CubeContext,
ident: MatrixIdent,
m: ExpandElementTyped<u32>,
n: ExpandElementTyped<u32>,
k: ExpandElementTyped<u32>,
layout: MatrixLayout,
value: ExpandElementTyped<C>,
) -> MatrixExpand<C> {
let mat = Self::__expand_uninitialized(context, ident, m, n, k, layout);
fill::expand(context, mat.clone(), value);
mat
}
#[allow(clippy::too_many_arguments)]
pub fn __expand_from_slice(
context: &mut CubeContext,
ident: MatrixIdent,
m: ExpandElementTyped<u32>,
n: ExpandElementTyped<u32>,
k: ExpandElementTyped<u32>,
layout: MatrixLayout,
value: ExpandElementTyped<Slice<C>>,
stride: ExpandElementTyped<u32>,
) -> MatrixExpand<C> {
let mat = Self::__expand_uninitialized(context, ident, m, n, k, layout);
load::expand(context, mat.clone(), value, stride);
mat
}
}
#[allow(unused_variables)]
pub fn fill<C: CubeType>(mat: &Matrix<C>, value: C) {
unexpanded!()
}
pub mod fill {
use super::*;
pub fn expand<C: CubeType>(
context: &mut CubeContext,
mat: MatrixExpand<C>,
value: ExpandElementTyped<C>,
) {
let value: ExpandElement = value.into();
context.register(Instruction::new(
ir::CoopMma::Fill { value: *value },
*mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn load<C: CubePrimitive, V: CubePrimitive>(mat: &Matrix<C>, value: &Slice<V>, stride: u32) {
unexpanded!()
}
pub mod load {
use super::*;
#[allow(unused_variables)]
pub fn expand<C: CubePrimitive, V: CubePrimitive>(
context: &mut CubeContext,
mat: MatrixExpand<C>,
value: ExpandElementTyped<Slice<V>>,
stride: ExpandElementTyped<u32>,
) {
let stride: ExpandElement = stride.into();
assert_ne!(
mat.ident,
MatrixIdent::Accumulator,
"Loading accumulator requires explicit layout. Use `load_with_layout` instead."
);
context.register(Instruction::new(
ir::CoopMma::Load {
value: *value.expand,
stride: *stride,
layout: None,
},
*mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn load_with_layout<C: CubePrimitive, V: CubePrimitive>(
mat: &Matrix<C>,
value: &Slice<V>,
stride: u32,
layout: MatrixLayout,
) {
unexpanded!()
}
pub mod load_with_layout {
use super::*;
#[allow(unused_variables)]
pub fn expand<C: CubeType, V: CubePrimitive>(
context: &mut CubeContext,
mat: MatrixExpand<C>,
value: ExpandElementTyped<Slice<V>>,
stride: ExpandElementTyped<u32>,
layout: MatrixLayout,
) {
let stride: ExpandElement = stride.into();
context.register(Instruction::new(
ir::CoopMma::Load {
value: *value.expand,
stride: *stride,
layout: Some(layout),
},
*mat.elem,
));
}
}
#[allow(unused_variables)]
pub fn store<C: CubePrimitive, O: CubePrimitive>(
output: &mut SliceMut<O>,
mat: &Matrix<C>,
stride: u32,
layout: MatrixLayout,
) {
unexpanded!()
}
pub mod store {
use super::*;
#[allow(unused_variables)]
pub fn expand<C: CubePrimitive, O: CubePrimitive>(
context: &mut CubeContext,
output: ExpandElementTyped<SliceMut<O>>,
mat: MatrixExpand<C>,
stride: ExpandElementTyped<u32>,
layout: MatrixLayout,
) {
let stride: ExpandElement = stride.into();
context.register(Instruction::new(
ir::CoopMma::Store {
mat: *mat.elem,
stride: *stride,
layout,
},
*output.expand,
));
}
}
#[allow(unused_variables)]
pub fn execute<A: CubePrimitive, B: CubePrimitive, C: CubePrimitive, D: CubePrimitive>(
mat_a: &Matrix<A>,
mat_b: &Matrix<B>,
mat_c: &Matrix<C>,
mat_d: &Matrix<D>,
) {
unexpanded!()
}
pub mod execute {
use super::*;
pub fn expand<A: CubePrimitive, B: CubePrimitive, C: CubePrimitive, D: CubePrimitive>(
context: &mut CubeContext,
mat_a: MatrixExpand<A>,
mat_b: MatrixExpand<B>,
mat_c: MatrixExpand<C>,
mat_d: MatrixExpand<D>,
) {
context.register(Instruction::new(
ir::CoopMma::Execute {
mat_a: *mat_a.elem,
mat_b: *mat_b.elem,
mat_c: *mat_c.elem,
},
*mat_d.elem,
));
}
}
#[allow(unused_variables)]
pub fn cast<C: CubePrimitive, O: CubePrimitive>(input: &Matrix<C>) -> Matrix<O> {
unexpanded!()
}
pub mod cast {
use super::*;
#[allow(unused_variables)]
pub fn expand<C: CubePrimitive, O: CubePrimitive>(
context: &mut CubeContext,
input: MatrixExpand<C>,
) -> MatrixExpand<O> {
let ident = input.ident;
if core::any::TypeId::of::<C>() == core::any::TypeId::of::<O>() {
return MatrixExpand {
elem: input.elem,
ident,
_c: PhantomData,
};
}
let input = *input.elem;
let input_mat = match input.kind {
ir::VariableKind::Matrix { mat, .. } => mat,
_ => unreachable!(),
};
let elem = O::as_elem(context);
let elem = context.create_matrix(ir::Matrix {
ident,
m: input_mat.m,
n: input_mat.n,
k: input_mat.k,
elem,
layout: MatrixLayout::Undefined,
});
let output = MatrixExpand {
ident,
elem,
_c: PhantomData,
};
context.register(Instruction::new(ir::CoopMma::Cast { input }, *output.elem));
output
}
}
impl From<ir::CoopMma> for Operation {
fn from(value: ir::CoopMma) -> Self {
Operation::CoopMma(value)
}
}