Versal Emulation Waveform Analysis - 2024.1 English

Vitis Tutorials: AI Engine

Document ID
Release Date
2024.1 English

Version: Vitis 2024.1


Simulating a complete system in the Vitis unified software platform allows for a near-hardware run of a design without the hardware and has the added benefit of detailed waveform analysis during hardware emulation to identify issues in the programmable logic (PL), AI Engine interfaces, and memory read/writes that might be harder to debug on hardware.

This tutorial demonstrates how you can use the AMD Vivado™ Design Suite logic simulator (XSIM) waveform GUI, and the Vitis analyzer to debug and analyze your design for an AMD Versal™ adaptive SoC. It steps through the process of building a design for hardware emulation, launching emulation with waveform viewing, and detailed information on how to read the waveforms, as well as using the Vitis analyzer to continue the analysis with generated trace output waveforms and data.

It is strongly recommended to go through the Versal Integration tutorial and the Versal System Design Clocking tutorial before running this tutorial.

IMPORTANT: Before beginning the tutorial, make sure you have installed the Vitis 2024.1 software. The Vitis release includes all the embedded base platforms including the VCK190 base platform that is used in this tutorial. In addition, ensure you have downloaded the Common Images for Embedded Vitis Platforms from this link: The common image package contains a prebuilt Linux kernel and root file system that can be used with the Versal board for embedded design development using Vitis.

Before starting this tutorial run the following steps:

  1. Go to the directory where you have unzipped the Versal Common Image package.

  2. In a Bash shell run the /Common Images Dir/xilinx-versal-common-v2024.1/environment-setup-cortexa72-cortexa53-xilinx-linux script. This script sets up the SDKTARGETSYSROOT and CXX variables. If the script is not present, you must run the /Common Images Dir/xilinx-versal-common-v2024.1/

  3. Set up your ROOTFS and IMAGE to point to the rootfs.ext4 and Image files located in the /Common Images Dir/xilinx-versal-common-v2024.1 directory.

  4. Set up your PLATFORM_REPO_PATHS environment variable to $XILINX_VITIS/lin64/Vitis/2024.1/base_platforms/.

This tutorial targets VCK190 production board for 2024.1 version.


After completing this tutorial you should be able to:

  • Use XSIM as a live waveform viewer to view signals to and from the AI Engine including stream data and run-time parameters (RTP).

  • Read/understand Transaction Level Modeling (TLM) information in a waveform.

  • Use the Vitis analyzer to read trace and profile data.

Tutorial Overview

Design Overview

The design is a simple FIR filter that takes in random noise generated by the PL kernel, random_noise, and gets asynchronous RTP updates to the AI Engine to update the FIR filter coefficients. To confirm the coefficients are applied, the host code reads back the coefficients.

Block Diagram

Transaction Level Modeling

Transaction level modeling (TLM) models Control Interfaces and Processing Systems (CIPS), Network on Chip (NoC), and AI Engine blocks, using SystemC, to show transaction-level communication in the waveform. It is cycle-approximate modeling. It can provide high-level information such as the address and data of the transactions to/from DDR memory or a specific PL kernel.

In the following diagram, the CIPS, NoC, and AI Engine are modeled in SystemC.

Model Block Diagram


Step 1: Building the Design

Step 2: Launching Emulation with the XSIM Waveform GUI

Step 3: Using XSIM Waveform GUI and QEMU

Step 4: Using Vitis Analyzer

Step 1: Build Design

  1. To build the design run the following commands.

    make aie
  2. After the ADF graph is compiled, run the AI Engine simulator (aiesimulator) to get additional profile data. This ensures the design is simulating correctly and generates extra profile information for performance analysis and optimizing the kernels.

    To run the simulator, run the following commands.

    make aiesim

    After running emulation a new directory, aiesimulator_output, is created and inside this directory, there is a file called aiesim-options.txt.

  3. Open the aiesim-options.txt and you should see content similar to the following.

  4. Close the text file.

    NOTE: To view all the aiesim_option.txt values, see Reusing AI Engine Simulator Options.

  5. Run the rest of the build process using the following commands.

    make kernels
    make xsa
    make host
    make package

Step 2: Launching Emulation with XSIM Waveform GUI

