MLIR-AIE 1.4.6.dev
AIEAssignPacketIds.cpp
Go to the documentation of this file.
1//===- AIEAssignPacketIds.cpp -----------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2026 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
12
13#include "mlir/Pass/Pass.h"
14
15using namespace mlir;
16using namespace xilinx;
17using namespace xilinx::AIE;
18
19namespace xilinx::AIE {
20#define GEN_PASS_DEF_AIEASSIGNPACKETIDS
21#include "aie/Dialect/AIE/Transforms/AIEPasses.h.inc"
22} // namespace xilinx::AIE
23
24namespace {
25
26struct AIEAssignPacketIdsPass
27 : public xilinx::AIE::impl::AIEAssignPacketIdsBase<AIEAssignPacketIdsPass> {
28 using Base::Base;
29
30 void runOnOperation() override {
31 DeviceOp device = getOperation();
32 if (clReserveControllerPacketIds)
33 AIEDialect::ReserveControllerPacketIdsAttrHelper(device.getContext())
34 .setAttr(device, UnitAttr::get(device.getContext()));
35 PacketIdSpace space(device);
36
37 // Pinned ids are checked before any are handed out, so a bad pin is
38 // reported as one rather than surfacing as an exhausted field.
39 for (auto route : device.getOps<RouteOp>()) {
40 std::optional<PacketInfoAttr> packet = route.getPacket();
41 if (packet && packet->isAssigned() &&
42 packet->assignedId() > space.maxId()) {
43 route.emitOpError("pkt_id ")
44 << packet->assignedId() << " is out of range (max " << space.maxId()
45 << ")";
46 return signalPassFailure();
47 }
48 }
49
50 // Ids go out in structural order, so a design declared in another order
51 // or under other names gets the same ones.
52 // The pass flag is a default for routes that express no preference, so a
53 // device may mix circuit- and packet-switched connections.
54 SmallVector<RouteOp> unpinned;
55 for (auto route : device.getOps<RouteOp>()) {
56 std::optional<PacketInfoAttr> packet = route.getPacket();
57 if ((packet || clPacketSwObjectFifos) &&
58 !(packet && packet->isAssigned()))
59 unpinned.push_back(route);
60 }
61 if (unpinned.size() > 1) {
62 DenseMap<Operation *, unsigned> rank = StructuralGraph::of(device).rank();
63 llvm::stable_sort(unpinned, [&](RouteOp a, RouteOp b) {
64 return rank.lookup(a) < rank.lookup(b);
65 });
66 }
67
68 // A DMA program states its BDs' header itself, so it cannot use an id
69 // handed out here. Indexed once instead of a device-wide
70 // SymbolTable::getSymbolUses walk per unpinned route's source: the first
71 // DMAStartOp naming a given endpoint is all the loop below needs.
72 DenseMap<StringRef, DMAStartOp> dmaStartByEndpoint;
73 device.walk([&](DMAStartOp start) {
74 if (FlatSymbolRefAttr name = start.getEndpoint())
75 dmaStartByEndpoint.try_emplace(name.getValue(), start);
76 });
77
78 for (auto route : unpinned) {
79 std::optional<PacketInfoAttr> packet = route.getPacket();
80 for (StringRef source : route.getSourceNames()) {
81 auto it = dmaStartByEndpoint.find(source);
82 if (it == dmaStartByEndpoint.end())
83 continue;
84 it->second.emitOpError("names @")
85 << source
86 << ", the source of a packet-switched route without a pinned "
87 "pkt_id; pin pkt_id on each route it sources and state that "
88 "header in each of the program's BDs";
89 return signalPassFailure();
90 }
91 std::optional<int> id = space.takeLowestFrom();
92 if (!id) {
93 route.emitOpError("max number of packet IDs reached");
94 return signalPassFailure();
95 }
96 uint16_t type = packet ? packet->getPktType() : 0;
97 route.setPacketAttr(PacketInfoAttr::get(device.getContext(), type, *id));
98 }
99 }
100};
101
102} // namespace
103
104std::unique_ptr<OperationPass<DeviceOp>>
106 return std::make_unique<AIEAssignPacketIdsPass>();
107}
108
109std::unique_ptr<OperationPass<DeviceOp>>
111 bool reserveControllerPacketIds) {
112 AIEAssignPacketIdsOptions options;
113 options.clPacketSwObjectFifos = packetSwitched;
114 options.clReserveControllerPacketIds = reserveControllerPacketIds;
115 return std::make_unique<AIEAssignPacketIdsPass>(options);
116}
std::optional< int > takeLowestFrom(int from=0)
Takes and returns the lowest free id at or above from, or nothing when the field is exhausted.
int maxId() const
The largest id the target's header field holds.
std::unique_ptr< mlir::OperationPass< DeviceOp > > createAIEAssignPacketIdsPass()
llvm::DenseMap< mlir::Operation *, unsigned > rank() const
Rank the nodes by their features and then, a round at a time until no class splits,...
static StructuralGraph of(DeviceOp device)
The ops directly in device but its runtime sequences, each with the ops nested in it,...