1use alloc::vec;
2use core::marker::PhantomData;
3
4use crate::dsl::{prelude::*, unexpanded};
5use ruda_core::ir::{Type, VectorSize};
6use ruda::runtime::server::TensorMapMeta;
7use ruda_core::tensor::{Strides, metadata::Metadata, strides};
8use paste::paste;
9
10pub use ruda::runtime::tma::*;
11
12pub trait TensorMapKind: RudaType + Clone + Copy + Send + Sync + 'static {
13 type Args: Clone;
14
15 fn as_format(args: Self::Args) -> TensorMapFormat;
16}
17
18#[derive(RudaType, RudaLaunch, Clone, Copy)]
20pub struct Tiled {}
21#[derive(RudaType, RudaLaunch, Clone, Copy)]
27pub struct Im2col;
28#[derive(RudaType, RudaLaunch, Clone, Copy)]
30pub struct Im2colWide;
31
32impl TensorMapKind for Tiled {
33 type Args = TiledArgs;
34
35 fn as_format(args: Self::Args) -> TensorMapFormat {
36 TensorMapFormat::Tiled(args)
37 }
38}
39
40impl TensorMapKind for Im2col {
41 type Args = Im2colArgs;
42
43 fn as_format(args: Self::Args) -> TensorMapFormat {
44 TensorMapFormat::Im2col(args)
45 }
46}
47
48impl TensorMapKind for Im2colWide {
49 type Args = Im2colWideArgs;
50
51 fn as_format(args: Self::Args) -> TensorMapFormat {
52 TensorMapFormat::Im2colWide(args)
53 }
54}
55
56pub struct TensorMapArg<R: Runtime, K: TensorMapKind> {
62 pub tensor: TensorArg<R>,
63 pub metadata: TensorMapMeta,
64 pub _kind: PhantomData<K>,
65}
66
67impl<R: Runtime, K: TensorMapKind> TensorMapArg<R, K> {
68 pub fn new(args: K::Args, tensor: TensorArg<R>, ty: impl Into<Type>) -> Self {
69 let ty = ty.into();
70 let TensorArg::Handle { handle, .. } = &tensor else {
71 panic!("Can't use alias for TensorMap")
72 };
73 let rank = handle.shape.len();
74 Self {
75 metadata: TensorMapMeta {
76 format: K::as_format(args),
77 metadata: Metadata::new(handle.shape.clone(), handle.strides.clone()),
78 elem_stride: strides![1; rank],
79 interleave: TensorMapInterleave::None,
80 swizzle: TensorMapSwizzle::None,
81 prefetch: TensorMapPrefetch::None,
82 oob_fill: OobFill::Zero,
83 storage_ty: ty.storage_type(),
84 },
85 tensor,
86 _kind: PhantomData,
87 }
88 }
89
90 pub fn with_elem_stride(mut self, elem_stride: Strides) -> Self {
91 self.metadata.elem_stride = elem_stride;
92 self
93 }
94
95 pub fn with_interleave(mut self, interleave: TensorMapInterleave) -> Self {
96 self.metadata.interleave = interleave;
97 self
98 }
99
100 pub fn with_swizzle(mut self, swizzle: TensorMapSwizzle) -> Self {
101 self.metadata.swizzle = swizzle;
102 self
103 }
104
105 pub fn with_prefetch(mut self, prefetch: TensorMapPrefetch) -> Self {
106 self.metadata.prefetch = prefetch;
107 self
108 }
109
110 pub fn with_nan_fill(mut self) -> Self {
111 self.metadata.oob_fill = OobFill::NaN;
112 self
113 }
114}
115
116#[derive(Clone)]
122pub struct TensorMap<E: RudaPrimitive, K: TensorMapKind> {
123 _ty: PhantomData<E>,
124 _kind: PhantomData<K>,
125}
126
127impl<E: RudaPrimitive, K: TensorMapKind> Copy for TensorMap<E, K> {}
128
129impl<E: RudaPrimitive, K: TensorMapKind> TensorMap<E, K> {}
130
131impl<E: RudaPrimitive, K: TensorMapKind> IntoMut for NativeExpand<TensorMap<E, K>> {
132 fn into_mut(self, _scope: &mut Scope) -> Self {
133 self
134 }
135}
136
137impl<E: RudaPrimitive, K: TensorMapKind> RudaType for TensorMap<E, K> {
138 type ExpandType = NativeExpand<TensorMap<E, K>>;
139}
140
141impl<E: RudaPrimitive, K: TensorMapKind> RudaType for *const TensorMap<E, K> {
142 type ExpandType = NativeExpand<TensorMap<E, K>>;
143}
144
145impl<E: RudaPrimitive, K: TensorMapKind> RudaType for *mut TensorMap<E, K> {
146 type ExpandType = NativeExpand<TensorMap<E, K>>;
147}
148
149impl<E: RudaPrimitive, K: TensorMapKind> Vectorized for TensorMap<E, K> {}
150impl<E: RudaPrimitive, K: TensorMapKind> VectorizedExpand for NativeExpand<TensorMap<E, K>> {
151 fn vector_size(&self) -> VectorSize {
152 1
153 }
154}
155
156impl<E: RudaPrimitive, K: TensorMapKind> LaunchArg for TensorMap<E, K> {
157 type RuntimeArg<R: Runtime> = TensorMapArg<R, K>;
158 type CompilationArg = ();
159
160 fn register<R: Runtime>(
161 arg: Self::RuntimeArg<R>,
162 launcher: &mut KernelLauncher<R>,
163 ) -> Self::CompilationArg {
164 let ty = launcher.with_scope(|scope| E::as_type(scope));
165 launcher.register_tensor_map(arg, ty);
166 }
167
168 fn expand(
169 _arg: &Self::CompilationArg,
170 builder: &mut KernelBuilder,
171 ) -> NativeExpand<TensorMap<E, K>> {
172 let tensor = builder.input_tensor_map(E::as_type(&builder.scope));
173 tensor.into()
174 }
175 fn expand_output(
176 _arg: &Self::CompilationArg,
177 builder: &mut KernelBuilder,
178 ) -> NativeExpand<TensorMap<E, K>> {
179 let tensor = builder.output_tensor_map(E::as_type(&builder.scope));
180 tensor.into()
181 }
182}
183
184pub fn tma_group_commit() {
187 unexpanded!()
188}
189
190pub mod tma_group_commit {
191 use ruda_core::ir::TmaOps;
192
193 use super::*;
194
195 pub fn expand(scope: &mut Scope) {
196 scope.register(TmaOps::CommitGroup)
197 }
198}
199
200pub fn tma_group_wait(_max_pending: u32) {
202 unexpanded!()
203}
204
205pub mod tma_group_wait {
206 use ruda_core::ir::TmaOps;
207
208 use super::*;
209
210 pub fn expand(scope: &mut Scope, max_pending: u32) {
211 scope.register(TmaOps::WaitGroup { max_pending })
212 }
213}
214
215pub fn tma_group_wait_read(_max_pending: u32) {
231 unexpanded!()
232}
233
234pub mod tma_group_wait_read {
235 use ruda_core::ir::TmaOps;
236
237 use super::*;
238
239 pub fn expand(scope: &mut Scope, max_pending: u32) {
240 scope.register(TmaOps::WaitGroupRead { max_pending })
241 }
242}
243
244macro_rules! tma_store {
245 ($dim: literal, $($arg: expr),*) => {
246 paste! {
247 #[allow(unused)]
251 pub fn [<tma_store_ $dim d>]<T: RudaPrimitive, T2: RudaPrimitive<Scalar = T::Scalar>>(
252 src: &Slice<T2>,
253 dst: &mut TensorMap<T, Tiled>,
254 $($arg: i32),*
255 ) {
256 unexpanded!()
257 }
258
259 pub mod [<tma_store_ $dim d>] {
260 use ruda_core::ir::{Instruction, TmaOps};
261
262 use super::*;
263
264 #[allow(clippy::too_many_arguments)]
265 pub fn expand<T: RudaPrimitive, T2: RudaPrimitive<Scalar = T::Scalar>>(
266 scope: &mut Scope,
267 src: SliceExpand<T2, ReadOnly>,
268 dst: NativeExpand<TensorMap<T, Tiled>>,
269 $($arg: NativeExpand<i32>),*
270 ) {
271 let (source, source_offset) = src.__to_raw_parts();
272 let dst = *dst.expand;
273 let coordinates = vec![$(*$arg.expand),*];
274 scope.register(Instruction::new(
275 TmaOps::TmaStore {
276 source,
277 coordinates,
278 offset_source: source_offset,
279 },
280 dst,
281 ))
282 }
283 }
284 }
285 };
286}
287
288tma_store!(1, x);
289tma_store!(2, y, x);
290tma_store!(3, z, y, x);
291tma_store!(4, w, z, y, x);
292tma_store!(5, v, w, z, y, x);
293
294mod metadata {
296 use ruda_core::ir::{ManagedVariable, Metadata, VariableKind};
297
298 use super::*;
299 use crate::dsl::{
300 ir::{Arithmetic, BinaryOperator, Instruction},
301 prelude::Array,
302 };
303
304 impl<T: Scalar, K: TensorMapKind> TensorMap<T, K> {
305 pub fn buffer<N: Size>(&self) -> Tensor<Vector<T, N>> {
307 unexpanded!()
308 }
309
310 pub fn stride(&self, _dim: usize) -> usize {
312 unexpanded!()
313 }
314
315 pub fn shape(&self, _dim: usize) -> usize {
317 unexpanded!()
318 }
319
320 pub fn coordinate(&self, _index: usize, _dim: usize) -> usize {
325 unexpanded!()
326 }
327
328 #[allow(clippy::len_without_is_empty)]
335 pub fn len(&self) -> usize {
336 unexpanded!()
337 }
338
339 #[allow(clippy::len_without_is_empty)]
346 pub fn buffer_len(&self) -> usize {
347 unexpanded!()
348 }
349
350 pub fn rank(&self) -> usize {
352 unexpanded!()
353 }
354
355 pub fn downcast<E: RudaPrimitive>(&self) -> TensorMap<E, K> {
360 unexpanded!()
361 }
362
363 pub fn __expand_buffer(
365 scope: &mut Scope,
366 expand: NativeExpand<TensorMap<T, K>>,
367 ) -> NativeExpand<Tensor<T>> {
368 expand.__expand_buffer_method(scope)
369 }
370
371 pub fn __expand_stride(
373 scope: &mut Scope,
374 expand: NativeExpand<TensorMap<T, K>>,
375 dim: NativeExpand<usize>,
376 ) -> NativeExpand<usize> {
377 expand.__expand_stride_method(scope, dim)
378 }
379
380 pub fn __expand_shape(
382 scope: &mut Scope,
383 expand: NativeExpand<TensorMap<T, K>>,
384 dim: NativeExpand<usize>,
385 ) -> NativeExpand<usize> {
386 expand.__expand_shape_method(scope, dim)
387 }
388
389 pub fn __expand_coordinate(
391 scope: &mut Scope,
392 expand: NativeExpand<TensorMap<T, K>>,
393 index: NativeExpand<usize>,
394 dim: NativeExpand<usize>,
395 ) -> NativeExpand<usize> {
396 expand.__expand_coordinate_method(scope, index, dim)
397 }
398
399 pub fn __expand_len(
401 scope: &mut Scope,
402 expand: NativeExpand<TensorMap<T, K>>,
403 ) -> NativeExpand<usize> {
404 expand.__expand_len_method(scope)
405 }
406
407 pub fn __expand_buffer_len(
409 scope: &mut Scope,
410 expand: NativeExpand<TensorMap<T, K>>,
411 ) -> NativeExpand<usize> {
412 expand.__expand_buffer_len_method(scope)
413 }
414
415 pub fn __expand_rank(
417 scope: &mut Scope,
418 expand: NativeExpand<TensorMap<T, K>>,
419 ) -> NativeExpand<usize> {
420 expand.__expand_rank_method(scope)
421 }
422 }
423
424 impl<T: RudaPrimitive, K: TensorMapKind> NativeExpand<TensorMap<T, K>> {
425 pub fn __expand_buffer_method(self, scope: &mut Scope) -> NativeExpand<Tensor<T>> {
427 let tensor = match self.expand.kind {
428 VariableKind::TensorMapInput(id) => scope.input(id, self.expand.ty),
429 VariableKind::TensorMapOutput(id) => scope.output(id, self.expand.ty),
430 _ => unreachable!(),
431 };
432 tensor.into()
433 }
434
435 pub fn __expand_stride_method(
437 self,
438 scope: &mut Scope,
439 dim: NativeExpand<usize>,
440 ) -> NativeExpand<usize> {
441 let dim: ManagedVariable = dim.into();
442 let out = scope.create_local(usize::as_type(scope));
443 scope.register(Instruction::new(
444 Metadata::Stride {
445 dim: *dim,
446 var: self.expand.into(),
447 },
448 out.clone().into(),
449 ));
450 out.into()
451 }
452
453 pub fn __expand_shape_method(
455 self,
456 scope: &mut Scope,
457 dim: NativeExpand<usize>,
458 ) -> NativeExpand<usize> {
459 let dim: ManagedVariable = dim.into();
460 let out = scope.create_local(usize::as_type(scope));
461 scope.register(Instruction::new(
462 Metadata::Shape {
463 dim: *dim,
464 var: self.expand.into(),
465 },
466 out.clone().into(),
467 ));
468 out.into()
469 }
470
471 pub fn __expand_coordinate_method(
473 self,
474 scope: &mut Scope,
475 index: NativeExpand<usize>,
476 dim: NativeExpand<usize>,
477 ) -> NativeExpand<usize> {
478 let index: ManagedVariable = index.into();
479 let stride = self.clone().__expand_stride_method(scope, dim.clone());
480 let shape = self.clone().__expand_shape_method(scope, dim.clone());
481
482 let num_strides = scope.create_local(usize::as_type(scope));
484 scope.register(Instruction::new(
485 Arithmetic::Div(BinaryOperator {
486 lhs: *index,
487 rhs: stride.expand.into(),
488 }),
489 num_strides.clone().into(),
490 ));
491
492 let coordinate = scope.create_local(usize::as_type(scope));
494 scope.register(Instruction::new(
495 Arithmetic::Modulo(BinaryOperator {
496 lhs: *num_strides,
497 rhs: shape.expand.into(),
498 }),
499 coordinate.clone().into(),
500 ));
501
502 coordinate.into()
503 }
504
505 pub fn __expand_len_method(self, scope: &mut Scope) -> NativeExpand<usize> {
507 let elem: NativeExpand<Array<u32>> = self.expand.into();
508 elem.__expand_len_method(scope)
509 }
510
511 pub fn __expand_buffer_len_method(self, scope: &mut Scope) -> NativeExpand<usize> {
513 let elem: NativeExpand<Array<u32>> = self.expand.into();
514 elem.__expand_buffer_len_method(scope)
515 }
516
517 pub fn __expand_rank_method(self, scope: &mut Scope) -> NativeExpand<usize> {
519 let out = scope.create_local(usize::as_type(scope));
520 scope.register(Instruction::new(Metadata::Rank { var: *self.expand }, *out));
521 out.into()
522 }
523
524 pub fn __expand_downcast_method<E: RudaPrimitive>(
526 self,
527 scope: &mut Scope,
528 ) -> NativeExpand<TensorMap<E, K>> {
529 if T::as_type(scope) != E::as_type(scope) && !is_tf32::<E, T>(scope) {
530 panic!("Downcast should only be used to satisfy the Rust type system.")
531 }
532
533 self.expand.into()
534 }
535 }
536}