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
110uint64_t AIE1TargetModel::getDmaBdAddress(int col, int row, uint32_t bd_id,
111 int channel,
112 AIE::DMAChannelDir direction) const {
113 uint32_t offset = 0;
114 if (isShimNOCTile(col, row)) {
115 offset = 0x0001D000 + (bd_id * 0x14);
116 } else if (isCoreTile(col, row)) {
117 offset = 0x0001D000 + (bd_id * 0x20);
118 } else {
119 llvm_unreachable(
120 "AIE1TargetModel::getDmaBdAddress called for non-DMA tile");
121 }
122 return ((col & 0xff) << getColumnShift()) | ((row & 0xff) << getRowShift()) |
123 offset;
124}
125
127 if (isShimNOCTile(col, row) || isCoreTile(col, row)) {
128 return 0;
129 }
130 llvm_unreachable(
131 "AIE1TargetModel::getDmaBdAddressOffset called for non-DMA tile");
132}
133
134uint32_t
136 AIE::DMAChannelDir direction) const {
137 uint32_t offset = 0;
138 if (isShimNOCTile(col, row))
139 offset = 0x0001D140 + (channel * 0x8);
140 else if (isCoreTile(col, row))
141 offset = 0x0001DE00 + (channel * 0x8);
142 else
143 llvm_unreachable(
144 "AIE1TargetModel::getDmaControlAddress called for non-DMA tile");
145
146 if (direction == AIE::DMAChannelDir::MM2S)
147 offset += 010;
148
149 return ((col & 0xff) << getColumnShift()) | ((row & 0xff) << getRowShift()) |
150 offset;
151}
152
153uint32_t
155 WireBundle bundle) const {
157 switch (bundle) {
158 case WireBundle::FIFO:
159 return 2;
160 case WireBundle::North:
161 return 6;
162 case WireBundle::West: {
163 if (col == 0)
164 return 0;
165 return 4;
166 }
167 case WireBundle::South:
168 return 6;
169 case WireBundle::East: {
170 if (col == columns() - 1)
171 return 0;
172 return 4;
173 }
174 case WireBundle::TileControl:
175 return isShimNOCTile(col, row) ? 1 : 0;
176 default:
177 return 0;
178 }
179
180 switch (bundle) {
181 case WireBundle::Core:
182 case WireBundle::DMA:
183 case WireBundle::FIFO:
184 return 2;
185 case WireBundle::North: {
186 if (row == rows() - 1)
187 return 0;
188 return 6;
189 }
190 case WireBundle::West: {
191 if (col == 0)
192 return 0;
193 return 4;
194 }
195 case WireBundle::South:
196 return 4;
197 case WireBundle::East: {
198 if (col == columns() - 1)
199 return 0;
200 return 4;
201 }
202 case WireBundle::TileControl:
203 return 1;
204 default:
205 return 0;
206 }
207}
208
209uint32_t
211 WireBundle bundle) const {
213 switch (bundle) {
214 case WireBundle::FIFO:
215 return 2;
216 case WireBundle::North:
217 return 4;
218 case WireBundle::West: {
219 if (col == 0)
220 return 0;
221 return 4;
222 }
223 case WireBundle::South:
224 return 8;
225 case WireBundle::East: {
226 if (col == columns() - 1)
227 return 0;
228 return 4;
229 }
230 case WireBundle::Trace:
231 return 1;
232 case WireBundle::TileControl:
233 return isShimNOCTile(col, row) ? 1 : 0;
234 default:
235 return 0;
236 }
237
238 switch (bundle) {
239 case WireBundle::Core:
240 case WireBundle::DMA:
241 case WireBundle::FIFO:
242 return 2;
243 case WireBundle::North: {
244 if (row == rows() - 1)
245 return 0;
246 return 4;
247 }
248 case WireBundle::West: {
249 if (col == 0)
250 return 0;
251 return 4;
252 }
253 case WireBundle::South:
254 return 6;
255 case WireBundle::East: {
256 if (col == columns() - 1)
257 return 0;
258 return 4;
259 }
260 case WireBundle::Trace:
261 return 2;
262 case WireBundle::TileControl:
263 return 1;
264 default:
265 return 0;
266 }
267}
268uint32_t
270 WireBundle bundle) const {
272 switch (bundle) {
273 case WireBundle::DMA:
274 return 2;
275 case WireBundle::NOC:
276 return 4;
277 case WireBundle::PLIO:
278 return 6;
279 case WireBundle::South:
280 return 8; // Connection to the south port of the stream switch
281 default:
282 return 0;
283 }
284 return 0;
285}
286uint32_t
288 WireBundle bundle) const {
290 switch (bundle) {
291 case WireBundle::DMA:
292 return 2;
293 case WireBundle::NOC:
294 return 4;
295 case WireBundle::PLIO:
296 return 8;
297 case WireBundle::South:
298 return 6; // Connection to the south port of the stream switch
299 default:
300 return 0;
301 }
302 return 0;
303}
304
306 WireBundle srcBundle, int srcChan,
307 WireBundle dstBundle,
308 int dstChan) const {
309 // Check Channel Id within the range
310 if (srcChan >= int(getNumSourceSwitchboxConnections(col, row, srcBundle)))
311 return false;
312 if (dstChan >= int(getNumDestSwitchboxConnections(col, row, dstBundle)))
313 return false;
314
315 // Memtile
316 if (isMemTile(col, row)) {
317 return false;
318 }
319 // Shimtile
320 else if (isShimNOCorPLTile(col, row)) {
321 if (srcBundle == WireBundle::Trace)
322 return dstBundle == WireBundle::South;
323 else
324 return true;
325 }
326 // Coretile
327 else if (isCoreTile(col, row)) {
328 if (srcBundle == WireBundle::Trace)
329 return dstBundle == WireBundle::South;
330 else
331 return true;
332 }
333 return false;
334}
335
336std::vector<std::pair<uint32_t, uint32_t>>
338 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256)};
339}
340
341std::optional<uint32_t>
342AIE1TargetModel::getLocalLockAddress(uint32_t lockId, TileID tile) const {
343 // This function is currently not supported for AIE1.
344 // In order to be implemented for this target model, the interface
345 // would need to change given the different way locks are written to in AIE1.
346 return std::nullopt;
347}
348
349///
350/// AIE2 TargetModel
351///
352
354
355// Return the tile ID of the memory to the west of the given tile, if it exists.
356std::optional<TileID> AIE2TargetModel::getMemWest(TileID src) const {
357 std::optional<TileID> ret({src.col - 1, src.row});
358 if (!isValidTile(*ret))
359 ret.reset();
360 return ret;
361}
362
363// Return the tile ID of the memory to the east of the given tile (ie self), if
364// it exists.
365std::optional<TileID> AIE2TargetModel::getMemEast(TileID src) const {
366 std::optional ret = src;
367 if (!isValidTile(*ret))
368 ret.reset();
369 return ret;
370}
371
372// Return the tile ID of the memory to the north of the given tile, if it
373// exists.
374std::optional<TileID> AIE2TargetModel::getMemNorth(TileID src) const {
375 std::optional<TileID> ret({src.col, src.row + 1});
376 if (!isValidTile(*ret))
377 ret.reset();
378 return ret;
379}
380
381std::optional<TileID> AIE2TargetModel::getMemSouth(TileID src) const {
382 std::optional<TileID> ret({src.col, src.row - 1});
383 // The first row doesn't have a tile memory south
384 // Memtiles don't have memory adjacency to neighboring core tiles.
385 if (!isValidTile(*ret) || ret->row == 0 || isMemTile(ret->col, ret->row))
386 ret.reset();
387 return ret;
388}
389
390bool AIE2TargetModel::isMemWest(int srcCol, int srcRow, int dstCol,
391 int dstRow) const {
392 return isWest(srcCol, srcRow, dstCol, dstRow);
393}
394
395bool AIE2TargetModel::isMemEast(int srcCol, int srcRow, int dstCol,
396 int dstRow) const {
397 return isInternal(srcCol, srcRow, dstCol, dstRow);
398}
399
400bool AIE2TargetModel::isMemNorth(int srcCol, int srcRow, int dstCol,
401 int dstRow) const {
402 return isNorth(srcCol, srcRow, dstCol, dstRow);
403}
404
405bool AIE2TargetModel::isMemSouth(int srcCol, int srcRow, int dstCol,
406 int dstRow) const {
407 return isSouth(srcCol, srcRow, dstCol, dstRow);
408}
409
410bool AIE2TargetModel::isLegalMemAffinity(int coreCol, int coreRow, int memCol,
411 int memRow) const {
412
413 bool IsMemWest = isMemWest(coreCol, coreRow, memCol, memRow);
414 bool IsMemEast = isMemEast(coreCol, coreRow, memCol, memRow);
415 bool IsMemNorth = isMemNorth(coreCol, coreRow, memCol, memRow);
416 bool IsMemSouth = isMemSouth(coreCol, coreRow, memCol, memRow);
417
418 if (isMemTile(coreCol, coreRow))
419 return isEast(coreCol, coreRow, memCol, memRow) ||
420 isInternal(coreCol, coreRow, memCol, memRow) ||
421 isWest(coreCol, coreRow, memCol, memRow);
422 return (IsMemSouth && !isMemTile(memCol, memRow)) || IsMemNorth ||
423 IsMemWest || IsMemEast;
424}
425
426uint64_t AIE2TargetModel::getDmaBdAddress(int col, int row, uint32_t bd_id,
427 int channel,
428 AIE::DMAChannelDir direction) const {
429 uint64_t offset = 0;
430 if (isShimNOCTile(col, row)) {
431 offset = 0x0001D000 + bd_id * 0x20;
432 } else if (isMemTile(col, row)) {
433 offset = 0x000A0000 + bd_id * 0x20;
434 } else if (isCoreTile(col, row)) {
435 offset = 0x0001D000 + bd_id * 0x20;
436 } else {
437 llvm_unreachable(
438 "AIE2TargetModel::getDmaBdAddress called for non-DMA tile");
439 }
440 return ((col & 0xff) << getColumnShift()) | ((row & 0xff) << getRowShift()) |
441 offset;
442}
443
445 if (isCoreTile(col, row))
446 return 0x0;
447 return 0x4;
448}
449
450uint32_t
452 AIE::DMAChannelDir direction) const {
453 uint32_t offset = 0;
454 if (isShimNOCTile(col, row)) {
455 offset = 0x0001D200 + (channel * 0x8);
456 if (direction == AIE::DMAChannelDir::MM2S)
457 offset += 0x10;
458 } else if (isMemTile(col, row)) {
459 offset = 0x000A0600 + (channel * 0x8);
460 if (direction == AIE::DMAChannelDir::MM2S)
461 offset += 0x30;
462 } else if (isCoreTile(col, row)) {
463 offset = 0x0001DE00 + (channel * 0x8);
464 if (direction == AIE::DMAChannelDir::MM2S)
465 offset += 0x10;
466 } else {
467 llvm_unreachable(
468 "AIE2TargetModel::getDmaControlAddress called for non-DMA tile");
469 }
470
471 return ((col & 0xff) << getColumnShift()) | ((row & 0xff) << getRowShift()) |
472 offset;
473}
474
475uint32_t
477 WireBundle bundle) const {
478 if (isMemTile(col, row))
479 switch (bundle) {
480 case WireBundle::DMA:
481 case WireBundle::North:
482 return 6;
483 case WireBundle::South:
484 return 4;
485 case WireBundle::TileControl:
486 return 1;
487 default:
488 return 0;
489 }
490
492 switch (bundle) {
493 case WireBundle::FIFO:
494 return 1;
495 case WireBundle::North:
496 return 6;
497 case WireBundle::West: {
498 if (col == 0)
499 return 0;
500 return 4;
501 }
502 case WireBundle::South:
503 return 6;
504 case WireBundle::East: {
505 if (col == columns() - 1)
506 return 0;
507 return 4;
508 }
509 case WireBundle::TileControl:
510 return isShimNOCTile(col, row) ? 1 : 0;
511 default:
512 return 0;
513 }
514
515 switch (bundle) {
516 case WireBundle::Core:
517 return 1;
518 case WireBundle::DMA:
519 return 2;
520 case WireBundle::FIFO:
521 return 1;
522 case WireBundle::North: {
523 if (row == rows() - 1)
524 return 0;
525 return 6;
526 }
527 case WireBundle::West: {
528 if (col == 0)
529 return 0;
530 return 4;
531 }
532 case WireBundle::South:
533 return 4;
534 case WireBundle::East: {
535 if (col == columns() - 1)
536 return 0;
537 return 4;
538 }
539 case WireBundle::TileControl:
540 return 1;
541 default:
542 return 0;
543 }
544}
545
546uint32_t
548 WireBundle bundle) const {
549 if (isMemTile(col, row))
550 switch (bundle) {
551 case WireBundle::DMA:
552 return 6;
553 case WireBundle::North:
554 return 4;
555 case WireBundle::South:
556 return 6;
557 case WireBundle::Trace:
558 case WireBundle::TileControl:
559 return 1;
560 default:
561 return 0;
562 }
563
565 switch (bundle) {
566 case WireBundle::FIFO:
567 return 1;
568 case WireBundle::North:
569 return 4;
570 case WireBundle::West: {
571 if (col == 0)
572 return 0;
573 return 4;
574 }
575 case WireBundle::South:
576 return 8;
577 case WireBundle::East: {
578 if (col == columns() - 1)
579 return 0;
580 return 4;
581 }
582 case WireBundle::Trace:
583 return 1;
584 case WireBundle::TileControl:
585 return isShimNOCTile(col, row) ? 1 : 0;
586 default:
587 return 0;
588 }
589
590 // compute/core tile
591 switch (bundle) {
592 case WireBundle::Core:
593 return 1;
594 case WireBundle::DMA:
595 return 2;
596 case WireBundle::FIFO:
597 return 1;
598 case WireBundle::North: {
599 if (row == rows() - 1)
600 return 0;
601 return 4;
602 }
603 case WireBundle::West: {
604 if (col == 0)
605 return 0;
606 return 4;
607 }
608 case WireBundle::South:
609 return 6;
610 case WireBundle::East: {
611 if (col == columns() - 1)
612 return 0;
613 return 4;
614 }
615 case WireBundle::Trace:
616 // Port 0: core trace. Port 1: memory trace.
617 return 2;
618 case WireBundle::TileControl:
619 return 1;
620 default:
621 return 0;
622 }
623}
624
625uint32_t
627 WireBundle bundle) const {
629 switch (bundle) {
630 case WireBundle::DMA:
631 return 2;
632 case WireBundle::NOC:
633 return 4;
634 case WireBundle::PLIO:
635 return 6;
636 case WireBundle::South:
637 return 8; // Connection to the south port of the stream switch
638 default:
639 return 0;
640 }
641
642 return 0;
643}
644
645uint32_t
647 WireBundle bundle) const {
649 switch (bundle) {
650 case WireBundle::DMA:
651 return 2;
652 case WireBundle::NOC:
653 return 4;
654 case WireBundle::PLIO:
655 return 8;
656 case WireBundle::South:
657 return 6; // Connection to the south port of the stream switch
658 default:
659 return 0;
660 }
661
662 return 0;
663}
664
666 WireBundle srcBundle, int srcChan,
667 WireBundle dstBundle,
668 int dstChan) const {
669 // Check Channel Id within the range
670 if (srcChan >= int(getNumSourceSwitchboxConnections(col, row, srcBundle)))
671 return false;
672 if (dstChan >= int(getNumDestSwitchboxConnections(col, row, dstBundle)))
673 return false;
674
675 // Lambda function to check if a bundle is in a list
676 auto isBundleInList = [](WireBundle bundle,
677 std::initializer_list<WireBundle> bundles) {
678 return std::find(bundles.begin(), bundles.end(), bundle) != bundles.end();
679 };
680
681 // Memtile
682 if (isMemTile(col, row)) {
683 if (srcBundle == WireBundle::DMA) {
684 if (dstBundle == WireBundle::DMA)
685 return srcChan == dstChan;
686 if (isBundleInList(dstBundle, {WireBundle::TileControl, WireBundle::South,
687 WireBundle::North}))
688 return true;
689 }
690 if (srcBundle == WireBundle::TileControl) {
691 if (dstBundle == WireBundle::DMA)
692 return dstChan == 5;
693 if (isBundleInList(dstBundle, {WireBundle::South, WireBundle::North}))
694 return true;
695 }
696 if (isBundleInList(srcBundle, {WireBundle::South, WireBundle::North})) {
697 if (isBundleInList(dstBundle, {WireBundle::DMA, WireBundle::TileControl}))
698 return true;
699 if (isBundleInList(dstBundle, {WireBundle::South, WireBundle::North}))
700 return srcChan == dstChan;
701 }
702 if (srcBundle == WireBundle::Trace) {
703 if (dstBundle == WireBundle::DMA)
704 return dstChan == 5;
705 if (dstBundle == WireBundle::South)
706 return true;
707 }
708 }
709 // Shimtile
710 else if (isShimNOCorPLTile(col, row)) {
711 if (srcBundle == WireBundle::TileControl)
712 return dstBundle != WireBundle::TileControl;
713 if (isBundleInList(srcBundle, {WireBundle::FIFO, WireBundle::South}))
714 return isBundleInList(dstBundle,
715 {WireBundle::TileControl, WireBundle::FIFO,
716 WireBundle::South, WireBundle::West,
717 WireBundle::North, WireBundle::East});
718 if (isBundleInList(srcBundle,
719 {WireBundle::West, WireBundle::North, WireBundle::East}))
720 return (srcBundle == dstBundle)
721 ? (srcChan == dstChan)
722 : isBundleInList(dstBundle,
723 {WireBundle::TileControl, WireBundle::FIFO,
724 WireBundle::South, WireBundle::West,
725 WireBundle::North, WireBundle::East});
726 if (srcBundle == WireBundle::Trace) {
727 if (isBundleInList(dstBundle, {WireBundle::FIFO, WireBundle::South}))
728 return true;
729 if (isBundleInList(dstBundle, {WireBundle::West, WireBundle::East}))
730 return dstChan == 0;
731 }
732 }
733 // Coretile
734 else if (isCoreTile(col, row)) {
735 if (isBundleInList(srcBundle,
736 {WireBundle::DMA, WireBundle::FIFO, WireBundle::South,
737 WireBundle::West, WireBundle::North, WireBundle::East}))
738 if (isBundleInList(dstBundle, {WireBundle::Core, WireBundle::DMA,
739 WireBundle::TileControl, WireBundle::FIFO,
740 WireBundle::South, WireBundle::West,
741 WireBundle::North, WireBundle::East}))
742 return (srcBundle == dstBundle) ? (srcChan == dstChan) : true;
743 if (srcBundle == WireBundle::Core)
744 return dstBundle != WireBundle::Core;
745 if (srcBundle == WireBundle::TileControl)
746 return dstBundle != WireBundle::TileControl &&
747 dstBundle != WireBundle::DMA;
748 if (srcBundle == WireBundle::Trace) {
749 if (dstBundle == WireBundle::DMA)
750 return dstChan == 0;
751 if (isBundleInList(dstBundle, {WireBundle::FIFO, WireBundle::South}))
752 return true;
753 }
754 }
755 return false;
756}
757
758std::vector<std::pair<uint32_t, uint32_t>>
760 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256)};
761}
762
763std::optional<uint32_t>
764AIE2TargetModel::getLocalLockAddress(uint32_t lockId, TileID tile) const {
765 auto computeTileBaseAddress = 0x0001F000;
766 auto memTileBaseAddress = 0x000C0000;
767 auto shimTileBaseAddress = 0x00014000;
768 auto lockAddrOffset = 0x10;
769
770 if (isCoreTile(tile.col, tile.row) &&
771 lockId < getNumLocks(tile.col, tile.row))
772 return computeTileBaseAddress + lockAddrOffset * lockId;
773
774 if (isMemTile(tile.col, tile.row) && lockId < getNumLocks(tile.col, tile.row))
775 return memTileBaseAddress + lockAddrOffset * lockId;
776
777 if (isShimNOCorPLTile(tile.col, tile.row) &&
778 lockId < getNumLocks(tile.col, tile.row))
779 return shimTileBaseAddress + lockAddrOffset * lockId;
780
781 return std::nullopt;
782}
783
785 // Every tile in a shimtile row must be a shimtile, and can only be one type
786 // of shim tile.
787 for (int j = 0; j < columns(); j++) {
788 assert(!isMemTile(j, 0) && (isShimPLTile(j, 0) || isShimNOCTile(j, 0)) &&
789 !isCoreTile(j, 0));
790 assert(isShimPLTile(j, 0) ^ isShimNOCTile(j, 0));
791 }
792
793 // Every tile in a memtile row must be a memtile.
794 for (int i = 1; i < 1 + static_cast<int>(getNumMemTileRows()); i++)
795 for (int j = 0; j < columns(); j++)
796 assert(isMemTile(j, i) && !isShimPLTile(j, i) && !isShimNOCTile(j, i) &&
797 !isCoreTile(j, i));
798
799 // Every other tile is a coretile.
800 for (int i = 1 + getNumMemTileRows(); i < rows(); i++)
801 for (int j = 0; j < columns(); j++)
802 assert(!isMemTile(j, i) && !isShimPLTile(j, i) && !isShimNOCTile(j, i) &&
803 isCoreTile(j, i));
804
805 // Looking North, buses must match
806 for (int i = 0; i < rows() - 1; i++)
807 for (int j = 0; j < columns(); j++)
808 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::North) ==
809 getNumDestSwitchboxConnections(j, i + 1, WireBundle::South));
810 // Looking South, buses must match
811 for (int i = 1; i < rows(); i++)
812 for (int j = 0; j < columns(); j++)
813 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::South) ==
814 getNumDestSwitchboxConnections(j, i - 1, WireBundle::North));
815 // Looking East, buses must match
816 for (int i = 0; i < rows(); i++)
817 for (int j = 0; j < columns() - 1; j++)
818 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::East) ==
819 getNumDestSwitchboxConnections(j + 1, i, WireBundle::West));
820 // Looking West, buses must match
821 for (int i = 0; i < rows(); i++)
822 for (int j = 1; j < columns(); j++)
823 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::West) ==
824 getNumDestSwitchboxConnections(j - 1, i, WireBundle::East));
825 // Edges have no connections
826 for (int j = 0; j < columns(); j++)
827 assert(getNumSourceSwitchboxConnections(j, rows() - 1, WireBundle::North) ==
828 0);
829 for (int i = 0; i < rows(); i++)
831 WireBundle::East) == 0);
832 for (int i = 0; i < rows(); i++)
833 assert(getNumSourceSwitchboxConnections(0, i, WireBundle::West) == 0);
834
835 // FIFOS are consistent
836 for (int i = 0; i < rows(); i++)
837 for (int j = 0; j < columns(); j++)
838 assert(getNumSourceSwitchboxConnections(j, i, WireBundle::FIFO) ==
839 getNumDestSwitchboxConnections(j, i, WireBundle::FIFO));
840}
841
842std::optional<uint32_t>
843AIETargetModel::getLockLocalBaseIndex(int localCol, int localRow, int lockCol,
844 int lockRow) const {
845 if (isCoreTile(localCol, localRow)) {
846 if (isMemSouth(localCol, localRow, lockCol, lockRow))
847 return 0;
848 if (isMemWest(localCol, localRow, lockCol, lockRow))
849 return getNumLocks(localCol, localRow);
850 if (isMemNorth(localCol, localRow, lockCol, lockRow))
851 return getNumLocks(localCol, localRow) * 2;
852 if (isMemEast(localCol, localRow, lockCol, lockRow))
853 return getNumLocks(localCol, localRow) * 3;
854 }
855
856 if (isMemTile(localCol, localRow)) {
857 if (isWest(localCol, localRow, lockCol, lockRow))
858 return 0;
859 if (isInternal(localCol, localRow, lockCol, lockRow))
860 return getNumLocks(localCol, localRow);
861 if (isEast(localCol, localRow, lockCol, lockRow))
862 return getNumLocks(localCol, localRow) * 2;
863 }
864
865 return std::nullopt;
866}
867
868std::optional<uint32_t>
869AIETargetModel::getMemLocalBaseAddress(int localCol, int localRow, int memCol,
870 int memRow) const {
871 if (isCoreTile(localCol, localRow)) {
872 if (isMemSouth(localCol, localRow, memCol, memRow))
873 return getMemSouthBaseAddress();
874 if (isMemWest(localCol, localRow, memCol, memRow))
875 return getMemWestBaseAddress();
876 if (isMemNorth(localCol, localRow, memCol, memRow))
877 return getMemNorthBaseAddress();
878 if (isMemEast(localCol, localRow, memCol, memRow))
879 return getMemEastBaseAddress();
880 }
881
882 if (isMemTile(localCol, localRow)) {
883 if (isWest(localCol, localRow, memCol, memRow))
884 return 0;
885 if (isInternal(localCol, localRow, memCol, memRow))
886 return getMemTileSize();
887 if (isEast(localCol, localRow, memCol, memRow))
888 return getMemTileSize() * 2;
889 }
890
891 return std::nullopt;
892}
893
894bool AIETargetModel::isSupportedBlockFormat(std::string const &format) const {
895 return false;
896}
897
898AIEArch BaseNPU2TargetModel::getTargetArch() const { return AIEArch::AIE2p; }
899
900std::vector<std::pair<uint32_t, uint32_t>>
902 return {std::pair(0, 64), std::pair(1, 128), std::pair(2, 256),
903 std::pair(3, 512)};
904}
905
907 std::string const &format) const {
908 std::set<std::string> supportedTypes = {"v8bfp16ebs8", "v16bfp16ebs16"};
909 return static_cast<bool>(supportedTypes.find(format) != supportedTypes.end());
910}
911
912} // namespace AIE
913} // 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.
uint32_t getDmaControlAddress(int col, int row, int channel, AIE::DMAChannelDir direction) const override
Return the array address of the dma task queue register for the given col, row, channel and direction...
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.
uint64_t getDmaBdAddress(int col, int row, uint32_t bd_id, int channel, AIE::DMAChannelDir direction) const override
Return the array address of the dma buffer descriptor for the given col, row, buffer descriptor id,...
uint32_t getRowShift() const override
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.
uint32_t getColumnShift() const override
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.
uint32_t getDmaBdAddressOffset(int col, int row) const override
Return the offset of the base address field within the shim dma buffer descriptor.
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.
uint32_t getRowShift() const override
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.
uint32_t getColumnShift() const override
uint64_t getDmaBdAddress(int col, int row, uint32_t bd_id, int channel, AIE::DMAChannelDir direction) const override
Return the array address of the dma buffer descriptor for the given col, row, buffer descriptor id,...
uint32_t getDmaControlAddress(int col, int row, int channel, AIE::DMAChannelDir direction) const override
Return the array address of the dma task queue register for the given col, row, channel and direction...
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.
uint32_t getDmaBdAddressOffset(int col, int row) const override
Return the offset of the base address field within the shim dma buffer descriptor.
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 isSupportedBlockFormat(std::string const &format) const
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.
std::vector< std::pair< uint32_t, uint32_t > > getShimBurstEncodingsAndLengths() const override
AIEArch getTargetArch() const override
AIE2 TargetModel.
bool isSupportedBlockFormat(std::string const &format) 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