Calculator_C++ example
Overview
calculator_c++ is an example for using standard C++ in shared objects. It creates an HLOS application that remotely invokes C++ functions on the DSP using FastRPC. This example is derived from the calculator example. For more information on the setup and how to compile, please refer to the calculator example. The remaining of this page focuses only on how to use C++ code for the DSP.
The calculator_c++ example includes the following five functions to showcase some C++ features
calculator_plus_sum
- calculates sum of elements of vector of integers.calculator_plus_static_sum
- calculates sum of elements of vector of integers of statically initialized object.calculator_plus_test_tls
- tests thread-local storage feature of C++11.calculator_plus_iostream_sum
- calculates sum of elements of stream of data passed as file using standard input/output streams library(iostream).calculator_plus_uppercase_count
- counts uppercase letters in passed string.
For more information on C++(eg. supported standards, tools), please check the C/C++ section of the reference manuals.
Please note that in this document we are discussing only the command-line procedure for running calculator_c++ example. For any IDE-related steps, refer to the IDE section of calculator example.
Simulator testing
The Hexagon simulator hexagon-sim
is located under $DEFAULT_HEXAGON_TOOLS\Tools\bin\
.
While building hexagon variant (with a command like make hexagon BUILD=Debug DSP_ARCH=v65
), the calculator example will create a binary ELF calculator_q.so
. The simulator command generated by the make file to run calculator_q.so
can be found in last section(Command line used to invoke simulator:
) of the generated file hexagon_Debug_toolv87_v65/pmu_stats.txt
. You can use this command directly and/or modify it as desired for running additional simulations. Some of the available simulator command line options are discussed in simulator testing section of calculator. For more information on available options, please refer hexagon simulator document.
Once the dynamic object has been created, you can execute it on the simulator as follows:
$DEFAULT_HEXAGON_TOOLS_ROOT/Tools/bin/hexagon-sim -mv65 --simulated_returnval --usefs hexagon_Debug_toolv87_v65 --pmu_statsfile hexagon_Debug_toolv87_v65/pmu_stats.txt --cosim_file hexagon_Debug_toolv87_v65/q6ss.cfg --l2tcm_base 0xd800 --rtos hexagon_Debug_toolv87_v65/osam.cfg C:\Qualcomm\Hexagon_SDK\5.4.1.0/rtos/qurt//computev65/sdksim_bin/runelf.pbn -- C:\Qualcomm\Hexagon_SDK\5.4.1.0/libs/run_main_on_hexagon/ship/hexagon_toolv87_v65/run_main_on_hexagon_sim -- calculator_q.so
The test should complete indicating that "1 test passed' in the Summary report displayed on the command line.
On-target testing
To run the calculator_plus
test on target, simply execute the following instructions. For more information, please refer to the calculator example.
-
Use ADB as root and remount system read/write
adb root adb wait-for-device adb remount
-
The HLOS side calculator_plus test executable and supporting calculator_c++ stub library must be pushed onto the device as follows:
adb push android_Debug_aarch64/ship/calculator_plus /vendor/bin adb shell chmod 777 /vendor/bin/calculator_plus
-
The Hexagon shared object must be pushed on to the device's file system as follows:
adb shell mkdir -p /vendor/lib/rfsa/dsp/sdk adb push hexagon_Debug_toolv87_v65/ship/libcalculator_plus_skel.so /vendor/lib/rfsa/dsp/sdk/ adb push hexagon_Debug_toolv87_v65/libc++.so.1 /vendor/lib/rfsa/dsp/sdk/ adb push hexagon_Debug_toolv87_v65/libc++abi.so.1 /vendor/lib/rfsa/dsp/sdk/ adb push calculator.input /vendor/lib/rfsa/dsp/sdk/
Note: The Hexagon Tools version 8.4.x introduces new symbols for c++17 compliance into the c++ libraries. The definitions of these symbols are not present on targets whose DSP image is built with a version of the Hexagon Tools older than 8.4.x.
To overcome this problem, when using Hexagon tools older than 8.4.x, link the static
weak_refs.a
library as a whole archive to your custom skel library to forcefully include the weak definitions of these new symbols in the resulting shared library. (If the library is not linked as a whole archive, the symbols will be garbage-collected by the linker and not included in the resulting library.)For example, to do so with the calculator_c++ example, add the following rule to the hexagon.min file:
libcalculator_plus_skel_LD_FLAGS +=--start-group --whole-archive $(HEXAGON_SDK_ROOT)/libs/weak_refs/ship/hexagon_toolv87/weak_refs.a --no-whole-archive --end-group
Note: Refer to the queries section for more information on the libraries
libc++.so.1
andlibc++abi.so.1
. -
Generate a device specific test signature based on the device's serial number
Follow the steps listed in the Use signer.py section of the signing documentation.
Note: This step only needs to be done once as the same test signature will enable loading any module.
-
Redirect DSP FARF messages to ADB logcat by creating a farf file
adb shell echo "0x1f > /vendor/lib/rfsa/dsp/sdk/calculator.farf"
-
Execute the example as follows:
adb shell "export LD_LIBRARY_PATH=/vendor/lib64/ DSP_LIBRARY_PATH=/vendor//lib/rfsa/dsp/sdk; /vendor/bin//calculator_plus -d <0/1/2/3> -U <0/1> -m sum -i 10"
The command line above shows how to execute calculator_plus_sum. You can replace the last two arguments -m sum -i 10
with the following to run other flavors of the benchmark:
Arguments | Description |
---|---|
-m static_sum -i <Input> |
calculates sum of elements of vector of integers of statically initialized object. |
-m test_tls |
tests thread-local storage feature of C++11 |
-m iostream_sum -i <Input file location> |
calculates sum of elements of stream of data passed as file using standard input/output streams library(iostream). The output file for the iostream test will be written to /vendor/lib/rfsa/dsp/sdk/calculator.output |
-m uppercase_count -i <Input string> |
counts uppercase letters in passed string |
All tests return 0 on success. Refer to the DSP logs for more details on the execution of each of these tests.
Note: test_tls
is unsupported on Waipio generation and older devices, due to the limitation of POSIX APIs on the unsigned cDSP on these devices.
Common queries
-
How to compile binaries for alternate C++ standards?
You can pass
-std
flag along with standard name inCXX_FLAGS
. For example:CXX_FLAGS += -std=c++14
Alternate available C++ standards are C++03 and C++14. For more information on C++ library support, please refer to the Hexagon LLVM C/C++ Compiler.
-
Which library to use:
libstdc++
orlibc++
for C++ code?libstdc++
should only be used when running a library compiled for the C++03 standard. For any newer standard, thelibc++
andlibc++abi
libraries should be used instead as shown inhexagon.min
. For more information on C++ library support, see Hexagon LLVM C/C++ Compiler -
How to find the libraries
libc++.so.1
andlibc++abi.so.1
?When the example is run on the target or in the hexagon simulator, the loader tries to load the dependent c++ libraries and looks for their symbolic links during this process. The symbolic links for the libraries
libc++.so
andlibc++abi.so
have to be present in the current directory to be available to the loader. These C++ libraries have symbolic links as follows:libc++.so -> libc++.so.1 -> libc++.so.1.0 libc++abi.so -> libc++abi.so.1 -> libc++abi.so.1.0
These symbolic links are copied to the current directory by adding copy rules as follows in the
hexagon.min
file:TARGET_DIR = $(HEXAGON_LIB_DIR)/$(V_ARCH)/G0/pic # Copy needed libraries to local build directory $(V)/libcalculator_plus_skel.so: $(V)/libc++.so.1 $(V)/libc++abi.so.1 # Copy both versions of the library to the local build directory # The loader will select one version at link time $(V)/libc++.so.1: $(V)/libc++abi.so.1 $(call cp_af,$(TARGET_DIR)/libc++.so.1 $(V)) $(call cp_af,$(TARGET_DIR)/libc++.so.1.0 $(V)) $(V)/libc++abi.so.1: $(call cp_af,$(TARGET_DIR)/libc++abi.so.1 $(V)) $(call cp_af,$(TARGET_DIR)/libc++abi.so.1.0 $(V))