Watchpoints - 2022.1 English

Versal ACAP AI Engine Programming Environment User Guide (UG1076)

Document ID
UG1076
Release Date
2022-05-25
Version
2022.1 English

A watchpoint is a type of breakpoint. Watchpoints can be used to stop the execution of a core when the value at an address changes. These are useful in determining the place where the value changes. For example, a variable value can be overwritten unexpectedly, which can break the program flow. Watchpoints help in detecting such cases.

AI Engine architecture supports read/write watchpoints. This means, a watchpoint is triggered on a read or write access, or both (based on your configuration). Each AI Engine tile supports two watchpoints per memory bank. Because every AI Engine core (excluding tiles on boundaries) has access to memory banks in adjacent tiles, a maximum of eight watchpoints can be used per core. However, because the memory banks are shared, the number of available watchpoints per core depends on how many watchpoints are already used from the memory bank. For example, if a core uses all eight watchpoints from its four adjacent memory banks, the other cores which share those four memory banks cannot use watchpoints from the shared memory banks. Debugger keeps track of watchpoints that are allocated from each bank, and throws an error if there are no unused watchpoints in that tile.

  1. To add a watchpoint in the Vitis IDE, click on the three dots at top-right corner of the Breakpoints view and select Add Watchpoint (C/C++).

  2. In the Watchpoint Properties dialog box, enter the memory address or the variable name of interest. Select read/write modes. If Enabled is unchecked, the watchpoint is not enabled regardless of the read/write mode during the debug session. This is to preserve the watchpoint configuration without removing it and adding it back when needed.

  3. By default, watchpoints are added to all debug cores. To apply the watchpoint to a specific core, click on Scope in the left pane of the Watchpoint Properties window, and select only specific cores to which the watchpoint applies.

  4. Verify the watchpoint in the Breakpoints view.

Triggering of Watchpoints

A watchpoint is triggered on a read access or write access, or both, based on how the watchpoint is configured. A triggered watchpoint causes the core to stop at the instruction that accessed the address. Debugger detects the core has stopped because of the watchpoint and reports that the core has stopped because of a watchpoint.

Important:
  • Watchpoints work on hardware only. AI Engine system C model is not supported.
  • Memory banks are shared. It may not be possible to add watchpoints for a core in a specific bank, if another core uses both the watchpoints from that bank.
  • Watchpoints must not be set for memory addresses which fall in unused tiles/memory banks. Setting watchpoints to unused tiles can cause AXI errors. Used AI Engine and memory tiles can be found at Work/aie/active_cores.json.
  • Watchpoints are triggered for memory access in full 16-byte aligned address range.
  • Debugger uses two broadcast channels to handle watchpoint events. When enabling watchpoints during debug, ensure that there are no conflicts in using these two broadcast channels.

The Variables view shows the kernel variables values. Depending on variable type, clicking on a variable shows its type, value, and the address of the variable. For array/structure variables, click on the arrow of the variable expands array/structure content of the array.

Figure 1. Variables View

Click on a variable to obtain address information and then click on the + from the Memory view and enter the memory address of the variable. The value of that variable shows up along with other memory content. Variable values can be changed by clicking on the variable’s value field, entering the new value, and pressing the Enter key.

You can specify the format of the data presented in the Memory window by clicking on the New Renderings tab, specifying the format of the data to present, and click Add Rendering(s).

Tip: You can export the contents of the Memory window by selecting the Copy to Clipboard command from the right-click menu to copy and paste the contents into a text editor and save to a file.
Figure 2. Registers View

In the Registers view, the values are updated during the debug process and are highlighted in the Vitis IDE.

Figure 3. Disassembly View

The Disassembly view displays machine code and assembly code. C/C++ source code is also embedded between the lines for source code referencing. In the Explorer view, select the AI Engine project and right-click and select Open Disassembly View. It will bring up the following window where you will be able to select the core for which you want to see disassembled code.

Figure 4. Select Core

Note: In the Disassembly view, NOP instructions are skipped by default. To step the debugger though the NOP instructions, click the Instruction Stepping Mode icon, circled in the following image.
Figure 5. Step Through NOP Instructions

Figure 6. Debugging Controls

The debug control commands let you step into/over/return from the source code. Other commands let you resume, stop, terminate, or disconnect the debugger from the Vitis IDE.

The Vitis IDE supports multi-kernel debug and multi-domain (PS and AI Engine) debug. Depending on the application, there can be hundreds of kernels being debugged. Having granular control of each core as well as all cores within one domain is important. Select one core from the Vitis IDE and click the Resume icon to resume debug execution for the core only. Select one level above all cores within the AI Engine domain, and click the Resume icon to resume all AI Engine core executions. Resuming execution for all the kernels in the graph is dependent on a variety of conditions such as the availability of data to each of the kernels to avoid stalls, or the setup of individual kernel breakpoints. You must also ensure that the kernels not being debugged are free to run.

Figure 7. Selection to Resume Multiple AI Engine Debug

Figure 8. Debug Perspective

Note: The main() function is created automatically by the AI Engine compiler for each core that wraps around the kernel implementation. The Debug view displays the complete source code including the inserted portion.