12#include "mlir/IR/PatternMatch.h"
13#include "mlir/Pass/Pass.h"
14#include "mlir/Transforms/DialectConversion.h"
19#define GEN_PASS_DEF_AIELEGALIZECONTROLPACKET
20#define GEN_PASS_DEF_AIETXNTOCONTROLPACKET
21#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
24#define DEBUG_TYPE "aie-txn-to-control"
32struct BlockWriteToControlPacketPattern
36 LogicalResult matchAndRewrite(AIEX::NpuBlockWriteOp op,
37 PatternRewriter &rewriter)
const override {
39 Value
memref = op.getData();
40 int64_t width = cast<MemRefType>(
memref.getType()).getElementTypeBitWidth();
42 return op.emitWarning(
"Only 32-bit data type is supported for now");
45 memref::GetGlobalOp getGlobal =
memref.getDefiningOp<memref::GetGlobalOp>();
47 return op.emitError(
"Only MemRefs from memref.get_global are supported");
50 auto global = dyn_cast_if_present<memref::GlobalOp>(
51 op->getParentOfType<AIE::DeviceOp>().lookupSymbol(getGlobal.getName()));
53 return op.emitError(
"Global symbol not found");
56 auto initVal = global.getInitialValue();
58 return op.emitError(
"Global symbol has no initial value");
61 auto data = dyn_cast<DenseIntElementsAttr>(*initVal);
64 "Global symbol initial value is not a dense int array");
66 std::vector<int32_t> dataVec(data.value_begin<int32_t>(),
67 data.value_end<int32_t>());
68 AIEX::NpuControlPacketOp::create(
69 rewriter, op->getLoc(), op.getAddressAttr(),
nullptr,
70 rewriter.getI32IntegerAttr(0),
71 rewriter.getI32IntegerAttr(0),
72 DenseI32ArrayAttr::get(op->getContext(), dataVec));
80static bool fitsInLine(AIEX::NpuControlPacketOp op, uint32_t maxWords) {
81 uint32_t wordInLine = (op.getAddress() /
sizeof(uint32_t)) % maxWords;
82 return wordInLine + op.getDataAttr().size() <= maxWords;
86struct ControlPacketSplitPattern
90 ControlPacketSplitPattern(MLIRContext *ctx, uint32_t max_payload_size)
93 LogicalResult matchAndRewrite(AIEX::NpuControlPacketOp op,
94 PatternRewriter &rewriter)
const override {
95 auto data = op.getData();
96 if (!data || fitsInLine(op, max_payload_size))
99 auto *context = op.getContext();
100 auto loc = op.getLoc();
101 uint32_t address = op.getAddress();
102 for (
const auto *it = data->begin(); it != data->end();) {
103 uint32_t wordInLine = (address /
sizeof(uint32_t)) % max_payload_size;
105 std::min<uint32_t>(max_payload_size - wordInLine, data->end() - it);
106 SmallVector<int32_t, 4> chunkData(it, it + count);
107 AIEX::NpuControlPacketOp::create(
108 rewriter, loc, rewriter.getUI32IntegerAttr(address),
nullptr,
109 op.getOpcodeAttr(), op.getStreamIdAttr(),
110 DenseI32ArrayAttr::get(context, chunkData));
111 address += count *
sizeof(uint32_t);
115 rewriter.eraseOp(op);
120 uint32_t max_payload_size;
123struct AIETxnToControlPacketPass
124 :
public xilinx::AIEX::impl::AIETxnToControlPacketBase<
125 AIETxnToControlPacketPass> {
126 void runOnOperation()
override {
127 AIE::DeviceOp device = getOperation();
129 ConversionTarget target(getContext());
130 target.addIllegalOp<AIEX::NpuBlockWriteOp>();
131 target.addLegalOp<AIEX::NpuControlPacketOp>();
133 RewritePatternSet patterns(&getContext());
134 patterns.add<BlockWriteToControlPacketPattern>(&getContext());
136 if (failed(applyPartialConversion(device, target, std::move(patterns)))) {
142struct AIELegalizeControlPacketPass
143 :
public xilinx::AIEX::impl::AIELegalizeControlPacketBase<
144 AIELegalizeControlPacketPass> {
145 void runOnOperation()
override {
146 AIE::DeviceOp device = getOperation();
148 ConversionTarget target(getContext());
149 target.addDynamicallyLegalOp<AIEX::NpuControlPacketOp>([](Operation *op) {
150 auto packetOp = cast<AIEX::NpuControlPacketOp>(op);
151 return !packetOp.getData() || fitsInLine(packetOp, 4);
154 RewritePatternSet patterns(&getContext());
155 patterns.add<ControlPacketSplitPattern>(&getContext(), 4);
157 if (failed(applyPartialConversion(device, target, std::move(patterns)))) {
165std::unique_ptr<OperationPass<AIE::DeviceOp>>
167 return std::make_unique<AIETxnToControlPacketPass>();
170std::unique_ptr<OperationPass<AIE::DeviceOp>>
172 return std::make_unique<AIELegalizeControlPacketPass>();
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIETxnToControlPacketPass()
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIELegalizeControlPacketPass()