SDSoC Debug Features
This section provides details on debugging in the SDx™ environment using the Vivado® Design Suite IDE or the command line.
SDx Environment Debug Tools
The SDx environment includes the Xilinx System Debugger (XSDB) for debugging SDSoC environment designs.
Xilinx System Debugger (XSDB)
Xilinx System Debugger (XSDB) uses
the Xilinx
hw_server
as the underlying debug engine.
The Xilinx
Software Development Kit (SDK) translates each user
interface action into a sequence of Target Communication Frameworks (TCF) commands. It
then processes the output from System Debugger to display the current state of the
program being debugged. It communicates to the processor on the hardware using Xilinx
hw_server
. You can debug multiple processors
simultaneously with a single System Debugger debug configuration. This is the
recommended debug engine for SDxenvironment
designs. The System Debugger can either be launched on the hardware or the QEMU
engine.
The workflow is made up of the following components:
- ELF file
- To debug your application, you must use an ELF file compiled for debugging. The debug ELF file contains additional debug information for the debugger to make direct associations between the source code and the binaries generated from that original source. Refer to Build Configurations for more information.
- Debug configuration
- To launch the debug session, you must create a debug configuration in the SDx environment. This configuration captures options required to start a debug session, including the executable name, processor target to debug, and other information. Refer to Setting Debug Configurations for more information.
- SDx debug perspective
- Using the debug perspective, you can manage the debugging or running of a program in the SDx workbench. You can control the execution of your program by setting breakpoints, suspending launched programs, stepping through your code, and examining the contents of variables.
You can repeat the cycle of modifying the code, building the executable, and debugging the program in the SDx environment.
Setting Debug Configurations
To debug, run, and profile an application, you must create a debug configuration that captures the settings for executing and debugging the application. To create a debug configuration, in the Assistant view, right-click on the Debug build configuration, and select from the menu. Alternatively, you can select the command from the main menu. The Debug Configurations dialog box opens as shown below.
In the Debug Configurations dialog box, select the Xilinx SDx Application Debugger to create a debug configuration for the project. A new debug configuration is created for the application project, and is opened with multiple tabs to manage the configuration.
Main Tab
Application Tab
The Application tab displays the compiled application .ELF file that is being downloaded to be run on the processor.
Target Setup Tab
For Linux applications, the Target Setup tab is blank. For standalone applications, the tab lets you specify the hardware platform, and whether to use the first stage boot loader (FSBL) flow for initialization (if you need to initialize devices on the platform).
Arguments Tab
In the Arguments tab, you can specify any variables that are needed for launching the debug session. Click Variables to display the Select Variable dialog box.
Environment Tab
In the Environment tab, you can set any environment variables for the debug configurations.
Click New to create and define a value for a new environment variable to add to the debug configuration. Click Select to display a list of existing environment variables that can be added to the debug configuration. These can be edited and set to specific values.
Remaining Debug Configuration Tabs
The Symbol Files, Source, Path Map, and Common tabs are for advanced debugging of application-specific functions that do not apply to XSDB, and can be safely ignored.
Target Connections
In the Target Connections view, you can configure multiple remote targets. It displays connected targets, and you can add or delete target connections. The SDx environment establishes target connections through the Hardware Server agent. In order to connect to remote targets, the hardware server agent must be running on the remote host, which is connected to the target.
Use the Hardware Server when the application is for standalone. The Hardware Server only requires a JTAG connection to the board. Use the Linux TCF Agent for when the application is compiled to run on Linux for the SoC. The Linux TCF Agent requires an Ethernet connection from the machine to the board.
For more information, refer to Connecting to the Hardware.
Debug Linux Applications in the SDx IDE
In the SDx IDE, use the following procedure to debug your application:
- Set the platform to boot from the SD card, as specified in the User Guide for the selected SDSoC platform.
- In the SDx Application Project Settings window, set the Target to Hardware, and enable the Generate SD card image checkbox.
- In the Assistant view, right-click the Debug build configuration, and select the Set Active command.
- Click the Build () button, in the Assistant view or the main menu, to build the Debug configuration.
- From a file browser, or command shell, copy the contents of the Debug/sd_card folder to an SD card.
- Insert the SD card into the card reader of the platform, and boot the card.
- Make sure the board is connected to the network, and note its IP address, for
example, by executing
ifconfig eth0
on the board at the command prompt using a terminal communicating with the board over UART. - In the Assistant view, right-click the Debug build configuration, and select to create a new debug configuration.
- Double click or right-click and select New on the Xilinx SDx Application Debugger.
- In the new configuration, click the New button next to Connection: Linux Agent.
- In the Target Connection Details specify the target name and enter the IP address of the board. It is highly suggested to test the connection by click the Test Connection button to make sure it can connect to the board.
- Click Apply to save the changes and click Debug.
- Switch to the SDSoC environment debug perspective, where you can start, stop, step, set breakpoints, examine variables and memory, and perform various other debug operations.
Debugging Standalone or FreeRTOS Applications in the SDx IDE
- In the Assistant view, right-click the Debug build configuration, and select the Set Active command.
- Click the Build () button, in the Assistant view or the main menu, to build the Debug configuration.
- In the Assistant view, right-click the Debug build configuration, and select to create a new debug configuration.
- Optional: Switch to the SDSoC environment Debug Perspective, where you can start, stop, step, set breakpoints, examine variables and memory, and perform various other debug operations.
- Optional: In the SDx IDE toolbar, click Debug, which provides a shortcut to the procedure described above.
Xilinx Software Command-Line Tool (XSCT)
Graphical development environments such as the SDx environment are useful for improving development for a new processor architecture. It helps to abstract away and group most of the common functions into logical wizards that even a novice can use. However, the scriptability of a tool is also essential for providing the flexibility to extend what is done with that tool. It is particularly useful when developing regression tests that are run nightly, or for running a set of commands that are used often by the developer.
Xilinx Software Command-line Tool (XSCT) is an interactive and scriptable command line interface to the SDx environment. As with other Xilinx tools, the scripting language for XSCT is based on Tool Command Language (Tcl). You can run XSCT commands interactively or script the commands for automation. XSCT supports the following actions:
- Create hardware, board support packages (BSPs), and application projects.
- Manage repositories.
- Set toolchain preferences.
- Configure and build BSPs/applications.
- Download and run applications on hardware targets.
- Create and flash boot images by running Bootgen and
program_flash
tools.
For information on XSCT commands, see the Xilinx Software Command-Line Tool (XSCT) Reference Guide (UG1208).
System Emulation
System emulation can be run on System Debugger using the Target Communications Framework (TCF) server.
Running System Emulation from the IDE
System emulation provides the same level of accuracy as the final implementation without the need to compile the system into a bitstream and program the device on the board. System emulation can be used for debugging applications without involving the actual hardware. It can also be used for identifying any bottlenecks in performance.
Enable System Emulation
- Set the Active build configuration to Debug.
- Set the Target to Emulation.
- Set the emulation model. There are two emulation model modes:
- Debug
- Builds the system through RTL generation, and the IP integrator block design containing the hardware function, elaborates the hardware design, and runs behavioral simulation on the design, with a waveform viewer to help you analyze the results. You interact with the Vivado simulator within the Vivado Design Suite to analyze the waveforms.
- Optimized
- Runs the behavioral simulation in batch mode, returning the results without the waveform data. While the Optimized model can be faster, it returns less information than the Debug model.
Because emulation does not require a full system compile, the tool disables the generation of the bitstream and the Generate SD card image option to improve runtime and iteration time. Using system emulation allows you to verify and debug the system with the same level of accuracy as a full bitstream compilation.
- After specifying the emulation model, click the Build button () to compile the system for emulation.
The duration of the build process depends on your application code, the size of your hardware functions, and the options you have selected. To compile the hardware functions, the tool stack includes the SDx environment, and Vivado High-Level Synthesis (HLS) tool, and the Vivado Design Suite.
Run the System Emulator
- After building the emulation target, you can run the system emulator using Assistant panel, by right-clicking, and then selecting Start/Stop Emulator. . Alternatively, you can also select the application in the
- When the Start/Stop Emulator dialog box opens, the emulation
mode is specified:
- If the emulation mode is Debug, you can choose to run the emulation with or without waveforms.
- If the emulation mode is Optimized, the Show Waveform check box is disabled, and cannot be changed.
The Start/Stop Emulator dialog box displays the Project name, the build Configuration, and has the Show Waveform option. Disabling the Show Waveform option lets you run emulation with the output directed solely at the Emulation Console view, which shows all system messages including the results of any print statements in the source code. Some of these statements might include the values transferred to and from the hardware functions, or a statement that the application has completed successfully, which would verify that the source code running on the PS and the compiled hardware functions running in the PL are functionally correct. Enabling the Show Waveform option provides the same functionality in the Console window, plus the behavioral simulation of the register transfer level (RTL), with a waveform window. The RTL waveform window allows you to see the value of any signal in the hardware functions over time. When using Show Waveform, you must manually add signals to the waveform window before starting the emulation.
- Use the Scopes pane to navigate the design hierarchy.
- Select the signals to monitor in the Object pane, and then right-click to add the signals to the waveform pane.
- Click the Run All
toolbar button to start updates to the waveform window. For more information
about working with the Vivado simulator
waveform window, refer to Vivado Design Suite User Guide: Logic
Simulation (UG900). Note: Running with RTL waveforms results in a slower runtime, but enables detailed analysis into the operation of the hardware functions.TIP:
You can also start the system emulation by selecting the active project in the Project Explorer view, and then right-clicking to select one of the following menu commands:
Launching the emulator from the Debug As menu causes the perspective change to the debug perspective to arrange the windows and views to facilitate debugging the project.
View Emulation Output
- After you run the system emulator, you can see the program output in the
console tab, and if the Show Waveform
option was selected, the Vivado IDE is
launched with the simulator
running.
Add waveforms to the Waveforms
window as desired. To start the simulation, click the Run All button.
- To start a debug session with the emulator running, in the Assistant view right-click on the Debug build configuration and select .
- The Confirm Perspective Switch dialog box is displayed. Click Yes to switch to the Debug perspective.
- The application is started in the Debug perspective and the program
execution is stopped at the main function. To resume the execution of the
application code, click Resume.
This starts execution of the application code. The output of the application code can be seen in the Emulation Console, as shown in the following figure:
The status of different signals is displayed in the Vivado Waveform window. You also see any appropriate response in the hardware functions in the register transfer level (RTL) waveform. During any pause in the execution of the code, the RTL waveform window continues to execute and update, just like an FPGA running on the board.
- You can stop the emulation at any time using the menu option Stop.TIP: For an example project to demonstrate emulation, create a new SDx environment project using the Emulation Example template. The README.txt file in the project has a step-by-step guide for doing emulation on both the SDx IDE and the command line.
, and then selecting
Running System Emulation from the Command Line
TARGET
flag defines
that the compilation should be done for
emulation.# FPGA Board Platform (Default ~ zcu102)
PLATFORM := zcu102
# Run Target:
# hw - Compile for hardware
# emu - Compile for emulation (Default)
TARGET := emu
debug
- Captures waveform data from the PL hardware emulation for viewing and debugging.
optimized
- Provides faster emulation without capturing hardware debug information.
# Target OS:
# linux (Default), standalone
TARGET_OS := linux
# Emulation Mode:
# debug - Include debug data
# optimized - Exclude debug data (Default)
EMU_MODE := optimized
Type make
to build the program at the command
prompt. If you want to view the waveform in the simulator, change directory to the level
where you have the _sds directory, then type
sdsoc_emulator -graphic-xsim
. This starts the
Vivado Simulator, as shown below.
Hardware Execution Features Available to All Platforms
- Full software debug using the Xilinx System Debugger (XSDB)
- Co-debug of hardware and software using the Xilinx System Debugger (XSDB)
- Event Tracing
Hardware Debugging in SDSoC Using ChipScope
After the final system image is generated and executed in the SDx environment, the entire system (including the embedded processor OS, the application code, and the accelerated hardware functions) can be validated to be executing correctly on the actual hardware, and any necessary debug activity can be performed. The ChipScope™ feature is used to debug designs in hardware using the Vivado IDE. Cross-probing hardware and software requires an advanced understanding of the SDx environment and the Vivado tool suite.
This debugging step can reveal issues relating to connecting to the target platform, booting the processor, and programming the hardware with the system image. It might also highlight problems with interactions between the application code and the hardware functions in the form of protocol violations, and with validating multiple hardware functions with the application code.
This step could also reveal system performance metrics that could shift your focus from debug to performance tuning. In the SDx environment, you can instrument the hardware to analyze transactions on the interfaces of the hardware accelerators and adapters. You can also debug the hardware portion of the design.
Using --dk to Enable Debugging the Accelerated Function
Visibility into a running design is crucial for debugging difficult situations, like when the application hangs. The System ILA debug core provides transaction-level visibility into an accelerated kernel or function running on hardware. AXI traffic of interest can also be captured and viewed using the System ILA core.
The System ILA core can be instantiated in the overall hardware of an existing
SDx environment design to enable debugging
features within that design, or it can be inserted automatically by the compiler. The sds++
compiler
provides the -–dk
switch to attach System ILA cores
at the interfaces to the hardware functions for debugging and performance monitoring
purposes. Use the -–dk
option to enable System
ILA core insertion:
--dk arg <[protocol|chipscope|list_ports]:<compute_unit_name>:<interface_name>>
The following is an example of the -–dk
option in use:
sds++ -c --dk chipscope:vadd_cu0:s_axi_control --dk chipscope:vadd_cu0:m_axi_gmem
The following is an example of a Makefile to insert debug cores:
APPSOURCES = main.cpp mmult.cpp madd.cpp
EXECUTABLE = mmultadd.elf
PLATFORM = zc702
CLKID =
DMCLKID =
SDSFLAGS = -sds-pf ${PLATFORM} ${DMCLKID} \
-sds-hw mmult mmult.cpp ${CLKID} -sds-end \
-sds-hw madd madd.cpp ${CLKID} -sds-end \
-debug-port mmult:A \
-debug-port madd:C \
--dk chipscope:madd_1:A \
--dk chipscope:madd_1_if:ap_ctrl
CC = sds++ ${SDSFLAGS}
CFLAGS = -O3 -c
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
LFLAGS = -O3
OBJECTS := $(APPSOURCES:.cpp=.o)
DEPS := $(OBJECTS:.o=.d)
.PHONY: all clean ultraclean
all: ${EXECUTABLE}
${EXECUTABLE}: ${OBJECTS}
${CC} ${LFLAGS} $^ -o $@
-include ${DEPS}
%.o: %.cpp
${CC} ${CFLAGS} $^ -o $@
clean:
${RM} ${EXECUTABLE} ${OBJECTS} ${DEPS}
ultraclean: clean
${RM} ${EXECUTABLE}.bit
${RM} -rf _sds sd_card
The –debug-port
option specifies a function
name and argument name to insert a System ILA for accelerators. The lower level --dk
option specifies the tool command language (Tcl) file
used to recreate the block design instance and port name, such as in the following
example.
-debug-port mmult:A
is equivalent to--dk chipscope:mmult_1:A
, but thesds++
command determines what the instance and port names are in the Tcl file used to recreate the block design.Note: A Tcl file is used by the SDx environment to recreate a block design in the hardware platform including the accelerators in the Vivado Design Suite.--xp param:compiler.userPostSysLinkTcl=<user_tcl_file>
, where <user_tcl_file
> contains IP integrator Tcl commands for advanced users who need to perform post-processing of the System ILA in the block diagram after system linking and before synthesis.Note: Advanced users can change ILA settings using Tcl commands. It is often possible to enable additional probes and interfaces in an ILA and debug other signals in the same clock domain as needed. Doing this can save logic resources in the FPGA. You can also cross-trigger a chain of ILAs using this feature.
--dk
can be used to insert the System ILA for accelerator and adapter ports. You need to use this option to observe the adapter ports. Once the design is built, you can debug the design using the Vivado hardware manager features, as described in Vivado Design Suite User Guide: Programming and Debugging (UG908).
Add Flags to Build Settings
- From the Assistant view, right-click the Debug or Release build configuration, and select the Settings command.
- In the Build Configuration Settings dialog box, click the Edit Toolchain Settings link.
- In the Tool Settings tab of the Properties for <Application_Name> dialog box, select .
- Click in the Linker Flags field and
add the debug flags as needed. TIP: At the top of the Tool Settings tab, there is a Configuration field that lets you select the build to apply the settings to the Debug build, the Release build, or All builds.
See the SDx Command and Utility Reference Guide for more information on compiler and linker options.
Analyzing the Hardware Design
- To confirm which signals can be debugged, navigate to Project
Explorer.
- Double-click prj.xpr, which opens the design in the Vivado IDE.
- In the Vivado IDE, click Open Block Design in the Flow Navigator under
IP integrator.
- In the Designs window, look for the instances of
system_ila_x
. - Select the System ILA instance(s) in the Design window to highlight the instances in the block
design.
- Select the interface nets connected to the System ILA and ensure that they have been connected to the interfaces specified in the SDx IDE.
Debugging Designs Using Vivado Hardware Manager
- Launch the Vivado Design Suite.
- Select Open Hardware Manager from the
Tasks menu. An alternate method is
to open the Vivado project from the
SDx IDE:
Then, from the Vivado Flow Navigator, click , as shown below.<application_project_name>/Debug/_sds/p0/vivado/prj/prj.xpr
- For either method you used to open the project, the Open New Hardware
Target wizard is displayed as shown below. Click Next.
- In Hardware Server Settings, connect to the correct target by clicking
Connect to, and then selecting
either Remote Server or Local Server. If you select Remote Server, you need to add a Host name and the correct Port number. The following example assumes that
you are connected locally:
- Click Next. The Select Hardware Target page opens which identifies the target(s) present on the board.
- Click Next. The Open Hardware
Target Summary page opens which summarizes the server name, the port it is
connected to, and the correct target and operating frequency.
- Click Finish. The Hardware Manager
window opens as shown below.
- The Vivado hardware manager can now be
used to connect to the ILA that is running on your design. Refer to the Vivado Design Suite User Guide:
Programming and Debugging (UG908) for more information
on working with the tool.
Hardware/Software Event Tracing
Event tracing provides visibility into each phase of the hardware function execution, including the software setup for the accelerators and data transfers, as well as the hardware execution of the accelerators and data transfers. Tracing an application produces a log that records correlation between events for a duration of time. The goal of tracing is to help debug execution by observing what happened when, and how long events took.
Software event tracing automatically instruments the stub of the hardware function to capture software control events associated with a hardware function call. The event types that are recorded include the setup and initialization of the hardware accelerator, data transfers, and hardware-software synchronization events.
Hardware event tracing of accelerators with data transfers over AXI4-Stream connections can also be enabled through the use of the
-trace
option of the sds++
system compiler. When the linker is invoked with the -trace
option, it inserts hardware monitor IP cores into the RTL implementation of the hardware function
to track the accelerator start and stop, and the duration of data transfers.
As with hardware debugging, event tracing requires you to connect the SDSoC environment platform to a host computer as described in Connecting to the Hardware. To run event tracing, execute the application using the SDx IDE from the host using a debug or release build configuration.
Hardware/Software System Runtime Operation
The system compiler implements hardware functions either by cross-compiling them into IP using the Vivado High-Level Synthesis (HLS) tool, or by linking them as C-callable IP, as described in the SDSoC Environment Platform Development Guide.
Each hardware function call site is rewritten to call a stub function that manages the execution of the hardware accelerator. The figure below shows an example of hardware function rewriting. The original user code is shown on the left. The code section on the right shows the hardware function calls rewritten with new function names.
The stub function initializes the hardware accelerator, initiates any
required data transfers for the function arguments, and then synchronizes hardware and
software by waiting at an appropriate point in the program for the accelerator and all
associated data transfers to complete. For example, if the hardware function foo()
is defined in foo.cpp, you can view the generated rewritten code in _sds/swstubs/foo.cpp for the project build configuration. As
an example, the stub code shown below replaces a user function marked for hardware. This
function starts the accelerator, starts data transfers to and from the accelerator, and
waits for those transfers to complete.
void _p0_mmult0(float *A, float *B, float *C) {
switch_to_next_partition(0);
int start_seq[3];
start_seq[0] = 0x00000f00;
start_seq[1] = 0x00010100;
start_seq[2] = 0x00020000;
cf_send_i(cmd_addr,start_seq,cmd_handle);
cf_wait(cmd_handle);
cf_send_i(A_addr, A, A_handle);
cf_send_i(B_addr, B, B_handle);
cf_receive_i(C_addr, C, C_handle);
cf_wait(A_handle);
cf_wait(B_handle);
cf_wait(C_handle);
Event tracing provides visibility into each phase of the hardware function execution, including the software setup for the accelerators and data transfers, as well as the hardware execution of the accelerators and data transfers. For example, the stub code below is instrumented for trace. Each command that starts the accelerator, starts a transfer, or waits for a transfer to complete is instrumented.
void_p0_mmult_0(float *A, float *B, float *C) {
switch_to_next_partition(0);
int start_seq[3];
start_seq[0] = 0x00000f00;
start_seq[1] = 0x00010100;
start_seq[2] = 0x00020000;
sds_trace(EVENT_START);
cf_send_i(cmd_addr,start_seq,cmd_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_wait(cmd_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_send_i(A_addr, A, A_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_send_i(B_addr, B, B_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_receive_i(C_addr, C, C_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_wait(A_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_wait(B_handle);
sds_trace(EVENT_STOP);
sds_trace(EVENT_START);
cf_wait(C_handle);
sds_trace(EVENT_STOP);
Software Tracing
Event tracing automatically instruments the stub function to capture software control events associated with the implementation of a hardware function call. The event types include the following:
- Accelerator setup and initiation
- Data transfer setup
- Hardware/software synchronization barriers (“wait for event”)
See SDSoC Environment Programmers Guide (UG1278) for more detail on these topics.
Each of these events is independently traced and results in a single AXI4-Lite write into the programmable logic, where it receives a time stamp from the same global timer as hardware events.
Hardware Tracing
The SDSoC environment supports hardware
event tracing of accelerators cross-compiled using Vivado
High-Level Synthesis (HLS) tool, and data transfers over AXI4-Stream connections. When sds++
is invoked with
the -trace
option, it automatically inserts hardware monitor IP
cores into the generated system to log the following event types:
- Accelerator start and stop, defined by
ap_start
andap_done
signals. - Data transfer start and stop, defined by AXI4-Stream handshake and
TLAST
signals.
ap_start
and ap_done
signals are not part of the IP
interface:#pragma HLS interface s_axilite port=foo
These debug cores use some hardware resources; less than 0.1% of the hardware resources available on a ZC706 board.
The AXI4-Stream monitor core has two modes: basic and statistics. The basic mode does just the start/stop trace event generation. The statistics mode enables an AXI4-Lite interface to two 32-bit registers. The register at offset 0x0 presents the word count of the current, on-going transfer. The register at offset 0x4 presents the word count of the previous transfer. As soon as a transfer is complete, the current count is moved to the previous register. By default, the AXI4-Stream core is configured in the basic mode.
In addition to the hardware trace monitor cores, the output trace event signals are combined by a single integration core. This core has a parameterizable number of ports (from 1–63), and can thus support up to 63 individual monitor cores (either accelerator or AXI4-Stream). The resource utilization of this core depends on the number of ports enabled, and thus the number of monitor cores inserted.
On a ZC706 platform, this can use between roughly 0.1-1.0 percent of the available hardware resources, and up to approximately 10% of the memories with the integration logic.
Implementation Flow
During the implementation flow, when tracing is enabled, tracing instrumentation is inserted into the software code and hardware monitors are inserted into the hardware system automatically. The hardware system (including the monitor cores) is then synthesized and implemented, producing the bitstream. The software tracing is compiled into the regular user program.
Hardware and software traces are time-stamped in hardware and collected into a single trace stream that is buffered up in the programmable logic.