Using ASIP Programmer#

ASIP Programmer is an optional retargetable toolchain for building VPU code. When installed, PVA SDK build scripts prefer it unless PVA_USE_NVVPU=ON forces the core NVVPU toolchain. Access and installation are described in Installing ASIP Programmer.

ChessDE Debugging#

The following pages describe using ChessDE, the debugging environment from ASIP Programmer, to debug applications.

Chess linker and BCF files#

The Chess linker, bridge, uses a BCF file to control linking and memory layout for VPU ELFs. The SDK provides a default BCF, which can be overridden with the BCF argument of pva_device when code layout must be tuned. A custom BCF should include cupva_vpu.bcf before adding its own directives. The following defines control the default layout; sizes are rounded up to 64-byte boundaries:

  • STACK_SIZE controls the stack size and defaults to 0x1000.

  • GLOBAL_SIZE controls the region for global and static variables that are not assigned to a specific bank, and defaults to 0x800.

  • CUPVA_NOMAP_MAIN prevents the default placement of CUPVA_MAIN at the start of the program, allowing the application to place it later.

Functions can be placed with _next directives. Function names are mangled by default:

#define STACK_SIZE 0x800
#include <cupva_vpu.bcf>

_symbol some_mangled_function_name _next
_symbol some_other_mangled_function_name _next

The compiler, archiver, and linker can also be invoked directly as chesscc, ear, and bridge. They require the VPU models installed under tools/vpu_sdks in the PVA SDK installation. Refer to the ASIP Programmer manual for their complete command-line interfaces.

Chess C/C++ frontends#

ASIP Programmer’s compiler is named Chess. Chess supports two different frontends:

  • The chess-noodle C/C++ front-end. Noodle supports the C language and limited C++ features, such as references, function and operator overloading.

  • The chess-clang front-end is a newer option based on clang. It has better support for C++ features, in particular template metaprogramming.

Starting with PVA SDK 2.6, we have deprecated support for Noodle. PVA SDK now builds using chess-clang by default. This can be overridden with the build system flag USE_NOODLE, however note that:

  • cuPVA device runtime headers are not guaranteed to compile with chess-noodle; and,

  • There are restrictions on link-compatibility between objects built with chess-clang and chess-noodle. Refer chess documentation for details.

Chess-clang migration guide#

In general, code which compiles with chess-noodle will also compile with chess-clang. However there are some compatibility issues to be aware of when migrating code between these front-ends.

Function Inlining Control#

LLVM front-end supports automatic function inlining. It may decide not to inline a function with an inline specifier or to inline a non-inline function. There are three ways to influence the LLVM front end to control function inlining:

  • Force the user to inline a function using the always_inline annotation.

    [[gnu::always_inline]] inline int foo(int x)
    { ... }
    
  • Instruct the LLVM front-end to never inline a function using noinline annotation.

    [[gnu::noinline]] int foo(int x)
    { ... }
    

Memory Fence#

LLVM front-end can perform more aggressive optimizations than the CHESS front-end, especially for those inline functions. In some cases, the LLVM front-end may optimize away some VMEM store instructions; e.g., it fails to detect data dependencies between VMEM store and gpo_set instructions. To resolve such an issue, it is recommended to insert a chess_memory_fence before gpo_set instruction.

Prevent Breaking-Up Load and AGEN Restore Operations#

The LLVM front-end may perform aggressive optimization and break-up the load and AGEN restore operations apart, which causes compilation to fail. To resolve this issue, it is recommended to use the chess_protect_access annotation to protect the accesses on AGEN variables.

chess_protect_access agen_A in1 = init_agen_A_from_cfg(agens.cfg[0]);

Vector Demotion Operation with Interleaving#

LLVM front-end doesn’t support passing .lo and .hi fields of a XARF (extended accumulator register file) double vector type by reference for some intrinsics; e.g., vdemote_i from VRF to XARF.

void vdemote_i(vintx src1, vintx src2, xvshortx &dst);

To workaround this issue, it is recommended to declare a single-vector XARF variable, and then pass it to the vdemote_i.

dvintx a;
xvshortx b;
vdemote_i(a.lo, a.hi, b);

Function Name Mangling#

The Chess linker (bridge) uses a BCF file to control linking and memory layout for VPU ELFs. VPU developers are allowed to create a custom BCF to control VPU code layout for performance reasons, which requires to use mangled function names.

The noodle front-end uses CHESS function name mangling scheme for function overloading support. By default, this name mangling scheme is enabled in PVA SDK. With LLVM front-end, the standard Itanium name mangling is used. To migrate an existing VPU kernel with a custom BCF file to LLVM front-end, a user needs to convert all mangled function names in the BCF to LLVM C++ symbol names. PVA SDK provides a Python script to facilitate this conversion process.

pvasdkConvertToLLVMBCF.py

Assuming that you have a cuPVA device target foo, which has an exiting noodle BCF file foo.bcf. The following steps are required to use the script to convert a noodle BCF to a LLVM BCF.

  1. Copy the foo.bcf to foo_noodle.bcf.

  2. Remove/disable all the lines started with _symbol in foo.bcf.

  3. Build the foo target to generate foo lst file, which is needed in step 4.

  4. Run pvasdkConvertToLLVMBCF.py to convert noodle symbol names to C++ symbol names.

    pvasdkConvertToLLVMBCF.py -i foo_noodle.bcf -l <FOO_LST_FILE> -o foo.bcf
    
  5. Rebuild foo target with LLVM front-end and the converted foo.bcf.

Note

Chess name mangling is a proprietary ASIP Programmer name mangling scheme. The pvasdkConvertToLLVMBCF.py script may not handle all the mangling cases.

Performance Optimization Tips#

The CHESS compiler provides chess_guard annotation for predicated execution. This annotation is currently not supported by LLVM front-end. The LLVM front-end does not try to map the operations inside the if-statements with chess_guard onto guarded instructions, instead it turns the if-statements into real branches using jumps, which can adversely impact performance, especially when the if-statements are inside a loop.

To resolve such an issue, the user can change the code to remove the if-statements if possible, and use the ternary operators instead.