diff --git a/include/aie/Dialect/AIE/IR/AIEOps.td b/include/aie/Dialect/AIE/IR/AIEOps.td index e79340a84e..f0b6ecd58d 100644 --- a/include/aie/Dialect/AIE/IR/AIEOps.td +++ b/include/aie/Dialect/AIE/IR/AIEOps.td @@ -29,13 +29,13 @@ class AIE_Op traits = []> : def AIE_DeviceOp: AIE_Op<"device", [ AIETarget, SymbolTable, SingleBlock, NoTerminator, IsolatedFromAbove - ]>, Results<(outs Index:$result)> { + ]> { let summary = "Define an AIE design targetting a complete device"; let description = [{ This operation describes a design that executes on a particular AIEngine device. - It does not replace the - default toplevel module in MLIR, the intention is that this could be the case - in the future. + + It does not replace the default toplevel module in MLIR since it can be + possible to have several devices in the same module. When using this operation, all resources in a physical device are available and the design does not need to be concerned with other potential users of a physical @@ -48,7 +48,7 @@ def AIE_DeviceOp: AIE_Op<"device", [ Example: ``` - %device = aie.device(xcvc1902) { + aie.device(xcvc1902) { %tile = aie.tile(1, 1) %CORE = aie.core(%tile) { ... } } @@ -643,13 +643,13 @@ def AIE_PacketFlowOp: AIE_Op<"packet_flow", [SingleBlockImplicitTerminator<"EndO let description = [{ A logical packet-switched flow between tiles. During place and route, this is replaced by MasterSets and PacketRules inside - switchboxes. - - The optional attribute keep_pkt_header indicates whether each - data packet's packet header gets preserved at the flow's + switchboxes. + + The optional attribute keep_pkt_header indicates whether each + data packet's packet header gets preserved at the flow's destination. The optional attribute priority_route indicates - whether the packet flow is routed in priority over other flows, - so that they always get allocated with the same master, slave + whether the packet flow is routed in priority over other flows, + so that they always get allocated with the same master, slave ports, arbiters and master selects (msel). Example: @@ -869,9 +869,9 @@ def AIE_DMABDOp: AIE_Op<"dma_bd", []> { ## DMA constant padding on AIE-ML Devices AIE-ML devices can apply constant padding at the buffer descriptor level, described with pairs of padding - counts before and after a dimension, to all dimensions in the data layout transformations. The padding - counts can be supplied to the `dma_bd` through an optional argument, an array of "tuple-like" attributes - `bd_pad_layout`, followed by an optional argument `const_val` (default + counts before and after a dimension, to all dimensions in the data layout transformations. The padding + counts can be supplied to the `dma_bd` through an optional argument, an array of "tuple-like" attributes + `bd_pad_layout`, followed by an optional argument `const_val` (default is 0). All counts are expressed in multiples of the element width. }]; @@ -1669,7 +1669,7 @@ def AIE_ObjectFifoCreateOp: AIE_Op<"objectfifo", [HasParent<"DeviceOp">, Symbol] BDDimLayoutArrayArrayAttr:$dimensionsFromStreamPerConsumer, DefaultValuedAttr:$via_DMA, DefaultValuedAttr:$plio, - // disable_synchronization==true will skip lock generation for + // disable_synchronization==true will skip lock generation for // objectfifo synchronous accesses DefaultValuedAttr:$disable_synchronization, // via_shared_mem==0 means use producer tile's memory module @@ -2006,11 +2006,11 @@ def AIE_ObjectFifoRegisterProcessOp: AIE_Op<"objectfifo.register_process", []> { def AIE_BDChainOp: AIE_Op<"bd_chain", [Symbol, SkipAccessibilityCheckTrait]> { let summary = "Definition of a Parametrizable Chain of Buffer Descriptors"; let description = [{ - This operation allows you to define buffer descriptor chains with parametrizable inputs. + This operation allows you to define buffer descriptor chains with parametrizable inputs. This is useful for common patterns such as double buffering (ping-pong) that may look identical but use different input/output buffers and locks. Currently, only buffers and locks are parametrizable. - Once defined, an abstract BD chain can be used elsewhere using AIEX ops in the runtime sequence. + Once defined, an abstract BD chain can be used elsewhere using AIEX ops in the runtime sequence. In the future, abstract BD chains will also be usable elsewhere, inside the static configuration. At its usage sites, the abstract BD chain will be concretized with the given input arguments. }]; diff --git a/lib/CIR/CIRToAIEPasses.cpp b/lib/CIR/CIRToAIEPasses.cpp index 2f70be6d59..ac075e3e1d 100644 --- a/lib/CIR/CIRToAIEPasses.cpp +++ b/lib/CIR/CIRToAIEPasses.cpp @@ -132,8 +132,8 @@ class CIRToAIETypesAnalysis { std::any data; // The AIE operation which is generated std::optional newAIEOperation; - // The new operation producing the result instead for replacement, typically - // an UnrealizedConversionCastOp fed by the newAIEOperation + // The new operation producing the result (if any) instead for replacement, + // typically an UnrealizedConversionCastOp fed by the newAIEOperation std::optional newProducer; // Display the content of AIELikeTypesDeconstruction @@ -246,26 +246,26 @@ class CIRToAIETypesAnalysis { return detail.value(); } + // Associate to a given aie++ C++ type the lowered AIE operation operation + void setProducerOp(mlir::Type t, mlir::Operation *op, mlir::OpBuilder &b) { + auto &detail = getTypeDetail(t); + detail.newAIEOperation = op; + isAIELoweredType.insert(t); + } + // Associate to a given aie++ C++ type the operation producing the value for // this type void setProducerOpWithUCCast(mlir::Type t, mlir::Operation *op, mlir::OpBuilder &b) { + setProducerOp(t, op, b); auto &detail = getTypeDetail(t); detail.newAIEOperation = op; detail.newProducer = b.create( op->getLoc(), t, mlir::ValueRange{op->getResult(0)}); - isAIELoweredType.insert(t); } - // Associate to a given aie++ C++ type the operation producing the value for - // this type - mlir::Operation *getProducerOp(mlir::Type t) { - auto &detail = getTypeDetail(t); - assert(detail.newProducer && - R"(This type should have an operation registered - with a previous setProducerOp())"); - return detail.newProducer.value(); - } + // Get the optional operation producing the value for the given aie++ C++ type + auto &getProducerOp(mlir::Type t) { return getTypeDetail(t).newProducer; } // Get the set of aie++ C++ types which have been lowered to an AIE operation // producing a value related to that type @@ -283,9 +283,7 @@ class CIRToAIETypesAnalysis { for (auto &operand : op->getOpOperands()) { auto type = operand.get().getType(); if (this->isAIELowered(type)) { - LLVM_DEBUG(op->emitRemark("visitAIEOperands") - << type << " to " - << this->getProducerOp(type)->getResult(0)); + LLVM_DEBUG(op->emitRemark("visitAIEOperands") << type); callBack(operand); } } @@ -661,7 +659,7 @@ struct CIRToAIE : CIRToAIEBase { "using the aie::device"); // Connect directly the aie::tile user to the one produced by the // matching aie.tile - cast.replaceAllUsesWith(cat->getProducerOp(cast.getType(0))); + cast.replaceAllUsesWith(cat->getProducerOp(cast.getType(0)).value()); oldCastsFromDevice.push_back(cast); } }); @@ -728,9 +726,9 @@ struct CIRToAIE : CIRToAIEBase { // Compute the remapping to be done while cloning from the old // operands to the new one produced by the lowered AIE operations cat->visitAIEOperands(scopeOp, [&](auto &operand) { - irm.map( - operand.get(), - cat->getProducerOp(operand.get().getType())->getResult(0)); + // Do not remap + if (auto producer = cat->getProducerOp(operand.get().getType())) + irm.map(operand.get(), producer.value()->getResult(0)); }); b.setInsertionPointToStart(&coreOp.getRegion().front()); auto *clone = b.clone(*scopeOp.getOperation(), irm); @@ -830,8 +828,9 @@ struct CIRToAIE : CIRToAIEBase { auto deviceOp = b.create(u.getLoc(), *deviceId); // The aie.device requires one block deviceOp.getRegion().emplaceBlock(); - cat->setProducerOpWithUCCast(u.getType(0), deviceOp, b); - u->replaceAllUsesWith(cat->getProducerOp(u.getType(0))); + // Keep for now the UnrealizedConversionCastOp for the aie.device since + // aie.device do not returns value + cat->setProducerOp(u.getType(0), deviceOp, b); // Note: aie.device does not require a terminator LLVM_DEBUG(deviceOp.emitRemark("DeviceLowering: end")); return true;