MLIR-AIE
AIETargetModel.cpp
Go to the documentation of this file.
1//===- AIETargetModel.cpp ---------------------------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// (c) Copyright 2019 Xilinx Inc.
8// (c) Copyright 2023 Advanced Micro Devices, Inc.
9//
10//===----------------------------------------------------------------------===//
11
13#include <cstdint>
14#include <utility>
15
16using namespace llvm;
17
18namespace xilinx {
19namespace AIE {
21
22///
23/// AIE1 TargetModel
24///
25
26AIEArch AIE1TargetModel::getTargetArch() const { return AIEArch::AIE1; }
27
28// Return the tile ID of the memory to the west of the given tile, if it exists.
29std::optional<TileID> AIE1TargetModel::getMemWest(TileID src) const {
30 bool isEvenRow = ((src.row % 2) == 0);
31 std::optional<TileID> ret;
32 if (isEvenRow)
33 ret = src;
34 else
35 ret = {src.col - 1, src.row};
36 if (!isValidTile(*ret))
37 ret.reset();
38 return ret;
39}
40
41// Return the tile ID of the memory to the west of the given tile, if it exists.
42std::optional<TileID> AIE1TargetModel::getMemEast(TileID src) const {
43 bool isEvenRow = (src.row % 2) == 0;
44 std::optional<TileID> ret;
45 if (isEvenRow)
46 ret = {src.col + 1, src.row};
47 else
48 ret = src;
49 if (!isValidTile(*ret))
50 ret.reset();
51 return ret;
52}
53
54// Return the tile ID of the memory to the west of the given tile, if it exists.
55std::optional<TileID> AIE1TargetModel::getMemNorth(TileID src) const {
56 std::optional<TileID> ret({src.col, src.row + 1});
57 if (!isValidTile(*ret))
58 ret.reset();
59 return ret;
60}
61
62std::optional<TileID> AIE1TargetModel::getMemSouth(TileID src) const {
63 std::optional<TileID> ret({src.col, src.row - 1});
64 // The first row doesn't have a tile memory south
65 if (!isValidTile(*ret) || ret->row == 0)
66 ret.reset();
67 return ret;
68}
69
70bool AIE1TargetModel::isMemWest(int srcCol, int srcRow, int dstCol,
71 int dstRow) const {
72 bool IsEvenRow = (srcRow % 2) == 0;
73 return (IsEvenRow && isInternal(srcCol, srcRow, dstCol, dstRow)) ||
74 (!IsEvenRow && isWest(srcCol, srcRow, dstCol, dstRow));
75}
76
77bool AIE1TargetModel::isMemEast(int srcCol, int srcRow, int dstCol,
78 int dstRow) const {
79 bool IsEvenRow = (srcRow % 2) == 0;
80 return (!IsEvenRow && isInternal(srcCol, srcRow, dstCol, dstRow)) ||
81 (IsEvenRow && isEast(srcCol, srcRow, dstCol, dstRow));
82}
83
84bool AIE1TargetModel::isMemNorth(int srcCol, int srcRow, int dstCol,
85 int dstRow) const {
86 return isNorth(srcCol, srcRow, dstCol, dstRow);
87}
88
89bool AIE1TargetModel::isMemSouth(int srcCol, int srcRow, int dstCol,
90 int dstRow) const {
91 return isSouth(srcCol, srcRow, dstCol, dstRow);
92}
93
94bool AIE1TargetModel::isLegalMemAffinity(int coreCol, int coreRow, int memCol,
95 int memRow) const {
96 bool IsEvenRow = ((coreRow % 2) == 0);
97
98 bool IsMemWest = (isWest(coreCol, coreRow, memCol, memRow) && !IsEvenRow) ||
99 (isInternal(coreCol, coreRow, memCol, memRow) && IsEvenRow);
100
101 bool IsMemEast = (isEast(coreCol, coreRow, memCol, memRow) && IsEvenRow) ||
102 (isInternal(coreCol, coreRow, memCol, memRow) && !IsEvenRow);
103
104 bool IsMemNorth = isNorth(coreCol, coreRow, memCol, memRow);
105 bool IsMemSouth = isSouth(coreCol, coreRow, memCol, memRow);
106
107 return IsMemSouth || IsMemNorth || IsMemWest || IsMemEast;
108}
109
110uint32_t
112 WireBundle bundle) const {
114 switch (bundle) {
115 case WireBundle::FIFO:
116 return 2;
117 case WireBundle::North:
118 return 6;
119 case WireBundle::West: {
120 if (col == 0)
121 return 0;
122 return 4;
123 }
124 case WireBundle::South:
125 return 6;
126 case WireBundle::East: {
127 if (col == columns() - 1)
128 return 0;
129 return 4;
130 }
131 case WireBundle::TileControl:
132 return isShimNOCTile(col, row) ? 1 : 0;
133 default:
134 return 0;
135 }
136
137 switch (bundle) {
138 case WireBundle::Core:
139 case WireBundle::DMA:
140 case WireBundle::FIFO:
141 return 2;
142 case WireBundle::North: {
143 if (row == rows() - 1)
144 return 0;
145 return 6;
146 }
147 case WireBundle::West: {
148 if (col == 0)
149 return 0;
150 return 4;
151 }
152 case WireBundle::South:
153 return 4;
154 case WireBundle::East: {
155 if (col == columns() - 1)
156 return 0;
157 return 4;
158 }
159 case WireBundle::TileControl:
160 return 1;
161 default:
162 return 0;
163 }
164}
165
166uint32_t
168 WireBundle bundle) const {
170 switch (bundle) {
171 case WireBundle::FIFO:
172 return 2;
173 case WireBundle::North:
174 return 4;
175 case WireBundle::West: {
176 if (col == 0)
177 return 0;
178 return 4;
179 }
180 case WireBundle::South:
181 return 8;
182 case WireBundle::East: {
183 if (col == columns() - 1)
184 return 0;
185 return 4;
186 }
187 case WireBundle::Trace:
188 return 1;
189 case WireBundle::TileControl:
190 return isShimNOCTile(col, row) ? 1 : 0;
191 default:
192 return 0;
193 }
194
195 switch (bundle) {
196 case WireBundle::Core:
197 case WireBundle::DMA:
198 case WireBundle::FIFO:
199 return 2;
200 case WireBundle::North: {
201 if (row == rows() - 1)
202 return 0;
203 return 4;
204 }
205 case WireBundle::West: {
206 if (col == 0)
207 return 0;
208 return 4;
209 }
210 case WireBundle::South:
211 return 6;
212 case WireBundle::East: {
213 if (col == columns() - 1)
214 return 0;
215 return 4;
216 }
217 case WireBundle::Trace:
218 return 2;
219 case WireBundle::TileControl:
220 return 1;
221 default:
222 return 0;
223 }
224}
225uint32_t
227 WireBundle bundle) const {
229 switch (bundle) {
230 case WireBundle::DMA:
231 return 2;
232 case WireBundle::NOC:
233 return 4;
234 case WireBundle::PLIO:
235 return 6;
236 case WireBundle::South:
237 return 8; // Connection to the south port of the stream switch
238 default:
239 return 0;
240 }
241 return 0;
242}
243uint32_t
245 WireBundle bundle) const {
247 switch (bundle) {
248 case WireBundle::DMA:
249 return 2;
250 case WireBundle::NOC:
251 return 4;
252 case WireBundle::PLIO:
253 return 8;
254 case WireBundle::South:
255 return 6; // Connection to the south port of the stream switch
256 default:
257 return 0;
258 }
259 return 0;
260}
261
263 WireBundle srcBundle, int srcChan,
264 WireBundle dstBundle,
265 int dstChan) const {
266 // Check Channel Id within the range
267 if (srcChan >= int(getNumSourceSwitchboxConnections(col, row, srcBundle)))
268 return false;
269 if (dstChan >= int(getNumDestSwitchboxConnections(col, row, dstBundle)))
270 return false;
271
272 // Memtile
273 if (isMemTile(col, row)) {
274 return false;
275 }
276 // Shimtile
277 else if (isShimNOCorPLTile(col, row)) {
278 if (srcBundle == WireBundle::Trace)
279 return dstBundle == WireBundle::South;
280 else
281 return true;
282 }
283 // Coretile
284 else if (isCoreTile(col, row)) {
285 if (srcBundle == WireBundle::Trace)
286 return dstBundle == WireBundle::South;
287 else
288 return true;
289 }
290 return false;
291}
292
293std::vector<std::pair<uint32_t, uint32_t>>
295 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256)};
296}
297
298std::optional<uint32_t>
299AIE1TargetModel::getLocalLockAddress(uint32_t lockId, TileID tile) const {
300 // This function is currently not supported for AIE1.
301 // In order to be implemented for this target model, the interface
302 // would need to change given the different way locks are written to in AIE1.
303 return std::nullopt;
304}
305
306///
307/// AIE2 TargetModel
308///
309
311
312// Return the tile ID of the memory to the west of the given tile, if it exists.
313std::optional<TileID> AIE2TargetModel::getMemWest(TileID src) const {
314 std::optional<TileID> ret({src.col - 1, src.row});
315 if (!isValidTile(*ret))
316 ret.reset();
317 return ret;
318}
319
320// Return the tile ID of the memory to the east of the given tile (ie self), if
321// it exists.
322std::optional<TileID> AIE2TargetModel::getMemEast(TileID src) const {
323 std::optional ret = src;
324 if (!isValidTile(*ret))
325 ret.reset();
326 return ret;
327}
328
329// Return the tile ID of the memory to the north of the given tile, if it
330// exists.
331std::optional<TileID> AIE2TargetModel::getMemNorth(TileID src) const {
332 std::optional<TileID> ret({src.col, src.row + 1});
333 if (!isValidTile(*ret))
334 ret.reset();
335 return ret;
336}
337
338std::optional<TileID> AIE2TargetModel::getMemSouth(TileID src) const {
339 std::optional<TileID> ret({src.col, src.row - 1});
340 // The first row doesn't have a tile memory south
341 // Memtiles don't have memory adjacency to neighboring core tiles.
342 if (!isValidTile(*ret) || ret->row == 0 || isMemTile(ret->col, ret->row))
343 ret.reset();
344 return ret;
345}
346
347bool AIE2TargetModel::isMemWest(int srcCol, int srcRow, int dstCol,
348 int dstRow) const {
349 return isWest(srcCol, srcRow, dstCol, dstRow);
350}
351
352bool AIE2TargetModel::isMemEast(int srcCol, int srcRow, int dstCol,
353 int dstRow) const {
354 return isInternal(srcCol, srcRow, dstCol, dstRow);
355}
356
357bool AIE2TargetModel::isMemNorth(int srcCol, int srcRow, int dstCol,
358 int dstRow) const {
359 return isNorth(srcCol, srcRow, dstCol, dstRow);
360}
361
362bool AIE2TargetModel::isMemSouth(int srcCol, int srcRow, int dstCol,
363 int dstRow) const {
364 return isSouth(srcCol, srcRow, dstCol, dstRow);
365}
366
367bool AIE2TargetModel::isLegalMemAffinity(int coreCol, int coreRow, int memCol,
368 int memRow) const {
369
370 bool IsMemWest = isMemWest(coreCol, coreRow, memCol, memRow);
371 bool IsMemEast = isMemEast(coreCol, coreRow, memCol, memRow);
372 bool IsMemNorth = isMemNorth(coreCol, coreRow, memCol, memRow);
373 bool IsMemSouth = isMemSouth(coreCol, coreRow, memCol, memRow);
374
375 if (isMemTile(coreCol, coreRow))
376 return isEast(coreCol, coreRow, memCol, memRow) ||
377 isInternal(coreCol, coreRow, memCol, memRow) ||
378 isWest(coreCol, coreRow, memCol, memRow);
379 return (IsMemSouth && !isMemTile(memCol, memRow)) || IsMemNorth ||
380 IsMemWest || IsMemEast;
381}
382
383uint32_t
385 WireBundle bundle) const {
386 if (isMemTile(col, row))
387 switch (bundle) {
388 case WireBundle::DMA:
389 case WireBundle::North:
390 return 6;
391 case WireBundle::South:
392 return 4;
393 case WireBundle::TileControl:
394 return 1;
395 default:
396 return 0;
397 }
398
400 switch (bundle) {
401 case WireBundle::FIFO:
402 return 1;
403 case WireBundle::North:
404 return 6;
405 case WireBundle::West: {
406 if (col == 0)
407 return 0;
408 return 4;
409 }
410 case WireBundle::South:
411 return 6;
412 case WireBundle::East: {
413 if (col == columns() - 1)
414 return 0;
415 return 4;
416 }
417 case WireBundle::TileControl:
418 return isShimNOCTile(col, row) ? 1 : 0;
419 default:
420 return 0;
421 }
422
423 switch (bundle) {
424 case WireBundle::Core:
425 return 1;
426 case WireBundle::DMA:
427 return 2;
428 case WireBundle::FIFO:
429 return 1;
430 case WireBundle::North: {
431 if (row == rows() - 1)
432 return 0;
433 return 6;
434 }
435 case WireBundle::West: {
436 if (col == 0)
437 return 0;
438 return 4;
439 }
440 case WireBundle::South:
441 return 4;
442 case WireBundle::East: {
443 if (col == columns() - 1)
444 return 0;
445 return 4;
446 }
447 case WireBundle::TileControl:
448 return 1;
449 default:
450 return 0;
451 }
452}
453
454uint32_t
456 WireBundle bundle) const {
457 if (isMemTile(col, row))
458 switch (bundle) {
459 case WireBundle::DMA:
460 return 6;
461 case WireBundle::North:
462 return 4;
463 case WireBundle::South:
464 return 6;
465 case WireBundle::Trace:
466 case WireBundle::TileControl:
467 return 1;
468 default:
469 return 0;
470 }
471
473 switch (bundle) {
474 case WireBundle::FIFO:
475 return 1;
476 case WireBundle::North:
477 return 4;
478 case WireBundle::West: {
479 if (col == 0)
480 return 0;
481 return 4;
482 }
483 case WireBundle::South:
484 return 8;
485 case WireBundle::East: {
486 if (col == columns() - 1)
487 return 0;
488 return 4;
489 }
490 case WireBundle::Trace:
491 return 1;
492 case WireBundle::TileControl:
493 return isShimNOCTile(col, row) ? 1 : 0;
494 default:
495 return 0;
496 }
497
498 // compute/core tile
499 switch (bundle) {
500 case WireBundle::Core:
501 return 1;
502 case WireBundle::DMA:
503 return 2;
504 case WireBundle::FIFO:
505 return 1;
506 case WireBundle::North: {
507 if (row == rows() - 1)
508 return 0;
509 return 4;
510 }
511 case WireBundle::West: {
512 if (col == 0)
513 return 0;
514 return 4;
515 }
516 case WireBundle::South:
517 return 6;
518 case WireBundle::East: {
519 if (col == columns() - 1)
520 return 0;
521 return 4;
522 }
523 case WireBundle::Trace:
524 // Port 0: core trace. Port 1: memory trace.
525 return 2;
526 case WireBundle::TileControl:
527 return 1;
528 default:
529 return 0;
530 }
531}
532
533uint32_t
535 WireBundle bundle) const {
537 switch (bundle) {
538 case WireBundle::DMA:
539 return 2;
540 case WireBundle::NOC:
541 return 4;
542 case WireBundle::PLIO:
543 return 6;
544 case WireBundle::South:
545 return 8; // Connection to the south port of the stream switch
546 default:
547 return 0;
548 }
549
550 return 0;
551}
552
553uint32_t
555 WireBundle bundle) const {
557 switch (bundle) {
558 case WireBundle::DMA:
559 return 2;
560 case WireBundle::NOC:
561 return 4;
562 case WireBundle::PLIO:
563 return 8;
564 case WireBundle::South:
565 return 6; // Connection to the south port of the stream switch
566 default:
567 return 0;
568 }
569
570 return 0;
571}
572
574 WireBundle srcBundle, int srcChan,
575 WireBundle dstBundle,
576 int dstChan) const {
577 // Check Channel Id within the range
578 if (srcChan >= int(getNumSourceSwitchboxConnections(col, row, srcBundle)))
579 return false;
580 if (dstChan >= int(getNumDestSwitchboxConnections(col, row, dstBundle)))
581 return false;
582
583 // Lambda function to check if a bundle is in a list
584 auto isBundleInList = [](WireBundle bundle,
585 std::initializer_list<WireBundle> bundles) {
586 return std::find(bundles.begin(), bundles.end(), bundle) != bundles.end();
587 };
588
589 // Memtile
590 if (isMemTile(col, row)) {
591 if (srcBundle == WireBundle::DMA) {
592 if (dstBundle == WireBundle::DMA)
593 return srcChan == dstChan;
594 if (isBundleInList(dstBundle, {WireBundle::TileControl, WireBundle::South,
595 WireBundle::North}))
596 return true;
597 }
598 if (srcBundle == WireBundle::TileControl) {
599 if (dstBundle == WireBundle::DMA)
600 return dstChan == 5;
601 if (isBundleInList(dstBundle, {WireBundle::South, WireBundle::North}))
602 return true;
603 }
604 if (isBundleInList(srcBundle, {WireBundle::South, WireBundle::North})) {
605 if (isBundleInList(dstBundle, {WireBundle::DMA, WireBundle::TileControl}))
606 return true;
607 if (isBundleInList(dstBundle, {WireBundle::South, WireBundle::North}))
608 return srcChan == dstChan;
609 }
610 if (srcBundle == WireBundle::Trace) {
611 if (dstBundle == WireBundle::DMA)
612 return dstChan == 5;
613 if (dstBundle == WireBundle::South)
614 return true;
615 }
616 }
617 // Shimtile
618 else if (isShimNOCorPLTile(col, row)) {
619 if (srcBundle == WireBundle::TileControl)
620 return dstBundle != WireBundle::TileControl;
621 if (isBundleInList(srcBundle, {WireBundle::FIFO, WireBundle::South}))
622 return isBundleInList(dstBundle,
623 {WireBundle::TileControl, WireBundle::FIFO,
624 WireBundle::South, WireBundle::West,
625 WireBundle::North, WireBundle::East});
626 if (isBundleInList(srcBundle,
627 {WireBundle::West, WireBundle::North, WireBundle::East}))
628 return (srcBundle == dstBundle)
629 ? (srcChan == dstChan)
630 : isBundleInList(dstBundle,
631 {WireBundle::TileControl, WireBundle::FIFO,
632 WireBundle::South, WireBundle::West,
633 WireBundle::North, WireBundle::East});
634 if (srcBundle == WireBundle::Trace) {
635 if (isBundleInList(dstBundle, {WireBundle::FIFO, WireBundle::South}))
636 return true;
637 if (isBundleInList(dstBundle, {WireBundle::West, WireBundle::East}))
638 return dstChan == 0;
639 }
640 }
641 // Coretile
642 else if (isCoreTile(col, row)) {
643 if (isBundleInList(srcBundle,
644 {WireBundle::DMA, WireBundle::FIFO, WireBundle::South,
645 WireBundle::West, WireBundle::North, WireBundle::East}))
646 if (isBundleInList(dstBundle, {WireBundle::Core, WireBundle::DMA,
647 WireBundle::TileControl, WireBundle::FIFO,
648 WireBundle::South, WireBundle::West,
649 WireBundle::North, WireBundle::East}))
650 return (srcBundle == dstBundle) ? (srcChan == dstChan) : true;
651 if (srcBundle == WireBundle::Core)
652 return dstBundle != WireBundle::Core;
653 if (srcBundle == WireBundle::TileControl)
654 return dstBundle != WireBundle::TileControl &&
655 dstBundle != WireBundle::DMA;
656 if (srcBundle == WireBundle::Trace) {
657 if (dstBundle == WireBundle::DMA)
658 return dstChan == 0;
659 if (isBundleInList(dstBundle, {WireBundle::FIFO, WireBundle::South}))
660 return true;
661 }
662 }
663 return false;
664}
665
666std::vector<std::pair<uint32_t, uint32_t>>
668 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256)};
669}
670
671std::optional<uint32_t>
672AIE2TargetModel::getLocalLockAddress(uint32_t lockId, TileID tile) const {
673 auto computeTileBaseAddress = 0x0001F000;
674 auto memTileBaseAddress = 0x000C0000;
675 auto shimTileBaseAddress = 0x00014000;
676 auto lockAddrOffset = 0x10;
677
678 if (isCoreTile(tile.col, tile.row) &&
679 lockId < getNumLocks(tile.col, tile.row))
680 return computeTileBaseAddress + lockAddrOffset * lockId;
681
682 if (isMemTile(tile.col, tile.row) && lockId < getNumLocks(tile.col, tile.row))
683 return memTileBaseAddress + lockAddrOffset * lockId;
684
685 if (isShimNOCorPLTile(tile.col, tile.row) &&
686 lockId < getNumLocks(tile.col, tile.row))
687 return shimTileBaseAddress + lockAddrOffset * lockId;
688
689 return std::nullopt;
690}
691
693 // Every tile in a shimtile row must be a shimtile, and can only be one type
694 // of shim tile.
695 for (int j = 0; j < columns(); j++) {
696 assert(!isMemTile(j, 0) && (isShimPLTile(j, 0) || isShimNOCTile(j, 0)) &&
697 !isCoreTile(j, 0));
698 assert(isShimPLTile(j, 0) ^ isShimNOCTile(j, 0));
699 }
700
701 // Every tile in a memtile row must be a memtile.
702 for (int i = 1; i < 1 + static_cast<int>(getNumMemTileRows()); i++)
703 for (int j = 0; j < columns(); j++)
704 assert(isMemTile(j, i) && !isShimPLTile(j, i) && !isShimNOCTile(j, i) &&
705 !isCoreTile(j, i));
706
707 // Every other tile is a coretile.
708 for (int i = 1 + getNumMemTileRows(); i < rows(); i++)
709 for (int j = 0; j < columns(); j++)
710 assert(!isMemTile(j, i) && !isShimPLTile(j, i) && !isShimNOCTile(j, i) &&
711 isCoreTile(j, i));
712
713 // Looking North, buses must match
714 for (int i = 0; i < rows() - 1; i++)
715 for (int j = 0; j < columns(); j++)
716 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::North) ==
717 getNumDestSwitchboxConnections(j, i + 1, WireBundle::South));
718 // Looking South, buses must match
719 for (int i = 1; i < rows(); i++)
720 for (int j = 0; j < columns(); j++)
721 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::South) ==
722 getNumDestSwitchboxConnections(j, i - 1, WireBundle::North));
723 // Looking East, buses must match
724 for (int i = 0; i < rows(); i++)
725 for (int j = 0; j < columns() - 1; j++)
726 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::East) ==
727 getNumDestSwitchboxConnections(j + 1, i, WireBundle::West));
728 // Looking West, buses must match
729 for (int i = 0; i < rows(); i++)
730 for (int j = 1; j < columns(); j++)
731 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::West) ==
732 getNumDestSwitchboxConnections(j - 1, i, WireBundle::East));
733 // Edges have no connections
734 for (int j = 0; j < columns(); j++)
735 assert(getNumSourceSwitchboxConnections(j, rows() - 1, WireBundle::North) ==
736 0);
737 for (int i = 0; i < rows(); i++)
739 WireBundle::East) == 0);
740 for (int i = 0; i < rows(); i++)
741 assert(getNumSourceSwitchboxConnections(0, i, WireBundle::West) == 0);
742
743 // FIFOS are consistent
744 for (int i = 0; i < rows(); i++)
745 for (int j = 0; j < columns(); j++)
746 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::FIFO) ==
747 getNumDestSwitchboxConnections(j, i, WireBundle::FIFO));
748}
749
750std::optional<uint32_t>
751AIETargetModel::getLockLocalBaseIndex(int localCol, int localRow, int lockCol,
752 int lockRow) const {
753 if (isCoreTile(localCol, localRow)) {
754 if (isMemSouth(localCol, localRow, lockCol, lockRow))
755 return 0;
756 if (isMemWest(localCol, localRow, lockCol, lockRow))
757 return getNumLocks(localCol, localRow);
758 if (isMemNorth(localCol, localRow, lockCol, lockRow))
759 return getNumLocks(localCol, localRow) * 2;
760 if (isMemEast(localCol, localRow, lockCol, lockRow))
761 return getNumLocks(localCol, localRow) * 3;
762 }
763
764 if (isMemTile(localCol, localRow)) {
765 if (isWest(localCol, localRow, lockCol, lockRow))
766 return 0;
767 if (isInternal(localCol, localRow, lockCol, lockRow))
768 return getNumLocks(localCol, localRow);
769 if (isEast(localCol, localRow, lockCol, lockRow))
770 return getNumLocks(localCol, localRow) * 2;
771 }
772
773 return std::nullopt;
774}
775
776std::optional<uint32_t>
777AIETargetModel::getMemLocalBaseAddress(int localCol, int localRow, int memCol,
778 int memRow) const {
779 if (isCoreTile(localCol, localRow)) {
780 if (isMemSouth(localCol, localRow, memCol, memRow))
781 return getMemSouthBaseAddress();
782 if (isMemWest(localCol, localRow, memCol, memRow))
783 return getMemWestBaseAddress();
784 if (isMemNorth(localCol, localRow, memCol, memRow))
785 return getMemNorthBaseAddress();
786 if (isMemEast(localCol, localRow, memCol, memRow))
787 return getMemEastBaseAddress();
788 }
789
790 if (isMemTile(localCol, localRow)) {
791 if (isWest(localCol, localRow, memCol, memRow))
792 return 0;
793 if (isInternal(localCol, localRow, memCol, memRow))
794 return getMemTileSize();
795 if (isEast(localCol, localRow, memCol, memRow))
796 return getMemTileSize() * 2;
797 }
798
799 return std::nullopt;
800}
801
802AIEArch NPU2TargetModel::getTargetArch() const { return AIEArch::AIE2p; }
803
804std::vector<std::pair<uint32_t, uint32_t>>
806 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256),
807 std::pair(3, 512)};
808}
809
810} // namespace AIE
811} // namespace xilinx
bool isMemNorth(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is North of dst.
std::optional< TileID > getMemSouth(TileID src) const override
Return the tile ID of the memory to the south of the given tile, if it exists.
std::optional< uint32_t > getLocalLockAddress(uint32_t lockId, TileID tile) const override
std::optional< TileID > getMemNorth(TileID src) const override
Return the tile ID of the memory to the north of the given tile, if it exists.
bool isMemSouth(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is South of dst.
std::optional< TileID > getMemWest(TileID src) const override
Return the tile ID of the memory to the west of the given tile, if it exists.
bool isLegalMemAffinity(int coreCol, int coreRow, int memCol, int memRow) const override
Return true if core can access the memory in mem.
uint32_t getNumSourceShimMuxConnections(int col, int row, WireBundle bundle) const override
Return the number of sources of connections inside a shimmux.
uint32_t getNumDestSwitchboxConnections(int col, int row, WireBundle bundle) const override
Return the number of destinations of connections inside a switchbox.
bool isMemEast(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is East of dst.
bool isMemWest(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is West of dst.
bool isCoreTile(int col, int row) const override
Return true if the given tile is a 'Core' tile.
std::vector< std::pair< uint32_t, uint32_t > > getShimBurstEncodingsAndLengths() const override
AIEArch getTargetArch() const override
AIE1 TargetModel.
uint32_t getNumDestShimMuxConnections(int col, int row, WireBundle bundle) const override
Return the number of destinations of connections inside a shimmux.
std::optional< TileID > getMemEast(TileID src) const override
Return the tile ID of the memory to the east of the given tile, if it exists.
bool isLegalTileConnection(int col, int row, WireBundle srcBundle, int srcChan, WireBundle dstBundle, int dstChan) const override
bool isMemTile(int col, int row) const override
Return true if the given tile is an AIE2 'Memory' tile.
uint32_t getNumSourceSwitchboxConnections(int col, int row, WireBundle bundle) const override
Return the number of sources of connections inside a switchbox.
bool isLegalTileConnection(int col, int row, WireBundle srcBundle, int srcChan, WireBundle dstBundle, int dstChan) const override
uint32_t getNumLocks(int col, int row) const override
Return the number of lock objects.
uint32_t getNumSourceSwitchboxConnections(int col, int row, WireBundle bundle) const override
Return the number of sources of connections inside a switchbox.
std::vector< std::pair< uint32_t, uint32_t > > getShimBurstEncodingsAndLengths() const override
std::optional< TileID > getMemWest(TileID src) const override
Return the tile ID of the memory to the west of the given tile, if it exists.
AIEArch getTargetArch() const override
AIE2 TargetModel.
bool isLegalMemAffinity(int coreCol, int coreRow, int memCol, int memRow) const override
Return true if core can access the memory in mem.
std::optional< TileID > getMemEast(TileID src) const override
Return the tile ID of the memory to the east of the given tile, if it exists.
bool isMemNorth(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is North of dst.
uint32_t getNumDestShimMuxConnections(int col, int row, WireBundle bundle) const override
Return the number of destinations of connections inside a shimmux.
std::optional< uint32_t > getLocalLockAddress(uint32_t lockId, TileID tile) const override
std::optional< TileID > getMemSouth(TileID src) const override
Return the tile ID of the memory to the south of the given tile, if it exists.
uint32_t getNumDestSwitchboxConnections(int col, int row, WireBundle bundle) const override
Return the number of destinations of connections inside a switchbox.
bool isMemWest(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is West of dst.
bool isMemSouth(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is South of dst.
std::optional< TileID > getMemNorth(TileID src) const override
Return the tile ID of the memory to the north of the given tile, if it exists.
bool isMemEast(int srcCol, int srcRow, int dstCol, int dstRow) const override
Return true if src has a memory tile which is East of dst.
uint32_t getNumSourceShimMuxConnections(int col, int row, WireBundle bundle) const override
Return the number of sources of connections inside a shimmux.
std::optional< uint32_t > getMemLocalBaseAddress(int localCol, int localRow, int memCol, int memRow) const
Return the memory base address (or offset) in the local tile when accessing a neighbor's memory or an...
bool isNorth(int srcCol, int srcRow, int dstCol, int dstRow) const
Return true if src is North of dst.
bool isSouth(int srcCol, int srcRow, int dstCol, int dstRow) const
Return true if src is South of dst.
bool isWest(int srcCol, int srcRow, int dstCol, int dstRow) const
Return true if src is West of dst.
virtual bool isMemNorth(int srcCol, int srcRow, int dstCol, int dstRow) const =0
Return true if src has a memory tile which is North of dst.
virtual uint32_t getMemSouthBaseAddress() const =0
Return the base address in the local address map for a core.
std::optional< uint32_t > getLockLocalBaseIndex(int localCol, int localRow, int lockCol, int lockRow) const
Return the lock base index (or offset) in the local tile when accessing a neighbor's lock or an empty...
virtual bool isCoreTile(int col, int row) const =0
Return true if the given tile is a 'Core' tile.
virtual bool isMemEast(int srcCol, int srcRow, int dstCol, int dstRow) const =0
Return true if src has a memory tile which is East of dst.
virtual bool isMemTile(int col, int row) const =0
Return true if the given tile is an AIE2 'Memory' tile.
virtual bool isValidTile(TileID src) const
Return true if the given tile ID is valid.
bool isEast(int srcCol, int srcRow, int dstCol, int dstRow) const
Return true if src is East of dst.
virtual bool isMemSouth(int srcCol, int srcRow, int dstCol, int dstRow) const =0
Return true if src has a memory tile which is South of dst.
virtual uint32_t getMemWestBaseAddress() const =0
Return the base address in the local address map for a core.
virtual uint32_t getNumLocks(int col, int row) const =0
Return the number of lock objects.
virtual int rows() const =0
Return the number of rows in the device.
virtual bool isShimNOCTile(int col, int row) const =0
Return true if the given tile is a Shim NOC tile.
virtual bool isShimNOCorPLTile(int col, int row) const =0
Return true if the given tile is either a Shim NOC or a Shim PL interface tile.
virtual bool isShimPLTile(int col, int row) const =0
Return true if the given tile is a Shim PL interface tile.
virtual uint32_t getMemNorthBaseAddress() const =0
Return the base address in the local address map for a core.
virtual int columns() const =0
Return the number of columns in the device.
virtual uint32_t getMemEastBaseAddress() const =0
Return the base address in the local address map for a core.
virtual uint32_t getNumMemTileRows() const =0
virtual bool isMemWest(int srcCol, int srcRow, int dstCol, int dstRow) const =0
Return true if src has a memory tile which is West of dst.
virtual uint32_t getNumDestSwitchboxConnections(int col, int row, WireBundle bundle) const =0
Return the number of destinations of connections inside a switchbox.
bool isInternal(int srcCol, int srcRow, int dstCol, int dstRow) const
Return true if src is the internal memory of dst.
virtual uint32_t getMemTileSize() const =0
Return the size (in bytes) of a MemTile.
virtual uint32_t getNumSourceSwitchboxConnections(int col, int row, WireBundle bundle) const =0
Return the number of sources of connections inside a switchbox.
AIEArch getTargetArch() const override
AIE2 TargetModel.
std::vector< std::pair< uint32_t, uint32_t > > getShimBurstEncodingsAndLengths() const override
TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")" TileID
PathEndPoint src
AIEArch
Definition Passes.h:21