MLIR-AIE 1.4.5.dev
AIELowerSetLock.cpp
Go to the documentation of this file.
1//===- AIELowerSetLock.cpp --------------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2025 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
13
14#include "mlir/Dialect/Arith/IR/Arith.h"
15#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16#include "mlir/Pass/Pass.h"
17#include "mlir/Transforms/DialectConversion.h"
18
19namespace xilinx::AIEX {
20#define GEN_PASS_DEF_AIELOWERSETLOCK
21#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
22} // namespace xilinx::AIEX
23
24#define DEBUG_TYPE "aie-lower-set-lock"
25
26using namespace mlir;
27using namespace xilinx;
28using namespace xilinx::AIE;
29using namespace xilinx::AIEX;
30
31struct SetLockToWrite32Pattern : OpConversionPattern<SetLockOp> {
32 using OpConversionPattern<SetLockOp>::OpConversionPattern;
33
34public:
35 SetLockToWrite32Pattern(MLIRContext *context)
36 : OpConversionPattern(context) {}
37
38 LogicalResult
39 matchAndRewrite(SetLockOp op, OpAdaptor adaptor,
40 ConversionPatternRewriter &rewriter) const override {
41 AIE::DeviceOp dev = op->getParentOfType<AIE::DeviceOp>();
42 const AIE::AIETargetModel &tm = dev.getTargetModel();
43
44 auto lockOp = op.getLockOp();
45 if (!lockOp.getLockID()) {
46 op->emitError("Tried to lower a SetLockOp on an unassigned lock");
47 return failure();
48 }
49
50 auto col = lockOp.colIndex();
51 auto row = lockOp.rowIndex();
52 uint32_t lockID = lockOp.getLockIDValue();
53
54 // The validity of this optional is already checked in the verifier.
55 auto localLockAddressOpt =
56 tm.getLocalLockAddress(lockID, lockOp.getTileID());
57 assert(localLockAddressOpt && "verifier guarantees a valid lock address");
58 auto localLockAddress = *localLockAddressOpt;
59
60 Location loc = op.getLoc();
61 Value value = adaptor.getValue();
62 uint32_t maxValue = tm.getMaxLockValue();
63 Value inRange = rewriter.createOrFold<arith::CmpIOp>(
64 loc, arith::CmpIPredicate::ule, value,
65 createConstantI32(rewriter, loc, maxValue));
66 if (failed(emitRuntimeCheck(
67 rewriter, loc, inRange,
68 "a runtime lock value must be in [0:" + Twine(maxValue) + "]")))
69 return failure();
70 rewriter.replaceOpWithNewOp<NpuWrite32Op>(
71 op, createConstantI32(rewriter, loc, localLockAddress), value, nullptr,
72 rewriter.getI32IntegerAttr(col), rewriter.getI32IntegerAttr(row));
73
74 return success();
75 };
76};
77
79 : public xilinx::AIEX::impl::AIELowerSetLockBase<AIELowerSetLockPass> {
80 void runOnOperation() override {
81
82 DeviceOp device = getOperation();
83
84 ConversionTarget target(getContext());
85 target.addLegalOp<NpuWrite32Op, cf::AssertOp>();
86 target.addLegalDialect<arith::ArithDialect>();
87 target.addIllegalOp<SetLockOp>();
88
89 RewritePatternSet patterns(&getContext());
90 patterns.add<SetLockToWrite32Pattern>(&getContext());
91
92 SmallVector<Operation *> roots;
93 device.walk([&](SetLockOp op) { roots.push_back(op); });
94 if (failed(applyPartialConversion(roots, target, std::move(patterns)))) {
95 signalPassFailure();
96 }
97 }
98};
99
100std::unique_ptr<OperationPass<DeviceOp>>
102 return std::make_unique<AIELowerSetLockPass>();
103}
virtual std::optional< uint32_t > getLocalLockAddress(uint32_t lockId, TileID tile) const =0
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIELowerSetLockPass()
mlir::LogicalResult emitRuntimeCheck(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value cond, const llvm::Twine &message)
mlir::Value createConstantI32(mlir::OpBuilder &builder, mlir::Location loc, uint32_t value)
void runOnOperation() override
LogicalResult matchAndRewrite(SetLockOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
SetLockToWrite32Pattern(MLIRContext *context)