1use super::{CubeDebug, CubePrimitive, CubeType, IntoMut, NativeExpand, SliceExpand};
50use crate::unexpanded;
51use crate::{self as cubecl, prelude::*};
52use core::marker::PhantomData;
53use cubecl_macros::{comptime_type, cube, intrinsic};
54
55use alloc::format;
56use cubecl_ir::{
57 ExpandValue, Scope, VectorSize,
58 attributes::ZeroAttr,
59 dialect::matrix::{
60 ColIndexOp, LdMatrixOp, MmaManualOp, MmaManualScaledOp, RowIndexOp, StMatrixOp,
61 },
62 ident,
63 interfaces::TypedExt,
64 pliron::{debug_info::set_operation_result_name, value::Value},
65 types,
66};
67
68pub use cubecl_ir::types::matrix::{MatrixIdent, MatrixLayout, MatrixShape, MatrixType};
69use pliron::r#type::TypeHandle;
70
71#[derive(Clone, Copy)]
72pub struct Plane;
73#[derive(Clone, Copy)]
74pub struct Cube;
75
76pub trait MatrixScope: Copy {
77 const SCOPE: types::MatrixScope;
78}
79
80impl MatrixScope for Plane {
81 const SCOPE: types::MatrixScope = types::MatrixScope::Plane;
82}
83
84impl MatrixScope for Cube {
85 const SCOPE: types::MatrixScope = types::MatrixScope::Cube;
86}
87
88#[derive(Copy, Clone)]
93pub struct Matrix<C: CubeType, S: MatrixScope = Plane> {
94 _c: PhantomData<C>,
95 _s: PhantomData<S>,
96}
97
98#[derive(Copy, Clone)]
100pub struct MmaDefinition<A: CubeType, B: CubeType, CD: CubeType> {
101 _a: PhantomData<A>,
102 _b: PhantomData<B>,
103 _cd: PhantomData<CD>,
104}
105
106pub struct MatrixExpand<C: CubeType, S: MatrixScope> {
108 elem: Value,
109 ident: MatrixIdent,
110 _c: PhantomData<C>,
111 _s: PhantomData<S>,
112}
113
114#[derive(Debug)]
116pub struct MmaDefinitionExpand<A: CubeType, B: CubeType, CD: CubeType> {
117 pub shape: MatrixShape,
118 pub a_type: TypeHandle,
119 pub b_type: TypeHandle,
120 pub cd_type: TypeHandle,
121 pub scales_factor: Option<usize>,
122 pub scales_type: Option<TypeHandle>,
123 _a: PhantomData<A>,
124 _b: PhantomData<B>,
125 _cd: PhantomData<CD>,
126}
127
128impl<C: CubeType, S: MatrixScope> Clone for MatrixExpand<C, S> {
129 fn clone(&self) -> Self {
130 Self {
131 elem: self.elem,
132 ident: self.ident,
133 _c: self._c,
134 _s: self._s,
135 }
136 }
137}
138
139impl<C: CubeType, S: MatrixScope> ExpandTypeClone for MatrixExpand<C, S> {
140 fn clone_unchecked(&self) -> Self {
141 self.clone()
142 }
143}
144
145impl<A: CubeType, B: CubeType, CD: CubeType> ExpandTypeClone for MmaDefinitionExpand<A, B, CD> {
146 fn clone_unchecked(&self) -> Self {
147 *self
148 }
149}
150
151impl<C: CubeType, S: MatrixScope> AsRefExpand for MatrixExpand<C, S> {
152 fn __expand_ref_method(&self, _scope: &Scope) -> &Self {
153 self
154 }
155}
156impl<C: CubeType, S: MatrixScope> AsMutExpand for MatrixExpand<C, S> {
157 fn __expand_ref_mut_method(&mut self, _scope: &Scope) -> &mut Self {
158 self
159 }
160}
161
162impl<A: CubeType, B: CubeType, CD: CubeType> AsRefExpand for MmaDefinitionExpand<A, B, CD> {
163 fn __expand_ref_method(&self, _scope: &Scope) -> &Self {
164 self
165 }
166}
167impl<A: CubeType, B: CubeType, CD: CubeType> AsMutExpand for MmaDefinitionExpand<A, B, CD> {
168 fn __expand_ref_mut_method(&mut self, _scope: &Scope) -> &mut Self {
169 self
170 }
171}
172
173impl<A: CubeType, B: CubeType, CD: CubeType> Copy for MmaDefinitionExpand<A, B, CD> {}
174impl<A: CubeType, B: CubeType, CD: CubeType> Clone for MmaDefinitionExpand<A, B, CD> {
175 fn clone(&self) -> Self {
176 *self
177 }
178}
179
180impl<C: CubeType, S: MatrixScope> CubeType for Matrix<C, S> {
181 type ExpandType = MatrixExpand<C, S>;
182}
183
184impl<A: CubeType, B: CubeType, CD: CubeType> CubeType for MmaDefinition<A, B, CD> {
185 type ExpandType = MmaDefinitionExpand<A, B, CD>;
186}
187
188impl<C: CubeType, S: MatrixScope> IntoExpand for MatrixExpand<C, S> {
189 type Expand = Self;
190
191 fn into_expand(self, _: &Scope) -> Self::Expand {
192 self
193 }
194}
195
196impl<C: CubeType, S: MatrixScope> IntoMut for MatrixExpand<C, S> {
197 fn into_mut(self, _scope: &Scope) -> Self {
198 self
199 }
200}
201
202impl<C: CubeType, S: MatrixScope> CubeDebug for MatrixExpand<C, S> {
203 fn set_debug_name(&self, scope: &Scope, name: &'static str) {
204 let op = self.elem.defining_op().unwrap();
205 set_operation_result_name(scope.ctx(), op, 0, Some(ident(name)));
206 }
207}
208
209impl<A: CubeType, B: CubeType, CD: CubeType> IntoExpand for MmaDefinitionExpand<A, B, CD> {
210 type Expand = Self;
211
212 fn into_expand(self, _: &Scope) -> Self::Expand {
213 self
214 }
215}
216
217impl<A: CubeType, B: CubeType, CD: CubeType> IntoMut for MmaDefinitionExpand<A, B, CD> {
218 fn into_mut(self, _scope: &Scope) -> Self {
219 self
220 }
221}
222
223impl<A: CubeType, B: CubeType, CD: CubeType> CubeDebug for MmaDefinitionExpand<A, B, CD> {}
224
225#[cube]
226impl<C: CubePrimitive, S: MatrixScope> Matrix<C, S> {
227 pub unsafe fn uninitialized(
245 #[comptime] ident: MatrixIdent,
246 #[comptime] m: usize,
247 #[comptime] n: usize,
248 #[comptime] k: usize,
249 layout: MatrixLayout,
250 ) -> Self {
251 intrinsic!(|scope| {
252 let props = scope.state().device_properties.clone();
258 if let Some(props) = props.filter(|_| S::SCOPE == types::MatrixScope::Plane) {
259 let elem_ty = C::Scalar::elem_type(scope);
260 let cmma = &props.features.matmul.cmma;
261 let supported = cmma.iter().any(|cfg| match ident {
262 MatrixIdent::A => {
263 cfg.a_type == elem_ty && cfg.m as usize == m && cfg.k as usize == k
264 }
265 MatrixIdent::B => {
266 cfg.b_type == elem_ty && cfg.k as usize == k && cfg.n as usize == n
267 }
268 MatrixIdent::Accumulator => {
269 cfg.cd_type == elem_ty && cfg.m as usize == m && cfg.n as usize == n
270 }
271 });
272 if !supported {
273 let (rows, cols) = match ident {
274 MatrixIdent::A => (m, k),
275 MatrixIdent::B => (k, n),
276 MatrixIdent::Accumulator => (m, n),
277 };
278 scope.push_error(format!(
279 "the device doesn't support a {rows}x{cols} {ident:?} cooperative \
280 matrix fragment of {elem_ty:?}; supported configurations: {cmma:?}"
281 ));
282 }
283 }
284
285 let elem = C::Scalar::__expand_as_type(scope);
286 let matrix_ty =
287 MatrixType::get(scope.ctx(), ident, (m, n, k).into(), elem, layout, S::SCOPE);
288 let null = ZeroAttr::new(matrix_ty);
289 let elem = scope.create_local_mut(matrix_ty, Some(null.into()));
290 MatrixExpand {
291 elem,
292 ident,
293 _c: PhantomData,
294 _s: PhantomData,
295 }
296 })
297 }
298
299 pub fn from_value(
313 #[comptime] ident: MatrixIdent,
314 #[comptime] m: usize,
315 #[comptime] n: usize,
316 #[comptime] k: usize,
317 layout: MatrixLayout,
318 value: C,
319 ) -> Self
320 where
321 C: Scalar,
322 {
323 let mut mat = unsafe { Self::uninitialized(ident, m, n, k, layout) };
324 fill(&mut mat, value);
325 mat
326 }
327
328 pub fn from_slice(
342 #[comptime] ident: MatrixIdent,
343 #[comptime] m: usize,
344 #[comptime] n: usize,
345 #[comptime] k: usize,
346 layout: MatrixLayout,
347 value: &[C],
348 stride: u32,
349 ) -> Self {
350 let mut mat = unsafe { Self::uninitialized(ident, m, n, k, layout) };
351
352 if comptime![ident == MatrixIdent::Accumulator] {
353 load_with_layout(&mut mat, value, stride, layout);
354 } else {
355 load(&mut mat, value, stride);
356 }
357 mat
358 }
359
360 pub fn from_tensor(
374 #[comptime] ident: MatrixIdent,
375 #[comptime] m: usize,
376 #[comptime] n: usize,
377 #[comptime] k: usize,
378 value: &TensorView<C>,
379 ) -> Self {
380 let mut mat = unsafe { Self::uninitialized(ident, m, n, k, MatrixLayout::Undefined) };
381 load_tensor(&mut mat, value);
382 mat
383 }
384}
385
386#[cube]
387impl<A: Scalar, B: Scalar, CD: Scalar> MmaDefinition<A, B, CD> {
388 pub fn new(#[comptime] m: usize, #[comptime] n: usize, #[comptime] k: usize) -> Self {
404 intrinsic!(|scope| {
405 let a_type = A::Scalar::__expand_as_type(scope);
406 let b_type = B::Scalar::__expand_as_type(scope);
407 let cd_type = CD::Scalar::__expand_as_type(scope);
408
409 MmaDefinitionExpand {
410 shape: (m, n, k).into(),
411 a_type,
412 b_type,
413 cd_type,
414 scales_factor: None,
415 scales_type: None,
416 _a: PhantomData,
417 _b: PhantomData,
418 _cd: PhantomData,
419 }
420 })
421 }
422
423 pub fn new_scaled<S: CubePrimitive>(
439 #[comptime] m: usize,
440 #[comptime] n: usize,
441 #[comptime] k: usize,
442 #[comptime] scale_factor: usize,
443 ) -> Self {
444 intrinsic!(|scope| {
445 let a_type = A::Scalar::__expand_as_type(scope);
446 let b_type = B::Scalar::__expand_as_type(scope);
447 let cd_type = CD::Scalar::__expand_as_type(scope);
448 let s_type = S::Scalar::__expand_as_type(scope);
449
450 MmaDefinitionExpand {
451 shape: (m, n, k).into(),
452 a_type,
453 b_type,
454 cd_type,
455 scales_factor: Some(scale_factor),
456 scales_type: Some(s_type),
457 _a: PhantomData,
458 _b: PhantomData,
459 _cd: PhantomData,
460 }
461 })
462 }
463
464 #[allow(unused)]
466 pub fn num_elems(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
467 intrinsic!(|scope| {
468 match ident {
469 MatrixIdent::A => {
470 (self.shape.m * self.shape.k) / self.a_type.packing_factor(scope.ctx())
471 }
472 MatrixIdent::B => {
473 (self.shape.k * self.shape.n) / self.b_type.packing_factor(scope.ctx())
474 }
475 MatrixIdent::Accumulator => {
476 (self.shape.m * self.shape.n) / self.cd_type.packing_factor(scope.ctx())
477 }
478 }
479 })
480 }
481
482 #[allow(unused)]
489 pub fn elems_per_lane(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
490 intrinsic!(|scope| {
491 let elems = self.__expand_num_elems_method(scope, ident);
492 let plane_dim = scope.state().target_properties.mma.const_plane_size as usize;
493 let duplication = match ident {
494 MatrixIdent::A => scope.state().target_properties.mma.register_duplication_a,
495 MatrixIdent::B => scope.state().target_properties.mma.register_duplication_b,
496 MatrixIdent::Accumulator => {
497 scope.state().target_properties.mma.register_duplication_acc
498 }
499 };
500 (elems * duplication) / plane_dim
501 })
502 }
503
504 #[allow(unused)]
510 pub fn vectors_per_lane(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(usize) {
511 intrinsic!(|scope| {
512 let elems = self.clone().__expand_elems_per_lane_method(scope, ident);
513 let vector_size = self.__expand_vector_size_method(scope, ident);
514 elems / vector_size
515 })
516 }
517
518 #[allow(unused)]
520 pub fn vector_layout(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(MatrixLayout) {
521 intrinsic!(|scope| {
522 match ident {
523 MatrixIdent::A => scope.state().target_properties.mma.register_layout_a,
524 MatrixIdent::B => scope.state().target_properties.mma.register_layout_b,
525 MatrixIdent::Accumulator => scope.state().target_properties.mma.register_layout_acc,
526 }
527 })
528 }
529
530 pub fn vector_size(&self, #[comptime] ident: MatrixIdent) -> comptime_type!(VectorSize) {
533 intrinsic!(|scope| {
534 let storage = match ident {
535 MatrixIdent::A => self.a_type,
536 MatrixIdent::B => self.b_type,
537 MatrixIdent::Accumulator => self.cd_type,
538 };
539 let matrix_ty = MatrixType::get(
540 scope.ctx(),
541 ident,
542 self.shape,
543 storage,
544 MatrixLayout::ColMajor,
545 types::MatrixScope::Plane,
546 );
547 scope
548 .state()
549 .target_properties
550 .mma
551 .contiguous_elements
552 .apply(scope.ctx(), ident, matrix_ty)
553 })
554 }
555
556 pub fn position_of_nth(
564 &self,
565 lane_id: u32,
566 elem_idx: u32,
567 #[comptime] ident: MatrixIdent,
568 ) -> (u32, u32) {
569 intrinsic!(|scope| {
570 let lane_id = lane_id.read_value(scope);
571 let elem_idx = elem_idx.read_value(scope);
572
573 let ty = match ident {
574 MatrixIdent::A => self.a_type,
575 MatrixIdent::B => self.b_type,
576 MatrixIdent::Accumulator => self.cd_type,
577 };
578 let layout = match ident {
579 MatrixIdent::A => scope.state().target_properties.mma.register_layout_a,
580 MatrixIdent::B => scope.state().target_properties.mma.register_layout_b,
581 MatrixIdent::Accumulator => scope.state().target_properties.mma.register_layout_acc,
582 };
583 let matrix_ty = MatrixType::get(
584 scope.ctx(),
585 ident,
586 self.shape,
587 ty,
588 layout,
589 types::MatrixScope::Plane,
590 );
591
592 let row_idx = RowIndexOp::new(scope.ctx_mut(), lane_id, elem_idx, matrix_ty);
593 let col_idx = ColIndexOp::new(scope.ctx_mut(), lane_id, elem_idx, matrix_ty);
594
595 let row = scope.register_with_result(&row_idx);
596 let col = scope.register_with_result(&col_idx);
597
598 (row.into(), col.into())
599 })
600 }
601
602 pub fn scales_index(&self, lane_id: u32, #[comptime] ident: MatrixIdent) -> u32 {
605 let quad_id = lane_id / 4;
607 let t_id = lane_id % 4;
608 match ident {
609 MatrixIdent::A => quad_id + (t_id % 2) * 8,
610 MatrixIdent::B => quad_id,
611 MatrixIdent::Accumulator => panic!("Accumulator doesn't have scales"),
612 }
613 }
614
615 pub fn scales_count(&self) -> comptime_type!(usize) {
617 intrinsic!(|_| {
620 self.scales_factor
621 .expect("Can't retrieve scales count for matrix with no scales")
622 })
623 }
624
625 pub fn scales_vector_size(&self) -> comptime_type!(VectorSize) {
627 intrinsic!(|scope| {
628 let elem = self
629 .scales_type
630 .expect("Can't retrieve scales vector size for matrix with no scales");
631 scope.state().target_properties.mma.register_size_bits / (elem.size_bits(scope.ctx()))
632 })
633 }
634
635 pub fn load_matrix<E: CubePrimitive, NO: Size>(
646 &self,
647 row: &[E],
648 #[comptime] ident: MatrixIdent,
649 #[comptime] num_matrices: usize,
650 #[comptime] transpose: bool,
651 ) -> Array<Vector<E::Scalar, NO>> {
652 intrinsic!(|scope| {
653 let ptr = unsafe { *row.__expand_as_ptr_method(scope) }.value(scope);
654 let slice_vector_size = ptr.vector_size(scope.ctx());
655 let out = Array::__expand_new(scope, num_matrices);
656 let out_ptr = out.__extract_list(scope);
657 scope.register(&LdMatrixOp::new(
658 scope.ctx_mut(),
659 ptr,
660 out_ptr,
661 num_matrices,
662 transpose,
663 ));
664 out
665 })
666 }
667
668 pub fn load_matrix_inplace<E: Scalar, N: Size>(
669 &self,
670 row: &[E],
671 fragment: &mut Array<Vector<E, N>>,
672 #[comptime] ident: MatrixIdent,
673 #[comptime] num_matrices: usize,
674 #[comptime] transpose: bool,
675 ) {
676 intrinsic!(|scope| {
677 let vector_size = self.__expand_vector_size_method(scope, ident);
678 let ptr = unsafe { *row.__expand_as_ptr_method(scope) }.value(scope);
679 let slice_vector_size = ptr.vector_size(scope.ctx());
680 let fragment = fragment.__extract_list(scope);
681 scope.register(&LdMatrixOp::new(
682 scope.ctx_mut(),
683 ptr,
684 fragment,
685 num_matrices,
686 transpose,
687 ));
688 })
689 }
690
691 pub fn store_matrix<E: CubePrimitive, N: Size>(
702 &self,
703 row: &mut [E],
704 registers: &Array<Vector<E::Scalar, N>>,
705 #[comptime] ident: MatrixIdent,
706 #[comptime] num_matrices: usize,
707 #[comptime] transpose: bool,
708 ) {
709 intrinsic!(|scope| {
710 let vector_size = self.__expand_vector_size_method(scope, ident);
711
712 let registers = registers.read_value(scope);
713 let destination = unsafe { *row.__expand_as_ptr_method(scope) }.value(scope);
714
715 scope.register(&StMatrixOp::new(
716 scope.ctx_mut(),
717 registers,
718 destination,
719 num_matrices,
720 transpose,
721 ));
722 })
723 }
724
725 #[allow(unused)]
728 pub fn execute<NA: Size, NB: Size, NC: Size>(
729 &self,
730 registers_a: &Array<Vector<A, NA>>,
731 registers_b: &Array<Vector<B, NB>>,
732 registers_c: &Array<Vector<CD, NC>>,
733 ) -> Array<Vector<CD, NC>> {
734 intrinsic!(|scope| {
735 let acc_elems = self
736 .clone()
737 .__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
738 let acc_vector_size = self
739 .clone()
740 .__expand_vector_size_method(scope, MatrixIdent::Accumulator);
741 let num_registers = acc_elems / acc_vector_size;
742
743 let registers_d_arr = Array::__expand_new(scope, num_registers);
744
745 let registers_a = registers_a.read_value(scope);
746 let registers_b = registers_b.read_value(scope);
747 let registers_c = registers_c.read_value(scope);
748 let registers_d = registers_d_arr.__extract_list(scope);
749
750 scope.register(&MmaManualOp::new(
751 scope.ctx_mut(),
752 registers_a,
753 registers_b,
754 registers_c,
755 registers_d,
756 self.shape,
757 ));
758
759 registers_d_arr
760 })
761 }
762
763 #[allow(unused)]
764 pub fn execute_inplace<NA: Size, NB: Size, NC: Size>(
765 &self,
766 registers_a: &Array<Vector<A, NA>>,
767 registers_b: &Array<Vector<B, NB>>,
768 registers_c: &mut Array<Vector<CD, NC>>,
769 ) {
770 intrinsic!(|scope| {
771 let acc_elems = self
772 .clone()
773 .__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
774 let acc_vector_size = self
775 .clone()
776 .__expand_vector_size_method(scope, MatrixIdent::Accumulator);
777 let num_registers = acc_elems / acc_vector_size;
778
779 let registers_d = registers_c.__extract_list(scope);
780 let registers_a = registers_a.read_value(scope);
781 let registers_b = registers_b.read_value(scope);
782 let registers_c = registers_c.read_value(scope);
783
784 scope.register(&MmaManualOp::new(
785 scope.ctx_mut(),
786 registers_a,
787 registers_b,
788 registers_c,
789 registers_d,
790 self.shape,
791 ));
792 })
793 }
794
795 #[allow(unused)]
798 pub fn execute_scaled<S: Scalar, NA: Size, NB: Size, NC: Size, NS: Size>(
799 &self,
800 registers_a: &Array<Vector<A, NA>>,
801 registers_b: &Array<Vector<B, NB>>,
802 registers_c: &Array<Vector<CD, NC>>,
803 scales_a: Vector<S, NS>,
804 scales_b: Vector<S, NS>,
805 ) -> Array<Vector<CD, NC>> {
806 intrinsic!(|scope| {
807 let acc_elems = self
808 .clone()
809 .__expand_elems_per_lane_method(scope, MatrixIdent::Accumulator);
810 let acc_vector_size = self
811 .clone()
812 .__expand_vector_size_method(scope, MatrixIdent::Accumulator);
813 let num_registers = acc_elems / acc_vector_size;
814
815 let registers_d_arr = Array::__expand_new(scope, num_registers);
816
817 let registers_a = registers_a.read_value(scope);
818 let registers_b = registers_b.read_value(scope);
819 let registers_c = registers_c.read_value(scope);
820 let registers_d = registers_d_arr.__extract_list(scope);
821 let scales_a = scales_a.read_value(scope);
822 let scales_b = scales_b.read_value(scope);
823
824 scope.register(&MmaManualScaledOp::new(
825 scope.ctx_mut(),
826 registers_a,
827 registers_b,
828 registers_c,
829 registers_d,
830 scales_a,
831 scales_b,
832 self.scales_factor.expect("Should have scales"),
833 self.shape,
834 ));
835
836 registers_d_arr
837 })
838 }
839}
840
841#[allow(unused_variables)]
843pub fn fill<C: Scalar, S: MatrixScope>(mat: &mut Matrix<C, S>, value: C) {
844 unexpanded!()
845}
846
847pub mod fill {
849 use cubecl_ir::dialect::matrix::FillOp;
850
851 use super::*;
852
853 pub fn expand<C: Scalar, S: MatrixScope>(
855 scope: &Scope,
856 mat: &mut MatrixExpand<C, S>,
857 value: NativeExpand<C>,
858 ) {
859 let value = value.read_value(scope);
860 scope.register(&FillOp::new(scope.ctx_mut(), mat.elem, value));
861 }
862}
863
864#[allow(unused_variables)]
866pub fn load<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
867 mat: &mut Matrix<C, S>,
868 value: &[V],
869 stride: u32,
870) {
871 unexpanded!()
872}
873
874pub mod load {
876 use cubecl_ir::dialect::matrix::LoadOp;
877
878 use super::*;
879
880 pub fn expand<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
882 scope: &Scope,
883 mat: &mut MatrixExpand<C, S>,
884 value: &SliceExpand<V>,
885 stride: NativeExpand<u32>,
886 ) {
887 let ctx = scope.ctx_mut();
888 let stride = stride.read_value(scope);
889 assert_ne!(
890 mat.ident,
891 MatrixIdent::Accumulator,
892 "Loading accumulator requires explicit layout. Use `load_with_layout` instead."
893 );
894
895 let ptr = unsafe { *value.__expand_as_ptr_method(scope) }.value(scope);
896
897 let layout = {
898 let ty = mat.elem.unwrap_ptr(ctx).deref(ctx);
899 ty.downcast_ref::<MatrixType>().unwrap().layout
900 };
901
902 scope.register(&LoadOp::new(ctx, mat.elem, ptr, stride, layout));
903 }
904}
905
906#[allow(unused_variables)]
908pub fn load_tensor<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
909 mat: &mut Matrix<C, S>,
910 value: &TensorView<V>,
911) {
912 unexpanded!()
913}
914
915pub mod load_tensor {
917 use cubecl_ir::dialect::spirv::LoadTensorOp;
918
919 use super::*;
920
921 pub fn expand<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
923 scope: &Scope,
924 mat: &mut MatrixExpand<C, S>,
925 value: &TensorViewExpand<V>,
926 ) {
927 assert_ne!(
928 mat.ident,
929 MatrixIdent::Accumulator,
930 "Loading accumulator requires explicit layout. Use `load_with_layout` instead."
931 );
932 let layout = value.layout.read_value(scope);
933 let buffer = value.buffer.__extract_list(scope);
934 let view = match &value.view {
935 ComptimeOptionExpand::None => None,
936 ComptimeOptionExpand::Some(view) => Some(view.read_value(scope)),
937 };
938 let out_ty = mat.elem.unwrap_ptr(scope.ctx());
939
940 let mat_out = scope.register_with_result(&LoadTensorOp::new(
941 scope.ctx_mut(),
942 out_ty,
943 buffer,
944 layout,
945 view,
946 ));
947 assign::expand_element(scope, mat_out.into(), mat.elem.into());
948 }
949}
950
951#[allow(unused_variables)]
954pub fn load_with_layout<C: CubePrimitive, V: CubePrimitive, S: MatrixScope>(
955 mat: &mut Matrix<C, S>,
956 value: &[V],
957 stride: u32,
958 layout: MatrixLayout,
959) {
960 unexpanded!()
961}
962
963pub mod load_with_layout {
965 use cubecl_ir::dialect::matrix::LoadOp;
966
967 use super::*;
968
969 pub fn expand<C: CubeType, V: CubePrimitive, S: MatrixScope>(
971 scope: &Scope,
972 mat: &mut MatrixExpand<C, S>,
973 value: &SliceExpand<V>,
974 stride: NativeExpand<u32>,
975 layout: MatrixLayout,
976 ) {
977 let stride: ExpandValue = stride.into();
978 let ptr = unsafe { *value.__expand_as_ptr_method(scope) }.value(scope);
979 let stride = stride.read_value(scope);
980
981 let load = LoadOp::new(scope.ctx_mut(), mat.elem, ptr, stride, layout);
982
983 scope.register(&load);
984 }
985}
986
987#[allow(unused_variables)]
989pub fn store<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
990 output: &mut [O],
991 mat: &Matrix<C, S>,
992 stride: u32,
993 layout: MatrixLayout,
994) {
995 unexpanded!()
996}
997
998pub mod store {
1000 use cubecl_ir::dialect::matrix::StoreOp;
1001
1002 use super::*;
1003
1004 pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1006 scope: &Scope,
1007 output: &mut SliceExpand<O>,
1008 mat: &MatrixExpand<C, S>,
1009 stride: NativeExpand<u32>,
1010 layout: MatrixLayout,
1011 ) {
1012 let stride = stride.read_value(scope);
1013
1014 let destination = unsafe { *output.__expand_as_ptr_method(scope) }.value(scope);
1015
1016 scope.register(&StoreOp::new(
1017 scope.ctx_mut(),
1018 mat.elem,
1019 destination,
1020 stride,
1021 layout,
1022 ));
1023 }
1024}
1025
1026#[allow(unused_variables)]
1028pub fn store_tensor<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1029 output: &mut TensorView<O>,
1030 mat: &Matrix<C, S>,
1031) {
1032 unexpanded!()
1033}
1034
1035pub mod store_tensor {
1037 use cubecl_ir::{dialect::spirv::StoreTensorOp, read_value};
1038
1039 use super::*;
1040
1041 pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1043 scope: &Scope,
1044 output: &mut TensorViewExpand<O>,
1045 mat: &MatrixExpand<C, S>,
1046 ) {
1047 let buffer = output.buffer.__extract_list(scope);
1048 let layout = output.layout.read_value(scope);
1049 let view = match &output.view {
1050 ComptimeOptionExpand::None => None,
1051 ComptimeOptionExpand::Some(view) => Some(view.read_value(scope)),
1052 };
1053
1054 scope.register(&StoreTensorOp::new(
1055 scope.ctx_mut(),
1056 buffer,
1057 read_value(scope, mat.elem),
1058 layout,
1059 view,
1060 ));
1061 }
1062}
1063
1064#[allow(unused_variables)]
1066pub fn execute<
1067 A: CubePrimitive,
1068 B: CubePrimitive,
1069 C: CubePrimitive,
1070 D: CubePrimitive,
1071 S: MatrixScope,
1072>(
1073 mat_a: &Matrix<A, S>,
1074 mat_b: &Matrix<B, S>,
1075 mat_c: &Matrix<C, S>,
1076 mat_d: &Matrix<D, S>,
1077) {
1078 unexpanded!()
1079}
1080
1081pub mod execute {
1083 use cubecl_ir::dialect::matrix::MultiplyAccumulateOp;
1084
1085 use super::*;
1086
1087 pub fn expand<
1089 A: CubePrimitive,
1090 B: CubePrimitive,
1091 C: CubePrimitive,
1092 D: CubePrimitive,
1093 S: MatrixScope,
1094 >(
1095 scope: &Scope,
1096 mat_a: &MatrixExpand<A, S>,
1097 mat_b: &MatrixExpand<B, S>,
1098 mat_c: &MatrixExpand<C, S>,
1099 mat_d: &MatrixExpand<D, S>,
1100 ) {
1101 scope.register(&MultiplyAccumulateOp::new(
1102 scope.ctx_mut(),
1103 mat_a.elem,
1104 mat_b.elem,
1105 mat_c.elem,
1106 mat_d.elem,
1107 ));
1108 }
1109}
1110
1111#[allow(unused_variables)]
1113pub fn cast<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1114 input: &Matrix<C, S>,
1115) -> Matrix<O, S> {
1116 unexpanded!()
1117}
1118
1119pub mod cast {
1121 use cubecl_ir::dialect::matrix::CastOp;
1122
1123 use super::*;
1124
1125 pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1127 scope: &Scope,
1128 input: &MatrixExpand<C, S>,
1129 ) -> MatrixExpand<O, S> {
1130 let ident = input.ident;
1131
1132 if core::any::TypeId::of::<C>() == core::any::TypeId::of::<O>() {
1133 return MatrixExpand {
1134 elem: input.elem,
1135 ident,
1136 _c: PhantomData,
1137 _s: PhantomData,
1138 };
1139 }
1140 let input = input.elem;
1141 let input_shape = {
1142 let ctx = scope.ctx();
1143 let input_mat = input.unwrap_ptr(ctx).deref(ctx);
1144 input_mat.downcast_ref::<MatrixType>().unwrap().shape
1145 };
1146
1147 let output = Matrix::<O, S>::__expand_uninitialized(
1148 scope,
1149 ident,
1150 input_shape.m,
1151 input_shape.n,
1152 input_shape.k,
1153 MatrixLayout::Undefined,
1154 );
1155
1156 scope.register(&CastOp::new(scope.ctx_mut(), input, output.elem));
1157
1158 output
1159 }
1160}
1161
1162#[allow(unused_variables)]
1166pub fn cast_with_ident<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1167 input: &Matrix<C, S>,
1168 ident: MatrixIdent,
1169) -> Matrix<O, S> {
1170 unexpanded!()
1171}
1172
1173pub mod cast_with_ident {
1175 use cubecl_ir::dialect::matrix::CastOp;
1176
1177 use super::*;
1178
1179 pub fn expand<C: CubePrimitive, O: CubePrimitive, S: MatrixScope>(
1181 scope: &Scope,
1182 input: MatrixExpand<C, S>,
1183 ident: MatrixIdent,
1184 ) -> MatrixExpand<O, S> {
1185 if core::any::TypeId::of::<C>() == core::any::TypeId::of::<O>() && ident == input.ident {
1186 return MatrixExpand {
1187 elem: input.elem,
1188 ident,
1189 _c: PhantomData,
1190 _s: PhantomData,
1191 };
1192 }
1193 let input = input.elem;
1194 let input_shape = {
1195 let ctx = scope.ctx();
1196 let input_mat = input.unwrap_ptr(ctx).deref(ctx);
1197 input_mat.downcast_ref::<MatrixType>().unwrap().shape
1198 };
1199
1200 let output = Matrix::<O, S>::__expand_uninitialized(
1201 scope,
1202 ident,
1203 input_shape.m,
1204 input_shape.n,
1205 input_shape.k,
1206 MatrixLayout::Undefined,
1207 );
1208
1209 scope.register(&CastOp::new(scope.ctx_mut(), input, output.elem));
1210
1211 output
1212 }
1213}
1214
1215impl CubeType for MatrixLayout {
1216 type ExpandType = Self;
1217}
1218
1219impl IntoExpand for MatrixLayout {
1220 type Expand = Self;
1221
1222 fn into_expand(self, _scope: &Scope) -> Self::Expand {
1223 self
1224 }
1225}
1226
1227impl ExpandTypeClone for MatrixLayout {
1228 fn clone_unchecked(&self) -> Self {
1229 *self
1230 }
1231}
1232
1233impl IntoMut for MatrixLayout {
1234 fn into_mut(self, _scope: &Scope) -> Self {
1235 self
1236 }
1237}
1238
1239impl CubeDebug for MatrixLayout {}
1240
1241impl AsRefExpand for MatrixLayout {
1242 fn __expand_ref_method(&self, _: &Scope) -> &Self {
1243 self
1244 }
1245}
1246impl AsMutExpand for MatrixLayout {
1247 fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
1248 self
1249 }
1250}
1251
1252#[allow(unused_variables)]
1256pub fn execute_elementwise_op<A: CubePrimitive, S: MatrixScope>(
1257 matrix_in: &Matrix<A, S>,
1258 matrix_out: &Matrix<A, S>,
1259 op: impl Fn(u32, u32, A::Scalar) -> A::Scalar,
1260) {
1261 unexpanded!()
1262}
1263
1264pub mod execute_elementwise_op {
1266 use alloc::vec;
1267 use cubecl_ir::{
1268 OpInserter,
1269 convert::lift_closure,
1270 dialect::{branch::ReturnOp, matrix::ElementwiseOp},
1271 pliron::builtin::{ops::FuncOp, types::FunctionType},
1272 };
1273
1274 use super::*;
1275
1276 pub fn expand<A: CubePrimitive, S: MatrixScope>(
1278 scope: &Scope,
1279 matrix_in: &MatrixExpand<A, S>,
1280 matrix_out: &MatrixExpand<A, S>,
1281 mut op: impl FnMut(
1282 &Scope,
1283 NativeExpand<u32>,
1284 NativeExpand<u32>,
1285 NativeExpand<A::Scalar>,
1286 ) -> NativeExpand<A::Scalar>,
1287 ) {
1288 let u32 = u32::__expand_as_type(scope);
1289 let elem = A::Scalar::__expand_as_type(scope);
1290
1291 let func_ty = FunctionType::get(scope.ctx(), vec![u32, u32, elem], vec![elem]);
1292 let func_name = scope.func_ident(Some("execute_elemwise"));
1293 let func = FuncOp::new(scope.ctx_mut(), func_name.clone(), func_ty);
1294 let func_body = func.get_entry_block(scope.ctx());
1295
1296 let row = func_body.deref(scope.ctx()).get_argument(0);
1297 let col = func_body.deref(scope.ctx()).get_argument(1);
1298 let elem = func_body.deref(scope.ctx()).get_argument(2);
1299
1300 let mut closure_scope = scope.func_child(OpInserter::new_at_block_end(func_body));
1301 let return_value = op(&mut closure_scope, row.into(), col.into(), elem.into()).value(scope);
1302 closure_scope.register(&ReturnOp::new_with_value(scope.ctx_mut(), return_value));
1303
1304 let captures = lift_closure(scope.ctx(), &func);
1305
1306 scope.register_func(func);
1307 scope.register(&ElementwiseOp::new(
1308 scope.ctx_mut(),
1309 matrix_in.elem,
1310 matrix_out.elem,
1311 func_name,
1312 captures,
1313 ));
1314 }
1315}