-
Notifications
You must be signed in to change notification settings - Fork 193
Expand file tree
/
Copy pathAIEPasses.td
More file actions
363 lines (312 loc) · 14.6 KB
/
Copy pathAIEPasses.td
File metadata and controls
363 lines (312 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
//===- AIEPasses.td ----------------------------------------*- tablegen -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// (c) Copyright 2019 Xilinx Inc.
//
//===----------------------------------------------------------------------===//
#ifndef AIE_PASSES
#define AIE_PASSES
include "mlir/Pass/PassBase.td"
def AIEAssignBufferAddresses : Pass<"aie-assign-buffer-addresses", "DeviceOp"> {
let summary = "Assign memory locations for buffers in each tile";
let description = [{
Buffers in a tile generally have an address that does not significantly
matter in the design. Hence, most of the time we can instantiate
aie.buffer operations without an address. This pass determines
updates each aie.buffer operation without an address to have a
well-defined address. This enables later passes to have a
consistent view of the memory map of a system.
}];
let constructor = "xilinx::AIE::createAIEAssignBufferAddressesPass()";
let options = [
Option<"clAllocScheme", "alloc-scheme", "std::string", /*default=*/"",
"Select allocation scheme: basic-sequential or bank-aware. Default is bank-aware, falling back to basic-sequential if it fails.">,
];
}
def AIEAssignLockIDs : Pass<"aie-assign-lock-ids", "DeviceOp"> {
let summary = "Assigns the lockIDs of locks that do not have IDs.";
let description = [{
Assigns the lockIDs of locks that do not have IDs.
}];
let constructor = "xilinx::AIE::createAIEAssignLockIDsPass()";
}
def AIECanonicalizeDevice : Pass<"aie-canonicalize-device", "mlir::ModuleOp"> {
let summary = "Canonicalize Designs to include a toplevel device";
let description = [{
This pass inserts a toplevel device operation in designs that do not have one.
This allows us to support backwards compatability for older models targetting the VC1902
device without explicit device operations.
}];
let constructor = "xilinx::AIE::createAIECanonicalizeDevicePass()";
}
def AIECoreToStandard : Pass<"aie-standard-lowering", "mlir::ModuleOp"> {
let summary = "Lowering operations in AIE cores' regions to Standard";
let description = [{
Outline code inside AIE.core operations into the llvm dialect.
BufferOp operations are converted to a GlobalMemrefOp and references to
those buffers are converted to GetGlobalMemrefOp. Other AIE operations
inside the cores are generally lowered to appropriate function intrinsics.
Other AIE operations (e.g. CoreOp, TileOp, LockOp) outside the core are removed.
Optionally, tileCol and tileRow can specify a single core to export
}];
let options = [
Option<"deviceName", "device", "std::string", /*default=*/"\"\"", "Device to generate code for">,
Option<"tileCol", "tilecol", "unsigned",
/*default=*/"-1", "X coordinate of tile to generate code for">,
Option<"tileRow", "tilerow", "unsigned",
/*default=*/"-1", "Y coordinate of tile to generate code for">
];
let constructor = "xilinx::AIE::createAIECoreToStandardPass()";
let dependentDialects = [
"mlir::func::FuncDialect",
"mlir::memref::MemRefDialect",
"xilinx::AIE::AIEDialect",
];
}
def AIELocalizeLocks : Pass<"aie-localize-locks", "DeviceOp"> {
let summary = "Convert global locks to a core-relative index";
let description = [{
An individual lock can be referenced by 4 different AIE cores. However, each individual core
accesses the lock through a different 'lock address space'. This pass converts a lock in the
conceptual global address space into a local index. e.g.:
```
%lock = AIE.lock(%tile, 2)
AIE.core(%tile) {
AIE.useLock(%lock, "Acquire", 1)
}
```
becomes
```
AIE.core(%tile) {
%lockindex = arith.constant ? : index
AIE.useLock(%lockindex, "Acquire", 1)
}
```
}];
let constructor = "xilinx::AIE::createAIELocalizeLocksPass()";
}
def AIEAssignBufferDescriptorIDs : Pass<"aie-assign-bd-ids", "DeviceOp"> {
let summary = "Assign bd ids to aie.dma_bd ops.";
let constructor = "xilinx::AIE::createAIEAssignBufferDescriptorIDsPass()";
}
def AIENormalizeAddressSpaces : Pass<"aie-normalize-address-spaces", "DeviceOp"> {
let summary = "Remove non-default address spaces";
let description = [{
Early in the flow, it is convenient to represent multiple memories using different
address spaces. However, after outlining code for AIE engines, the core itself only
has access to a single address space. To avoid confusion, this pass normalizes
any address spaces remaining in the code, converting them to the default address
space.
}];
let constructor = "xilinx::AIE::createAIENormalizeAddressSpacesPass()";
let dependentDialects = [
"mlir::func::FuncDialect",
"mlir::memref::MemRefDialect",
"xilinx::AIE::AIEDialect",
];
}
def AIERoutePathfinderFlows : Pass<"aie-create-pathfinder-flows", "DeviceOp"> {
let summary = "Route aie.flow and aie.packetflow operations through switchboxes";
let description = [{
Uses Pathfinder congestion-aware algorithm.
Each aie.flow is replaced with aie.connect operation.
Each aie.packetflow is replace with the set of aie.amsel, aie.masterset
and aie.packet_rules operations.
}];
let constructor = "xilinx::AIE::createAIEPathfinderPass()";
let dependentDialects = [
"xilinx::AIE::AIEDialect",
];
let options = [
Option<"clRouteCircuit", "route-circuit", "bool", /*default=*/"true",
"Flag to enable aie.flow lowering.">,
Option<"clRoutePacket", "route-packet", "bool", /*default=*/"true",
"Flag to enable aie.packetflow lowering.">,
];
}
def AIEFindFlows : Pass<"aie-find-flows", "DeviceOp"> {
let summary = "Recover flows from switchbox configuration";
let description = [{
Under normal circumstances, every configured aie.switchbox operation
should contribute to describing an end-to-end flow from one point
to another. These flows may be circuit-switched flows (represented
by aie.flow) or a packet-switched connection (represensted by
aie.packetflow). This pass is primarily used for testing automatic
routing.
}];
let constructor = "xilinx::AIE::createAIEFindFlowsPass()";
let dependentDialects = [
"xilinx::AIE::AIEDialect",
];
}
def AIEVectorOpt : Pass<"aie-vector-opt", "mlir::func::FuncOp"> {
let summary = "optimize vector instructions for AIE";
let description = [{
After super-vectorization, some additional optimizations are important
for improving QOR and enabling lowering to LLVM.
}];
let constructor = "xilinx::AIE::createAIEVectorOptPass()";
}
def AIEVectorTransferLowering : Pass<"aie-vector-transfer-lowering", "DeviceOp"> {
let summary = "Lower vector.transfer_read/write to vector.load/store for AIE";
let description = [{
This pass lowers vector.transfer_read operations to vector.load + vector.broadcast
and vector.transfer_write operations to vector.store, when applicable.
It's a wrapper for the upstream `populateVectorTransferLoweringPatterns`.
TODO: Deprecate this pass once `populateVectorTransferLoweringPatterns` is included in
`convert-to-llvm`.
}];
let constructor = "xilinx::AIE::createAIEVectorTransferLoweringPass()";
let options = [
Option<"maxTransferRank", "max-transfer-rank", "unsigned",
/*default=*/"-1", "Maximum vector rank to lower. -1 means no limit.">,
];
}
def AIEVectorToPointerLoops : Pass<"aie-vector-to-pointer-loops", "DeviceOp"> {
let summary = "Transform vector load/store loops to use ptr dialect for explicit pointer arithmetic";
let description = [{
This pass transforms scf.for loops containing vector.load/store operations
with loop-carried index arguments to use ptr dialect operations.
The transformation makes pointer increment patterns explicit to help the
LLVM backend generate efficient post-increment addressing modes (GEP fusion).
Example transformation:
Before:
scf.for iter_args(%idx = %0) {
%v = vector.load %memref[%idx]
%next = arith.addi %idx, %stride
scf.yield %next
}
After:
%ptr = ptr.to_ptr %memref
%init_ptr = ptr.ptr_add %ptr, %0
scf.for iter_args(%p = %init_ptr) {
%m = ptr.from_ptr %p
%v = vector.load %m[%c0]
%next_p = ptr.ptr_add %p, %stride
scf.yield %next_p
}
}];
let constructor = "xilinx::AIE::createAIEVectorToPointerLoopsPass()";
}
def AIEHoistVectorTransferPointers : Pass<"aie-hoist-vector-transfer-pointers", "mlir::ModuleOp"> {
let summary = "Hoist vector transfer pointer computations out of scf.for loops in aie.core regions";
let description = [{
This pass optimizes vector transfer operations inside scf.for loops by hoisting
pointer computations. It operates on aie.core regions within aie.device operations.
When vector transfer operations have indices that depend on the loop induction variable,
the pass:
1. Flattens multi-dimensional memrefs to 1D
2. Computes a base pointer before the loop
3. Adds the pointer as a loop iter_arg
4. Updates the pointer by a constant stride each iteration
5. Replaces the transfer operations to use the iter_arg pointer
This eliminates redundant index computation and affine.apply operations within
the loop body, replacing them with simple pointer arithmetic.
This pass must run before scf-to-cf conversion and before cores are outlined
to functions, since it operates on scf.for loops within aie.core regions.
}];
let constructor = "xilinx::AIE::createAIEHoistVectorTransferPointersPass()";
}
def AIEObjectFifoStatefulTransform : Pass<"aie-objectFifo-stateful-transform", "DeviceOp"> {
let summary = "Instantiate the buffers and locks of aie.objectFifo.createObjectFifo operations";
let description = [{
Replace each aie.objectFifo.createObjectFifo operation with aie.buffer and aie.lock operations in the
producer tile. Convert aie.objectFifo.acquire, aie.objectFifo.release and aie.objectFifo.subviewAccess
operations into useLock operations by keeping track of acquire/release operations on each objectFifo by
each process.
If the producer and consumer tiles of an aie.objectFifo.createObjectFifo operation are not adjacent, the
pass also establised aie.flow and aie.dma operations to enable communication between the tiles.
Extend the body of each loop that contains operations on objectFifos such that it is unrolled
based on the number of elements in the objectFifos. If the number of iterations of the loop
cannot be divided pefectly by the unrolling factor, the pass duplicates the loop body after
the original loop.
}];
let constructor = "xilinx::AIE::createAIEObjectFifoStatefulTransformPass()";
let dependentDialects = [
"mlir::scf::SCFDialect",
"mlir::func::FuncDialect",
"mlir::arith::ArithDialect",
"mlir::memref::MemRefDialect",
"xilinx::AIE::AIEDialect",
];
let options = [
Option<"clDynamicObjectFifos", "dynamic-objFifos", "bool", /*default=*/"false",
"Flag to enable dynamic object fifo lowering in cores instead of loop unrolling.">,
Option<"clPacketSwObjectFifos", "packet-sw-objFifos", "bool", /*default=*/"false",
"Flag to enable aie.packetflow lowering from objectfifos.">,
];
}
def AIEObjectFifoRegisterProcess : Pass<"aie-register-objectFifos", "DeviceOp"> {
let summary = "Generate acquire/release patterns for producer/consumer processes registered to an objectFifo";
let description = [{
Generate acquire/release patterns in the CoreOps of associated cores for each
aie.objectfifo.register_process operation. Patterns are generated as for loops
of different sizes depending on input patterns.
}];
let constructor = "xilinx::AIE::createAIEObjectFifoRegisterProcessPass()";
let dependentDialects = [
"mlir::scf::SCFDialect",
"mlir::func::FuncDialect",
"mlir::arith::ArithDialect",
"xilinx::AIE::AIEDialect",
];
}
def AIELowerCascadeFlows : Pass<"aie-lower-cascade-flows", "DeviceOp"> {
let summary = "Lower aie.cascade_flow operations through `aie.configure_cascade` operations";
let description = [{
Replace each aie.cascade_flow operation with an equivalent set of `aie.configure_cascade`
operations.
}];
let constructor = "xilinx::AIE::createAIELowerCascadeFlowsPass()";
let dependentDialects = [
"xilinx::AIE::AIEDialect",
];
}
def AIEAssignTileCtrlIDs : Pass<"aie-assign-tile-controller-ids", "DeviceOp"> {
let summary = "Assign controller id per aie.tile_op";
let description = [{
For each aie.tile_op used in the design, assign a unique controller ID.
}];
let constructor = "xilinx::AIE::createAIEAssignTileCtrlIDsPass()";
let dependentDialects = [
"xilinx::AIE::AIEDialect",
];
let options = [
Option<"clColumnWiseUniqueIDs", "column-wise-unique-ids", "bool", /*default=*/"true",
"Flag to generate controller ids only unique within each column. Otherwise globally unique.">,
];
}
def AIEGenerateColumnControlOverlay : Pass<"aie-generate-column-control-overlay", "DeviceOp"> {
let summary = "Spawns streaming interconnect network for column control";
let description = [{
For each column of AIE tiles being employed in the design, spawn a network of control packet
streaming interconnects which overlay on top of the design.
}];
let constructor = "xilinx::AIE::createAIEGenerateColumnControlOverlayPass()";
let dependentDialects = [
"xilinx::AIE::AIEDialect",
];
let options = [
Option<"clRouteShimCTRLToTCT", "route-shim-to-tct", "std::string", /*default=*/"\"shim-only\"",
"Flag to generate TCT routing between tile CTRL and shim SOUTH ports. Available options: ['shim-only', 'all-tiles', 'disable'].">,
Option<"clRouteShimDmaToTileCTRL", "route-shim-to-tile-ctrl", "bool", /*default=*/"false",
"Flag to generate routing between shim dma DMA and tile CTRL ports, for configuration.">,
];
}
def AIEExternalMangle : Pass<"aie-external-mangle", "mlir::ModuleOp"> {
let summary = "Mangle external function names";
let description = [{
This pass mangles the names of external functions to match the C++ ABI.
It looks for the `link_with` attribute on `AIE.core` or `func.func` operations,
reads the specified object file, and renames the function to the matching mangled symbol.
It handles symbol collisions by uniquifying the function name and adding a `link_name` attribute.
}];
let constructor = "xilinx::AIE::createAIEExternalManglePass()";
let dependentDialects = [
"mlir::func::FuncDialect",
];
}
#endif