How to compile CVU Configuration Application?

This section we’ll discuss about how we can write and compile the CVU Configuration Application for configuring the EV74 graphs.

Need of CVU Configuration Application

The CVU Configuration Application is needed to configure the EV74 graphs or kernels.
To use the EV74 graph, one needs to first configure its parameters so that it can operate on incoming data and send back the required data after performing desired operation.
For example, if one wants to resize the incoming image from 1280x720 resolution to 640x480 using EV74’s SIMA_RESIZE graph/kernel, the kernel must know what is the input shape and what is the expected output shape. This configuration will set such parameters and graph becomes ready to use.

File Structure

There are 3 files needed for any CVU Configuration Application to compile.

cvu_cfg_main.cpp

This is source file which holds a code to mostly parse the command line parameters (such as a JSON configuration file) to the app and calling a necessary function.

cvu_cfg_graph.cpp

This is the most important file which actually holds the logic of reading the configuration parameters from config json of the graph and sending them to EV74.
Main functions used to send the parameters of int and double type.
  1. send_i32_param

    This sends the integer type parameter to EV74 for configuration

  2. send_float_param

    This sends double type parameter to EV74 for configuration

CMakeLists.txt

This is a cmake file required to cross-compile the CVU Configuration Application and generate an executable binary compatible with A65.

Compilation

Let’s see how to compile and generate a binary for any given graph.
As an example, let’s generate a CVU Configuration Application for SIMA_RESIZE graph.

cvu_cfg_main.cpp

The cvu_cfg_main.cpp for this will look like this.

Note

Here, we’re considering the process_resize.json passed as the only argument to the main.

cvu_cfg_main.cpp
 1#include <getopt.h>
 2#include <sys/stat.h>
 3#include <unistd.h>
 4
 5#include <cstring>
 6#include <iostream>
 7
 8extern void configure_graph(const char *json_fpath);
 9
10bool is_valid_path(const char *path) {
11    struct stat buffer;
12    return (stat(path, &buffer) == 0);
13}
14
15int main(int argc, char **argv) {
16    const char *json_path = argv[1];
17
18    if(is_valid_path(json_path)) {
19    configure_graph(json_path);
20    } else {
21    std::cerr << "Invalid path: " << json_path << std::endl;
22    return 1;
23    }
24
25    return 0;
26}

cvu_cfg_graph.cpp

The cvu_cfg_graph.cpp looks like this.

cvu_cfg_graph.cpp
 1#include <string.h>
 2#include <simaai/parser.h>
 3#include <simaai/ev_cfg_helper.h>
 4#include <simaai/platform/simaevxxipc.h>
 5
 6#define SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE (8)
 7#define INPUT_WIDTH   (1)
 8#define INPUT_HEIGHT  (2)
 9#define OUTPUT_WIDTH  (3)
10#define OUTPUT_HEIGHT (4)
11#define BATCH_SIZE    (5)
12#define RSZ_TYPE      (6)
13
14void configure_graph(const char *json_in) {
15    simaai_params_t *params = parser_node_struct_init();
16    if (params == NULL) {
17        std::cout << "Unable to create params \n";
18    }
19    if ((parse_json_file(json_in, params) != PARSER_SUCCESS)) {
20        std::cout << "Unable to start parser \n";
21    }
22
23    uint8_t *buf = (uint8_t *)calloc(1, sizeof(uint8_t) * 16);
24
25    int val = *((int *)parser_get_int(params, "img_height"));
26    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_HEIGHT, buf, val);
27    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_HEIGHT, buf, val);
28
29    val = *((int *)parser_get_int(params, "img_width"));
30    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_WIDTH, buf, val);
31
32    val = *((int *)parser_get_int(params, "output_width"));
33    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, OUTPUT_WIDTH, buf, val);
34
35    val = *((int *)parser_get_int(params, "output_height"));
36    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, OUTPUT_HEIGHT, buf, val);
37
38    val = *((int *)parser_get_int(params, "batch_size"));
39    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, BATCH_SIZE, buf, val);
40
41    val = *((int *)parser_get_int(params, "rsz_type"));
42    send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, RSZ_TYPE, buf, val);
43
44    std::cout << "Completed Resize Graph Configure \n";
45    free(buf);
46}

CMakeLists.txt

This CMakeLists.txt contains the configuration to compile and generate binary. It looks like this.

CMakeLists.txt
 1 cmake_minimum_required(VERSION 3.16)
 2
 3 # set the project name
 4 set(GRAPH_NAME "resize_008")
 5 set(PROJECT_NAME "CVU Graph Cfg. App.")
 6
 7 project("${PROJECT_NAME}"
 8     VERSION 0.1
 9     DESCRIPTION "CVU Graph Configuration Application"
10     LANGUAGES C CXX)
11
12 set(PIPELINE_SOURCES
13     cvu_cfg_graph.cpp)
14
15 execute_process(
16     COMMAND git rev-parse --abbrev-ref HEAD
17     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
18     OUTPUT_VARIABLE GIT_BRANCH
19     OUTPUT_STRIP_TRAILING_WHITESPACE
20 )
21
22 # Get the latest abbreviated commit hash of the working branch
23 execute_process(
24     COMMAND git log -1 --format=%h
25     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
26     OUTPUT_VARIABLE GIT_COMMIT_HASH
27     OUTPUT_STRIP_TRAILING_WHITESPACE
28 )
29
30 link_directories(${CMAKE_INSTALL_DIR}/core
31     ${CMAKE_INSTALL_DIR}/gst
32 )
33
34 include(GNUInstallDirs)
35
36 # ev-configuration genertion executable
37 set(EV_EXEC_NAME "${GRAPH_NAME}_cvu_cfg_app")
38
39 add_executable(${EV_EXEC_NAME}
40     cvu_cfg_main.cpp
41     cvu_cfg_graph.cpp)
42
43 target_link_libraries(${EV_EXEC_NAME}
44     PUBLIC
45     simaaiparser
46     evhelpers)
47
48 INSTALL(TARGETS "${EV_EXEC_NAME}")

Compile

  • Create a directory named build and change directory to it.

1mkdir build && cd build
  • Export poky’s environment for using cmake.

1source /opt/poky/4.0.10/environment-setup-cortexa65-poky-linux
  • Run cmake

1cmake ..
  • Run make

1make

This will generate a binary named ev_cfg_app inside build directory which is A65 executable.