26 for (
auto program : device.getOps<DmaBody>()) {
27 for (Block &block : program.getDmaBody()) {
28 for (
auto start : block.getOps<DMAStartOp>()) {
30 if (start.getEndpoint())
32 usedChannels.try_emplace(std::make_tuple(getTileKey(program.getTile()),
33 start.getChannelDir(),
34 start.getChannelIndex()),
35 start.getOperation());
45 auto streamDMA = [&](Value tile, DMAChannelDir dir,
int channel,
47 streamedChannels.try_emplace(
48 std::make_tuple(getTileKey(tile), dir, channel), owner);
50 for (
auto flowOp : device.getOps<FlowOp>()) {
51 if (flowOp.getSourceBundle() == WireBundle::Core) {
52 usedStreams.try_emplace({getTileKey(flowOp.getSource()),
53 DMAChannelDir::MM2S, flowOp.getSourceChannel()},
54 StreamClaim{flowOp,
false});
56 if (flowOp.getDestBundle() == WireBundle::Core) {
57 usedStreams.try_emplace({getTileKey(flowOp.getDest()),
58 DMAChannelDir::S2MM, flowOp.getDestChannel()},
59 StreamClaim{flowOp,
false});
61 if (flowOp.getSourceBundle() == WireBundle::DMA)
62 streamDMA(flowOp.getSource(), DMAChannelDir::MM2S,
63 flowOp.getSourceChannel(), flowOp);
64 if (flowOp.getDestBundle() == WireBundle::DMA)
65 streamDMA(flowOp.getDest(), DMAChannelDir::S2MM, flowOp.getDestChannel(),
68 for (
auto packetFlow : device.getOps<PacketFlowOp>()) {
69 for (
auto source : packetFlow.getOps<PacketSourceOp>())
70 if (source.getBundle() == WireBundle::DMA)
71 streamDMA(source.getTile(), DMAChannelDir::MM2S, source.getChannel(),
73 for (
auto dest : packetFlow.getOps<PacketDestOp>())
74 if (dest.getBundle() == WireBundle::DMA)
75 streamDMA(dest.getTile(), DMAChannelDir::S2MM, dest.getChannel(),
81 device.walk([&](AIEX::DMAConfigureTaskOp task) {
82 usedChannels.try_emplace(std::make_tuple(getTileKey(task.getTile()),
84 (
int)task.getChannel()),
88 for (
auto flow : device.getOps<PacketFlowOp>()) {
89 Block &ports = flow.getPorts().front();
90 for (
auto source : ports.getOps<PacketSourceOp>())
91 if (source.getBundle() == WireBundle::Core)
92 usedStreams.try_emplace({getTileKey(source.getTile()),
93 DMAChannelDir::MM2S, source.channelIndex()},
94 StreamClaim{source,
true});
95 for (
auto dest : ports.getOps<PacketDestOp>())
96 if (dest.getBundle() == WireBundle::Core)
97 usedStreams.try_emplace({getTileKey(dest.getTile()),
98 DMAChannelDir::S2MM, dest.channelIndex()},
99 StreamClaim{dest,
true});
103 for (
auto allocOp : device.getOps<ShimDMAAllocationOp>()) {
104 usedChannels.try_emplace(std::make_tuple(getTileKey(allocOp.getTile()),
105 allocOp.getChannelDir(),
106 (
int)allocOp.getChannelIndex()),
107 allocOp.getOperation());
112 TileLike tile, DMAChannelDir dir,
bool requiresAdjacentTileAccessChannels) {
113 int maxChannelNum = (dir == DMAChannelDir::MM2S)
114 ? tile.getNumSourceConnections(WireBundle::DMA)
115 : tile.getNumDestConnections(WireBundle::DMA);
117 if (!requiresAdjacentTileAccessChannels)
118 return maxChannelNum;
120 std::optional<int> col = tile.tryGetCol();
121 std::optional<int> row = tile.tryGetRow();
124 return std::min<int>(
126 targetModel.getMaxChannelNumForAdjacentMemTile(*col, *row));
130 bool foundPosition =
false;
131 for (
int c = 0; c < targetModel.columns(); ++c) {
132 if (col && c != *col)
134 for (
int r = 0; r < targetModel.rows(); ++r) {
135 if ((row && r != *row) ||
136 targetModel.getTileType(c, r) != tile.getTileType())
138 foundPosition =
true;
139 maxChannelNum = std::min<int>(
140 maxChannelNum, targetModel.getMaxChannelNumForAdjacentMemTile(c, r));
144 return foundPosition ? maxChannelNum : 0;
194 auto [it, inserted] = usedStreams.try_emplace(
195 {getTileKey(tile->getResult(0)), chan.direction, chan.channel},
196 StreamClaim{user, packet});
197 if (inserted || (packet && it->second.packet)) {
200 auto diag = user->emitOpError(
"Core ")
201 << (chan.direction == DMAChannelDir::MM2S ?
"output " :
"input ")
203 <<
" is already in use on this tile; a core stream port carries "
204 "one circuit or only packet flows";
205 diag.attachNote(it->second.owner->getLoc()) <<
"the other stream is here";