After the building and packaging of the design is complete, you can run hardware emulation on your design. Ensure that is in the sw directory.

  1. To launch emulation with the XSIM Waveform GUI, run the following command.

    ./ -g -aie-sim-options ../aiesimulator_output/aiesim_options.txt


    make run_emu


    You can include more options during emulation launch to see transactions logs:

    To see all the transactions generated by PS (QEMU) to either PL/AIE, set the env variable ENABLE_RP_LOGS=true. You can see the logs at sim/behav_waveform/xsim/rp_log.txt.

    NOTE: The PS to DDR transactions cannot be seen here as QEMU has a backdoor direct connection into DDR buffer.

    To capture AIE transaction logs generated at runtime, set the env variable ENABLE_AIE_DBG_TRACE. You can see the logs created in the folder aie_log/ e.g., sw/sim/behav_waveform/xsim/aie_log/S00_AXI.log file. This helps to debug the AIE systemC models only and contains transaction information per interface at each simulation cycle.

    At launch emulation, you can pass -xtlm-aximm-log switch. This logs all the transactions generated from CIPS to AIE or PL that is captured in xsc_report.log file e.g., sw/sim/behav_waveform/xsim/xsc_report.log.

    ./ -g -aie-sim-options ../aiesimulator_output/aiesim_options.txt -xtlm-aximm-log

    The terminal shows the following.

    Starting QEMU
    - Press <Ctrl-a h> for help
    Waiting for QEMU to start.
    running directly on console
    QEMU started. qemu_pid=3208
    Waiting for PMU to start.
    qemu-system-aarch64: -chardev socket,path=./qemu-rport-_pmc@0,server,id=ps-pmc-rp: info: QEMU waiting for connection on: disconnected:unix:./qemu-rport-_pmc@0,server
    PMC started. pmc_pid=3243
    qemu-system-aarch64: -chardev socket,id=pl-rp,host=,port=7043,server: info: QEMU waiting for connection on: disconnected:tcp:,server
    XSIM started. xsim_pid=3300

    This shows QEMU starting and launching XSIM. The QEMU and XSIM are linked together, meaning closing one closes the other. The use of the -g flag opens up the XSIM Waveform GUI as shown in the following image with two config files (.wcfg and Untitled1).

    XSIM GUI Startup Default

    You can keep any of the one file (preferably close .wcfg file) to continue adding signals or creating wave groups for waveform analysis.

    XSIM GUI Startup

    In this view, you can select the signals you want to watch from the Scope and Objects views.

  2. In the Tcl Console, at the bottom of the view, run the following command.

    source ../../../../tcl/add_waveforms.tcl

    The add_waveforms.tcl file removes any default signals provided by the simulation environment, and adds in all the signals you want to view. There are some signals that are important to have such as: NoC, DDR memory, PL Kernel, and CIPS signals. Your design interacts with these components, and being able to trace signal changes from CIPS to the NoC to/from DDR memory, and then to your design can prove helpful in debugging any potential issue with data transfers. This file contains the following.

    ## Remove all waveforms before adding new ones
    remove_wave -of [get_wave_config] [get_waves -of [get_wave_config] -regexp ".*"]
    ## Set the appropriate paths based upon the platform being used
    set scope_path "/vitis_design_wrapper_sim_wrapper/vitis_design_wrapper_i/vitis_design_i"
    ## Create a wave group called CIPS and add all signals for the CIPS_0 to it
    set CIPS [add_wave_group CIPS]
    set cips_intf [get_objects -r $scope_path/CIPS_0/* -filter {type==proto_inst}]
    add_wave -into $CIPS $cips_intf
    ## Create a wave group called NOISE and add all signals of the random_noise_1 to it
    set NOISE [add_wave_group NOISE]
    set noise_intf [get_objects -r $scope_path/random_noise_1/* -filter {type==proto_inst}]
    add_wave -into $NOISE $noise_intf
    ## Create a wave group called S2MM and add all signals of the S2MM kernel to it
    set S2MM [add_wave_group S2MM]
    set s2mm_intf [get_objects -r $scope_path/s2mm_1/* -filter {type==proto_inst}]
    add_wave -into $S2MM $s2mm_intf
    ## Create a wave group called CIPS_NOC and all signals of the CIPS NoC to it
    set CIPS_NOC [add_wave_group CIPS_NOC]
    set cips_intf [get_objects -r $scope_path/cips_noc/* -filter {type==proto_inst}]
    add_wave -into $CIPS_NOC $cips_intf
    ## Create a wave group called DDR4 and all signals to/from DDR4
    set DDR4 [add_wave_group DDR4]
    set ddr4_intf [get_objects -r $scope_path/noc_ddr4/* -filter {type==proto_inst}]
    add_wave -into $DDR4 $ddr4_intf
    ## Create a wave group called AIENGINE and all signals of the AI Engine block to it
    set AIENGINE [add_wave_group AIENGINE]
    set aie_intf [get_objects -r $scope_path/ai_engine_0/* -filter {type==proto_inst}]
    add_wave -into $AIENGINE $aie_intf

    NOTE: This file can be executed automatically from the command by using the -user-pre-sim-script add_waveforms.tcl.

    IMPORTANT: Add all the signals you need before starting emulation. If after starting emulation, you pause it, and add more signals, there will not be any data for the new signals.

    You will see a waveform view as shown in the following figure.