1212declared with :func:`custom_op`, which gives them a schema in a private domain so
1313the exporter emits them as a single node.
1414
15- Supporting a new op is one :class:`StreamKernel` plus one :data:`TORCH_OPS` entry --
16- the kernel source is IRON's existing ``aie_kernels/<dir>/<name>.cc``, exactly as the
17- hand-written operators use it.
15+ Supporting a new op is one :class:`~iron.common.stream.kernels. StreamKernel` plus one
16+ :data:`TORCH_OPS` entry -- the kernel source is IRON's existing
17+ ``aie_kernels/<dir>/<name>.cc``, exactly as the hand-written operators use it.
1818"""
1919
2020from __future__ import annotations
2727from onnxscript import opset18
2828from onnxscript .values import Op , Opset
2929
30- from iron .common .layout import TiledStridedLayout , tiled_2d
31-
32- # Intrinsic MAC tile dimensions of the aie2p kernels stream-dse targets. The
33- # operand layouts are the contract the generated DMAs and the compiled kernel
34- # objects agree on.
35- # mm.cc takes an 8-row MAC tile when bf16 matmuls run on the bfp16 MACs and a
36- # 4-row one when they do not.
37- R , S , T = 4 , 8 , 8
38- MAC_ROWS_BFP16 = 8
39-
40- # Element tile the stream-dse elementwise kernels are written against.
41- ELEMENTWISE_TILE = (32 , 64 )
30+ from iron .common .stream .kernels import ELTWISE_MUL , GEMM , SILU , StreamKernel
4231
4332# Private domain for ops that exist as an AIE kernel but not as an ONNX operator.
4433CUSTOM_DOMAIN = Opset ("com.example" , 1 )
@@ -59,99 +48,6 @@ def custom_op(name: str, arity: int = 1) -> Op:
5948 return Op (CUSTOM_DOMAIN , name , schema )
6049
6150
62- def mac_rows (bfp16_mmul : bool ) -> int :
63- """Rows of the MAC tile a kernel object compiled this way takes."""
64- return MAC_ROWS_BFP16 if bfp16_mmul else R
65-
66-
67- def gemm_layouts (
68- m : int , k : int , n : int , bfp16_mmul : bool = False
69- ) -> tuple [TiledStridedLayout , ...]:
70- """Layouts of a GEMM's ``A[m,k]``, ``B[k,n]`` and ``C[m,n]`` operands."""
71- rows = mac_rows (bfp16_mmul )
72- return (tiled_2d (m , k , rows , S ), tiled_2d (k , n , S , T ), tiled_2d (m , n , rows , T ))
73-
74-
75- def elementwise_layouts (
76- nb_operands : int , bfp16_mmul : bool = False
77- ) -> tuple [TiledStridedLayout , ...]:
78- """Identical tiled layout for each operand of an elementwise kernel."""
79- return (tiled_2d (* ELEMENTWISE_TILE , mac_rows (bfp16_mmul ), T ),) * nb_operands
80-
81-
82- def _gemm_artifacts (kernels_dir , kernel_dir , m : int , k : int , n : int ):
83- """The ``mm.cc`` object specialized for one tile shape.
84-
85- stream-dse emits dimension-suffixed symbols so GEMMs of different tile shapes
86- coexist in one design (``GemmKernel.function_name``/``zero_name``); rename
87- ``mm.cc``'s unsuffixed symbols to match.
88- """
89- from iron .common .compilation import KernelObjectArtifact , SourceArtifact
90-
91- suffix = f"{ m } _{ k } _{ n } "
92- return [
93- KernelObjectArtifact (
94- f"mm_{ suffix } .o" ,
95- dependencies = [SourceArtifact (kernels_dir / kernel_dir / "mm.cc" )],
96- extra_flags = [
97- f"-DDIM_M={ m } " ,
98- f"-DDIM_K={ k } " ,
99- f"-DDIM_N={ n } " ,
100- "-Dbf16_bf16_ONLY" ,
101- # Emulating the matmul on the bfp16 MACs is what makes the 8-row
102- # MAC tile available, so it and the layouts move together.
103- "-DAIE_API_EMULATE_BFLOAT16_MMUL_WITH_BFP16" ,
104- "-DROUND_CONV_EVEN" ,
105- ],
106- rename_symbols = {
107- "matmul_bf16_bf16" : f"matmul_bf16_bf16_{ suffix } " ,
108- "zero_bf16" : f"zero_bf16_{ suffix } " ,
109- },
110- )
111- ]
112-
113-
114- @dataclass (frozen = True )
115- class StreamKernel :
116- """An AIE kernel: its stream-dse identity, its source, and its operand layouts.
117-
118- ``source``/``subdir`` name the file in IRON's ``aie_kernels`` library the same
119- way the hand-written operators do (``subdir=None`` means the device directory,
120- e.g. ``aie2p``). The object name must equal the kernel's ``linkwith_name`` in
121- stream-dse, since the generated MLIR links against it.
122- """
123-
124- key : str # stream-dse AIEKernels key
125- layouts : Callable [..., tuple [TiledStridedLayout , ...]]
126- source : str | None = None
127- subdir : str | None = None
128- artifacts : Callable | None = None # overrides source/subdir when tile-specialized
129-
130- def kernel_artifacts (self , kernels_dir , kernel_dir , ** kwargs ):
131- """Compilation artifacts building this kernel's object file."""
132- if self .artifacts is not None :
133- return self .artifacts (kernels_dir , kernel_dir , ** kwargs )
134- from iron .common .compilation import KernelObjectArtifact , SourceArtifact
135-
136- subdir = self .subdir or kernel_dir
137- return [
138- KernelObjectArtifact (
139- f"{ self .source } .o" ,
140- dependencies = [
141- SourceArtifact (kernels_dir / subdir / f"{ self .source } .cc" )
142- ],
143- )
144- ]
145-
146-
147- GEMM = StreamKernel (key = "gemm" , layouts = gemm_layouts , artifacts = _gemm_artifacts )
148- SILU = StreamKernel (key = "silu" , layouts = lambda : elementwise_layouts (2 ), source = "silu" )
149- ELTWISE_MUL = StreamKernel (
150- key = "eltwise_mul" ,
151- layouts = lambda : elementwise_layouts (3 ),
152- source = "mul" ,
153- )
154-
15551Silu = custom_op ("Silu" )
15652
15753
0 commit comments