-
Notifications
You must be signed in to change notification settings - Fork 173
Allow multiple devices in one design and add device configuration op (aiex.configure)
#2532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
a61bdd1
415dd91
5ef4d24
ddf1615
22cfe40
6c1f28c
22f76f5
b5ab950
473bbef
deb46ee
6d261d1
3aca900
aa9ccdb
e85e889
102a00e
2741ca5
65065d6
b1f7934
1e428de
991bc3b
19dd016
551b043
272ead7
e016165
71df8a1
52dc724
0088ed6
9063ade
dd1e206
ec9add7
988fd88
deff8c3
08f611d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -47,6 +47,7 @@ createAIEAssignBufferDescriptorIDsPass(); | |||
| std::unique_ptr<mlir::OperationPass<DeviceOp>> | ||||
| createAIEGenerateColumnControlOverlayPass(); | ||||
| std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIEAssignTileCtrlIDsPass(); | ||||
| std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIESetELFforCorePass(); | ||||
|
||||
| std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIESetELFforCorePass(); |
I think this was removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed, thanks for catching this
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,7 @@ def AIECoreToStandard : Pass<"aie-standard-lowering", "mlir::ModuleOp"> { | |
|
|
||
| }]; | ||
| 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", | ||
|
|
@@ -272,4 +273,24 @@ def AIEGenerateColumnControlOverlay : Pass<"aie-generate-column-control-overlay" | |
| ]; | ||
| } | ||
|
|
||
| def AIESetELFforCore : Pass<"aie-set-elf-for-core", "DeviceOp"> { | ||
|
||
| let summary = "Set the ELF file for a core"; | ||
| let description = [{ | ||
| This pass sets the `elf_file` attribute for the given core in the design, | ||
| erasing the core's MLIR body. | ||
| }]; | ||
|
|
||
| let constructor = "xilinx::AIE::createAIESetELFforCorePass()"; | ||
| let dependentDialects = [ | ||
| "xilinx::AIE::AIEDialect", | ||
| ]; | ||
|
|
||
| let options = [ | ||
| Option<"clDevice", "device", "std::string", /*default=*/"\"\"", "Device for whose cores ELF file should be set.">, | ||
| Option<"clTileCol", "col", "unsigned", /*default=*/"0", "Column index of tile to set the ELF file for.">, | ||
| Option<"clTileRow", "row", "unsigned", /*default=*/"0", "Row index of tile to set the ELF file for.">, | ||
| Option<"clElfFile", "elf-file", "std::string", /*default=*/"", "Path to the ELF file to set for the core.">, | ||
| ]; | ||
| } | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //===- AIEUtils.h -----------------------------------------------*- C++ -*-===// | ||
| // | ||
| // 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 2025 Advanced Micro Devices, Inc. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "mlir/Dialect/MemRef/IR/MemRef.h" | ||
| #include "aie/Dialect/AIE/IR/AIEDialect.h" | ||
|
|
||
| using namespace mlir; | ||
|
|
||
| namespace xilinx { | ||
| namespace AIEX { | ||
|
|
||
| memref::GlobalOp getOrCreateDataMemref(OpBuilder &builder, AIE::DeviceOp dev, mlir::Location loc, ArrayRef<uint32_t> words); | ||
|
|
||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ include "aie/Dialect/AIE/IR/AIEInterfaces.td" | |
| include "mlir/IR/OpBase.td" | ||
| include "mlir/IR/AttrTypeBase.td" | ||
| include "mlir/IR/EnumAttr.td" | ||
| include "mlir/IR/BuiltinAttributes.td" | ||
| include "mlir/IR/SymbolInterfaces.td" | ||
| include "mlir/Interfaces/SideEffectInterfaces.td" | ||
| include "mlir/Interfaces/DataLayoutInterfaces.td" | ||
|
|
@@ -527,7 +528,11 @@ def AIE_SelectOp: AIEX_Op<"select", []>, Results<(outs Index)> { | |
| ]; | ||
| } | ||
|
|
||
| def AIE_RuntimeSequenceOp : AIEX_Op<"runtime_sequence", [NoTerminator, HasParent<"AIE::DeviceOp">]> { | ||
| def AIE_RuntimeSequenceOp : AIEX_Op<"runtime_sequence", [ | ||
| Symbol, | ||
| NoTerminator, | ||
| HasParent<"AIE::DeviceOp">, | ||
| ]> { | ||
| let summary = "Program the configuration co-processor of the AI Engine array"; | ||
| let description = [{ | ||
| Instructions in this operation allow for runtime (re-)configuration of the AI Engine array, such as configuring data movement buffer descriptors. | ||
|
|
@@ -537,13 +542,61 @@ def AIE_RuntimeSequenceOp : AIEX_Op<"runtime_sequence", [NoTerminator, HasParent | |
| The input arguments are arguments passed in from the host at kernel invocation time. This may include buffers on the host. | ||
| }]; | ||
| let arguments = ( | ||
| ins OptionalAttr<SymbolNameAttr>:$sym_name | ||
| ins DefaultValuedAttr<SymbolNameAttr, "xilinx::AIEX::defaultRuntimeSequenceName">:$sym_name | ||
| ); | ||
| let regions = (region | ||
| AnyRegion:$body | ||
| ); | ||
| let hasCustomAssemblyFormat = 1; | ||
| let hasVerifier = 1; | ||
| let extraClassDeclaration = [{ | ||
| static RuntimeSequenceOp getForSymbolInDevice(AIE::DeviceOp module, llvm::StringRef symbol); | ||
| static RuntimeSequenceOp getForSymbolInDeviceOrError(AIE::DeviceOp module, llvm::StringRef symbol); | ||
| }]; | ||
| } | ||
|
|
||
| def AIE_ConfigureOp: AIEX_Op<"configure", [ | ||
| HasParent<"RuntimeSequenceOp">, | ||
| NoTerminator | ||
| ]>, | ||
| Results<(outs Index:$result)> | ||
| { | ||
| let summary = "Set up a configuration (program memories, stream switches, etc.) on the NPU device."; | ||
| let arguments = ( | ||
| ins FlatSymbolRefAttr:$symbol | ||
| ); | ||
|
|
||
| let assemblyFormat = [{ | ||
| $symbol regions attr-dict | ||
| }]; | ||
|
|
||
| let extraClassDeclaration = [{ | ||
| AIE::DeviceOp getReferencedDeviceOp(); | ||
| }]; | ||
|
|
||
| let regions = (region | ||
| AnyRegion:$body | ||
| ); | ||
|
|
||
| let hasVerifier = 1; | ||
| } | ||
|
|
||
| def AIE_RunOp: AIEX_Op<"run", [HasParent<"ConfigureOp">]> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add a short summary for this operation?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
| let arguments = ( | ||
| ins FlatSymbolRefAttr:$runtime_sequence_symbol, | ||
| Variadic<AnyType>:$args | ||
| ); | ||
|
|
||
| let assemblyFormat = [{ | ||
| $runtime_sequence_symbol `(` $args `)` `:` `(` type($args) `)` attr-dict | ||
| }]; | ||
|
|
||
| let extraClassDeclaration = [{ | ||
| AIE::DeviceOp getCalleeDeviceOp(); | ||
| RuntimeSequenceOp getCalleeRuntimeSequenceOp(); | ||
| }]; | ||
|
|
||
| let hasVerifier = 1; | ||
| } | ||
|
|
||
| def AIE_NpuDmaMemcpyNdOp: AIEX_Op<"npu.dma_memcpy_nd", [ | ||
|
|
@@ -772,6 +825,9 @@ def AIE_NpuWrite32Op: AIEX_Op<"npu.write32", []> { | |
| If 'buffer' is not present and 'column' and 'row' are not present then | ||
| 'address' is interpreted as a full 32-bit address in the AIE array. | ||
| }]; | ||
| let extraClassDeclaration = [{ | ||
| std::optional<uint32_t> getAbsoluteAddress(); | ||
| }]; | ||
| } | ||
|
|
||
| // MASKWRITE | ||
|
|
@@ -798,6 +854,9 @@ def AIE_NpuMaskWrite32Op: AIEX_Op<"npu.maskwrite32", []> { | |
| If 'buffer' is not present and 'column' and 'row' are not present then | ||
| 'address' is interpreted as a full 32-bit address in the AIE array. | ||
| }]; | ||
| let extraClassDeclaration = [{ | ||
| std::optional<uint32_t> getAbsoluteAddress(); | ||
| }]; | ||
| } | ||
|
|
||
| // BLOCKWRITE | ||
|
|
@@ -823,6 +882,10 @@ def AIE_NpuBlockWriteOp: AIEX_Op<"npu.blockwrite", []> { | |
| If 'buffer' is not present and 'column' and 'row' are not present then | ||
| 'address' is interpreted as a full 32-bit address in the AIE array. | ||
| }]; | ||
| let extraClassDeclaration = [{ | ||
| std::optional<uint32_t> getAbsoluteAddress(); | ||
| mlir::DenseIntElementsAttr getDataWords(); | ||
| }]; | ||
| } | ||
|
|
||
| // OP_SYNC | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,12 @@ | |
|
|
||
| #include "aie/Dialect/AIE/IR/AIEDialect.h" | ||
|
|
||
| #include "mlir/IR/BuiltinAttributes.h" | ||
|
|
||
| namespace xilinx::AIEX { | ||
| const char defaultRuntimeSequenceName[] = "sequence"; | ||
|
||
| } | ||
|
|
||
| // Include dialect declarations such as parseAttributes, parseType | ||
| #include "aie/Dialect/AIEX/IR/AIEXDialect.h.inc" | ||
| #include "mlir/IR/Operation.h" | ||
|
|
@@ -24,6 +30,10 @@ | |
| #define GET_TYPEDEF_CLASSES | ||
| #include "aie/Dialect/AIEX/IR/AIEXTypes.h.inc" | ||
|
|
||
| #include "llvm/ADT/StringRef.h" | ||
|
|
||
| #include <optional> | ||
|
|
||
| namespace xilinx { | ||
| namespace AIEX { | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does the presence of the attribute require that the core body is deleted? It seems to hard code things for the current aiecc use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it would be more clear this way, removing the ambiguity of which code gets executed if both the attribute is there and there is code inside the body. If this complicates some use case I'm not aware of, I can remove this restriction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have left this check in place for now. Let me know if you want to discuss it further.