From b39945242f7f0b8f274132f70a84b32ac5f81163 Mon Sep 17 00:00:00 2001 From: Stephen Neuendorffer Date: Tue, 5 Dec 2023 15:51:40 -0800 Subject: [PATCH] [AIE2] Fix support for cascade ops Cascade operations operate on wide data types, 512-bits wide in aie2. This patch generalizes the dialect support for cascade to go through backend code generation. --- include/aie/Dialect/AIE/IR/AIEOps.td | 12 ++++--- lib/Dialect/AIE/IR/AIEDialect.cpp | 34 +++++++++++++++++++ .../AIE/Transforms/AIECoreToStandard.cpp | 23 +++++++++---- test/dialect/AIE/badcascade-vc1902.mlir | 23 +++++++++++++ test/dialect/AIE/badcascade-ve2802.mlir | 23 +++++++++++++ test/dialect/AIE/badgetcascade-vc1902.mlir | 22 ++++++++++++ test/dialect/AIE/badgetcascade-ve2802.mlir | 22 ++++++++++++ test/dialect/AIE/cascade-vc1902.mlir | 23 +++++++++++++ test/dialect/AIE/cascade-ve2802.mlir | 23 +++++++++++++ 9 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 test/dialect/AIE/badcascade-vc1902.mlir create mode 100644 test/dialect/AIE/badcascade-ve2802.mlir create mode 100644 test/dialect/AIE/badgetcascade-vc1902.mlir create mode 100644 test/dialect/AIE/badgetcascade-ve2802.mlir create mode 100644 test/dialect/AIE/cascade-vc1902.mlir create mode 100644 test/dialect/AIE/cascade-ve2802.mlir diff --git a/include/aie/Dialect/AIE/IR/AIEOps.td b/include/aie/Dialect/AIE/IR/AIEOps.td index 76f6d4c608..baf04dd9ee 100644 --- a/include/aie/Dialect/AIE/IR/AIEOps.td +++ b/include/aie/Dialect/AIE/IR/AIEOps.td @@ -1279,12 +1279,14 @@ def AIE_PutStreamOp: AIE_Op<"putStream", [HasParent<"CoreOp">]> { }]; } -def AIE_GetCascadeOp: AIE_Op<"getCascade", [HasParent<"CoreOp">]>, Results<(outs AnyI<384>)> { +def AIE_GetCascadeOp: AIE_Op<"getCascade", [HasParent<"CoreOp">]>, Results<(outs AnyType:$cascadeValue)> { let summary = "An op to read from a cascading stream from a neighboring core"; let description = [{ An op to read from a cascading stream from a neighboring core. + The result type of this operation must have a size that matches the cascade size, + which is architecture-dependent. e.g. AIE1: i384 or vector<8xi48> AIE2: i512 or vector<16xi32> }]; - let results = (outs AnyI<384>:$cascadeValue); + let hasVerifier = 1; let assemblyFormat = [{ `(` `)` attr-dict `:` type($cascadeValue) }]; } @@ -1292,10 +1294,12 @@ def AIE_PutCascadeOp: AIE_Op<"putCascade", [HasParent<"CoreOp">]> { let summary = "An op to write to a cascading stream from a neighboring core"; let description = [{ An op to write to a cascading stream from a neighboring core. + The argument type of this operation must have a size that matches the cascade size, + which is architecture-dependent. e.g. AIE1: i384 or vector<8xi48> AIE2: i512 or vector<16xi32> }]; - let arguments = (ins AnyI<384>:$cascadeValue); - + let arguments = (ins AnyType:$cascadeValue); + let hasVerifier = 1; let assemblyFormat = [{ `(` $cascadeValue `:` type($cascadeValue) `)` attr-dict }]; } diff --git a/lib/Dialect/AIE/IR/AIEDialect.cpp b/lib/Dialect/AIE/IR/AIEDialect.cpp index e4b9eefcbf..e8666c078d 100644 --- a/lib/Dialect/AIE/IR/AIEDialect.cpp +++ b/lib/Dialect/AIE/IR/AIEDialect.cpp @@ -802,6 +802,40 @@ ObjectFifoCreateOp ObjectFifoRegisterProcessOp::getObjectFifo() { return {}; } +// PutCascadeOp +LogicalResult PutCascadeOp::verify() { + const auto &targetModel = getTargetModel(*this); + Type type = getCascadeValue().getType(); + DataLayout dataLayout = DataLayout::closest(*this); + auto bits = dataLayout.getTypeSizeInBits(type); + if(targetModel.getTargetArch() == AIEArch::AIE1) { + if(bits != 384) + return emitOpError("must be a 384-bit type"); + } else if(targetModel.getTargetArch() == AIEArch::AIE2) { + if(bits != 512) + return emitOpError("must be a 512-bit type"); + } else + return emitOpError("cascade not supported in ") << stringifyAIEArch(targetModel.getTargetArch()); + return success(); +} + +// GetCascadeOp +LogicalResult GetCascadeOp::verify() { + const auto &targetModel = getTargetModel(*this); + Type type = getCascadeValue().getType(); + DataLayout dataLayout = DataLayout::closest(*this); + auto bits = dataLayout.getTypeSizeInBits(type); + if(targetModel.getTargetArch() == AIEArch::AIE1) { + if(bits != 384) + return emitOpError("must be a 384-bit type"); + } else if(targetModel.getTargetArch() == AIEArch::AIE2) { + if(bits != 512) + return emitOpError("must be a 512-bit type"); + } else + return emitOpError("cascade not supported in ") << stringifyAIEArch(targetModel.getTargetArch()); + return success(); +} + const AIETargetModel &DeviceOp::getTargetModel() { switch (getDevice()) { case AIEDevice::xcvc1902: diff --git a/lib/Dialect/AIE/Transforms/AIECoreToStandard.cpp b/lib/Dialect/AIE/Transforms/AIECoreToStandard.cpp index 1265264ec0..7ae05e4846 100644 --- a/lib/Dialect/AIE/Transforms/AIECoreToStandard.cpp +++ b/lib/Dialect/AIE/Transforms/AIECoreToStandard.cpp @@ -86,13 +86,13 @@ static auto getAIE1Intrinsics(OpBuilder &builder) { static auto getAIE2Intrinsics(OpBuilder &builder) { Type int32Type = IntegerType::get(builder.getContext(), 32); - Type int512Type = IntegerType::get(builder.getContext(), 512); + Type accType = VectorType::get({16}, int32Type); IntrinsicDecls functions = { {"debug_i32", {int32Type}, {}}, {"llvm.aie2.put.ms", {int32Type, int32Type}, {}}, //(%value, %tlast) -> () {"llvm.aie2.get.ss", {}, {int32Type, int32Type}}, //() -> (%value, %tlast) - {"llvm.aie2.put.mcd", {int512Type}, {}}, - {"llvm.aie2.get.scd", {}, {int512Type}}, + {"llvm.aie2.mcd.write.vec", {accType, int32Type}, {}}, // (%value, %enable) -> () + {"llvm.aie2.scd.read.vec", {int32Type}, {accType}}, // (%enable) -> (%value) {"llvm.aie2.acquire", {int32Type, int32Type}, {}}, //(%lock_id, %lock_val) -> () @@ -275,13 +275,18 @@ struct AIEPutCascadeToStdLowering : OpConversionPattern { if (targetModel.getTargetArch() == AIEArch::AIE1) funcName = "llvm.aie.put.mcd"; else - funcName = "llvm.aie2.put.mcd"; + funcName = "llvm.aie2.mcd.write.vec"; auto putMCDFunc = module.lookupSymbol(funcName); if (!putMCDFunc) return op.emitOpError("Could not find the intrinsic function ") << funcName; SmallVector args; args.push_back(op.getCascadeValue()); + if (targetModel.getTargetArch() == AIEArch::AIE2) + args.push_back(rewriter.create( + op.getLoc(), IntegerType::get(rewriter.getContext(), 32), + rewriter.getI32IntegerAttr(1))); // enable + rewriter.create(rewriter.getUnknownLoc(), putMCDFunc, args); rewriter.eraseOp(Op); return success(); @@ -305,13 +310,19 @@ struct AIEGetCascadeToStdLowering : OpConversionPattern { if (targetModel.getTargetArch() == AIEArch::AIE1) funcName = "llvm.aie.get.scd"; else - funcName = "llvm.aie2.get.scd"; + funcName = "llvm.aie2.scd.read.vec"; auto getSCDFunc = module.lookupSymbol(funcName); if (!getSCDFunc) return op.emitOpError("Could not find the intrinsic function ") << funcName; + SmallVector args; + if (targetModel.getTargetArch() == AIEArch::AIE2) + args.push_back(rewriter.create( + op.getLoc(), IntegerType::get(rewriter.getContext(), 32), + rewriter.getI32IntegerAttr(1))); // enable + auto getSCDCall = rewriter.create(rewriter.getUnknownLoc(), - getSCDFunc, ValueRange({})); + getSCDFunc, args); rewriter.replaceOp(op, getSCDCall.getResult(0)); return success(); } diff --git a/test/dialect/AIE/badcascade-vc1902.mlir b/test/dialect/AIE/badcascade-vc1902.mlir new file mode 100644 index 0000000000..a393193d84 --- /dev/null +++ b/test/dialect/AIE/badcascade-vc1902.mlir @@ -0,0 +1,23 @@ +//===- badcore.mlir --------------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: not aie-opt %s 2>&1 | FileCheck %s +// CHECK: error{{.*}}'AIE.putCascade' op must be a 384-bit type + +module @test { + AIE.device(xcvc1902) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = arith.constant 1 : i64 + AIE.putCascade(%val2: i64) + AIE.end + } + } +} diff --git a/test/dialect/AIE/badcascade-ve2802.mlir b/test/dialect/AIE/badcascade-ve2802.mlir new file mode 100644 index 0000000000..23c592a211 --- /dev/null +++ b/test/dialect/AIE/badcascade-ve2802.mlir @@ -0,0 +1,23 @@ +//===- badcore.mlir --------------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: not aie-opt %s 2>&1 | FileCheck %s +// CHECK: error{{.*}}'AIE.putCascade' op must be a 512-bit type + +module @test { + AIE.device(xcve2802) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = arith.constant 1 : i64 + AIE.putCascade(%val2: i64) + AIE.end + } + } +} diff --git a/test/dialect/AIE/badgetcascade-vc1902.mlir b/test/dialect/AIE/badgetcascade-vc1902.mlir new file mode 100644 index 0000000000..3105c44b25 --- /dev/null +++ b/test/dialect/AIE/badgetcascade-vc1902.mlir @@ -0,0 +1,22 @@ +//===- badcore.mlir --------------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: not aie-opt %s 2>&1 | FileCheck %s +// CHECK: error{{.*}}'AIE.getCascade' op must be a 384-bit type + +module @test { + AIE.device(xcvc1902) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = AIE.getCascade() : i64 + AIE.end + } + } +} diff --git a/test/dialect/AIE/badgetcascade-ve2802.mlir b/test/dialect/AIE/badgetcascade-ve2802.mlir new file mode 100644 index 0000000000..bd822919ae --- /dev/null +++ b/test/dialect/AIE/badgetcascade-ve2802.mlir @@ -0,0 +1,22 @@ +//===- badcore.mlir --------------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: not aie-opt %s 2>&1 | FileCheck %s +// CHECK: error{{.*}}'AIE.getCascade' op must be a 512-bit type + +module @test { + AIE.device(xcve2802) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = AIE.getCascade() : i64 + AIE.end + } + } +} diff --git a/test/dialect/AIE/cascade-vc1902.mlir b/test/dialect/AIE/cascade-vc1902.mlir new file mode 100644 index 0000000000..601c633124 --- /dev/null +++ b/test/dialect/AIE/cascade-vc1902.mlir @@ -0,0 +1,23 @@ +// NOTE: Assertions have been autogenerated by utils/update_mlir_test_checks.py +//===- cascade-ve2802.mlir -------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: aie-opt %s + +module @test { + AIE.device(xcvc1902) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = AIE.getCascade() : i384 + AIE.putCascade(%val2: i384) + AIE.end + } + } +} diff --git a/test/dialect/AIE/cascade-ve2802.mlir b/test/dialect/AIE/cascade-ve2802.mlir new file mode 100644 index 0000000000..6423332949 --- /dev/null +++ b/test/dialect/AIE/cascade-ve2802.mlir @@ -0,0 +1,23 @@ +//===- cascade-ve2802.mlir -------------------------------------*- MLIR -*-===// +// +// 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 2023 Advanced Micro Devices, Inc. +// +//===----------------------------------------------------------------------===// + +// RUN: aie-opt %s + +module @test { + AIE.device(xcve2802) { + %t33 = AIE.tile(3, 3) + %c33 = AIE.core(%t33) { + %val2 = AIE.getCascade() : vector<16xi32> + AIE.putCascade(%val2: vector<16xi32>) + AIE.end + + } + } +}