From 57ab67c19c1c0ca0758ab569aa702b0c4a168d77 Mon Sep 17 00:00:00 2001 From: max Date: Sat, 4 Nov 2023 18:36:08 -0500 Subject: [PATCH] implement getAsmResultNames --- include/aie/Dialect/AIE/IR/AIE.td | 48 ++++++++++++----- include/aie/Dialect/AIE/IR/AIEInterfaces.td | 19 ++++++- test/find-flows/shim.mlir | 57 ++++++++++++++++++++- 3 files changed, 108 insertions(+), 16 deletions(-) diff --git a/include/aie/Dialect/AIE/IR/AIE.td b/include/aie/Dialect/AIE/IR/AIE.td index adaf6b58af..833b5dd357 100644 --- a/include/aie/Dialect/AIE/IR/AIE.td +++ b/include/aie/Dialect/AIE/IR/AIE.td @@ -110,7 +110,10 @@ def AIE_DeviceOp: AIE_Op<"device", [ let hasVerifier = 1; } -def AIE_TileOp: AIE_Op<"tile", [FlowEndPoint]>, Results<(outs Index:$result)> { +def AIE_TileOp: AIE_Op<"tile", [ + FlowEndPoint, + DeclareOpInterfaceMethods, + ]>, Results<(outs Index:$result)> { let arguments = ( ins ConfinedAttr]>:$col, ConfinedAttr]>:$row @@ -173,6 +176,17 @@ def AIE_TileOp: AIE_Op<"tile", [FlowEndPoint]>, Results<(outs Index:$result)> { $_builder.getI32IntegerAttr(row)); }]> ]; + + let extraClassDefinition = [{ + void $cppClass::getAsmResultNames( + function_ref setNameFn) { + std::string nameWithoutDialect = + getOperationName().str().substr(getOperationName().find('.') + 1); + setNameFn(getResult(), nameWithoutDialect + "_" + + std::to_string(getCol()) + "_" + + std::to_string(getRow())); + } + }]; } def AIE_EndOp: AIE_Op<"end", [Terminator]> { @@ -213,6 +227,7 @@ def AIE_SwitchboxOp: AIE_Op<"switchbox", [ int colIndex(); int rowIndex(); TileOp getTileOp(); + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -280,6 +295,7 @@ def AIE_ShimMuxOp: AIE_Op<"shimmux", [ int getNumSourceConnections(WireBundle bundle); int getNumDestConnections(WireBundle bundle); TileOp getTileOp(); + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -327,7 +343,7 @@ def AIE_ShimDMAOp: AIE_Op<"shimDMA", [ int colIndex(); int rowIndex(); TileOp getTileOp(); - static llvm::StringRef getDefaultDialect() { return "AIE"; } + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; } @@ -378,6 +394,7 @@ def AIE_CoreOp: AIE_Op<"core", [ int rowIndex(); bool isMemWest() { return ((rowIndex() % 2) == 0); }; TileOp getTileOp(); + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -751,7 +768,7 @@ def AIE_DMABDPACKETOp: AIE_Op<"dmaBdPacket", []> { let description = [{ This operation enables packet headers for a block descriptor for DMA operations. In particular, it specifies the packet type (3-bits) and packet ID (5-bits). - + This operation must be used in an MLIR block that lives inside a MemOp's region, and before AIE.dmaBd. The block descriptor specifies what lock to use and the buffer configuration. @@ -765,6 +782,7 @@ def AIE_DMABDPACKETOp: AIE_Op<"dmaBdPacket", []> { AIE.useLock(%lck, "Release", 1) br ^bd6 // point to the next Block, which is also a different Block Descriptor ``` + }]; let arguments = ( @@ -802,7 +820,7 @@ def AIE_DMABDOp: AIE_Op<"dmaBd", []> { let description = [{ This operation describes a block descriptor for DMA operations. In particular, it specifies what buffer addresss to use, the transfer length, and the buffer type (A or B). - + This operation must be used in an MLIR block that lives inside a MemOp's region. The block descriptor specifies what lock to use and the buffer configuration. @@ -836,7 +854,7 @@ def AIE_DMABDOp: AIE_Op<"dmaBd", []> { wrap, the last element of the array gives the lowest-dimension. Strides are always expressed in units of `i32`s; this is an architectural - requirement, as data is moved by the DMA at this fundamental size. + requirement, as data is moved by the DMA at this fundamental size. We can model the access pattern strides and wraps generate by a series of nested loops. In general, a set of strides and wraps like this... @@ -852,14 +870,14 @@ def AIE_DMABDOp: AIE_Op<"dmaBd", []> { for(int i = 0; i < wrap_2; i++) for(int j = 0; j < wrap_1; j++) for(int k = 0; k < wrap_0; k++) - // access/store element at/to buffer[ i * stride_2 - // + j * stride_1 + // access/store element at/to buffer[ i * stride_2 + // + j * stride_1 // + k * stride_0] ``` - The following example shows an access pattern that corresponds to - alternating between even and odd elements of the buffer/stream every 8 - elements: + The following example shows an access pattern that corresponds to + alternating between even and odd elements of the buffer/stream every 8 + elements: ``` AIE.dmaBd(<%buf : memref<128xi32>, 0, 128>, 0, [<8, 16>, <2, 1>, <8, 2>]) @@ -950,7 +968,7 @@ def AIE_DMAStartOp: AIE_Op<"dmaStart", [ ]; } -// MemOps are not actually Callable, but we want to inline code into them, so we have to +// MemOps are not actually Callable, but we want to inline code into them, so we have to // implement CallableOpInterface def AIE_MemOp: AIE_Op<"mem", [ TileElement, FlowEndPoint, CallableOpInterface, @@ -992,7 +1010,7 @@ def AIE_MemOp: AIE_Op<"mem", [ mlir::Region *getCallableRegion(); llvm::ArrayRef getArgumentTypes() { return getOperand().getType(); } llvm::ArrayRef getResultTypes() { return getType(); } - static llvm::StringRef getDefaultDialect() { return "AIE"; } + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -1047,7 +1065,7 @@ def AIE_MemTileDMAOp: AIE_Op<"memTileDMA", [ mlir::Region *getCallableRegion(); llvm::ArrayRef getArgumentTypes() { return getOperand().getType(); } llvm::ArrayRef getResultTypes() { return getType(); } - static llvm::StringRef getDefaultDialect() { return "AIE"; } + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -1132,6 +1150,7 @@ def AIE_LockOp: AIE_Op<"lock", [TileElement]>, Results<(outs Index)> { int colIndex(); int rowIndex(); TileOp getTileOp(); + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; let builders = [ @@ -1229,6 +1248,7 @@ def AIE_BufferOp: AIE_Op<"buffer", [ // Return the number of bytes that need to be allocated for this buffer. int64_t getAllocationSize(); TileOp getTileOp(); + using ::xilinx::AIE::TileElement::Trait::getAsmResultNames; }]; } @@ -1603,6 +1623,8 @@ def AIE_ObjectFifoRegisterExternalBuffersOp: AIE_Op<"objectFifo.registerExternal let extraClassDeclaration = [{ TileOp getTileOp(); ObjectFifoCreateOp getObjectFifo(); + // No results so just use default impl. + using ::mlir::OpAsmOpInterface::Trait::getAsmResultNames; }]; } diff --git a/include/aie/Dialect/AIE/IR/AIEInterfaces.td b/include/aie/Dialect/AIE/IR/AIEInterfaces.td index 223fea1bd7..86732408cc 100644 --- a/include/aie/Dialect/AIE/IR/AIEInterfaces.td +++ b/include/aie/Dialect/AIE/IR/AIEInterfaces.td @@ -14,6 +14,7 @@ include "mlir/IR/OpBase.td" include "mlir/IR/EnumAttr.td" +include "mlir/IR/OpAsmInterface.td" // Op is a DMA-like operation with BD contraints def HasValidBDs : NativeOpTrait<"HasValidBDs"> { @@ -83,7 +84,10 @@ def Interconnect : OpInterface<"Interconnect"> { ]; } -def TileElement : OpInterface<"TileElement"> { + +def TileElement : OpInterface<"TileElement", [ + DeclareOpInterfaceMethods, + ]> { let description = [{ Interface for operations that exist in a TileOp. }]; @@ -98,8 +102,19 @@ def TileElement : OpInterface<"TileElement"> { ConcreteOp op = llvm::cast(this->getOperation()); return op.getTileOp().getTileID(); }] - > + >, ]; + let extraTraitClassDeclaration = [{ + void getAsmResultNames( + llvm::function_ref setNameFn) { + ConcreteOp op = llvm::cast(this->getOperation()); + std::string nameWithoutDialect = + op.getOperationName().str().substr(op.getOperationName().find('.') + 1); + setNameFn(op.getResult(), nameWithoutDialect + "_" + + std::to_string(this->getTileID().col) + "_" + + std::to_string(this->getTileID().row)); + } + }]; } def AIETarget : OpInterface<"AIETarget"> { diff --git a/test/find-flows/shim.mlir b/test/find-flows/shim.mlir index e9b25f57a3..c7dba477b9 100644 --- a/test/find-flows/shim.mlir +++ b/test/find-flows/shim.mlir @@ -8,12 +8,67 @@ // //===----------------------------------------------------------------------===// -// RUN: aie-opt --aie-find-flows %s | FileCheck %s +// RUN: aie-opt --aie-find-flows -split-input-file %s | FileCheck %s // CHECK: %[[VAL_0:.*]] = AIE.tile(2, 1) // CHECK: %[[VAL_1:.*]] = AIE.tile(2, 0) // CHECK: %[[VAL_6:.*]] = AIE.shimDMA(%[[VAL_1]]) // CHECK: AIE.flow(%[[VAL_0]], Core : 0, %[[VAL_6]], DMA : 0) +module { + AIE.device(xcvc1902) { + %t21 = AIE.tile(2, 1) + %t20 = AIE.tile(2, 0) + %c21 = AIE.core(%t21) { + AIE.end + } + %s21 = AIE.switchbox(%t21) { + AIE.connect + } + %s20 = AIE.switchbox(%t20) { + AIE.connect + } + %mux = AIE.shimmux(%t20) { + AIE.connect + } + %dma = AIE.shimDMA(%t20) { + AIE.end + } + AIE.wire(%s21 : South, %s20 : North) + AIE.wire(%s20 : South, %mux : North) + AIE.wire(%mux : DMA, %dma : DMA) + AIE.wire(%mux : South, %t20 : DMA) + AIE.wire(%s21 : Core, %c21 : Core) + AIE.wire(%s21 : Core, %t21 : Core) + } +} + +// ----- + +// CHECK: %tile_2_1 = AIE.tile(2, 1) +// CHECK: %tile_2_0 = AIE.tile(2, 0) +// CHECK: %core_2_1 = AIE.core(%tile_2_1) { +// CHECK: AIE.end +// CHECK: } +// CHECK: %switchbox_2_1 = AIE.switchbox(%tile_2_1) { +// CHECK: AIE.connect +// CHECK: } +// CHECK: %switchbox_2_0 = AIE.switchbox(%tile_2_0) { +// CHECK: AIE.connect +// CHECK: } +// CHECK: %shimmux_2_0 = AIE.shimmux(%tile_2_0) { +// CHECK: AIE.connect +// CHECK: } +// CHECK: %shimDMA_2_0 = AIE.shimDMA(%tile_2_0) { +// CHECK: AIE.end +// CHECK: } +// CHECK: AIE.wire(%switchbox_2_1 : South, %switchbox_2_0 : North) +// CHECK: AIE.wire(%switchbox_2_0 : South, %shimmux_2_0 : North) +// CHECK: AIE.wire(%shimmux_2_0 : DMA, %shimDMA_2_0 : DMA) +// CHECK: AIE.wire(%shimmux_2_0 : South, %tile_2_0 : DMA) +// CHECK: AIE.wire(%switchbox_2_1 : Core, %core_2_1 : Core) +// CHECK: AIE.wire(%switchbox_2_1 : Core, %tile_2_1 : Core) +// CHECK: AIE.flow(%tile_2_1, Core : 0, %shimDMA_2_0, DMA : 0) + module { AIE.device(xcvc1902) { %t21 = AIE.tile(2, 1)