MLIR-AIE 1.4.5.dev
test_library.cpp
Go to the documentation of this file.
1//===- test_library.cpp -----------------------------------------*- C++ -*-===//
2//
3// Copyright (C) 2021-2022 Xilinx, Inc.
4// Copyright (C) 2022-2025 Advanced Micro Devices, Inc.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9/// \file
10/// This file contains common libraries used for testing. Many of these
11/// functions are relatively thin wrappers around underlying libXAIE call and
12/// are provided to expose a relatively consistent API. Others are more
13/// complex.
14
15#include "test_library.h"
16#include "math.h"
17#include <assert.h>
18#include <fcntl.h>
19#include <stdio.h>
20#include <sys/mman.h>
21
22/// @brief Release access to the libXAIE context.
23/// @param ctx The context
25 AieRC RC = XAie_Finish(ctx->XAieDevInst);
26 if (RC != XAIE_OK) {
27 printf("Failed to finish tiles.\n");
28 }
29
30 delete ctx->XAieConfig;
31 delete ctx->XAieDevInst;
32 delete ctx;
33}
34
35/// @brief Initialize the device represented by the context.
36/// @param ctx The AIE context
37/// @param device_id The device ID to initialize
38/// @return Zero on success, negative value on error
39int mlir_aie_init_device(aie_libxaie_ctx_t *ctx, uint32_t device_id) {
40 AieRC RC = XAIE_OK;
41
42 RC = XAie_CfgInitialize(ctx->XAieDevInst, ctx->XAieConfig);
43 if (RC != XAIE_OK) {
44 printf("Driver initialization failed.\n");
45 return -1;
46 }
47
48 // Without this special case, the simulator generates
49 // FATAL::[ xtlm::907 ] b_transport_cb is not registered with the utils
50 const XAie_Backend *Backend = ctx->XAieDevInst->Backend;
51 if (Backend->Type != XAIE_IO_BACKEND_SIM) {
52 RC = XAie_PmRequestTiles(ctx->XAieDevInst, NULL, 0);
53 if (RC != XAIE_OK) {
54 printf("Failed to request tiles.\n");
55 return -1;
56 }
57
58 // TODO Extra code to really teardown the partitions
59 RC = XAie_Finish(ctx->XAieDevInst);
60 if (RC != XAIE_OK) {
61 printf("Failed to finish tiles.\n");
62 return -1;
63 }
64
65 RC = XAie_CfgInitialize(ctx->XAieDevInst, ctx->XAieConfig);
66 if (RC != XAIE_OK) {
67 printf("Driver initialization failed.\n");
68 return -1;
69 }
70 RC = XAie_PmRequestTiles(ctx->XAieDevInst, NULL, 0);
71 if (RC != XAIE_OK) {
72 printf("Failed to request tiles.\n");
73 return -1;
74 }
75 }
76
77 if (Backend->Type == XAIE_IO_BACKEND_SIM) {
78 printf("Turning ecc off\n");
79 XAie_TurnEccOff(ctx->XAieDevInst);
80 }
81
82 return 0;
83}
84
85/// @brief Acquire a physical lock
86/// @param ctx The context
87/// @param col The column of the lock
88/// @param row The row of the lock
89/// @param lockid The ID of the lock in the tile.
90/// @param lockval The value to acquire the lock with.
91/// @param timeout The number of microseconds to wait
92/// @return Return non-zero on success, i.e. the operation did not timeout.
93int mlir_aie_acquire_lock(aie_libxaie_ctx_t *ctx, int col, int row, int lockid,
94 int lockval, int timeout) {
95 return (XAie_LockAcquire(ctx->XAieDevInst, XAie_TileLoc(col, row),
96 XAie_LockInit(lockid, lockval), timeout) == XAIE_OK);
97}
98
99/// @brief Release a physical lock
100/// @param ctx The context
101/// @param col The column of the lock
102/// @param row The row of the lock
103/// @param lockid The ID of the lock in the tile.
104/// @param lockval The value to acquire the lock with.
105/// @param timeout The number of microseconds to wait
106/// @return Return non-zero on success, i.e. the operation did not timeout.
107int mlir_aie_release_lock(aie_libxaie_ctx_t *ctx, int col, int row, int lockid,
108 int lockval, int timeout) {
109 return (XAie_LockRelease(ctx->XAieDevInst, XAie_TileLoc(col, row),
110 XAie_LockInit(lockid, lockval), timeout) == XAIE_OK);
111}
112
113/// @brief Read the AIE configuration memory at the given physical address.
115 u32 val;
116 XAie_Read32(ctx->XAieDevInst, addr, &val);
117 return val;
118}
119
120/// @brief Write the AIE configuration memory at the given physical address.
121/// It's almost always better to use some more indirect method of accessing
122/// configuration registers, but this is provided as a last resort.
123void mlir_aie_write32(aie_libxaie_ctx_t *ctx, u64 addr, u32 val) {
124 XAie_Write32(ctx->XAieDevInst, addr, val);
125}
126
127/// @brief Read a value from the data memory of a particular tile memory
128/// @param ctx The AIE context
129/// @param col The column coordinate of the tile
130/// @param row The row coordinate of the tile
131/// @param addr The address within the tile\'s data memory
132/// @return The 32-bit data value read from the specified address
134 u64 addr) {
135 u32 data;
136 XAie_DataMemRdWord(ctx->XAieDevInst, XAie_TileLoc(col, row), addr, &data);
137 return data;
138}
139
140/// @brief Write a value to the data memory of a particular tile memory
141/// @param ctx The AIE context
142/// @param col The column coordinate of the tile
143/// @param row The row coordinate of the tile
144/// @param addr The address within the tile\'s data memory
145/// @param data The 32-bit data value to write
147 u64 addr, u32 data) {
148 XAie_DataMemWrWord(ctx->XAieDevInst, XAie_TileLoc(col, row), addr, data);
149}
150
151/// @brief Return the base address of the given tile.
152/// The configuration address space of most tiles is very similar,
153/// relative to this base address.
154u64 mlir_aie_get_tile_addr(aie_libxaie_ctx_t *ctx, int col, int row) {
155 return (((u64)row & 0xFFU) << ctx->XAieDevInst->DevProp.RowShift) |
156 (((u64)col & 0xFFU) << ctx->XAieDevInst->DevProp.ColShift);
157}
158
159/// @brief Dump the tile memory of the given tile
160/// Values that are zero are not shown
161void mlir_aie_dump_tile_memory(aie_libxaie_ctx_t *ctx, int col, int row) {
162 for (int i = 0; i < 0x2000; i++) {
163 uint32_t d;
164 AieRC rc = XAie_DataMemRdWord(ctx->XAieDevInst, XAie_TileLoc(col, row),
165 (i * 4), &d);
166 if (rc == XAIE_OK && d != 0)
167 printf("Tile[%d][%d]: mem[%d] = %d\n", col, row, i, d);
168 }
169}
170
171/// @brief Fill the tile memory of the given tile with zeros.
172/// Values that are zero are not shown
173void mlir_aie_clear_tile_memory(aie_libxaie_ctx_t *ctx, int col, int row) {
174 for (int i = 0; i < 0x2000; i++) {
175 XAie_DataMemWrWord(ctx->XAieDevInst, XAie_TileLoc(col, row), (i * 4), 0);
176 }
177}
178
179static void print_aie1_dmachannel_status(aie_libxaie_ctx_t *ctx, int col,
180 int row, const char *dmatype,
181 const char *channel, int channelNum,
182 int running, int stalled) {
183 printf("%s [%d, %d] AIE1 %s%d ", dmatype, col, row, channel, channelNum);
184 switch (running) {
185 case 0:
186 printf("IDLE ");
187 break;
188 case 1:
189 printf("STARTING ");
190 break;
191 case 2:
192 printf("RUNNING ");
193 break;
194 }
195 if (stalled) {
196 printf("Stalled on lock");
197 }
198 printf("\n");
199}
200
201static void print_aie2_dmachannel_status(aie_libxaie_ctx_t *ctx, int col,
202 int row, const char *dmatype,
203 const char *channel, int channelNum,
204 u32 statusOffset, u32 controlOffset,
205 int &current_bd) {
206 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
207 u32 status, control;
208 XAie_Read32(ctx->XAieDevInst, tileAddr + statusOffset, &status);
209 XAie_Read32(ctx->XAieDevInst, tileAddr + controlOffset, &control);
210 u32 running = status & 0x3;
211 u32 stalled_acq = (status >> 2) & 0x1;
212 u32 stalled_rel = (status >> 3) & 0x1;
213 u32 stalled_data = (status >> 4) & 0x1;
214 u32 stalled_complete = (status >> 5) & 0x1;
215 current_bd = status >> 24;
216 printf("%s [%d, %d] AIE2 %s%d ", dmatype, col, row, channel, channelNum);
217 switch (running) {
218 case 0:
219 printf("IDLE ");
220 break;
221 case 1:
222 printf("STARTING ");
223 break;
224 case 2:
225 printf("RUNNING ");
226 break;
227 }
228 if (stalled_acq)
229 printf("Stalled on Acquire ");
230 if (stalled_rel)
231 printf("Stalled on Release ");
232 if (stalled_data)
233 printf("Stalled on Data ");
234 if (stalled_complete)
235 printf("Stalled on Completion ");
236 printf("status:%08X ctrl:%02X\n", status, control);
237};
238
239static void print_bd(int bd, int bd_valid, u32 nextBd, u32 useNextBd,
240 int isPacket, u32 packetID, u32 packetType,
241 int words_to_transfer, int base_address,
242 int acquireEnabled, u32 acquireLock, int acquireValue,
243 int releaseEnabled, u32 releaseLock, int releaseValue,
244 int s2mm_current_bd[], int mm2s_current_bd[],
245 int numchannels) {
246
247 if (bd_valid) {
248 printf("BD %d valid ", bd);
249 if (useNextBd)
250 printf("(Next BD: %d)\n", nextBd);
251 else
252 printf("(Last BD)\n");
253
254 for (int i = 0; i < numchannels; i++) {
255 if (bd == s2mm_current_bd[i]) {
256 printf(" * Current BD for s2mm channel %d\n", i);
257 }
258 if (bd == mm2s_current_bd[i]) {
259 printf(" * Current BD for mm2s channel %d\n", i);
260 }
261 }
262
263 if (isPacket) {
264 printf(" Packet ID: %02X\n", packetID);
265 printf(" Packet Type: %01X\n", packetType);
266 }
267 printf(" Transferring %d 32 bit words to/from byte address %06X\n",
268 words_to_transfer, base_address * 4);
269
270 // printf(" ");
271 // for (int w = 0; w < 7; w++) {
272 // u32 tmpd;
273 // XAie_DataMemRdWord(ctx->XAieDevInst, XAie_TileLoc(col, row),
274 // (base_address + w) * 4, &tmpd);
275 // printf("%08X ", tmpd);
276 // }
277 // printf("\n");
278 if (acquireEnabled) { // acquire is enabled
279 printf(" Acquires lock %d ", acquireLock);
280 printf("with value %d\n", acquireValue);
281 }
282 if (releaseEnabled) {
283 printf(" Releases lock %d ", releaseLock);
284 printf("with value %d\n", releaseValue);
285 }
286 // printf("currently ");
287 // u32 locks;
288 // XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001EF00, &locks);
289 // u32 two_bits = (locks >> (lock_id * 2)) & 0x3;
290 // if (two_bits) {
291 // u32 acquired = two_bits & 0x1;
292 // u32 value = two_bits & 0x2;
293 // if (acquired)
294 // printf("Acquired ");
295 // printf(value ? "1" : "0");
296 // } else
297 // printf("0");
298 // }
299 }
300}
301
302/// @brief Print a summary of the status of the given Tile DMA.
303void mlir_aie_print_dma_status(aie_libxaie_ctx_t *ctx, int col, int row) {
304 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
305 auto TileType = ctx->XAieDevInst->DevOps->GetTTypefromLoc(
306 ctx->XAieDevInst, XAie_TileLoc(col, row));
307 assert(TileType == XAIEGBL_TILE_TYPE_AIETILE);
308
309 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
310 const int num_bds = 2;
311 int s2mm_current_bd[num_bds];
312 int mm2s_current_bd[num_bds];
313
314 for (int i = 0; i < num_bds; i++) {
315 print_aie2_dmachannel_status(ctx, col, row, "DMA", "s2mm", i,
316 0x0001DF00 + 4 * i, 0x0001DE00 + 8 * i,
317 s2mm_current_bd[i]);
318 u32 write_count;
319 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DF18 + (0x4 * i),
320 &write_count);
321 printf("DMA [%d, %d] s2mm%d write_count = %d\n", col, row, i,
322 write_count);
323 }
324 for (int i = 0; i < num_bds; i++)
325 print_aie2_dmachannel_status(ctx, col, row, "DMA", "mm2s", i,
326 0x0001DF10 + 4 * i, 0x0001DE10 + 8 * i,
327 mm2s_current_bd[i]);
328
329 for (int bd = 0; bd < 8; bd++) {
330 u32 dma_bd_addr;
331 u32 dma_bd_packet;
332 u32 dma_bd_control;
333 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D000 + (0x20 * bd),
334 &dma_bd_addr);
335 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D004 + (0x20 * bd),
336 &dma_bd_packet);
337 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D014 + (0x20 * bd),
338 &dma_bd_control);
339
340 int bd_valid = (dma_bd_control >> 25) & 0x1;
341 u32 nextBd = ((dma_bd_control >> 27) & 0xF);
342 u32 useNextBd = ((dma_bd_control >> 26) & 0x1);
343 int isPacket = (dma_bd_packet >> 30) & 0x1;
344 u32 packetID = (dma_bd_packet >> 19) & 0x1F;
345 u32 packetType = (dma_bd_packet >> 16) & 0x7;
346 int words_to_transfer = (dma_bd_addr & 0x3FFF);
347 int base_address = dma_bd_addr >> 14;
348 int acquireEnabled = (dma_bd_control >> 12) & 0x1;
349 u32 acquireLock = dma_bd_control & 0xf;
350 int acquireValue = (((int)dma_bd_control << 20) >> 25);
351 u32 releaseLock = (dma_bd_control >> 13) & 0xf;
352 int releaseValue = (((int)dma_bd_control << 7) >> 25);
353 int releaseEnabled = releaseValue != 0;
354
355 print_bd(bd, bd_valid, nextBd, useNextBd, isPacket, packetID, packetType,
356 words_to_transfer, base_address, acquireEnabled, acquireLock,
357 acquireValue, releaseEnabled, releaseLock, releaseValue,
358 s2mm_current_bd, mm2s_current_bd, num_bds);
359 }
360 } else { // AIE1
361 u32 dma_mm2s_status;
362 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DF10, &dma_mm2s_status);
363 u32 dma_s2mm_status;
364 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DF00, &dma_s2mm_status);
365 u32 dma_mm2s0_control;
366 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DE10, &dma_mm2s0_control);
367 u32 dma_mm2s1_control;
368 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DE18, &dma_mm2s1_control);
369 u32 dma_s2mm0_control;
370 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DE00, &dma_s2mm0_control);
371 u32 dma_s2mm1_control;
372 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DE08, &dma_s2mm1_control);
373
374 u32 s2mm_ch0_running = dma_s2mm_status & 0x3;
375 u32 s2mm_ch1_running = (dma_s2mm_status >> 2) & 0x3;
376 u32 mm2s_ch0_running = dma_mm2s_status & 0x3;
377 u32 mm2s_ch1_running = (dma_mm2s_status >> 2) & 0x3;
378 int s2mm0_current_bd, s2mm1_current_bd;
379 int mm2s0_current_bd, mm2s1_current_bd;
380 s2mm0_current_bd = (dma_s2mm_status >> 16) & 0xf;
381 s2mm1_current_bd = (dma_s2mm_status >> 20) & 0xf;
382 mm2s0_current_bd = (dma_mm2s_status >> 16) & 0xf;
383 mm2s1_current_bd = (dma_mm2s_status >> 20) & 0xf;
384 u32 s2mm_ch0_stalled = (dma_s2mm_status >> 4) & 0x1;
385 u32 s2mm_ch1_stalled = (dma_s2mm_status >> 5) & 0x1;
386 u32 mm2s_ch0_stalled = (dma_mm2s_status >> 4) & 0x1;
387 u32 mm2s_ch1_stalled = (dma_mm2s_status >> 5) & 0x1;
388
389 printf("DMA [%d, %d] mm2s_status/0ctrl/1ctrl is %08X %02X %02X, "
390 "s2mm_status/0ctrl/1ctrl is %08X %02X %02X\n",
391 col, row, dma_mm2s_status, dma_mm2s0_control, dma_mm2s1_control,
392 dma_s2mm_status, dma_s2mm0_control, dma_s2mm1_control);
393 print_aie1_dmachannel_status(ctx, col, row, "DMA", "s2mm", 0,
394 s2mm_ch0_running, s2mm_ch0_stalled);
395 print_aie1_dmachannel_status(ctx, col, row, "DMA", "s2mm", 1,
396 s2mm_ch1_running, s2mm_ch1_stalled);
397 print_aie1_dmachannel_status(ctx, col, row, "DMA", "mm2s", 0,
398 mm2s_ch0_running, mm2s_ch0_stalled);
399 print_aie1_dmachannel_status(ctx, col, row, "DMA", "mm2s", 1,
400 mm2s_ch1_running, mm2s_ch1_stalled);
401 for (int bd = 0; bd < 8; bd++) {
402 u32 dma_bd_addr_a;
403 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D000 + (0x20 * bd),
404 &dma_bd_addr_a);
405 u32 dma_bd_control;
406 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D018 + (0x20 * bd),
407 &dma_bd_control);
408 // It appears that in the simulator, bd's are not initialized according to
409 // the spec, and instead the control word is all 1's.
410 if ((dma_bd_control >> 31) & 0x1 && (dma_bd_control != 0xFFFFFFFF)) {
411 printf("BD %d valid ", bd);
412 u32 nextBd = ((dma_bd_control >> 13) & 0xF);
413 u32 useNextBd = ((dma_bd_control >> 17) & 0x1);
414 if (useNextBd)
415 printf("(Next BD: %d)\n", nextBd);
416 else
417 printf("(Last BD)\n");
418
419 if (bd == s2mm0_current_bd) {
420 printf(" * Current BD for s2mm channel 0\n");
421 }
422 if (bd == s2mm1_current_bd) {
423 printf(" * Current BD for s2mm channel 1\n");
424 }
425 if (bd == mm2s0_current_bd) {
426 printf(" * Current BD for mm2s channel 0\n");
427 }
428 if (bd == mm2s1_current_bd) {
429 printf(" * Current BD for mm2s channel 1\n");
430 }
431
432 if (dma_bd_control & 0x08000000) {
433 u32 dma_packet;
434 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D010 + (0x20 * bd),
435 &dma_packet);
436 printf(" Packet mode: %02X\n", dma_packet & 0x1F);
437 }
438 int words_to_transfer = 1 + (dma_bd_control & 0x1FFF);
439 int base_address = dma_bd_addr_a & 0x1FFF;
440 printf(" Transferring %d 32 bit words to/from byte address %06X\n",
441 words_to_transfer, base_address * 4);
442
443 printf(" ");
444 for (int w = 0; w < 7; w++) {
445 u32 tmpd;
446 XAie_DataMemRdWord(ctx->XAieDevInst, XAie_TileLoc(col, row),
447 (base_address + w) * 4, &tmpd);
448 printf("%08X ", tmpd);
449 }
450 printf("\n");
451 int hasAcquire = (dma_bd_addr_a >> 18) & 0x1;
452 int hasRelease = (dma_bd_addr_a >> 21) & 0x1;
453 if (hasAcquire || hasRelease) {
454 u32 lock_id = (dma_bd_addr_a >> 22) & 0xf;
455 if (hasAcquire) {
456 printf(" Acquires lock %d ", lock_id);
457 if ((dma_bd_addr_a >> 16) & 0x1)
458 printf("with value %d ", (dma_bd_addr_a >> 17) & 0x1);
459 }
460 if (hasRelease) {
461 printf(" Releases lock %d ", lock_id);
462 if ((dma_bd_addr_a >> 19) & 0x1)
463 printf("with value %d ", (dma_bd_addr_a >> 20) & 0x1);
464 }
465
466 printf("currently ");
467 u32 locks;
468 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001EF00, &locks);
469 u32 two_bits = (locks >> (lock_id * 2)) & 0x3;
470 if (two_bits) {
471 u32 acquired = two_bits & 0x1;
472 u32 value = two_bits & 0x2;
473 if (acquired)
474 printf("Acquired ");
475 printf(value ? "1" : "0");
476 } else
477 printf("0");
478 printf("\n");
479 }
480
481 if (dma_bd_control & 0x30000000) { // FIFO MODE
482 int FIFO = (dma_bd_control >> 28) & 0x3;
483 u32 dma_fifo_counter;
484 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001DF20,
485 &dma_fifo_counter);
486 printf(" Using FIFO Cnt%d : %08X\n", FIFO, dma_fifo_counter);
487 }
488 }
489 }
490 }
491}
492
493void print_aie2_lock_status(aie_libxaie_ctx_t *ctx, int col, int row,
494 const char *type, int lockOffset, int locks) {
495 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
496 printf("%s [%d, %d] AIE2 locks are: ", type, col, row);
497 int lockAddr = tileAddr + lockOffset;
498 for (int lock = 0; lock < locks; lock++) {
499 u32 val;
500 XAie_Read32(ctx->XAieDevInst, lockAddr, &val);
501 printf("%X ", val);
502 lockAddr += 0x10;
503 }
504 printf("\n");
505}
506
507/// @brief Print a summary of the status of the given MemTile DMA.
509 int row) {
510 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
511 auto TileType = ctx->XAieDevInst->DevOps->GetTTypefromLoc(
512 ctx->XAieDevInst, XAie_TileLoc(col, row));
513 assert(TileType == XAIEGBL_TILE_TYPE_MEMTILE);
514 assert(ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML);
515
516 int s2mm_current_bd[6];
517 int mm2s_current_bd[6];
518
519 for (int i = 0; i < 6; i++) {
520 print_aie2_dmachannel_status(ctx, col, row, "MemTileDMA", "s2mm", i,
521 0x000A0660 + 4 * i, 0x000A0600 + 8 * i,
522 s2mm_current_bd[i]);
523 u32 write_count;
524 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000A06B0 + (0x4 * i),
525 &write_count);
526 printf("MemTileDMA [%d, %d] s2mm%d write_count = %d\n", col, row, i,
527 write_count);
528 }
529 for (int i = 0; i < 6; i++)
530 print_aie2_dmachannel_status(ctx, col, row, "MemTileDMA", "mm2s", i,
531 0x000A0680 + 4 * i, 0x000A0630 + 8 * i,
532 mm2s_current_bd[i]);
533
534 print_aie2_lock_status(ctx, col, row, "MemTileDMA", 0x000C0000, 64);
535
536 for (int bd = 0; bd < 8; bd++) {
537 u32 dma_bd_0;
538 u32 dma_bd_1;
539 u32 dma_bd_7;
540 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000A0000 + (0x20 * bd),
541 &dma_bd_0);
542 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000A0004 + (0x20 * bd),
543 &dma_bd_1);
544 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000A001C + (0x20 * bd),
545 &dma_bd_7);
546
547 int bd_valid = (dma_bd_7 >> 31) & 0x1;
548 u32 nextBd = ((dma_bd_1 >> 20) & 0xF);
549 u32 useNextBd = ((dma_bd_1 >> 19) & 0x1);
550 int isPacket = (dma_bd_0 >> 31) & 0x1;
551 u32 packetID = (dma_bd_0 >> 23) & 0x1F;
552 u32 packetType = (dma_bd_0 >> 28) & 0x7;
553 int words_to_transfer = (dma_bd_0 & 0x1FFFF);
554 int base_address = dma_bd_1 & 0x7FFFF;
555 int acquireEnabled = (dma_bd_7 >> 12) & 0x1;
556 u32 acquireLock = dma_bd_7 & 0xff;
557 int acquireValue = (((int)dma_bd_7 << 17) >> 25);
558 u32 releaseLock = (dma_bd_7 >> 16) & 0xff;
559 int releaseValue = (((int)dma_bd_7 << 1) >> 25);
560 int releaseEnabled = releaseValue != 0;
561
562 print_bd(bd, bd_valid, nextBd, useNextBd, isPacket, packetID, packetType,
563 words_to_transfer, base_address, acquireEnabled, acquireLock,
564 acquireValue, releaseEnabled, releaseLock, releaseValue,
565 s2mm_current_bd, mm2s_current_bd, 6);
566 }
567}
568
569/// @brief Print a summary of the status of the given Shim DMA.
571 // int col = loc.Col;
572 // int row = loc.Row;
573 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
574 auto TileType = ctx->XAieDevInst->DevOps->GetTTypefromLoc(
575 ctx->XAieDevInst, XAie_TileLoc(col, row));
576 assert(TileType == XAIEGBL_TILE_TYPE_SHIMNOC);
577
578 const int num_bds = 2;
579 int s2mm_current_bd[num_bds];
580 int mm2s_current_bd[num_bds];
581 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
582 for (int i = 0; i < num_bds; i++) {
583 print_aie2_dmachannel_status(ctx, col, row, "ShimDMA", "s2mm", i,
584 0x0001D220 + 4 * i, 0x0001D200 + 8 * i,
585 s2mm_current_bd[i]);
586 u32 write_count;
587 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D230 + (0x4 * i),
588 &write_count);
589 printf("ShimDMA [%d, %d] s2mm%d write_count = %d\n", col, row, i,
590 write_count);
591 }
592 for (int i = 0; i < num_bds; i++)
593 print_aie2_dmachannel_status(ctx, col, row, "ShimDMA", "mm2s", i,
594 0x0001D228 + 4 * i, 0x0001D210 + 8 * i,
595 mm2s_current_bd[i]);
596 } else {
597 u32 dma_mm2s_status, dma_s2mm_status;
598 u32 dma_mm2s0_control, dma_mm2s1_control;
599 u32 dma_s2mm0_control, dma_s2mm1_control;
600 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D164, &dma_mm2s_status);
601 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D160, &dma_s2mm_status);
602 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D150, &dma_mm2s0_control);
603 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D158, &dma_mm2s1_control);
604 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D140, &dma_s2mm0_control);
605 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D148, &dma_s2mm1_control);
606
607 u32 s2mm_ch0_running = dma_s2mm_status & 0x3;
608 u32 s2mm_ch1_running = (dma_s2mm_status >> 2) & 0x3;
609 u32 mm2s_ch0_running = dma_mm2s_status & 0x3;
610 u32 mm2s_ch1_running = (dma_mm2s_status >> 2) & 0x3;
611 s2mm_current_bd[0] = (dma_s2mm_status >> 16) & 0xf;
612 s2mm_current_bd[1] = (dma_s2mm_status >> 20) & 0xf;
613 mm2s_current_bd[0] = (dma_mm2s_status >> 16) & 0xf;
614 mm2s_current_bd[1] = (dma_mm2s_status >> 20) & 0xf;
615 u32 s2mm_ch0_stalled = (dma_s2mm_status >> 4) & 0x1;
616 u32 s2mm_ch1_stalled = (dma_s2mm_status >> 5) & 0x1;
617 u32 mm2s_ch0_stalled = (dma_mm2s_status >> 4) & 0x1;
618 u32 mm2s_ch1_stalled = (dma_mm2s_status >> 5) & 0x1;
619
620 printf("ShimDMA [%d, %d] AIE1 mm2s_status/0ctrl/1ctrl is %08X %02X %02X, "
621 "s2mm_status/0ctrl/1ctrl is %08X %02X %02X\n",
622 col, row, dma_mm2s_status, dma_mm2s0_control, dma_mm2s1_control,
623 dma_s2mm_status, dma_s2mm0_control, dma_s2mm1_control);
624 print_aie1_dmachannel_status(ctx, col, row, "ShimDMA", "s2mm", 0,
625 s2mm_ch0_running, s2mm_ch0_stalled);
626 print_aie1_dmachannel_status(ctx, col, row, "ShimDMA", "s2mm", 1,
627 s2mm_ch1_running, s2mm_ch1_stalled);
628 print_aie1_dmachannel_status(ctx, col, row, "ShimDMA", "mm2s", 0,
629 mm2s_ch0_running, mm2s_ch0_stalled);
630 print_aie1_dmachannel_status(ctx, col, row, "ShimDMA", "mm2s", 1,
631 mm2s_ch1_running, mm2s_ch1_stalled);
632 }
633
634 u32 locks;
635 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
636 print_aie2_lock_status(ctx, col, row, "ShimDMA", 0x00014000, 16);
637 int overflowAddr = tileAddr + 0x00014120;
638 int underflowAddr = tileAddr + 0x00014128;
639 u32 overflow, underflow;
640 // XAie_Read32(ctx->XAieDevInst, overflowAddr, &overflow);
641 // XAie_Read32(ctx->XAieDevInst, underflowAddr, &underflow);
642 printf(" overflow?:%x underflow?:%x\n", overflow, underflow);
643 } else {
644 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00014F00, &locks);
645 printf("ShimDMA [%d, %d] AIE1 locks are %08X\n", col, row, locks);
646 for (int lock = 0; lock < 16; lock++) {
647 u32 two_bits = (locks >> (lock * 2)) & 0x3;
648 if (two_bits) {
649 printf("Lock %d: ", lock);
650 u32 acquired = two_bits & 0x1;
651 u32 value = two_bits & 0x2;
652 if (acquired)
653 printf("Acquired ");
654 printf(value ? "1" : "0");
655 printf("\n");
656 }
657 }
658 }
659
660 for (int bd = 0; bd < 8; bd++) {
661 int words_to_transfer; // transfer size in 32-bit words
662 u64 base_address; // address in bytes
663 bool bd_valid;
664 int use_next_bd;
665 int next_bd;
666 int acquire_lockID, release_lockID;
667 int enable_lock_release;
668 int lock_release_val;
669 int use_release_val;
670 int enable_lock_acquire;
671 int lock_acquire_val;
672 int use_acquire_val;
673
674 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
675 u32 dma_bd_addr_low;
676 u32 dma_bd_buffer_length;
677 u32 dma_bd_2;
678 u32 dma_bd_7;
679 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D000 + (0x20 * bd),
680 &dma_bd_buffer_length);
681 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D004 + (0x20 * bd),
682 &dma_bd_addr_low);
683 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D008 + (0x20 * bd),
684 &dma_bd_2);
685 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D01C + (0x20 * bd),
686 &dma_bd_7);
687 // printf("test: %d %d %d %d\n", dma_bd_buffer_length, dma_bd_addr_low,
688 // dma_bd_2, dma_bd_7);
689 words_to_transfer = dma_bd_buffer_length;
690 base_address =
691 u64(dma_bd_addr_low & 0xFFFC) + (u64(dma_bd_2 & 0xFF) << 32);
692 bd_valid = (dma_bd_7 >> 25) & 0x1;
693 use_next_bd = ((dma_bd_7 >> 26) & 0x1);
694 next_bd = ((dma_bd_7 >> 27) & 0xF);
695 acquire_lockID = ((dma_bd_7 >> 0) & 0xF);
696 release_lockID = ((dma_bd_7 >> 13) & 0xF);
697 lock_release_val = (s32(dma_bd_7) << 7) >> 25; // sign extend
698 enable_lock_release = lock_release_val != 0;
699 use_release_val = 1;
700 lock_acquire_val = (s32(dma_bd_7) << 20) >> 25; // sign extend
701 enable_lock_acquire = ((dma_bd_7 >> 12) & 0x1);
702 use_acquire_val = 1;
703 } else {
704 u32 dma_bd_addr_a;
705 u32 dma_bd_buffer_length;
706 u32 dma_bd_control;
707 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D000 + (0x14 * bd),
708 &dma_bd_addr_a);
709 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D004 + (0x14 * bd),
710 &dma_bd_buffer_length);
711 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001D008 + (0x14 * bd),
712 &dma_bd_control);
713 words_to_transfer = dma_bd_buffer_length;
714 base_address =
715 (u64)dma_bd_addr_a + ((u64)((dma_bd_control >> 16) & 0xFFFF) << 32);
716 bd_valid = dma_bd_control & 0x1;
717 use_next_bd = ((dma_bd_control >> 15) & 0x1);
718 next_bd = ((dma_bd_control >> 11) & 0xF);
719 release_lockID = acquire_lockID = ((dma_bd_control >> 7) & 0xF);
720 enable_lock_release = ((dma_bd_control >> 6) & 0x1);
721 lock_release_val = ((dma_bd_control >> 5) & 0x1);
722 use_release_val = ((dma_bd_control >> 4) & 0x1);
723 enable_lock_acquire = ((dma_bd_control >> 3) & 0x1);
724 lock_acquire_val = ((dma_bd_control >> 2) & 0x1);
725 use_acquire_val = ((dma_bd_control >> 1) & 0x1);
726 }
727 bool isPacket = false;
728 int packetID = 0;
729 int packetType = 0;
730 print_bd(bd, bd_valid, next_bd, use_next_bd, isPacket, packetID, packetType,
731 words_to_transfer, base_address, enable_lock_acquire,
732 acquire_lockID, lock_acquire_val, enable_lock_release,
733 release_lockID, lock_release_val, s2mm_current_bd, mm2s_current_bd,
734 num_bds);
735 }
736}
737
738/// @brief Print the status of a core represented by the given tile, at the
739/// given coordinates.
740void mlir_aie_print_tile_status(aie_libxaie_ctx_t *ctx, int col, int row) {
741 // int col = loc.Col;
742 // int row = loc.Row;
743 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
744 u32 status, coreTimerLow, PC, LR, SP, locks, R0, R4;
745 u32 trace_status;
746 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
747 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x032004, &status);
748 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0340F8, &coreTimerLow);
749 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00031100, &PC);
750 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00031130, &LR);
751 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00031120, &SP);
752 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000340D8, &trace_status);
753
754 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00030C00, &R0);
755 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00030C40, &R4);
756
757 } else {
758 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x032004, &status);
759 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0340F8, &coreTimerLow);
760 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00030280, &PC);
761 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000302B0, &LR);
762 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000302A0, &SP);
763 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x000140D8, &trace_status);
764
765 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00030000, &R0);
766 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x00030040, &R4);
767 }
768 printf("Core [%d, %d] status is %08X, timer is %u, PC is %08X"
769 ", LR is %08X, SP is %08X, R0 is %08X,R4 is %08X\n",
770 col, row, status, coreTimerLow, PC, LR, SP, R0, R4);
771 printf("Core [%d, %d] trace status is %08X\n", col, row, trace_status);
772
773 if (ctx->XAieConfig->AieGen == XAIE_DEV_GEN_AIEML) {
774 print_aie2_lock_status(ctx, col, row, "Core", 0x0001F000, 16);
775 } else {
776 XAie_Read32(ctx->XAieDevInst, tileAddr + 0x0001EF00, &locks);
777 printf("Core [%d, %d] AIE1 locks are %08X\n", col, row, locks);
778 for (int lock = 0; lock < 16; lock++) {
779 u32 two_bits = (locks >> (lock * 2)) & 0x3;
780 if (two_bits) {
781 printf("Lock %d: ", lock);
782 u32 acquired = two_bits & 0x1;
783 u32 value = two_bits & 0x2;
784 if (acquired)
785 printf("Acquired ");
786 printf(value ? "1" : "0");
787 printf("\n");
788 }
789 }
790 }
791
792 // Note that not all strings are valid for all architectures
793 const char *core_status_strings[] = {
794 "Enabled",
795 "In Reset",
796 "Memory Stall S",
797 "Memory Stall W",
798 "Memory Stall N",
799 "Memory Stall E",
800 "Lock Stall S",
801 "Lock Stall W",
802 "Lock Stall N",
803 "Lock Stall E",
804 "Stream Stall SS0",
805 "Stream Stall SS1", // AIE1 only
806 "Stream Stall MS0",
807 "Stream Stall MS1", // AIE1 only
808 "Cascade Stall Slave",
809 "Cascade Stall Master",
810 "Debug Halt",
811 "ECC Error",
812 "ECC Scrubbing",
813 "Error Halt",
814 "Core Done",
815 "Core Processor Bus Stall", // AIE2 only
816 };
817
818 printf("Core Status: ");
819 for (int i = 0; i <= 21; i++) {
820 if ((status >> i) & 0x1)
821 printf("%s ", core_status_strings[i]);
822 }
823 printf("\n");
824}
825
826static void clear_range(XAie_DevInst *devInst, u64 tileAddr, u64 low,
827 u64 high) {
828 for (int i = low; i <= high; i += 4) {
829 XAie_Write32(devInst, tileAddr + i, 0);
830 // int x = XAie_Read32(ctx->XAieDevInst,tileAddr+i);
831 // if(x != 0) {
832 // printf("@%x = %x\n", i, x);
833 // XAie_Write32(ctx->XAieDevInst,tileAddr+i, 0);
834 // }
835 }
836}
837
838/// @brief Clear the configuration of the given (non-shim) tile.
839/// This includes: clearing the program memory, data memory,
840/// DMA descriptors, and stream switch configuration.
841void mlir_aie_clear_config(aie_libxaie_ctx_t *ctx, int col, int row) {
842 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
843
844 // Put the core in reset first, otherwise bus collisions
845 // result in arm bus errors.
846 // TODO Check if this works
847 XAie_CoreDisable(ctx->XAieDevInst, XAie_TileLoc(col, row));
848
849 // Program Memory
850 clear_range(ctx->XAieDevInst, tileAddr, 0x20000, 0x200FF);
851 // TileDMA
852 clear_range(ctx->XAieDevInst, tileAddr, 0x1D000, 0x1D1F8);
853 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1DE00, 0);
854 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1DE08, 0);
855 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1DE10, 0);
856 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1DE08, 0);
857 // Stream Switch master config
858 clear_range(ctx->XAieDevInst, tileAddr, 0x3F000, 0x3F060);
859 // Stream Switch slave config
860 clear_range(ctx->XAieDevInst, tileAddr, 0x3F100, 0x3F168);
861 // Stream Switch slave slot config
862 clear_range(ctx->XAieDevInst, tileAddr, 0x3F200, 0x3F3AC);
863
864 // TODO Check if this works
865 XAie_CoreEnable(ctx->XAieDevInst, XAie_TileLoc(col, row));
866}
867
868/// @brief Clear the configuration of the given shim tile.
869/// This includes: clearing the program memory, data memory,
870/// DMA descriptors, and stream switch configuration.
871void mlir_aie_clear_shim_config(aie_libxaie_ctx_t *ctx, int col, int row) {
872 u64 tileAddr = mlir_aie_get_tile_addr(ctx, col, row);
873
874 // ShimDMA
875 clear_range(ctx->XAieDevInst, tileAddr, 0x1D000, 0x1D13C);
876 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1D140, 0);
877 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1D148, 0);
878 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1D150, 0);
879 XAie_Write32(ctx->XAieDevInst, tileAddr + 0x1D158, 0);
880
881 // Stream Switch master config
882 clear_range(ctx->XAieDevInst, tileAddr, 0x3F000, 0x3F058);
883 // Stream Switch slave config
884 clear_range(ctx->XAieDevInst, tileAddr, 0x3F100, 0x3F15C);
885 // Stream Switch slave slot config
886 clear_range(ctx->XAieDevInst, tileAddr, 0x3F200, 0x3F37C);
887}
888
889/*
890 ******************************************************************************
891 * COMMON
892 ******************************************************************************
893 */
894
895/// @brief Given an array of values, compute and print statistics about those
896/// values.
897/// @param performance_counter An array of values
898/// @param n The number of values
899void computeStats(u32 performance_counter[], int n) {
900 u32 total_0 = 0;
901
902 for (int i = 0; i < n; i++) {
903 total_0 += performance_counter[i];
904 }
905
906 float mean_0 = (float)total_0 / n;
907
908 float sdev_0 = 0;
909
910 for (int i = 0; i < n; i++) {
911 float x = (float)performance_counter[i] - mean_0;
912 sdev_0 += x * x;
913 }
914
915 sdev_0 = sqrtf(sdev_0 / n);
916
917 printf("Mean and Standard Devation: %f, %f \n", mean_0, sdev_0);
918}
XAie_DevInst * XAieDevInst
Definition target.h:24
XAie_Config * XAieConfig
Definition target.h:23
void mlir_aie_print_memtiledma_status(aie_libxaie_ctx_t *ctx, int col, int row)
Print a summary of the status of the given MemTile DMA.
int mlir_aie_acquire_lock(aie_libxaie_ctx_t *ctx, int col, int row, int lockid, int lockval, int timeout)
Acquire a physical lock.
u32 mlir_aie_data_mem_rd_word(aie_libxaie_ctx_t *ctx, int col, int row, u64 addr)
Read a value from the data memory of a particular tile memory.
void mlir_aie_clear_tile_memory(aie_libxaie_ctx_t *ctx, int col, int row)
Fill the tile memory of the given tile with zeros.
void print_aie2_lock_status(aie_libxaie_ctx_t *ctx, int col, int row, const char *type, int lockOffset, int locks)
u64 mlir_aie_get_tile_addr(aie_libxaie_ctx_t *ctx, int col, int row)
Return the base address of the given tile.
void mlir_aie_clear_shim_config(aie_libxaie_ctx_t *ctx, int col, int row)
Clear the configuration of the given shim tile.
void mlir_aie_clear_config(aie_libxaie_ctx_t *ctx, int col, int row)
Clear the configuration of the given (non-shim) tile.
void mlir_aie_print_dma_status(aie_libxaie_ctx_t *ctx, int col, int row)
Print a summary of the status of the given Tile DMA.
int mlir_aie_release_lock(aie_libxaie_ctx_t *ctx, int col, int row, int lockid, int lockval, int timeout)
Release a physical lock.
int mlir_aie_init_device(aie_libxaie_ctx_t *ctx, uint32_t device_id)
Initialize the device represented by the context.
void mlir_aie_print_shimdma_status(aie_libxaie_ctx_t *ctx, int col, int row)
Print a summary of the status of the given Shim DMA.
u32 mlir_aie_read32(aie_libxaie_ctx_t *ctx, u64 addr)
Read the AIE configuration memory at the given physical address.
void mlir_aie_dump_tile_memory(aie_libxaie_ctx_t *ctx, int col, int row)
Dump the tile memory of the given tile Values that are zero are not shown.
void computeStats(u32 performance_counter[], int n)
Given an array of values, compute and print statistics about those values.
void mlir_aie_write32(aie_libxaie_ctx_t *ctx, u64 addr, u32 val)
Write the AIE configuration memory at the given physical address.
void mlir_aie_data_mem_wr_word(aie_libxaie_ctx_t *ctx, int col, int row, u64 addr, u32 data)
Write a value to the data memory of a particular tile memory.
void mlir_aie_deinit_libxaie(aie_libxaie_ctx_t *ctx)
Release access to the libXAIE context.
void mlir_aie_print_tile_status(aie_libxaie_ctx_t *ctx, int col, int row)
Print the status of a core represented by the given tile, at the given coordinates.