MLIR-AIE 1.4.5.dev
AIEDialect.h
Go to the documentation of this file.
1//===- AIEDialect.h ---------------------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2019-2022 Xilinx, Inc.
4// Copyright (C) 2022-2026 Advanced Micro Devices, Inc.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef MLIR_AIE_DIALECT_H
10#define MLIR_AIE_DIALECT_H
11
12#include "AIEEnums.h"
14
16
17#include "mlir/Dialect/DLTI/Traits.h"
18#include "mlir/Dialect/Func/IR/FuncOps.h"
19#include "mlir/Dialect/MemRef/IR/MemRef.h"
20#include "mlir/IR/BuiltinAttributes.h"
21#include "mlir/IR/OpDefinition.h"
22#include "mlir/IR/OpImplementation.h"
23#include "mlir/IR/SymbolTable.h"
24#include "mlir/Interfaces/DataLayoutInterfaces.h"
25
26#include "llvm/ADT/ArrayRef.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/StringRef.h"
29#include "llvm/ADT/StringSwitch.h"
30
31namespace xilinx::AIE {
32
33// Check that the given DMA-like op (e.g. MemOp, ShimDMAOp)
34// has valid BDs.
35template <typename ConcreteType>
36struct HasValidBDs : mlir::OpTrait::TraitBase<ConcreteType, HasValidBDs> {
37 static mlir::LogicalResult verifyTrait(mlir::Operation *op);
38};
39
40// Check that the given DMA-like op (e.g. MemOp, ShimDMAOp)
41// has valid channels.
42template <typename ConcreteType>
44 : mlir::OpTrait::TraitBase<ConcreteType, HasValidBDs> {
45 static mlir::LogicalResult verifyTrait(mlir::Operation *op);
46};
47
48template <typename ConcreteType>
50 : mlir::OpTrait::TraitBase<ConcreteType, SkipAccessibilityCheckTrait> {};
51
52// Supplies `Symbol`'s visibility accessors for ops that keep visibility in a
53// plain `sym_visibility` attribute rather than in a tablegen-declared argument
54// (which is what upstream's `SymbolVisibility` trait requires).
55template <typename ConcreteType>
57 : mlir::OpTrait::TraitBase<ConcreteType, AttrBasedSymbolVisibility> {
58 static constexpr llvm::StringRef getVisibilityAttrName() {
59 return "sym_visibility";
60 }
61
62 // `mlir::detail::verifySymbol` only checks the inherent attribute, so it
63 // never sees ours.
64 static mlir::LogicalResult verifyTrait(mlir::Operation *op) {
65 mlir::Attribute vis = op->getAttr(getVisibilityAttrName());
66 if (!vis)
67 return mlir::success();
68 auto visStrAttr = llvm::dyn_cast<mlir::StringAttr>(vis);
69 if (!visStrAttr)
70 return op->emitOpError()
71 << "requires visibility attribute '" << getVisibilityAttrName()
72 << "' to be a string attribute, but got " << vis;
73 if (!llvm::is_contained(
74 llvm::ArrayRef<llvm::StringRef>{"public", "private", "nested"},
75 visStrAttr.getValue()))
76 return op->emitOpError()
77 << "visibility expected to be one of [\"public\", \"private\", "
78 "\"nested\"], but got "
79 << visStrAttr;
80 return mlir::success();
81 }
82
83 mlir::SymbolTable::Visibility getVisibility() {
84 mlir::StringAttr vis =
85 this->getOperation()->template getAttrOfType<mlir::StringAttr>(
87 if (!vis)
88 return mlir::SymbolTable::Visibility::Public;
89 return llvm::StringSwitch<mlir::SymbolTable::Visibility>(vis.getValue())
90 .Case("private", mlir::SymbolTable::Visibility::Private)
91 .Case("nested", mlir::SymbolTable::Visibility::Nested)
92 .Default(mlir::SymbolTable::Visibility::Public);
93 }
94
95 void setVisibility(mlir::SymbolTable::Visibility vis) {
96 mlir::Operation *op = this->getOperation();
97 if (vis == mlir::SymbolTable::Visibility::Public) {
98 op->removeAttr(getVisibilityAttrName());
99 return;
100 }
101 assert((vis == mlir::SymbolTable::Visibility::Private ||
102 vis == mlir::SymbolTable::Visibility::Nested) &&
103 "unknown symbol visibility kind");
104 llvm::StringRef visName =
105 vis == mlir::SymbolTable::Visibility::Private ? "private" : "nested";
106 op->setAttr(getVisibilityAttrName(),
107 mlir::StringAttr::get(op->getContext(), visName));
108 }
109};
110
111// Marker trait for operations that can be flow endpoints (e.g., TileOp, CoreOp,
112// MemOp)
113template <typename ConcreteType>
114struct IsFlowEndPoint : mlir::OpTrait::TraitBase<ConcreteType, IsFlowEndPoint> {
115};
116
117class TileOp;
118class RouteEndpointOp;
119
121 uint32_t burstLength);
123 uint32_t burstLength);
124
125// Looks up a name, falling back to a scan for the `sym_name` attribute.
126// `aie.buffer`, `aie.external_buffer`, `aie.lock` and `aie.dma` are referred to
127// by name but define an SSA value, so they cannot be `Symbol` ops and
128// `mlir::SymbolTable` does not find them.
129mlir::Operation *lookupNamedOpIn(mlir::Operation *symbolTableOp,
130 mlir::StringAttr name);
131mlir::Operation *lookupNamedOpIn(mlir::Operation *symbolTableOp,
132 llvm::StringRef name);
133// Looks in the symbol table nearest to (or at) `from`.
134mlir::Operation *lookupNamedOp(mlir::Operation *from, mlir::StringAttr name);
135mlir::Operation *lookupNamedOp(mlir::Operation *from, llvm::StringRef name);
136
137template <typename OpTy, typename NameT>
138OpTy lookupNamedOpIn(mlir::Operation *symbolTableOp, NameT name) {
139 return llvm::dyn_cast_if_present<OpTy>(lookupNamedOpIn(symbolTableOp, name));
140}
141
142template <typename OpTy, typename NameT>
143OpTy lookupNamedOp(mlir::Operation *from, NameT name) {
144 return llvm::dyn_cast_if_present<OpTy>(lookupNamedOp(from, name));
145}
146
147// `lookupNamedOpIn` indexed once, for resolving many names in a symbol table
148// whose named ops do not change meanwhile.
150public:
151 explicit NamedOpTable(mlir::Operation *symbolTableOp);
152
153 mlir::Operation *lookup(mlir::StringAttr name) const {
154 return ops.lookup(name);
155 }
156 template <typename OpTy>
157 OpTy lookup(mlir::StringAttr name) const {
158 return llvm::dyn_cast_if_present<OpTy>(lookup(name));
159 }
160
161 // "<prefix><n>" for the first n from `counter` up that no op in the table
162 // has. `counter` moves past n, so names drawn from one counter differ
163 // although the table does not record them.
164 std::string uniqueName(llvm::StringRef prefix, unsigned &counter) const;
165
166private:
167 mlir::MLIRContext *context;
168 llvm::DenseMap<mlir::StringAttr, mlir::Operation *> ops;
169};
170
171// The NamedOpTables of several symbol tables, each indexed on first use, as
172// mlir::SymbolTableCollection is for symbols.
174public:
175 NamedOpTable &getTable(mlir::Operation *symbolTableOp) {
176 return tables.try_emplace(symbolTableOp, symbolTableOp).first->second;
177 }
178 template <typename OpTy>
179 OpTy lookupIn(mlir::Operation *symbolTableOp, mlir::StringAttr name) {
180 return getTable(symbolTableOp).lookup<OpTy>(name);
181 }
182
183private:
184 llvm::DenseMap<mlir::Operation *, NamedOpTable> tables;
185};
186
187mlir::LogicalResult
188verifyOffsetSizeAndStrideOp(mlir::OffsetSizeAndStrideOpInterface op);
189
190// custom<TypedDynamicIndexList>($values, $integers, type($values)): the
191// upstream custom<DynamicIndexList> with an optional type on each SSA entry,
192// `%v` for i64 and `%v : type` otherwise.
194 mlir::OpAsmParser &parser,
195 llvm::SmallVectorImpl<mlir::OpAsmParser::UnresolvedOperand> &values,
196 mlir::DenseI64ArrayAttr &integers,
197 llvm::SmallVectorImpl<mlir::Type> &types);
198void printTypedDynamicIndexList(mlir::OpAsmPrinter &printer,
199 mlir::Operation *op, mlir::OperandRange values,
200 llvm::ArrayRef<int64_t> integers,
201 mlir::TypeRange types);
202
203} // namespace xilinx::AIE
204
205namespace xilinx::AIE {
206mlir::LogicalResult
207myVerifyOffsetSizeAndStrideOp(mlir::OffsetSizeAndStrideOpInterface op);
208template <typename ConcreteOp>
211 static ::mlir::LogicalResult verifyTrait(::mlir::Operation *op) {
213 ::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>(op));
214 }
215};
216
218 : ::mlir::OffsetSizeAndStrideOpInterface {
219 template <typename ConcreteOp>
220 struct Trait : public MyOffsetSizeAndStrideOpInterfaceTrait<ConcreteOp> {};
221};
222} // namespace xilinx::AIE
223
224// Include dialect declarations such as parseAttributes, parseType
225#include "aie/Dialect/AIE/IR/AIEDialect.h.inc"
226
227namespace xilinx::AIE {
228
230
231} // namespace xilinx::AIE
232
233////////////////////////////////////////////////////////////////////////////////
234/////////////////////// Custom Types for the Dialect ///////////////////////////
235////////////////////////////////////////////////////////////////////////////////
236
237#define GET_TYPEDEF_CLASSES
238#include "aie/Dialect/AIE/IR/AIETypes.h.inc"
239
240////////////////////////////////////////////////////////////////////////////////
241// Custom Attributes ///////////////////////////////////////////////////////////
242////////////////////////////////////////////////////////////////////////////////
243
244#define GET_ATTRDEF_CLASSES
245#include "aie/Dialect/AIE/IR/AIEAttrs.h.inc"
246
247// Interfaces come after the attributes and types their methods traffic in.
248#include "aie/Dialect/AIE/IR/AIEInterfaces.h.inc"
249
250////////////////////////////////////////////////////////////////////////////////
251//////////////////// Custom Operations for the Dialect /////////////////////////
252////////////////////////////////////////////////////////////////////////////////
253
254namespace xilinx::AIE {
255
256WireBundle getConnectingBundle(WireBundle dir);
257
258#define GENERATE_TO_STRING(TYPE_WITH_INSERTION_OP) \
259 friend std::string to_string(const TYPE_WITH_INSERTION_OP &s) { \
260 std::ostringstream ss; \
261 ss << s; \
262 return ss.str(); \
263 }
264
265using Port = struct Port {
266 WireBundle bundle;
267 int channel;
268
269 bool operator==(const Port &rhs) const {
270 return std::tie(bundle, channel) == std::tie(rhs.bundle, rhs.channel);
271 }
272
273 bool operator!=(const Port &rhs) const { return !(*this == rhs); }
274
275 bool operator<(const Port &rhs) const {
276 return std::tie(bundle, channel) < std::tie(rhs.bundle, rhs.channel);
277 }
278
279 friend std::ostream &operator<<(std::ostream &os, const Port &port) {
280 os << "(";
281 os << stringifyWireBundle(port.bundle).str();
282 os << ": " << std::to_string(port.channel) << ")";
283 return os;
284 }
285
287
288 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
289 const Port &port) {
290 os << to_string(port);
291 return os;
292 }
293};
294
295std::optional<std::pair<TileID, Port>>
296getConnectingWireEndpoint(const AIETargetModel &targetModel, TileID tile,
297 Port port);
298
299using Connect = struct Connect {
300 Port src;
301 Port dst;
302
303 bool operator==(const Connect &rhs) const {
304 return std::tie(src, dst) == std::tie(rhs.src, rhs.dst);
305 }
306
307 bool operator!=(const Connect &rhs) const { return !(*this == rhs); }
308
309 bool operator<(const Connect &rhs) const {
310 return std::tie(src, dst) < std::tie(rhs.src, rhs.dst);
311 }
312};
313
314using DMAChannel = struct DMAChannel {
315 DMAChannelDir direction;
316 int channel;
317
318 bool operator==(const DMAChannel &rhs) const {
319 return std::tie(direction, channel) == std::tie(rhs.direction, rhs.channel);
320 }
321};
322
323const AIETargetModel &getTargetModel(mlir::Operation *op);
324const AIETargetModel &getTargetModel(AIEDevice device);
325
326/// Which of `a`'s and `b`'s memory modules both tiles can address.
328
329mlir::ParseResult
330parseObjectFifoProducerTile(mlir::OpAsmParser &parser,
331 mlir::OpAsmParser::UnresolvedOperand &operand,
332 BDDimLayoutArrayAttr &dimensions);
333
334void printObjectFifoProducerTile(mlir::OpAsmPrinter &printer,
335 mlir::Operation *op, mlir::Value operand,
336 BDDimLayoutArrayAttr dimensions);
337
338mlir::ParseResult parseDMAStartChannel(mlir::OpAsmParser &parser,
339 mlir::Attribute &channel);
340
341void printDMAStartChannel(mlir::OpAsmPrinter &printer, mlir::Operation *op,
342 mlir::Attribute channel);
343
344mlir::ParseResult
345parseObjectFifoAcquireObjects(mlir::OpAsmParser &parser,
346 ObjectFifoPortAttr &port,
347 llvm::SmallVectorImpl<mlir::Type> &objects);
348
349void printObjectFifoAcquireObjects(mlir::OpAsmPrinter &printer,
350 mlir::Operation *op, ObjectFifoPortAttr port,
351 mlir::TypeRange objects);
352
353mlir::ParseResult parseObjectFifoReleaseCount(mlir::OpAsmParser &parser,
354 ObjectFifoPortAttr &port,
355 mlir::IntegerAttr &size);
356
357void printObjectFifoReleaseCount(mlir::OpAsmPrinter &printer,
358 mlir::Operation *op, ObjectFifoPortAttr port,
359 mlir::IntegerAttr size);
360
362 mlir::OpAsmParser &parser,
363 llvm::SmallVectorImpl<mlir::OpAsmParser::UnresolvedOperand> &tiles,
364 BDDimLayoutArrayArrayAttr &dimensions);
365
366void printObjectFifoConsumerTiles(mlir::OpAsmPrinter &printer,
367 mlir::Operation *op, mlir::OperandRange tiles,
368 BDDimLayoutArrayArrayAttr dimsPerTileAttr);
369
370mlir::ParseResult
371parseFlowVias(mlir::OpAsmParser &parser,
372 llvm::SmallVectorImpl<mlir::OpAsmParser::UnresolvedOperand> &vias,
373 mlir::DenseI32ArrayAttr &ingressBundles,
374 mlir::DenseI32ArrayAttr &ingressChannels,
375 mlir::DenseI32ArrayAttr &egressBundles,
376 mlir::DenseI32ArrayAttr &egressChannels);
377
378void printFlowVias(mlir::OpAsmPrinter &printer, mlir::Operation *op,
379 mlir::OperandRange vias,
380 mlir::DenseI32ArrayAttr ingressBundles,
381 mlir::DenseI32ArrayAttr ingressChannels,
382 mlir::DenseI32ArrayAttr egressBundles,
383 mlir::DenseI32ArrayAttr egressChannels);
384
385int32_t getBufferBaseAddress(mlir::Operation *bufOp);
386
387// Trace Event Value Parsing/Printing (handles both string and typed enums)
388mlir::ParseResult parseTraceEvent(mlir::AsmParser &parser,
389 mlir::Attribute &result);
390void printTraceEventEnum(mlir::AsmPrinter &printer, mlir::Attribute attr);
391
392} // namespace xilinx::AIE
393
394namespace xilinx::AIE {
395
396// A draining walk over a whole stream of objects rather than one of them:
397// output `j` walks `inner` from object `advance * j - top` on, reading `span`
398// consecutive objects through the inner dimension `rowDim` steps by one
399// object (none when `span` is 1); the `top` objects before the first and
400// `bottom` past the last of `objects` read as zeros.
402 int64_t objectSize;
403 int64_t outputs;
404 int64_t advance;
405 int64_t span;
406 int64_t top;
407 int64_t bottom;
408 int64_t objects;
409 int64_t rowDim;
410 llvm::SmallVector<BDDimLayoutAttr> inner;
411
412 // Elements each output moves.
413 int64_t transfer() const;
414};
415
416// One output of a StreamWindow: the first object it reads, counting the `top`
417// zero objects, and the lock units it takes before and gives back after.
419 int64_t first;
420 int64_t acquire;
421 int64_t release;
422};
423
424} // namespace xilinx::AIE
425
426// include TableGen generated Op definitions
427#define GET_OP_CLASSES
428#include "aie/Dialect/AIE/IR/AIEOps.h.inc"
429
430namespace xilinx::AIE {
431
432// The endpoints `end`'s `turns` names, each once, in order of first turn;
433// none when it takes no turns.
434llvm::SmallVector<ObjectFifoDmaEndpointOp>
435turnEndpoints(ObjectFifoDmaEndpointOp end);
436
437// Passes a chain of turns is unrolled for, given each end's turns a pass and
438// descriptors: until every end is back at its first descriptor. An end on a
439// contiguous pool, given 0 descriptors, takes as many as its turns need.
440int64_t turnPasses(llvm::ArrayRef<std::pair<int64_t, int64_t>> ends);
441
442// Whether packets leave `master` of `tile` with their header: not into a DMA,
443// nor down the shim's South to one, unless `keep` says.
444bool keepsPktHeader(TileID tile, Port master, std::optional<bool> keep);
445
446// Whether `bundle` links a switchbox to a neighbouring one.
447inline bool isDirectional(WireBundle bundle) {
448 return bundle == WireBundle::North || bundle == WireBundle::South ||
449 bundle == WireBundle::East || bundle == WireBundle::West;
450}
451
452void collectTiles(DeviceOp &device,
453 llvm::DenseMap<TileID, mlir::Operation *> &tiles);
454
456 DeviceOp &device,
457 llvm::DenseMap<mlir::Operation *, llvm::SmallVector<BufferOp, 4>> &buffers);
458
459// Returns true when a BDDimLayoutAttr array (outermost-first) describes a
460// contiguous row-major scan: innermost stride == 1 and each outer stride
461// equals the product of all inner sizes. Used by DMABDOp verification and
462// canonicalization to allow natural ND forms on shim tiles that will be
463// linearized by the compiler.
464bool isContiguousBDTransfer(llvm::ArrayRef<BDDimLayoutAttr> dims);
465
466// The elements a BD streaming `dims` with `pads` sends, each dimension widened
467// by its padding; `fallback` unless it has both.
468int64_t paddedSize(llvm::ArrayRef<BDDimLayoutAttr> dims,
469 llvm::ArrayRef<BDPadLayoutAttr> pads, int64_t fallback);
470
471// The dimensions aie-normalize-dma-bd-dims leaves a constant BD with, given its
472// dimensions (outermost first) and its length in elements: none when it
473// becomes one linear transfer, else its size-1 dimensions dropped. nullopt
474// when it stays as written: no size-1 dimension, or a length that is not the
475// dimensions' product (a leading repeat outside the length).
476std::optional<llvm::SmallVector<BDDimLayoutAttr>>
477normalizedBDDims(llvm::ArrayRef<BDDimLayoutAttr> dims, int64_t len);
478
479// The byte size of `lengthUnit` elements of `buffer`, checked to be a multiple
480// of 16 bytes whose word count fits a 32-bit BD length.
481mlir::FailureOr<int64_t> getLengthUnitBytes(mlir::Operation *op,
482 int64_t lengthUnit,
483 mlir::BaseMemRefType buffer);
484
485// Validate a BD's runtime length (`length_parameter`, see aie.dma_bd) against
486// its static pattern, shared by aie.dma_bd and aiex.npu.dma_memcpy_nd.
487// `lenElems` is the static length of one iteration, in elements. `contiguous`
488// says the BD is lowered in linear mode; otherwise the added length continues
489// the third dimension as placed by placeRuntimeLengthDimension, so
490// `innerSizes` (the three innermost sizes, innermost-first) must give it a
491// size above one and a row that divides the length unit.
492mlir::LogicalResult verifyLengthParameter(mlir::Operation *op,
493 std::optional<int64_t> lengthUnit,
494 mlir::BaseMemRefType buffer,
495 std::optional<int64_t> lenElems,
496 bool contiguous,
497 llvm::ArrayRef<int64_t> innerSizes);
498
499// The added length of a runtime-length BD steps the third dimension. When that
500// dimension has size one, its stride is not encoded, so a pattern stepping
501// rows in its second dimension is lowered with them in the third instead and
502// the second left at size one. `sizes` and `strides` are innermost-first and
503// hold at least three dimensions.
504void placeRuntimeLengthDimension(llvm::MutableArrayRef<int64_t> sizes,
505 llvm::MutableArrayRef<int64_t> strides);
506
507// Validate the tile a runtime-length BD is lowered on: an AIE2/AIE2P shim NOC
508// tile whose BD buffer length is a whole 32-bit register, which the firmware
509// update adds to.
510mlir::LogicalResult verifyLengthParameterTile(mlir::Operation *op,
511 const AIETargetModel &targetModel,
512 int col, int row);
513
514// Validate the sender-side out_of_order_id field on a single BD. Callable from
515// the AIEX dialect, whose runtime-sequence task BDs skip DMABDOp::verify.
516mlir::LogicalResult
517verifyDMABDOutOfOrderId(DMABDOp bd, bool packetEnabledByContext = false);
518
519// Validate a BD's iteration attribute against its tile type's iteration and
520// step fields. Callable from the AIEX dialect, like verifyDMABDOutOfOrderId.
521mlir::LogicalResult verifyDMABDIteration(DMABDOp bd, AIETileType tileType);
522
523// Below allocation a packet header is only useful once its id is assigned.
524// `what` names the attribute in the diagnostic. Callable from the AIEX
525// dialect, whose runtime ops carry the same header.
526mlir::LogicalResult verifyAssignedPacket(mlir::Operation *op,
527 PacketInfoAttr packet,
528 llvm::StringRef what = "packet");
529
530// Validate an out-of-order S2MM channel and its receive BDs.
531mlir::LogicalResult
532verifyOutOfOrderChannel(mlir::Operation *op, DMAChannelDir dir, bool outOfOrder,
533 llvm::ArrayRef<DMABDOp> bds,
534 bool packetEnabledByContext = false);
535
536// Validate the use_locks of one BD block and return them. A BD has one acquire
537// field and one release field; by convention the block uses either no lock or
538// both, except that an out-of-order BD may release alone. Either result is
539// null when the block has no such lock.
540mlir::LogicalResult verifyBdLockPair(mlir::Block &block, bool outOfOrder,
541 UseLockOp &acquire, UseLockOp &release);
542
543// The stream window `dims` (outermost first) and `pads` (`(top, bottom)` on
544// the outermost dimension only) describe over objects of `objectSize`
545// elements. The outermost dimension steps whole objects between outputs; at
546// most one inner dimension steps whole objects, by one; the others stay
547// within an object. Fills `window` on success.
548mlir::LogicalResult
549inferStreamWindow(llvm::ArrayRef<BDDimLayoutAttr> dims,
550 llvm::ArrayRef<BDPadLayoutAttr> pads, int64_t objectSize,
551 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
552 StreamWindow &window);
553
554// Each output's step: it takes the objects up to the newest it reads and gives
555// back those no later output reads, the last one all that are left.
556llvm::SmallVector<StreamWindowStep> streamWindowSteps(const StreamWindow &w);
557
558// BD ids already assigned within a tile's static DMA program (the
559// aie.dma_bd chain(s) inside one DmaBody-implementing op: aie.mem,
560// aie.memtile_dma, aie.shim_dma).
561llvm::SmallVector<uint32_t> getAssignedBdIds(DmaBody program);
562
563// Fails, with an error on each, if a dma_start in `device` still names a route
564// endpoint in place of a channel index. For passes and translations that need
565// the index, which aie-objectfifo-allocate assigns.
566mlir::LogicalResult verifyDMAChannelsResolved(DeviceOp device);
567
568} // namespace xilinx::AIE
569
570namespace llvm {
571// Functions hash just like pointers.
572template <>
573struct DenseMapInfo<xilinx::AIE::ObjectFifoAcquireOp> {
574 static unsigned getHashValue(xilinx::AIE::ObjectFifoAcquireOp val) {
575 return hash_value(val.getAsOpaquePointer());
576 }
577
578 static bool isEqual(xilinx::AIE::ObjectFifoAcquireOp lhs,
579 xilinx::AIE::ObjectFifoAcquireOp rhs) {
580 return lhs == rhs;
581 }
582};
583} // namespace llvm
584
585namespace llvm {
586// Functions hash just like pointers.
587template <>
588struct DenseMapInfo<xilinx::AIE::ObjectFifoCreateOp> {
589 static unsigned getHashValue(xilinx::AIE::ObjectFifoCreateOp val) {
590 return hash_value(val.getAsOpaquePointer());
591 }
592
593 static bool isEqual(xilinx::AIE::ObjectFifoCreateOp lhs,
594 xilinx::AIE::ObjectFifoCreateOp rhs) {
595 return lhs == rhs;
596 }
597};
598
599template <>
600struct DenseMapInfo<xilinx::AIE::DMAChannel> {
601 using FirstInfo = DenseMapInfo<xilinx::AIE::DMAChannelDir>;
602 using SecondInfo = DenseMapInfo<int>;
603
604 static unsigned getHashValue(const xilinx::AIE::DMAChannel &d) {
605 return detail::combineHashValue(FirstInfo::getHashValue(d.direction),
606 SecondInfo::getHashValue(d.channel));
607 }
608
609 static bool isEqual(const xilinx::AIE::DMAChannel &lhs,
610 const xilinx::AIE::DMAChannel &rhs) {
611 return lhs == rhs;
612 }
613};
614
615template <>
616struct DenseMapInfo<xilinx::AIE::Port> {
617 using FirstInfo = DenseMapInfo<xilinx::AIE::WireBundle>;
618 using SecondInfo = DenseMapInfo<int>;
619
620 static unsigned getHashValue(const xilinx::AIE::Port &d) {
621 return detail::combineHashValue(FirstInfo::getHashValue(d.bundle),
622 SecondInfo::getHashValue(d.channel));
623 }
624
625 static bool isEqual(const xilinx::AIE::Port &lhs,
626 const xilinx::AIE::Port &rhs) {
627 return lhs == rhs;
628 }
629};
630
631} // namespace llvm
632
633template <>
634struct std::less<xilinx::AIE::Port> {
636 const xilinx::AIE::Port &b) const {
637 return a.bundle == b.bundle ? a.channel < b.channel : a.bundle < b.bundle;
638 }
639};
640
641template <>
642struct std::hash<xilinx::AIE::Port> {
643 std::size_t operator()(const xilinx::AIE::Port &p) const noexcept {
644 std::size_t h1 = std::hash<xilinx::AIE::WireBundle>{}(p.bundle);
645 std::size_t h2 = std::hash<int>{}(p.channel);
646 return h1 ^ h2 << 1;
647 }
648};
649
650#endif
#define GENERATE_TO_STRING(TYPE_WITH_INSERTION_OP)
Definition AIEDialect.h:258
SharedMemory
Which of two tiles' memory modules both of them can address.
OpTy lookupIn(mlir::Operation *symbolTableOp, mlir::StringAttr name)
Definition AIEDialect.h:179
NamedOpTable & getTable(mlir::Operation *symbolTableOp)
Definition AIEDialect.h:175
NamedOpTable(mlir::Operation *symbolTableOp)
std::string uniqueName(llvm::StringRef prefix, unsigned &counter) const
OpTy lookup(mlir::StringAttr name) const
Definition AIEDialect.h:157
mlir::Operation * lookup(mlir::StringAttr name) const
Definition AIEDialect.h:153
bool isContiguousBDTransfer(llvm::ArrayRef< BDDimLayoutAttr > dims)
mlir::ParseResult parseFlowVias(mlir::OpAsmParser &parser, llvm::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &vias, mlir::DenseI32ArrayAttr &ingressBundles, mlir::DenseI32ArrayAttr &ingressChannels, mlir::DenseI32ArrayAttr &egressBundles, mlir::DenseI32ArrayAttr &egressChannels)
void printObjectFifoProducerTile(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::Value operand, BDDimLayoutArrayAttr dimensions)
void printTypedDynamicIndexList(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRange values, llvm::ArrayRef< int64_t > integers, mlir::TypeRange types)
llvm::SmallVector< ObjectFifoDmaEndpointOp > turnEndpoints(ObjectFifoDmaEndpointOp end)
std::optional< llvm::SmallVector< BDDimLayoutAttr > > normalizedBDDims(llvm::ArrayRef< BDDimLayoutAttr > dims, int64_t len)
mlir::LogicalResult verifyLengthParameterTile(mlir::Operation *op, const AIETargetModel &targetModel, int col, int row)
uint32_t getShimBurstLengthBytes(const AIE::AIETargetModel &tm, uint32_t burstLength)
void collectTiles(DeviceOp &device, llvm::DenseMap< TileID, mlir::Operation * > &tiles)
void collectBuffers(DeviceOp &device, llvm::DenseMap< mlir::Operation *, llvm::SmallVector< BufferOp, 4 > > &buffers)
mlir::ParseResult parseTraceEvent(mlir::AsmParser &parser, mlir::Attribute &result)
mlir::LogicalResult verifyOffsetSizeAndStrideOp(mlir::OffsetSizeAndStrideOpInterface op)
void registerAIETranslations()
void printObjectFifoAcquireObjects(mlir::OpAsmPrinter &printer, mlir::Operation *op, ObjectFifoPortAttr port, mlir::TypeRange objects)
mlir::LogicalResult verifyBdLockPair(mlir::Block &block, bool outOfOrder, UseLockOp &acquire, UseLockOp &release)
mlir::LogicalResult verifyAssignedPacket(mlir::Operation *op, PacketInfoAttr packet, llvm::StringRef what="packet")
mlir::ParseResult parseTypedDynamicIndexList(mlir::OpAsmParser &parser, llvm::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &values, mlir::DenseI64ArrayAttr &integers, llvm::SmallVectorImpl< mlir::Type > &types)
void printObjectFifoConsumerTiles(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRange tiles, BDDimLayoutArrayArrayAttr dimsPerTileAttr)
mlir::Operation * lookupNamedOpIn(mlir::Operation *symbolTableOp, mlir::StringAttr name)
uint32_t getShimBurstLengthEncoding(const AIE::AIETargetModel &tm, uint32_t burstLength)
mlir::LogicalResult verifyDMABDOutOfOrderId(DMABDOp bd, bool packetEnabledByContext=false)
mlir::ParseResult parseObjectFifoAcquireObjects(mlir::OpAsmParser &parser, ObjectFifoPortAttr &port, llvm::SmallVectorImpl< mlir::Type > &objects)
mlir::LogicalResult verifyOutOfOrderChannel(mlir::Operation *op, DMAChannelDir dir, bool outOfOrder, llvm::ArrayRef< DMABDOp > bds, bool packetEnabledByContext=false)
struct Connect { Port src; Port dst; bool operator==(const Connect &rhs) const { return std::tie(src, dst)==std::tie(rhs.src, rhs.dst); } bool operator!=(const Connect &rhs) const { return !(*this==rhs);} bool operator<(const Connect &rhs) const { return std::tie(src, dst)< std::tie(rhs.src, rhs.dst); } } Connect
Definition AIEDialect.h:299
void printDMAStartChannel(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::Attribute channel)
mlir::LogicalResult verifyLengthParameter(mlir::Operation *op, std::optional< int64_t > lengthUnit, mlir::BaseMemRefType buffer, std::optional< int64_t > lenElems, bool contiguous, llvm::ArrayRef< int64_t > innerSizes)
struct TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")"; return os; } friend std::string to_string(const TileID &s) { std::ostringstream ss; ss<< s; return ss.str(); } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const TileID &s) { os<< to_string(s); return os; } inline bool operator<(const TileID &rhs) const { return std::tie(col, row)< std::tie(rhs.col, rhs.row); } bool operator==(const TileID &rhs) const { return std::tie(col, row)==std::tie(rhs.col, rhs.row); } bool operator!=(const TileID &rhs) const { return !(*this==rhs);} int col, row;} TileID
int32_t getBufferBaseAddress(mlir::Operation *bufOp)
bool isDirectional(WireBundle bundle)
Definition AIEDialect.h:447
mlir::ParseResult parseDMAStartChannel(mlir::OpAsmParser &parser, mlir::Attribute &channel)
llvm::SmallVector< uint32_t > getAssignedBdIds(DmaBody program)
llvm::SmallVector< StreamWindowStep > streamWindowSteps(const StreamWindow &w)
int64_t turnPasses(llvm::ArrayRef< std::pair< int64_t, int64_t > > ends)
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const SwitchSettings &ss)
const AIETargetModel & getTargetModel(mlir::Operation *op)
bool keepsPktHeader(TileID tile, Port master, std::optional< bool > keep)
struct DMAChannel { DMAChannelDir direction; int channel; bool operator==(const DMAChannel &rhs) const { return std::tie(direction, channel)==std::tie(rhs.direction, rhs.channel); } } DMAChannel
Definition AIEDialect.h:314
mlir::LogicalResult verifyDMAChannelsResolved(DeviceOp device)
mlir::Operation * lookupNamedOp(mlir::Operation *from, mlir::StringAttr name)
mlir::ParseResult parseObjectFifoProducerTile(mlir::OpAsmParser &parser, mlir::OpAsmParser::UnresolvedOperand &operand, BDDimLayoutArrayAttr &dimensions)
void printTraceEventEnum(mlir::AsmPrinter &printer, mlir::Attribute attr)
void placeRuntimeLengthDimension(llvm::MutableArrayRef< int64_t > sizes, llvm::MutableArrayRef< int64_t > strides)
mlir::LogicalResult myVerifyOffsetSizeAndStrideOp(mlir::OffsetSizeAndStrideOpInterface op)
mlir::LogicalResult inferStreamWindow(llvm::ArrayRef< BDDimLayoutAttr > dims, llvm::ArrayRef< BDPadLayoutAttr > pads, int64_t objectSize, llvm::function_ref< mlir::InFlightDiagnostic()> emitError, StreamWindow &window)
mlir::LogicalResult verifyDMABDIteration(DMABDOp bd, AIETileType tileType)
void printFlowVias(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRange vias, mlir::DenseI32ArrayAttr ingressBundles, mlir::DenseI32ArrayAttr ingressChannels, mlir::DenseI32ArrayAttr egressBundles, mlir::DenseI32ArrayAttr egressChannels)
struct Port { WireBundle bundle; int channel; bool operator==(const Port &rhs) const { return std::tie(bundle, channel)==std::tie(rhs.bundle, rhs.channel); } bool operator!=(const Port &rhs) const { return !(*this==rhs);} bool operator<(const Port &rhs) const { return std::tie(bundle, channel)< std::tie(rhs.bundle, rhs.channel); } friend std::ostream &operator<<(std::ostream &os, const Port &port) { os<< "("; os<< stringifyWireBundle(port.bundle).str(); os<< ": "<< std::to_string(port.channel)<< ")"; return os; } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Port &port) { os<< to_string(port); return os; } } Port
Definition AIEDialect.h:265
mlir::ParseResult parseObjectFifoReleaseCount(mlir::OpAsmParser &parser, ObjectFifoPortAttr &port, mlir::IntegerAttr &size)
AIETargetModel::SharedMemory sharedMemory(TileOp a, TileOp b)
Which of a's and b's memory modules both tiles can address.
std::optional< std::pair< TileID, Port > > getConnectingWireEndpoint(const AIETargetModel &targetModel, TileID tile, Port port)
mlir::FailureOr< int64_t > getLengthUnitBytes(mlir::Operation *op, int64_t lengthUnit, mlir::BaseMemRefType buffer)
int64_t paddedSize(llvm::ArrayRef< BDDimLayoutAttr > dims, llvm::ArrayRef< BDPadLayoutAttr > pads, int64_t fallback)
mlir::ParseResult parseObjectFifoConsumerTiles(mlir::OpAsmParser &parser, llvm::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &tiles, BDDimLayoutArrayArrayAttr &dimensions)
void printObjectFifoReleaseCount(mlir::OpAsmPrinter &printer, mlir::Operation *op, ObjectFifoPortAttr port, mlir::IntegerAttr size)
WireBundle getConnectingBundle(WireBundle dir)
static bool isEqual(const xilinx::AIE::DMAChannel &lhs, const xilinx::AIE::DMAChannel &rhs)
Definition AIEDialect.h:609
DenseMapInfo< xilinx::AIE::DMAChannelDir > FirstInfo
Definition AIEDialect.h:601
static unsigned getHashValue(const xilinx::AIE::DMAChannel &d)
Definition AIEDialect.h:604
static bool isEqual(xilinx::AIE::ObjectFifoAcquireOp lhs, xilinx::AIE::ObjectFifoAcquireOp rhs)
Definition AIEDialect.h:578
static unsigned getHashValue(xilinx::AIE::ObjectFifoAcquireOp val)
Definition AIEDialect.h:574
static bool isEqual(xilinx::AIE::ObjectFifoCreateOp lhs, xilinx::AIE::ObjectFifoCreateOp rhs)
Definition AIEDialect.h:593
static unsigned getHashValue(xilinx::AIE::ObjectFifoCreateOp val)
Definition AIEDialect.h:589
static unsigned getHashValue(const xilinx::AIE::Port &d)
Definition AIEDialect.h:620
DenseMapInfo< xilinx::AIE::WireBundle > FirstInfo
Definition AIEDialect.h:617
static bool isEqual(const xilinx::AIE::Port &lhs, const xilinx::AIE::Port &rhs)
Definition AIEDialect.h:625
std::size_t operator()(const xilinx::AIE::Port &p) const noexcept
Definition AIEDialect.h:643
bool operator()(const xilinx::AIE::Port &a, const xilinx::AIE::Port &b) const
Definition AIEDialect.h:635
mlir::SymbolTable::Visibility getVisibility()
Definition AIEDialect.h:83
void setVisibility(mlir::SymbolTable::Visibility vis)
Definition AIEDialect.h:95
static mlir::LogicalResult verifyTrait(mlir::Operation *op)
Definition AIEDialect.h:64
static constexpr llvm::StringRef getVisibilityAttrName()
Definition AIEDialect.h:58
static mlir::LogicalResult verifyTrait(mlir::Operation *op)
static mlir::LogicalResult verifyTrait(mlir::Operation *op)
::mlir::LogicalResult verifyTrait(::mlir::Operation *op)
Definition AIEDialect.h:211
llvm::SmallVector< BDDimLayoutAttr > inner
Definition AIEDialect.h:410