.. _dependent_app_ev74_app: How to compile |dependent_app|? ############################### This section we'll discuss about how we can write and compile the |dependent_app| for configuring the EV74 graphs. Need of |dependent_app| ======================= | The |dependent_app| 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 :ref:`ev74_graph_8_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 |dependent_app| 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. #. ``send_i32_param`` This sends the integer type parameter to EV74 for configuration #. ``send_float_param`` This sends double type parameter to EV74 for configuration ``CMakeLists.txt`` ^^^^^^^^^^^^^^^^^^ This is a cmake file required to cross-compile the |dependent_app| 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 |dependent_app| for :ref:`ev74_graph_8_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. .. code-block:: cpp :caption: cvu_cfg_main.cpp :linenos: #include #include #include #include #include extern void configure_graph(const char *json_fpath); bool is_valid_path(const char *path) { struct stat buffer; return (stat(path, &buffer) == 0); } int main(int argc, char **argv) { const char *json_path = argv[1]; if(is_valid_path(json_path)) { configure_graph(json_path); } else { std::cerr << "Invalid path: " << json_path << std::endl; return 1; } return 0; } ``cvu_cfg_graph.cpp`` --------------------- The ``cvu_cfg_graph.cpp`` looks like this. .. code-block:: :caption: cvu_cfg_graph.cpp :linenos: #include #include #include #include #define SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE (8) #define INPUT_WIDTH (1) #define INPUT_HEIGHT (2) #define OUTPUT_WIDTH (3) #define OUTPUT_HEIGHT (4) #define BATCH_SIZE (5) #define RSZ_TYPE (6) void configure_graph(const char *json_in) { simaai_params_t *params = parser_node_struct_init(); if (params == NULL) { std::cout << "Unable to create params \n"; } if ((parse_json_file(json_in, params) != PARSER_SUCCESS)) { std::cout << "Unable to start parser \n"; } uint8_t *buf = (uint8_t *)calloc(1, sizeof(uint8_t) * 16); int val = *((int *)parser_get_int(params, "img_height")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_HEIGHT, buf, val); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_HEIGHT, buf, val); val = *((int *)parser_get_int(params, "img_width")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, INPUT_WIDTH, buf, val); val = *((int *)parser_get_int(params, "output_width")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, OUTPUT_WIDTH, buf, val); val = *((int *)parser_get_int(params, "output_height")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, OUTPUT_HEIGHT, buf, val); val = *((int *)parser_get_int(params, "batch_size")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, BATCH_SIZE, buf, val); val = *((int *)parser_get_int(params, "rsz_type")); send_i32_param(2, SIMA_IPC_CODE_GRAPH_SIMA_ATOMIC_RESIZE, RSZ_TYPE, buf, val); std::cout << "Completed Resize Graph Configure \n"; free(buf); } ``CMakeLists.txt`` ------------------ This ``CMakeLists.txt`` contains the configuration to compile and generate binary. It looks like this. .. code-block:: cmake :caption: CMakeLists.txt :linenos: cmake_minimum_required(VERSION 3.16) # set the project name set(GRAPH_NAME "resize_008") set(PROJECT_NAME "CVU Graph Cfg. App.") project("${PROJECT_NAME}" VERSION 0.1 DESCRIPTION "CVU Graph Configuration Application" LANGUAGES C CXX) set(PIPELINE_SOURCES cvu_cfg_graph.cpp) execute_process( COMMAND git rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE ) # Get the latest abbreviated commit hash of the working branch execute_process( COMMAND git log -1 --format=%h WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) link_directories(${CMAKE_INSTALL_DIR}/core ${CMAKE_INSTALL_DIR}/gst ) include(GNUInstallDirs) # ev-configuration genertion executable set(EV_EXEC_NAME "${GRAPH_NAME}_cvu_cfg_app") add_executable(${EV_EXEC_NAME} cvu_cfg_main.cpp cvu_cfg_graph.cpp) target_link_libraries(${EV_EXEC_NAME} PUBLIC simaaiparser evhelpers) INSTALL(TARGETS "${EV_EXEC_NAME}") .. _dependent_app_ev74_app_compilation: Compile ^^^^^^^ * Create a directory named ``build`` and change directory to it. .. code-block:: :linenos: mkdir build && cd build * Export ``poky``'s environment for using ``cmake``. .. code-block:: :linenos: source /opt/poky/4.0.10/environment-setup-cortexa65-poky-linux * Run ``cmake`` .. code-block:: :linenos: cmake .. * Run ``make`` .. code-block:: :linenos: make This will generate a binary named ``ev_cfg_app`` inside ``build`` directory which is A65 executable.