1use cubecl::{intrinsic, prelude::*, std::Swizzle};
8
9use crate::MatrixLayout;
10use crate::stage::{StageMemoryConfig, as_swizzle_object};
11use crate::tile::variants::instruction::{
12 cmma::cmma_write_to_shared,
13 interleaved::interleaved_write_to_shared,
14 mma::{MmaFragment, MmaFragmentExpand, mma_write_to_shared},
15 plane_vec::planevec_write_to_shared,
16 register::register_write_to_shared,
17};
18use crate::tile::{Tile, TileKind, TileKindExpand, TileScope};
19
20#[derive(CubeType, Clone)]
21#[expand(derive(Clone))]
22pub struct StridedTile<ES: Numeric, N: Size> {
25 pub container: Box<[Vector<ES, N>]>,
27 pub start: u32,
29 pub end: u32,
31 pub stride: u32,
33 pub swizzle: Swizzle,
35 #[cube(comptime)]
36 pub layout: MatrixLayout,
38}
39
40#[cube]
41impl<ES: Numeric, N: Size> StridedTile<ES, N> {
42 pub fn new_contiguous(
46 container: &[Vector<ES, N>],
47 start: u32,
48 #[comptime] config: StageMemoryConfig,
49 ) -> StridedTile<ES, N> {
50 let len = config.elements_per_tile() / config.vector_size;
51 let layout = config.matrix_layout;
52 let stride = match layout {
53 MatrixLayout::RowMajor => config.elements_per_tile_along_col,
54 MatrixLayout::ColMajor => config.elements_per_tile_along_row,
55 };
56
57 let stride = stride / config.vector_size;
58
59 StridedTile::<ES, N> {
60 container: unsafe { container.as_boxed_unchecked() },
61 start,
62 end: start + len,
63 stride,
64 swizzle: as_swizzle_object(config.swizzle),
65 layout,
66 }
67 }
68
69 pub fn new_strided(
73 container: &[Vector<ES, N>],
74 start: u32,
75 end: u32,
76 stride: u32,
77 swizzle: Swizzle,
78 #[comptime] layout: MatrixLayout,
79 ) -> StridedTile<ES, N> {
80 StridedTile::<ES, N> {
81 container: unsafe { container.as_boxed_unchecked() },
82 start,
83 end,
84 stride,
85 swizzle,
86 layout,
87 }
88 }
89}
90
91#[cube]
92impl<ES: Numeric, N: Size> StridedTile<ES, N> {
93 pub fn unvectorized_stride(&self) -> u32 {
94 let stage_vector_size = self.container.vector_size();
95 self.stride * stage_vector_size as u32
96 }
97}
98
99#[cube]
100impl<ES: Numeric, N: Size> StridedTile<ES, N> {
101 pub fn as_slice(&self) -> &[Vector<ES, N>] {
104 &self.container[self.start as usize..self.end as usize]
105 }
106
107 pub fn as_slice_mut(&mut self) -> &mut [Vector<ES, N>] {
110 &mut self.container[self.start as usize..self.end as usize]
111 }
112}
113
114#[cube]
115impl<ES: Numeric, N: Size> StridedTile<ES, N> {
116 pub fn get_vector(&self, coor_strided: u32, coor_contiguous: u32) -> Vector<ES, N> {
118 let offset = coor_strided * self.stride + coor_contiguous;
119 let offset_abs = self.start + offset;
120 let type_size = Vector::<ES, N>::type_size();
121 let offset_swizzled = self.swizzle.apply(offset_abs, type_size);
122 self.container[offset_swizzled as usize]
123 }
124
125 pub fn stage_offset(&self, relative_offset: u32) -> u32 {
126 let offset = self.start + relative_offset;
127 let type_size = Vector::<ES, N>::type_size();
128 self.swizzle.apply(offset, type_size)
129 }
130
131 #[allow(unused_variables)]
132 pub fn with_vector_size<N2: Size>(&self) -> StridedTile<ES, N2> {
133 let vector_size = N2::value();
134 intrinsic!(|scope| {
135 let stage_vector_size = self.container.vector_size();
136
137 if vector_size == self.container.vector_size() {
138 return self.__expand_with_stage_vector_size_method(scope);
139 }
140
141 let current = stage_vector_size;
142 let mut out: StridedTileExpand<ES, N2> =
143 self.clone().__expand_with_stage_vector_size_method(scope);
144
145 if current < vector_size {
146 let ratio = ((vector_size / current) as u32).into_expand(scope);
147 let start = self.start.__expand_div_method(scope, ratio);
148 let end = self.end.__expand_div_method(scope, ratio);
149 let stride = self.stride.__expand_div_method(scope, ratio);
150 out.start = start;
151 out.end = end;
152 out.stride = stride;
153 } else {
154 let ratio = ((current / vector_size) as u32).into_expand(scope);
155 let start = self.start.__expand_mul_method(scope, ratio);
156 let end = self.end.__expand_mul_method(scope, ratio);
157 let stride = self.stride.__expand_mul_method(scope, ratio);
158 out.start = start;
159 out.end = end;
160 out.stride = stride;
161 }
162
163 out
164 })
165 }
166
167 #[allow(unused)]
172 unsafe fn with_stage_vector_size<N2: Size>(&self) -> StridedTile<ES, N2> {
173 StridedTile::<ES, N2> {
174 container: unsafe { self.container.with_vector_size::<N2>().as_boxed_unchecked() },
175 start: self.start,
176 end: self.end,
177 stride: self.stride,
178 swizzle: self.swizzle,
179 layout: self.layout,
180 }
181 }
182}
183
184#[derive(CubeType, Clone)]
187pub struct SharedTile<E: Numeric> {
188 pub(crate) container: Box<[E]>,
189 pub(crate) start: u32,
190 pub(crate) end: u32,
191 pub(crate) stride: u32,
192 pub(crate) swizzle: Swizzle,
193 #[cube(comptime)]
194 pub(crate) layout: MatrixLayout,
195}
196
197#[cube]
198impl<E: Numeric> SharedTile<E> {
199 pub fn wrap<V: Size>(tile: StridedTile<E, V>) -> SharedTile<E> {
201 let container = unsafe { tile.container.downcast_unchecked::<E>() };
202 SharedTile::<E> {
203 container: unsafe { container.as_boxed_unchecked() },
204 start: tile.start,
205 end: tile.end,
206 stride: tile.stride,
207 swizzle: tile.swizzle,
208 layout: tile.layout,
209 }
210 }
211
212 pub fn view<V: Size>(&self) -> StridedTile<E, V> {
215 let container = unsafe { self.container.downcast_unchecked::<Vector<E, V>>() };
216 StridedTile::<E, V> {
217 container: unsafe { container.as_boxed_unchecked() },
218 start: self.start,
219 end: self.end,
220 stride: self.stride,
221 swizzle: self.swizzle,
222 layout: self.layout,
223 }
224 }
225}
226
227#[cube]
228impl<E: Numeric> SharedTile<E> {
229 pub fn copy_from<SE: Numeric, SS: Size, L: Numeric, R: Numeric, Sc: TileScope>(
232 &mut self,
233 source: &Tile<SE, Sc>,
234 ) {
235 match &source.kind {
236 TileKind::Cmma(t) => cmma_write_to_shared::<E, SS, SE>(self, &t.matrix),
237 TileKind::Bounce(b) => cmma_write_to_shared::<E, SS, SE>(self, &b.cmma.matrix),
238 TileKind::Mma(t) => match &t.fragment {
239 MmaFragment::Acc(f) => {
240 mma_write_to_shared::<E, SS, SE, L, R>(self, f, t.tile_size, t.mma_io_config);
241 }
242 MmaFragment::Lhs(_) | MmaFragment::Rhs(_) => {
243 panic!("Mma write_to_shared only supported for Acc role")
244 }
245 },
246 TileKind::Register(t) => {
247 register_write_to_shared::<E, SS, SE>(self, &t.tile.data, t.tile_size);
248 }
249 TileKind::PlaneVec(t) => {
250 planevec_write_to_shared::<SE, E, SS>(
251 self,
252 &t.data,
253 t.tile_size,
254 t.reduce_vector_size,
255 );
256 }
257 TileKind::Interleaved(t) => {
258 interleaved_write_to_shared::<E, SS, SE>(self, &t.data, t.tile_size);
259 }
260 _ => panic!("SharedTile::copy_from: unsupported source variant"),
261 }
262 }
263}