MLIR-AIE 1.4.5.dev
AIELowerCoreReset.cpp
Go to the documentation of this file.
1//===- AIELowerCoreReset.cpp ------------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2026 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
11
12#include "mlir/Dialect/Arith/IR/Arith.h"
13#include "mlir/Pass/Pass.h"
14#include "mlir/Transforms/DialectConversion.h"
15
16namespace xilinx::AIEX {
17#define GEN_PASS_DEF_AIELOWERCORERESET
18#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
19} // namespace xilinx::AIEX
20
21#define DEBUG_TYPE "aie-lower-core-reset"
22
23using namespace mlir;
24using namespace xilinx;
25using namespace xilinx::AIE;
26using namespace xilinx::AIEX;
27
28struct CoreResetToMaskWrite32Pattern : OpConversionPattern<CoreResetOp> {
29 using OpConversionPattern<CoreResetOp>::OpConversionPattern;
30
31 CoreResetToMaskWrite32Pattern(MLIRContext *context)
32 : OpConversionPattern(context) {}
33
34 LogicalResult
35 matchAndRewrite(CoreResetOp op, OpAdaptor adaptor,
36 ConversionPatternRewriter &rewriter) const override {
37 AIE::TileOp tile = op.getTileOp();
38 int col = tile.getCol();
39 int row = tile.getRow();
40
41 AIE::DeviceOp dev = op->getParentOfType<AIE::DeviceOp>();
42 const AIE::AIETargetModel &tm = dev.getTargetModel();
43
44 // Resolve CORE_CONTROL and its reset bit from the register database rather
45 // than restating the layout here. Core tiles only; the verifier rejects
46 // mem/shim, so this is always the "core" module.
47 const AIE::RegisterInfo *ctrlReg =
48 tm.lookupRegister("Core_Control", tile.getTileID());
49 if (!ctrlReg)
50 return op.emitOpError("target has no Core_Control register in its "
51 "register database");
52 const AIE::BitFieldInfo *resetField = ctrlReg->getField("Reset");
53 if (!resetField)
54 return op.emitOpError("Core_Control has no Reset field in the register "
55 "database");
56 std::optional<uint32_t> resetMask = tm.getFieldMask(*resetField);
57 if (!resetMask)
58 return op.emitOpError("Core_Control Reset field does not fit in a 32-bit "
59 "register");
60 std::optional<uint32_t> resetValue = tm.encodeFieldValue(*resetField, 1);
61 if (!resetValue)
62 return op.emitOpError(
63 "Core_Control Reset field value does not fit in its bit width");
64
65 Location loc = op.getLoc();
66 IntegerAttr colAttr = rewriter.getI32IntegerAttr(col);
67 IntegerAttr rowAttr = rewriter.getI32IntegerAttr(row);
68
69 // NpuMaskWrite32Op re-folds col/row from the attributes, so the address
70 // operand is the tile-local offset, mirroring how AIELowerSetLock passes
71 // the local lock address with col/row.
72 //
73 // Reset pulse: assert the reset bit, then clear it. Both writes mask to the
74 // reset bit only, so the pulse preserves the Enable field packed in the
75 // same word instead of clobbering it. This mirrors aie-rt's
76 // XAie_CoreReset/XAie_CoreUnreset, which drive the reset bit with a
77 // MaskWrite32. Constants are materialized in named locals so the emitted IR
78 // order does not depend on unspecified C++ argument-evaluation order.
79 Value assertAddr = createConstantI32(rewriter, loc, ctrlReg->offset);
80 Value assertVal = createConstantI32(rewriter, loc, *resetValue);
81 Value assertMask = createConstantI32(rewriter, loc, *resetMask);
82 NpuMaskWrite32Op::create(rewriter, loc, assertAddr, assertVal, assertMask,
83 nullptr, colAttr, rowAttr);
84
85 Value clearAddr = createConstantI32(rewriter, loc, ctrlReg->offset);
86 Value clearVal = createConstantI32(rewriter, loc, 0u);
87 Value clearMask = createConstantI32(rewriter, loc, *resetMask);
88 rewriter.replaceOpWithNewOp<NpuMaskWrite32Op>(
89 op, clearAddr, clearVal, clearMask, nullptr, colAttr, rowAttr);
90
91 return success();
92 };
93};
94
96 : public xilinx::AIEX::impl::AIELowerCoreResetBase<AIELowerCoreResetPass> {
97 void runOnOperation() override {
98 DeviceOp device = getOperation();
99
100 ConversionTarget target(getContext());
101 target.addLegalOp<NpuMaskWrite32Op>();
102 target.addLegalDialect<arith::ArithDialect>();
103 target.addIllegalOp<CoreResetOp>();
104
105 RewritePatternSet patterns(&getContext());
106 patterns.add<CoreResetToMaskWrite32Pattern>(&getContext());
107
108 SmallVector<Operation *> roots;
109 device.walk([&](CoreResetOp op) { roots.push_back(op); });
110 if (failed(applyPartialConversion(roots, target, std::move(patterns))))
111 signalPassFailure();
112 }
113};
114
115std::unique_ptr<OperationPass<DeviceOp>>
117 return std::make_unique<AIELowerCoreResetPass>();
118}
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIELowerCoreResetPass()
mlir::Value createConstantI32(mlir::OpBuilder &builder, mlir::Location loc, uint32_t value)
void runOnOperation() override
LogicalResult matchAndRewrite(CoreResetOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
CoreResetToMaskWrite32Pattern(MLIRContext *context)
Bit field information for a register.
const BitFieldInfo * getField(llvm::StringRef fieldName) const