Co-authored-by: HailoRT-Automation <contact@hailo.ai>
This commit is contained in:
HailoRT-Automation
2023-01-08 12:14:08 +02:00
committed by GitHub
parent d61a3bc83f
commit 5c346eddad
287 changed files with 20837 additions and 11457 deletions

View File

@@ -1,19 +1,5 @@
cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYBIND "Build Python binding" OFF)
option(HAILO_BUILD_PYHAILORT_VENV "Build pyhailort in venv. Only used if HAILO_BUILD_PYBIND is on" ON)
option(HAILO_BUILD_EMULATOR "Build hailort for emulator" OFF)
option(HAILO_BUILD_UT "Build Unit Tests" OFF)
option(HAILO_BUILD_GSTREAMER "Compile gstreamer plugins" OFF)
option(HAILO_BUILD_EXAMPLES "Build examples" OFF)
option(HAILO_OFFLINE_COMPILATION "Don't download external dependencies" OFF)
option(HAILO_MICROPROFILE "Microprofile code" OFF)
option(HAILO_BUILD_SERVICE "Build hailort service" OFF)
if(WIN32 AND ${HAILO_BUILD_SERVICE})
message(FATAL_ERROR "HailoRT service is not supported on Windows")
endif()
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
@@ -67,14 +53,6 @@ else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
enable_testing()
# Flag for emulator (FPGA/Veloce)
if(HAILO_BUILD_EMULATOR)
message(WARNING "HailoRT is building with Emulator flag on")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -DHAILO_EMULATOR)
endif()
# Enable output of compile commands during generation
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

View File

@@ -23,12 +23,20 @@ HailoRT supports Linux and Windows, and can be compiled from sources to be integ
See [**hailo.ai developer zone documentation**](https://hailo.ai/developer-zone/documentation/hailort/latest/) (registration is required for full documentation access).
For compilation instructions, see [**Compiling HailoRT from Sources**](https://hailo.ai/developer-zone/documentation/hailort/latest/?sp_referrer=install/install.html#compiling-from-sources).
For HailoRT API examples - see [**HailoRT examples**](https://github.com/hailo-ai/hailort/tree/master/hailort/libhailort/examples).
## Changelog
See [**hailo.ai developer zone - HailoRT changelog**](https://hailo.ai/developer-zone/documentation/hailort/latest/?sp_referrer=changelog/changelog.html) (registration required).
## Licenses
HailoRT uses 2 licenses:
- libhailort, pyhailort & hailortcli - distributed under the [**MIT license**](https://opensource.org/licenses/MIT)
- hailonet (GStreamer plugin) - distributed under the [**LGPL 2.1 license**](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt)
## Contact
Contact information and support is available at [**hailo.ai**](https://hailo.ai/contact-us/).

View File

@@ -96,16 +96,25 @@ typedef enum __attribute__((packed)) {
CONTEXT_SWITCH_DEFS__ACTION_TYPE_DEACTIVATE_CFG_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_REPEATED_ACTION,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_DMA_IDLE_ACTION,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS_IDLE,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CCW_BURSTS,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_RESET,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_INPUT_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_OUTPUT_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_NMS,
/* Must be last */
CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT
} CONTEXT_SWITCH_DEFS__ACTION_TYPE_t;
typedef enum {
CONTEXT_SWITCH_DEFS__EDGE_LAYER_DIRECTION_UNINITIALIZED = 0,
CONTEXT_SWITCH_DEFS__EDGE_LAYER_DIRECTION_HOST_TO_DEVICE,
CONTEXT_SWITCH_DEFS__EDGE_LAYER_DIRECTION_DEVICE_TO_HOST,
} CONTEXT_SWITCH_DEFS__EDGE_LAYER_DIRECTION_t;
typedef struct {
CONTEXT_SWITCH_DEFS__ACTION_TYPE_t action_type;
uint32_t time_stamp;
@@ -164,9 +173,20 @@ typedef struct {
uint8_t config_stream_index;
} CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t;
typedef struct {
uint8_t initial_l3_cut;
uint16_t initial_l3_offset;
uint32_t active_apu;
uint32_t active_ia;
uint64_t active_sc;
uint64_t active_l2;
uint64_t l2_offset_0;
uint64_t l2_offset_1;
} CONTEXT_SWITCH_DEFS__sequencer_config_t;
typedef struct {
uint8_t cluster_index;
CONTORL_PROTOCOL__sequencer_config_t sequencer_config;
CONTEXT_SWITCH_DEFS__sequencer_config_t sequencer_config;
} CONTEXT_SWITCH_DEFS__trigger_sequencer_action_data_t;
typedef struct {
@@ -198,17 +218,22 @@ typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t edge_layer_direction;
bool is_inter_context;
bool is_single_context_network_group;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t;
typedef enum {
CONTEXT_SWITCH_DEFS__CREDIT_TYPE_UNINITIALIZED = 0,
CONTEXT_SWITCH_DEFS__CREDIT_IN_BYTES,
CONTEXT_SWITCH_DEFS__CREDIT_IN_DESCRIPTORS,
} CONTEXT_SWITCH_DEFS__CREDIT_TYPE_t;
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t network_index;
uint32_t frame_periph_size;
uint8_t credit_type;
uint8_t credit_type; // CONTEXT_SWITCH_DEFS__CREDIT_TYPE_t
uint16_t periph_bytes_per_buffer;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t, relevant only for descriptors credit.
} CONTEXT_SWITCH_DEFS__fetch_data_action_data_t;
@@ -247,7 +272,7 @@ typedef struct {
uint8_t pred_cluster_ob_interface;
uint8_t succ_prepost_ob_index;
uint8_t succ_prepost_ob_interface;
} CONTEXT_SWITCH_DEFS__wait_nms_idle_data_t;
} CONTEXT_SWITCH_DEFS__wait_nms_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
@@ -259,10 +284,6 @@ typedef struct {
uint8_t module_index;
} CONTEXT_SWITCH_DEFS__module_config_done_interrupt_data_t;
typedef struct {
uint8_t application_index;
} CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t;
/* edge layers structs */
typedef struct {
uint8_t packed_vdma_channel_id;
@@ -270,7 +291,6 @@ typedef struct {
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
bool is_single_context_app;
} CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t;
typedef struct {
@@ -314,14 +334,15 @@ typedef struct {
uint32_t buffered_rows_count;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t;
typedef union {
CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t activate_boundary_input_data;
CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t activate_inter_context_input_data;
CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t activate_ddr_buffer_input_data;
CONTEXT_SWITCH_DEFS__activate_boundary_output_data_t activate_boundary_output_data;
CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t activate_inter_context_output_data;
CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t activate_ddr_buffer_output_data;
} CONTEXT_SWITCH_COMMON__activate_edge_layer_action_t;
typedef struct {
uint8_t packed_vdma_channel_id;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__open_boundary_input_channel_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__open_boundary_output_channel_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
@@ -334,6 +355,11 @@ typedef struct {
uint8_t config_stream_index;
} CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t;
typedef struct {
uint8_t nms_unit_index;
uint8_t network_index;
} CONTEXT_SWITCH_DEFS__enable_nms_action_t;
#pragma pack(pop)
#ifdef __cplusplus

View File

@@ -38,7 +38,6 @@ extern "C" {
#define CONTROL_PROTOCOL__MAX_CONTEXT_SWITCH_APPLICATIONS (32)
#define CONTROL_PROTOCOL__MAX_NUMBER_OF_CLUSTERS (8)
#define CONTROL_PROTOCOL__MAX_CONTROL_LENGTH (1500)
#define CONTROL_PROTOCOL__MAX_TOTAL_CONTEXTS (128)
#define CONTROL_PROTOCOL__SOC_ID_LENGTH (32)
#define CONTROL_PROTOCOL__MAX_CFG_CHANNELS (4)
#define CONTROL_PROTOCOL__MAX_NETWORKS_PER_NETWORK_GROUP (8)
@@ -67,13 +66,6 @@ extern "C" {
*/
#define CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE (0)
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_SHIFT (0)
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_BIT_MASK (0x000000FF)
#define CONTROL_PROTOCOL__TRIGGER_INDEX_SHIFT (16)
#define CONTROL_PROTOCOL__TRIGGER_INDEX_BIT_MASK (0x00FF0000)
#define CONTROL_PROTOCOL__TRIGGER_TYPE_SHIFT (28)
#define CONTROL_PROTOCOL__TRIGGER_TYPE_BIT_MASK (0xF0000000)
// Tightly coupled with BOARD_CONFIG_supported_features_t struct
#define CONTROL_PROTOCOL__SUPPORTED_FEATURES_ETHERNET_BIT_OFFSET (0)
#define CONTROL_PROTOCOL__SUPPORTED_FEATURES_MIPI_BIT_OFFSET (1)
@@ -86,19 +78,6 @@ extern "C" {
/* Value to represent an operation should be performed on all streams. */
#define CONTROL_PROTOCOL__ALL_DATAFLOW_MANAGERS (0xFF)
#define CONTROL_PROTOCOL__WRITE_TRIGGER_SUB_INDEX(val)\
(((uint32_t)val) << CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_SHIFT)
#define CONTROL_PROTOCOL__READ_TRIGGER_SUB_INDEX(val)\
(((uint32_t)(val) & CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_BIT_MASK) >> (CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_SHIFT))
#define CONTROL_PROTOCOL__WRITE_TRIGGER_INDEX(val)\
(((uint32_t)val) << CONTROL_PROTOCOL__TRIGGER_INDEX_SHIFT)
#define CONTROL_PROTOCOL__READ_TRIGGER_INDEX(val)\
(((uint32_t)(val) & CONTROL_PROTOCOL__TRIGGER_INDEX_BIT_MASK) >> (CONTROL_PROTOCOL__TRIGGER_INDEX_SHIFT))
#define CONTROL_PROTOCOL__WRITE_TRIGGER_TYPE(val)\
(((uint32_t)val) << CONTROL_PROTOCOL__TRIGGER_TYPE_SHIFT)
#define CONTROL_PROTOCOL__READ_TRIGGER_TYPE(val)\
(((uint32_t)(val) & CONTROL_PROTOCOL__TRIGGER_TYPE_BIT_MASK) >> (CONTROL_PROTOCOL__TRIGGER_TYPE_SHIFT))
#define CONTROL_PROTOCOL__OPCODES_VARIABLES \
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_IDENTIFY, true, CPU_ID_APP_CPU)\
@@ -133,7 +112,7 @@ extern "C" {
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SENSOR_LOAD_AND_START, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SENSOR_RESET, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SENSOR_GET_SECTIONS_INFO, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_SET_MAIN_HEADER, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_SET_NETWORK_GROUP_HEADER, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_SET_CONTEXT_INFO, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_IDLE_TIME_SET_MEASUREMENT, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_IDLE_TIME_GET_MEASUREMENT, false, CPU_ID_APP_CPU)\
@@ -173,6 +152,8 @@ extern "C" {
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CORE_WD_ENABLE, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CORE_WD_CONFIG, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_CLEAR_CONFIGURED_APPS, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_GET_HW_CONSTS, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SET_SLEEP_STATE, false, CPU_ID_APP_CPU)\
typedef enum {
#define CONTROL_PROTOCOL__OPCODE_X(name, is_critical, cpu_id) name,
@@ -432,6 +413,11 @@ typedef struct {
bool should_activate;
} CONTROL_PROTOCOL__set_overcurrent_state_request_t;
typedef struct {
uint32_t sleep_state_length;
uint8_t sleep_state; /* of type CONTROL_PROTOCOL__sleep_state_t */
} CONTROL_PROTOCOL__set_sleep_state_request_t;
typedef struct {
uint32_t is_required_length;
bool is_required;
@@ -446,6 +432,7 @@ typedef struct {
uint16_t core_bytes_per_buffer;
uint16_t core_buffers_per_frame;
uint16_t periph_bytes_per_buffer;
uint16_t periph_buffers_per_frame;
uint16_t feature_padding_payload;
uint16_t buffer_padding_payload;
uint16_t buffer_padding;
@@ -868,10 +855,6 @@ typedef struct {
uint32_t inbound_to_outbound_latency_nsec;
} CONTROL_PROTOCOL__latency_read_response_t;
typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_VER_V1_0_0 = 0x010000,
} CONTROL_PROTOCOL__CONTEXT_SWITCH_VERSION_t;
typedef struct {
bool is_abbale_supported;
} CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t;
@@ -882,8 +865,6 @@ typedef struct {
typedef struct {
uint8_t dynamic_contexts_count;
uint32_t host_boundary_channels_bitmap[CONTROL_PROTOCOL__MAX_VDMA_ENGINES_COUNT];
uint8_t power_mode; // CONTROL_PROTOCOL__power_mode_t
CONTROL_PROTOCOL__INFER_FEATURE_LIST_t infer_features;
CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t validation_features;
uint8_t networks_count;
@@ -891,13 +872,9 @@ typedef struct {
} CONTROL_PROTOCOL__application_header_t;
typedef struct {
uint32_t context_switch_version_length;
uint32_t context_switch_version;
uint32_t application_count_length;
uint8_t application_count;
uint32_t application_header_length;
CONTROL_PROTOCOL__application_header_t application_header[CONTROL_PROTOCOL__MAX_CONTEXT_SWITCH_APPLICATIONS];
} CONTROL_PROTOCOL__context_switch_set_main_header_request_t;
CONTROL_PROTOCOL__application_header_t application_header;
} CONTROL_PROTOCOL__context_switch_set_network_group_header_request_t;
typedef enum {
CONTROL_PROTOCOL__WATCHDOG_MODE_HW_SW = 0,
@@ -908,7 +885,6 @@ typedef enum {
} CONTROL_PROTOCOL__WATCHDOG_MODE_t;
typedef struct {
CONTROL_PROTOCOL__CONTEXT_SWITCH_VERSION_t context_switch_version;
uint8_t application_count;
CONTROL_PROTOCOL__application_header_t application_header[CONTROL_PROTOCOL__MAX_CONTEXT_SWITCH_APPLICATIONS];
} CONTROL_PROTOCOL__context_switch_main_header_t;
@@ -943,107 +919,11 @@ typedef struct {
CONTROL_PROTOCOL__temperature_info_t info;
} CONTROL_PROTOCOL__get_chip_temperature_response_t;
typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_NONE = 0,
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_LCU,
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_INPUT_STREAM,
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_OUTPUT_STREAM,
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_NMS_IDLE,
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_DMA_IDLE,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_COUNT,
} CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_t;
typedef enum {
/* this enum starts from 128 for each debug while reading memory buffer */
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_START_INDEX = 128,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_READ_VDMA = CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_START_INDEX,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_TRIGGER_SEQUENCER,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_WAIT_FOR_SEQUENCER_DONE,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_TRIGGER_NEW_DATA_FROM_DATA_INPUT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_NON_DEFAULT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_DISABLE_LCU,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_WAIT_FOR_MODULE_CONFIG_DONE,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_DDR_PAIR_INFO,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_DDR_BUFFERING_START,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_REPEATED,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_FETCH_CCW_BURSTS,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_BURST_CREDITS_TASK_START,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_EDGE_LAYER_ACTIVATION_ACTIONS_POSITION,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_COUNT,
} CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_TYPE_t;
typedef uint8_t CONTROL_PROTOCOL__TRIGGER_TYPE_t;
typedef struct {
/* Empty struct - place holder */
uint8_t reserved;
} CONTROL_PROTOCOL__TRIGGER_NONE_t;
typedef struct {
uint8_t cluster_index;
uint8_t lcu_index;
} CONTROL_PROTOCOL__TRIGGER_LCU_t;
typedef struct {
uint8_t stream_index;
} CONTROL_PROTOCOL__TRIGGER_INPUT_STREAM_t;
typedef struct {
uint8_t stream_index;
} CONTROL_PROTOCOL__TRIGGER_OUTPUT_STREAM_t;
typedef struct {
uint8_t aggregator_index;
uint8_t pred_cluster_ob_index;
uint8_t pred_cluster_ob_cluster_index;
uint8_t pred_cluster_ob_interface;
uint8_t succ_prepost_ob_index;
uint8_t succ_prepost_ob_interface;
} CONTROL_PROTOCOL__TRIGGER_NMS_IDLE_t;
typedef struct {
uint8_t stream_index;
} CONTROL_PROTOCOL__TRIGGER_DMA_IDLE_t;
typedef union {
CONTROL_PROTOCOL__TRIGGER_NONE_t none_trigger;
CONTROL_PROTOCOL__TRIGGER_LCU_t lcu_trigger;
CONTROL_PROTOCOL__TRIGGER_INPUT_STREAM_t input_stream_trigger;
CONTROL_PROTOCOL__TRIGGER_OUTPUT_STREAM_t output_stream_trigger;
CONTROL_PROTOCOL__TRIGGER_NMS_IDLE_t nms_idle_trigger;
CONTROL_PROTOCOL__TRIGGER_DMA_IDLE_t dma_idle_trigger;
} CONTROL_PROTOCOL__trigger_parameters_t;
typedef struct {
CONTROL_PROTOCOL__TRIGGER_TYPE_t type;
CONTROL_PROTOCOL__trigger_parameters_t params;
} CONTROL_PROTOCOL__TRIGGER_t;
typedef uint8_t CONTROL_PROTOCOL__shmifo_to_pcie_channel_mapping_t;
typedef enum {
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_NETWORK_BOUNDARY_INPUT,
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_NETWORK_BOUNDARY_OUTPUT,
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_INTERMEDIATE_BUFFER_INPUT,
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_INTERMEDIATE_BUFFER_OUTPUT,
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_DDR_BUFFER_INPUT,
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_DDR_BUFFER_OUTPUT,
/* must be last */
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_COUNT
} CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_t;
typedef enum {
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_EXTERNAL_DESC = 0,
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_CCB,
// The buffer uses external descriptors that is host managed - the firmware don't need to config this buffer
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_HOST_MANAGED_EXTERNAL_DESC,
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_HOST_MANAGED_EXTERNAL_DESC, /* DEPRECATED */
/* must be last */
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_COUNT
@@ -1057,74 +937,6 @@ typedef struct {
uint32_t bytes_in_pattern;
} CONTROL_PROTOCOL__host_buffer_info_t;
/* TODO: merge CONTROL_PROTOCOL__edge_layer_common_info_t into the header (HRT-7113) */
typedef struct {
uint8_t communication_type;
uint8_t edge_connection_type;
} CONTROL_PROTOCOL__edge_layer_header_t;
typedef struct {
uint8_t engine_index;
uint8_t vdma_channel_index;
uint8_t stream_index;
uint8_t network_index;
CONTROL_PROTOCOL__nn_stream_config_t nn_stream_config;
} CONTROL_PROTOCOL__edge_layer_common_info_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTROL_PROTOCOL__network_boundary_output_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTROL_PROTOCOL__inter_context_output_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t buffered_rows_count;
} CONTROL_PROTOCOL__ddr_buffer_output_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
} CONTROL_PROTOCOL__eth_network_boundary_output_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__network_boundary_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__inter_context_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
uint8_t connected_d2h_engine_index;
uint8_t connected_d2h_channel_index;
} CONTROL_PROTOCOL__ddr_buffer_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
} CONTROL_PROTOCOL__eth_network_boundary_input_t;
typedef struct {
uint8_t should_use_stream_remap;
} CONTROL_PROTOCOL__stream_remap_data_t;
typedef struct {
CONTROL_PROTOCOL__host_buffer_info_t config_buffer_info;
uint8_t engine_index;
uint8_t vdma_channel_index;
} CONTROL_PROTOCOL__config_channel_info_t;
#if defined(_MSC_VER)
// TODO: warning C4200
@@ -1136,16 +948,10 @@ typedef struct {
uint8_t is_first_control_per_context;
uint32_t is_last_control_per_context_length;
uint8_t is_last_control_per_context;
uint32_t cfg_channels_count_length;
uint8_t cfg_channels_count;
uint32_t config_channel_infos_length;
CONTROL_PROTOCOL__config_channel_info_t config_channel_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint32_t context_stream_remap_data_length;
CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
uint32_t number_of_edge_layers_length;
uint8_t number_of_edge_layers;
uint32_t number_of_trigger_groups_length;
uint8_t number_of_trigger_groups;
uint32_t context_type_length;
uint8_t context_type; // CONTROL_PROTOCOL__context_switch_context_type_t
uint32_t actions_count_length;
uint32_t actions_count;
uint32_t context_network_data_length;
uint8_t context_network_data[0];
} CONTROL_PROTOCOL__context_switch_set_context_info_request_t;
@@ -1153,169 +959,12 @@ typedef struct {
#pragma warning(pop)
#endif
typedef uint8_t CONTROL_PROTOCOL__ACTION_TYPE_t;
/* Each CONTROL_PROTOCOL__*_ACTION_t must start with a CONTROL_PROTOCOL__ACTION_HEADER_t */
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_TYPE_t action_type;
uint8_t action_type; // CONTEXT_SWITCH_DEFS__ACTION_TYPE_t
bool is_repeated;
} CONTROL_PROTOCOL__ACTION_HEADER_t;
/**
* Repeated actions are sent in the following manner via the control protocol:
* 1) CONTROL_PROTOCOL__REPEATED_ACTION_t with:
* a) 'action_type' = CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_REPEATED
* b) 'is_repeated' = false
* 2) 'count' sub-actions whose type matches the 'sub_action_type' defined by (1).
* The sub-actions will be consecutive, and will all be marked as 'is_repeated' = true in thier headers.
* The sub-actions may be in different slices, if there is a 'CONTROL_PROTOCOL__CONTEXT_SWITCH_TRIGGER_TYPE_NONE' between them.
*
* E.g. - 3 repeated 'CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT's:
* |--------------------------------------------------------------------------------------------------|
* | time | data |
* |--------------------------------------------------------------------------------------------------|
* | ... | |
* | | | CONTROL_PROTOCOL__REPEATED_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_REPEATED, false}; |
* | | | .sub_action_type = CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT; |
* | | | .num_actions = 3; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | V | } |
* | ... | (Next action control) |
* |--------------------------------------------------------------------------------------------------|
* See also: "CONTEXT_SWITCH_DEFS__repeated_action_header_t" in "context_switch_defs.h"
*/
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
CONTROL_PROTOCOL__ACTION_TYPE_t sub_action_type;
uint8_t num_actions;
} CONTROL_PROTOCOL__REPEATED_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint16_t descriptors_count;
uint8_t config_stream_index;
} CONTROL_PROTOCOL__READ_VDMA_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint16_t ccw_bursts;
uint8_t config_stream_index;
} CONTROL_PROTOCOL__FETCH_CCW_BURSTS_ACTION_t;
typedef struct {
uint8_t initial_l3_cut;
uint16_t initial_l3_offset;
uint32_t active_apu;
uint32_t active_ia;
uint64_t active_sc;
uint64_t active_l2;
uint64_t l2_offset_0;
uint64_t l2_offset_1;
} CONTORL_PROTOCOL__sequencer_config_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
CONTORL_PROTOCOL__sequencer_config_t sequencer_config;
} CONTROL_PROTOCOL__TRIGGER_SEQUENCER_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t sequencer_index;
} CONTROL_PROTOCOL__WAIT_FOR_SEQUENCER_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t stream_index;
} CONTROL_PROTOCOL__FETCH_NEW_DATA_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
uint8_t lcu_index;
uint16_t kernel_done_address;
uint32_t kernel_done_count;
uint8_t network_index;
} CONTROL_PROTOCOL__ENABLE_LCU_NON_DEAFULT_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
uint8_t lcu_index;
uint8_t network_index;
} CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
uint8_t lcu_index;
} CONTROL_PROTOCOL__DISABLE_LCU_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t module_index;
} CONTORL_PROTOCOL__WAIT_FOR_MODULE_CONFIG_DONE_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t h2d_engine_index;
uint8_t h2d_vdma_channel_index;
uint8_t d2h_engine_index;
uint8_t d2h_vdma_channel_index;
uint32_t descriptors_per_frame;
uint16_t programmed_descriptors_count;
} CONTROL_PROTOCOL__ADD_DDR_PAIR_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__ADD_DDR_BUFFERING_START_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__BURST_CREDITS_TASK_START_ACTION_T;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__EDGE_LAYER_ACTIVATION_ACTIONS_POSITION_MARKER_T;
typedef struct {
CONTROL_PROTOCOL__TRIGGER_t trigger;
uint16_t triggers_action_count;
} CONTROL_PROTOCOL__trigger_group_t;
typedef CONTROL_PROTOCOL__read_memory_request_t CONTROL_PROTOCOL__read_user_config_request_t;
typedef CONTROL_PROTOCOL__read_memory_response_t CONTROL_PROTOCOL__read_user_config_response_t;
typedef CONTROL_PROTOCOL__write_memory_request_t CONTROL_PROTOCOL__write_user_config_request_t;
@@ -1331,6 +980,10 @@ typedef struct {
} CONTROL_PROTOCOL__idle_time_get_measurement_response_t;
typedef struct {
uint32_t network_group_id_length;
uint32_t network_group_id;
uint32_t context_type_length;
uint8_t context_type; // CONTROL_PROTOCOL__context_switch_context_type_t
uint32_t context_index_length;
uint8_t context_index;
uint32_t action_list_offset_length;
@@ -1579,7 +1232,15 @@ typedef enum {
CONTROL_PROTOCOL__TOP_MEM_BLOCK_SUB_SERVER6_26,
CONTROL_PROTOCOL__TOP_MEM_BLOCK_SUB_SERVER7_27,
CONTROL_PROTOCOL__TOP_NUM_MEM_BLOCKS
} CONTROL_PROTOCOL__biTOP_st_top_mem_block_t;
} CONTROL_PROTOCOL__bist_top_mem_block_t;
/* Must be identical to hailo_sleep_state_t, tightly coupled */
typedef enum {
CONTROL_PROTOCOL_SLEEP_STATE_SLEEPING = 0,
CONTROL_PROTOCOL_SLEEP_STATE_AWAKE = 1,
/* must be last */
CONTROL_PROTOCOL_SLEEP_STATE_COUNT
} CONTROL_PROTOCOL__sleep_state_t;
/*only allowing bist on the following memories*/
#define CONTROL_PROTOCOL__BIST_TOP_WHITELIST ((1 << CONTROL_PROTOCOL__TOP_MEM_BLOCK_L4_0_2) | \
@@ -1603,6 +1264,21 @@ typedef struct {
uint32_t cluster_bypass_bitmap_1;
} CONTROL_PROTOCOL__run_bist_test_request_t;
typedef struct {
uint32_t fifo_word_granularity_bytes;
uint16_t max_periph_buffers_per_frame;
uint16_t max_periph_bytes_per_buffer;
uint16_t max_acceptable_bytes_per_buffer;
uint32_t outbound_data_stream_size;
uint8_t should_optimize_credits;
uint32_t default_initial_credit_size;
} CONTROL_PROTOCOL__hw_consts_t;
typedef struct {
uint32_t hw_consts_length;
CONTROL_PROTOCOL__hw_consts_t hw_consts;
} CONTROL_PROTOCOL__get_hw_consts_response_t;
typedef union {
CONTROL_PROTOCOL_identify_response_t identity_response;
CONTROL_PROTOCOL__core_identify_response_t core_identity_response;
@@ -1628,6 +1304,8 @@ typedef union {
CONTROL_PROTOCOL__get_health_information_response_t get_health_information_response;
CONTROL_PROTOCOL__get_throttling_state_response_t get_throttling_state_response;
CONTROL_PROTOCOL__get_overcurrent_state_response_t get_overcurrent_state_response;
CONTROL_PROTOCOL__get_hw_consts_response_t get_hw_consts_response;
// Note: This array is larger than any legal request:
// * Functions in this module won't write more than CONTROL_PROTOCOL__MAX_CONTROL_LENGTH bytes
// when recieving a pointer to CONTROL_PROTOCOL__request_parameters_t.
@@ -1660,7 +1338,7 @@ typedef union {
CONTROL_PROTOCOL__sensor_reset_request_t sensor_reset_request;
CONTROL_PROTOCOL__sensor_get_config_request_t sensor_get_config_request;
CONTROL_PROTOCOL__sensor_set_generic_i2c_slave_request_t sensor_set_generic_i2c_slave_request;
CONTROL_PROTOCOL__context_switch_set_main_header_request_t context_switch_set_main_header_request;
CONTROL_PROTOCOL__context_switch_set_network_group_header_request_t context_switch_set_network_group_header_request;
CONTROL_PROTOCOL__context_switch_set_context_info_request_t context_switch_set_context_info_request;
CONTROL_PROTOCOL__idle_time_set_measurement_request_t idle_time_set_measurement_request;
CONTROL_PROTOCOL__download_context_action_list_request_t download_context_action_list_request;
@@ -1685,6 +1363,7 @@ typedef union {
CONTROL_PROTOCOL__set_throttling_state_request_t set_throttling_state_request;
CONTROL_PROTOCOL__sensor_set_i2c_bus_index_t sensor_set_i2c_bus_index;
CONTROL_PROTOCOL__set_overcurrent_state_request_t set_overcurrent_state_request;
CONTROL_PROTOCOL__set_sleep_state_request_t set_sleep_state_request;
// Note: This array is larger than any legal request:
// * Functions in this module won't write more than CONTROL_PROTOCOL__MAX_CONTROL_LENGTH bytes
// when recieving a pointer to CONTROL_PROTOCOL__request_parameters_t.
@@ -1721,28 +1400,40 @@ typedef struct {
#define CONTROL_PROTOCOL__CONTEXT_NETWORK_DATA_SINGLE_CONTROL_MAX_SIZE \
(CONTROL_PROTOCOL__MAX_REQUEST_PARAMETERS_LENGTH - sizeof(CONTROL_PROTOCOL__context_switch_set_context_info_request_t))
typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_PRELIMINARY,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_DYNAMIC,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_BATCH_SWITCHING,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_ACTIVATION,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_COUNT,
} CONTROL_PROTOCOL__context_switch_context_type_t;
typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_INDEX_ACTIVATION_CONTEXT = 0,
CONTROL_PROTOCOL__CONTEXT_SWITCH_INDEX_BATCH_SWITCHING_CONTEXT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_INDEX_PRELIMINARY_CONTEXT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_NUMBER_OF_NON_DYNAMIC_CONTEXTS,
CONTROL_PROTOCOL__CONTEXT_SWITCH_INDEX_FIRST_DYNAMIC_CONTEXT = CONTROL_PROTOCOL__CONTEXT_SWITCH_NUMBER_OF_NON_DYNAMIC_CONTEXTS,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_INDEX_COUNT,
} CONTROL_PROTOCOL__context_switch_context_index_t;
#define CONTROL_PROTOCOL__MAX_CONTEXTS_PER_NETWORK_GROUP (64)
typedef struct {
bool is_first_control_per_context;
bool is_last_control_per_context;
uint8_t cfg_channels_count;
CONTROL_PROTOCOL__config_channel_info_t config_channel_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
uint8_t number_of_edge_layers;
uint8_t number_of_trigger_groups;
uint8_t context_type; // CONTROL_PROTOCOL__context_switch_context_type_t
uint32_t actions_count;
uint32_t context_network_data_length;
uint8_t context_network_data[CONTROL_PROTOCOL__CONTEXT_NETWORK_DATA_SINGLE_CONTROL_MAX_SIZE];
} CONTROL_PROTOCOL__context_switch_context_info_single_control_t;
/* Context switch user structs */
#define CONTROL_PROTOCOL__CONTEXT_NETWORK_DATA_MAX_SIZE (8 * 1024)
typedef struct {
uint8_t interrupt_type;
uint8_t interrupt_index;
uint8_t interrupt_sub_index;
} CONTROL_PROTOCOL__dataflow_interrupt_t;
/* End of context switch structs */
CASSERT(sizeof(CONTROL_PROTOCOL__context_switch_context_index_t)<=UINT8_MAX, control_protocol_h);
CASSERT(sizeof(CONTROL_PROTOCOL__context_switch_context_type_t)<=UINT8_MAX, control_protocol_h);
typedef enum {
CONTROL_PROTOCOL__MESSAGE_TYPE__REQUEST = 0,
@@ -1769,7 +1460,6 @@ typedef enum {
CONTROL_PROTOCOL__RESET_TYPE__COUNT
} CONTROL_PROTOCOL__reset_type_t;
typedef union {
/* Needed in order to parse unknown header */
CONTROL_PROTOCOL__common_header_t common;

View File

@@ -29,7 +29,7 @@ typedef enum {
typedef enum {
D2H_EVENT_COMMUNICATION_TYPE_UDP = 0,
D2H_EVENT_COMMUNICATION_TYPE_PCIE,
D2H_EVENT_COMMUNICATION_TYPE_VDMA,
D2H_EVENT_COMMUNICATION_TYPE__COUNT
} D2H_EVENT_COMMUNICATION_TYPE_t;
@@ -72,7 +72,7 @@ typedef struct {
typedef struct {
uint32_t connection_status;
uint32_t connection_type;
uint32_t pcie_is_active;
uint32_t vdma_is_active;
uint32_t host_port;
uint32_t host_ip_addr;
} D2H_EVENT_host_info_event_message_t;
@@ -156,7 +156,16 @@ typedef struct {
D2H_EVENT__message_parameters_t message_parameters;
} D2H_EVENT_MESSAGE_t;
#define PCIE_D2H_EVENT_MAX_SIZE (0x370)
#define D2H_EVENT_BUFFER_NOT_IN_USE (0)
#define D2H_EVENT_BUFFER_IN_USE (1)
#define D2H_EVENT_MAX_SIZE (0x370)
typedef struct {
uint16_t is_buffer_in_use;
uint16_t buffer_len;
uint8_t buffer[D2H_EVENT_MAX_SIZE];
} D2H_event_buffer_t;
/**********************************************************************
* Public Functions
**********************************************************************/

View File

@@ -22,26 +22,28 @@ extern "C" {
#define REVISION_NUMBER_SHIFT (0)
#define REVISION_APP_CORE_FLAG_BIT_SHIFT (27)
#define REVISION_RESERVED_0_FLAG_BIT_SHIFT (28)
#define REVISION_RESERVED_1_FLAG_BIT_SHIFT (29)
#define REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_SHIFT (29)
#define REVISION_DEV_FLAG_BIT_SHIFT (30)
#define REVISION_SECOND_STAGE_FLAG_BIT_SHIFT (31)
#define REVISION_NUMBER_WIDTH (27U)
#define REVISION_APP_CORE_FLAG_BIT_WIDTH (1U)
#define REVISION_RESERVED_0_FLAG_BIT_WIDTH (1U)
#define REVISION_RESERVED_1_FLAG_BIT_WIDTH (1U)
#define REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_WIDTH (1U)
#define REVISION_DEV_FLAG_BIT_WIDTH (1U)
#define REVISION_SECOND_STAGE_FLAG_BIT_WIDTH (1U)
#define REVISION_NUMBER_MASK (GET_MASK(REVISION_NUMBER_WIDTH, REVISION_NUMBER_SHIFT))
#define REVISION_APP_CORE_FLAG_BIT_MASK (GET_MASK(REVISION_APP_CORE_FLAG_BIT_WIDTH, REVISION_APP_CORE_FLAG_BIT_SHIFT))
#define REVISION_RESERVED_0_FLAG_BIT_MASK (GET_MASK(REVISION_RESERVED_0_FLAG_BIT_WIDTH, REVISION_RESERVED_0_FLAG_BIT_SHIFT))
#define REVISION_RESERVED_1_FLAG_BIT_MASK (GET_MASK(REVISION_RESERVED_1_FLAG_BIT_WIDTH, REVISION_RESERVED_1_FLAG_BIT_SHIFT))
#define REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_MASK (GET_MASK(REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_WIDTH, REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_SHIFT))
#define REVISION_DEV_FLAG_BIT_MASK (GET_MASK(REVISION_DEV_FLAG_BIT_WIDTH, REVISION_DEV_FLAG_BIT_SHIFT))
#define REVISION_SECOND_STAGE_FLAG_BIT_MASK (GET_MASK(REVISION_SECOND_STAGE_FLAG_BIT_WIDTH, REVISION_SECOND_STAGE_FLAG_BIT_SHIFT))
#define GET_REVISION_NUMBER_VALUE(binary_revision) (REVISION_NUMBER_MASK & binary_revision)
#define IS_REVISION_DEV(binary_revision) (REVISION_DEV_FLAG_BIT_MASK == (REVISION_DEV_FLAG_BIT_MASK & binary_revision))
#define IS_REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER(binary_revision) (REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_MASK == \
(REVISION_EXTENDED_CONTEXT_SWITCH_BUFFER_FLAG_BIT_MASK & binary_revision))
#define DEV_STRING_NOTE(__is_release) ((__is_release)? "" : " (dev)")
/**

View File

@@ -307,7 +307,7 @@ Updating rules:
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_APP_HEADER_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_CLUSTER_END_GARANTEE_TRIGGER_LENGTH)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_NUMBER_OF_EDGE_LAYERS_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_NUMBER_OF_TRIGGER_GROUPS_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_NUMBER_OF_ACTION_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_TRIGGER_GROUPS_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_CONTEXT_SWITCH_CONTEXT_NETWORK_DATA_LENGTH_HIGHER_THEN_MAX_CONTROL_SIZE)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_IDLE_TIME_MEASUREMENT_ALREADY_SET)\
@@ -404,6 +404,11 @@ Updating rules:
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_INFER_FEATURES_LENGTH) /* DEPRECATED */\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONFIG_CHANNEL_INFOS)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_IS_BATCH_SIZE_FLOW_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_CONTEXT_TYPE_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_CONTEXT_NETWORK_GROUP_ID_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_SET_SLEEP_STATE_FAILED)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_SLEEP_STATE_SIZE)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_SLEEP_STATE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__POWER_MEASUREMENT)\
FIRMWARE_STATUS__X(HAILO_POWER_MEASUREMENT_STATUS_POWER_INIT_ERROR)\
@@ -650,7 +655,7 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_ACTION_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_CONTEXT_INFO_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_PARSING_ERROR_WHILE_READING_TRIGGER_GROUPS)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_TRIGGER_GROUP_POINTER_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_POINTER_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_DOWNLOAD_ACTION_LIST_INVALID_CONTEXT_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_RECEIVED_INVALID_APPLICATION_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_RECEIVED_INVALID_TOTAL_CONTEXTS_COUNT)\
@@ -732,10 +737,6 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_WAIT_FOR_PREDICATE_INTERRUPTED_BY_RESET_REQUEST)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_WAIT_FOR_DMA_IDLE_INTERRUPTED_BY_RESET_REQUEST)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_ACTION_NOT_SUPPORTED)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_AGGREGATOR_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_CLUSTER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INTERFACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_ACTION_IS_NOT_SUPPORTED)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CFG_CHANNELS_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_HOST_BUFFER_TYPE)\
@@ -745,6 +746,11 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_ADD_ACTION_TO_BATCH_SWITCH_BUFFER_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_WAIT_FOR_INTERRUPT_INTERRUPTED_BY_BATCH_CHANGE_REQUEST)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_CANT_CLEAR_CONFIGURED_APPS_WHILE_ACTIVATED)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CONTEXT_TYPE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_UNEXPECTED_CONTEXT_ORDER)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_DYNAMIC_CONTEXT_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_CONTEXT_INDEX_OUT_OF_RANGE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_TOTAL_PROVIDED_EDGE_LAYERS_LARGER_THEN_EXPECTED)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\
@@ -753,11 +759,12 @@ Updating rules:
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_INVALID_MESSAGE_QUEUE_HANDLE)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_SENDING_MESSAGE_FAIL)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_SEND_EVENT_OVER_UDP_FAIL)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_SEND_EVENT_OVER_PCIE_FAIL)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_SEND_EVENT_OVER_VDMA_FAIL)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_INVALID_COMMUNICATION_TYPE)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_PCIE_NOT_ACTIVE)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_VDMA_COMMUNICATION_NOT_ACTIVE)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_INVALID_PRIORITY_QUEUE_HANDLE)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_INIT_UDP_FAIL)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_INVALID_PARAMETERS)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__WD)\
FIRMWARE_STATUS__X(WD_STATUS_INVALID_PARAMETERS)\
@@ -997,6 +1004,8 @@ Updating rules:
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_TOO_LARGE_BYTES_IN_PATTERN)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_ENGINE_INDEX)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_CONSTANTS)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_CHANNEL_INDEX)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_EDGE_LAYER_DIRECTION)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__MEMORY_LOGGER)\
FIRMWARE_STATUS__X(MEMORY_LOGGER_STATUS_DEBUG_INSUFFICIENT_MEMORY)\
@@ -1049,6 +1058,30 @@ Updating rules:
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_INFER_REACHED_TIMEOUT)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TASK_DEACTIVATED)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__TASK_SYNC_EVENTS)\
FIRMWARE_STATUS__X(TASK_SYNC_EVENTS_STATUS_START_TASK_WHILE_IT_IS_RUNNING)\
FIRMWARE_STATUS__X(TASK_SYNC_EVENTS_STATUS_START_TASK_WHILE_TASK_NOT_DONE)\
FIRMWARE_STATUS__X(TASK_SYNC_EVENTS_STATUS_FAILED_TO_RESET_STATE_MACHINE)\
FIRMWARE_STATUS__X(TASK_SYNC_EVENTS_STATUS_DONE_TASK_WHILE_IT_IS_NOT_RUNNING)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__NMS_MANAGER)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_ARGUMENT)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_WAIT_FOR_INTERRUPT_INTERRUPTED_BY_RESET_REQUEST)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_AGGREGATOR_INDEX)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_OUTPUT_BUFFER_INDEX)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_OUTPUT_BUFFER_CLUSTER_INDEX)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_OUTPUT_BUFFER_INTERFACE)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_NOT_SUPPORTED_OPERATION)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_NETWORK_INDEX)\
FIRMWARE_STATUS__X(NMS_MANAGER_STATUS_INVALID_NMS_UNIT_INDEX)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__CLUSTER_MANAGER)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_INVALID_CLUSTER_INDEX)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_INVALID_INITIAL_L3_CUT)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_INVALID_INITIAL_L3_OFFSET)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_INVALID_LCU_INDEX)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_INVALID_KERNEL_DONE_ADDRESS)\
FIRMWARE_STATUS__X(CLUSTER_MANAGER_STATUS_RECEIVED_UNEXPECTED_INTERRUPT)\
typedef enum {

View File

@@ -66,7 +66,8 @@ typedef enum {
SOC__NN_CLOCK_250MHz = 250 * 1000 * 1000,
SOC__NN_CLOCK_225MHz = 225 * 1000 * 1000,
SOC__NN_CLOCK_200MHz = 200 * 1000 * 1000,
SOC__NN_CLOCK_100MHz = 100 * 1000 * 1000
SOC__NN_CLOCK_100MHz = 100 * 1000 * 1000,
SOC__NN_CLOCK_25MHz = 25 * 1000 * 1000
} SOC__NN_CLOCK_HZ_t;
typedef enum {
@@ -79,7 +80,8 @@ typedef enum {
SOC__CPU_CLOCK_125MHz = SOC__NN_CLOCK_250MHz >> 1,
SOC__CPU_CLOCK_112MHz = SOC__NN_CLOCK_225MHz >> 1,
SOC__CPU_CLOCK_100MHz = SOC__NN_CLOCK_200MHz >> 1,
SOC__CPU_CLOCK_50MHz = SOC__NN_CLOCK_100MHz >> 1
SOC__CPU_CLOCK_50MHz = SOC__NN_CLOCK_100MHz >> 1,
SOC__CPU_CLOCK_12MHz = SOC__NN_CLOCK_25MHz >> 1
} SOC__CPU_CLOCK_HZ_t;
typedef enum {

View File

@@ -1,32 +1,35 @@
cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYBIND "Build Python binding" OFF)
option(HAILO_BUILD_EMULATOR "Build hailort for emulator" OFF)
option(HAILO_BUILD_UT "Build Unit Tests" OFF)
option(HAILO_BUILD_HW_DEBUG_TOOL "Build hw debug tool" OFF)
option(HAILO_BUILD_GSTREAMER "Compile gstreamer plugins" OFF)
option(HAILO_BUILD_EXAMPLES "Build examples" OFF)
option(HAILO_OFFLINE_COMPILATION "Don't download external dependencies" OFF)
option(HAILO_BUILD_SERVICE "Build hailort service" OFF)
option(HAILO_BUILD_PROFILER "Build hailort profiler" ON)
if(WIN32 AND ${HAILO_BUILD_SERVICE})
message(FATAL_ERROR "HailoRT service is not supported on Windows")
endif()
# Flag for emulator (FPGA/Veloce)
if(HAILO_BUILD_EMULATOR)
message(WARNING "HailoRT is building with Emulator flag on")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -DHAILO_EMULATOR)
endif()
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
add_definitions( -DFIRMWARE_VERSION_MINOR=10 )
add_definitions( -DFIRMWARE_VERSION_MINOR=12 )
add_definitions( -DFIRMWARE_VERSION_REVISION=0 )
if(HAILO_BUILD_SERVICE)
add_definitions( -DHAILO_SUPPORT_MULTI_PROCESS )
endif()
message(STATUS "Building pre_build")
include(${CMAKE_CURRENT_LIST_DIR}/cmake/execute_cmake.cmake)
set(HAILO_EXTERNAL_DIR ${CMAKE_CURRENT_LIST_DIR}/external)
set(HAILO_PRE_BUILD_BUILD_TOOLS ${CMAKE_CURRENT_LIST_DIR}/pre_build/build/tools)
set(PRE_BUILD_BUILD_TYPE "Release")
execute_cmake(
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/pre_build
BUILD_DIR ${CMAKE_CURRENT_LIST_DIR}/pre_build/build
CONFIGURE_ARGS
-DCMAKE_BUILD_TYPE=${PRE_BUILD_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_LIST_DIR}/pre_build/install
-DHAILO_EXTERNAL_DIR=${HAILO_EXTERNAL_DIR}
-DHAILO_OFFLINE_COMPILATION=${HAILO_OFFLINE_COMPILATION}
-DHAILO_BUILD_SERVICE=${HAILO_BUILD_SERVICE}
BUILD_ARGS
--config ${PRE_BUILD_BUILD_TYPE} --target install ${CMAKE_EXTRA_BUILD_ARGS}
PARALLEL_BUILD
)
# The logic of prepare_externals is executed in a sperate module so that it can be run externally (via cmake -P prepare_externals.cmake)
include(prepare_externals.cmake)
# BENCHMARK_ENABLE_TESTING can be used by other 3rd party projects, therefore we define it
# before adding projects
@@ -83,7 +86,7 @@ if(HAILO_BUILD_PYBIND)
if(NOT PYTHON_EXECUTABLE AND PYBIND11_PYTHON_VERSION)
# PYBIND11_PYTHON_VERSION is prioritized (not virtual environment) if PYTHON_EXECUTABLE is not set.
# See https://pybind11.readthedocs.io/en/stable/changelog.html#v2-6-0-oct-21-2020
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
if(${CMAKE_VERSION} VERSION_LESS "3.22.0")
find_package(PythonInterp ${PYBIND11_PYTHON_VERSION} REQUIRED)
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
else()
@@ -116,32 +119,12 @@ if(HAILO_BUILD_SERVICE)
add_subdirectory(rpc)
endif()
# microprofile
if(HAILO_MICROPROFILE)
add_library(microprofile STATIC EXCLUDE_FROM_ALL external/microprofile/microprofile.cpp)
set_target_properties(microprofile PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
POSITION_INDEPENDENT_CODE ON
)
target_compile_definitions(microprofile
PRIVATE
-DMICROPROFILE_WEBSERVER=1
-DMICROPROFILE_GPU_TIMERS=0
-DMICROPROFILE_NAME_MAX_LEN=256
PUBLIC
-DMICROPROFILE_ENABLED=1
)
target_include_directories(microprofile PUBLIC external/microprofile)
else()
add_library(microprofile INTERFACE)
target_compile_definitions(microprofile INTERFACE -DMICROPROFILE_ENABLED=0)
target_include_directories(microprofile INTERFACE external/microprofile)
endif()
add_subdirectory(common)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
if(HAILO_BUILD_HW_DEBUG_TOOL)
add_subdirectory(tools/hw_debug)
endif()
if(HAILO_BUILD_SERVICE)
add_subdirectory(hailort_service)

View File

@@ -3,7 +3,7 @@
| CLI11 | University of Cincinnati | 3-Clause BSD | 2.2.0 | Fork | https://github.com/hailo-ai/CLI11 |
| Catch2 | Catch2 Authors | BSL-1.0 | 2.13.7 | Cloned entire package | https://github.com/catchorg/Catch2 |
| protobuf | Google Inc. | BSD | 3.19.4 | Cloned entire package | https://github.com/protocolbuffers/protobuf |
| pybind11 | Wenzel Jakob | BSD | 2.6.2 | Cloned entire package | https://github.com/pybind/pybind11 |
| pybind11 | Wenzel Jakob | BSD | 2.10.1 | Cloned entire package | https://github.com/pybind/pybind11 |
| spdlog | Gabi Melman | MIT | 1.6.1 | Cloned entire package | https://github.com/gabime/spdlog |
| folly | Facebook, Inc. and its affiliates | Apache License 2.0 | v2020.08.17.00 | Copied only the file `folly/TokenBucket.h` | https://github.com/facebook/folly |
| nlohmann_json_cmake_fetchcontent | ArthurSonzogni | MIT License | v3.9.1 | Cloned entire package | https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent |
@@ -12,5 +12,4 @@
| benchmark | Google Inc. | Apache License 2.0 | 1.6.0 | Cloned entire package | https://github.com/google/benchmark.git |
| md5 | Alexander Peslyak | cut-down BSD | - | Copied code from website | http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 |
| pevents | Mahmoud Al-Qudsi | MIT License | master | Cloned entire package | https://github.com/neosmart/pevents.git |
| microprofile | Jonas Meyer | Unlicense License | 3.1 | Cloned entire package | https://github.com/jonasmr/microprofile |
| grpc | Google Inc. | Apache License 2.0 | 1.46.0 | Cloned entire package | https://github.com/grpc/grpc |

View File

@@ -4,7 +4,8 @@
**/
/**
* @file circular_buffer.hpp
* @brief
* @brief Manages a Single-Producer Single-Consumer queue. The size of the queue must be a power of 2.
* This file exports both low level C struct, and a C++ wrapper.
*
**/
@@ -77,7 +78,7 @@ public:
void push_back(const T& element)
{
// assert(CB_AVAIL(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ)));
assert(CB_AVAIL(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ)));
m_array[CB_HEAD(m_circ)] = element;
CB_ENQUEUE(m_circ, 1);
}

View File

@@ -22,6 +22,7 @@
#include <dirent.h>
#endif
namespace hailort
{
@@ -34,11 +35,35 @@ public:
static Expected<time_t> get_file_modified_time(const std::string &file_path);
static Expected<bool> is_directory(const std::string &path);
static hailo_status create_directory(const std::string &dir_path);
static Expected<std::string> get_current_dir();
static std::string get_home_directory();
static bool is_path_accesible(const std::string &path);
static bool does_file_exists(const std::string &path);
static bool has_suffix(const std::string &file_name, const std::string &suffix)
{
return (file_name.size() >= suffix.size()) && equal(suffix.rbegin(), suffix.rend(), file_name.rbegin());
}
static std::string remove_suffix(const std::string &file_name, const std::string &suffix)
{
if (!has_suffix(file_name, suffix)) {
return file_name;
}
return file_name.substr(0, file_name.length() - suffix.length());
}
// Emultes https://docs.python.org/3/library/os.path.html#os.path.basename
static std::string basename(const std::string &file_name)
{
const auto last_separator_index = file_name.find_last_of(SEPARATOR);
if (std::string::npos == last_separator_index) {
// No separator found => the file_name is a "basename"
return file_name;
}
return file_name.substr(last_separator_index + 1);
}
private:
// OS-specific filesystem directory separator char (i.e. backslash on Windows or forward slash on UNIX)
static const char *SEPARATOR;
@@ -117,6 +142,11 @@ public:
static Expected<LockedFile> create(const std::string &file_path, const std::string &mode);
~LockedFile();
LockedFile(const LockedFile &other) = delete;
LockedFile &operator=(const LockedFile &other) = delete;
LockedFile &operator=(LockedFile &&other) = delete;
LockedFile(LockedFile &&other);
int get_fd() const;
private:

View File

@@ -29,12 +29,12 @@ public:
using duration = std::chrono::nanoseconds;
using TimestampsArray = CircularArray<duration>;
explicit LatencyMeter(const std::set<uint32_t> &output_channels, size_t timestamps_list_length) :
explicit LatencyMeter(const std::set<std::string> &output_names, size_t timestamps_list_length) :
m_start_timestamps(timestamps_list_length),
m_latency_count(0),
m_latency_sum(0)
{
for (uint32_t ch : output_channels) {
for (auto &ch : output_names) {
m_end_timestamps_per_channel.emplace(ch, TimestampsArray(timestamps_list_length));
}
}
@@ -54,12 +54,12 @@ public:
* after this function is called on all channels.
* @note Assumes that only one thread per channel is calling this function.
*/
void add_end_sample(uint32_t channel_index, duration timestamp)
void add_end_sample(const std::string &stream_name, duration timestamp)
{
// Safe to access from several threads (when each pass different channel) because the map cannot
// be changed in runtime.
assert(m_end_timestamps_per_channel.find(channel_index) != m_end_timestamps_per_channel.end());
m_end_timestamps_per_channel.at(channel_index).push_back(timestamp);
assert(m_end_timestamps_per_channel.find(stream_name) != m_end_timestamps_per_channel.end());
m_end_timestamps_per_channel.at(stream_name).push_back(timestamp);
update_latency();
}
@@ -118,7 +118,7 @@ private:
std::mutex m_lock;
TimestampsArray m_start_timestamps;
std::unordered_map<uint32_t, TimestampsArray> m_end_timestamps_per_channel;
std::unordered_map<std::string, TimestampsArray> m_end_timestamps_per_channel;
size_t m_latency_count;
duration m_latency_sum;

View File

@@ -11,9 +11,11 @@
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include <iostream>
#include <errno.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <pwd.h>
namespace hailort
{
@@ -145,7 +147,12 @@ static_assert(false, "Unsupported Platform!");
Expected<bool> Filesystem::is_directory(const std::string &path)
{
struct stat path_stat{};
CHECK(0 == stat(path.c_str(), &path_stat), make_unexpected(HAILO_FILE_OPERATION_FAILURE),
auto ret_Val = stat(path.c_str(), &path_stat);
if (ret_Val != 0 && (errno == ENOENT)) {
// Directory path does not exist
return false;
}
CHECK(0 == ret_Val, make_unexpected(HAILO_FILE_OPERATION_FAILURE),
"stat() on path \"{}\" failed. errno {}", path.c_str(), errno);
return S_ISDIR(path_stat.st_mode);
@@ -158,6 +165,54 @@ hailo_status Filesystem::create_directory(const std::string &dir_path)
return HAILO_SUCCESS;
}
Expected<std::string> Filesystem::get_current_dir()
{
char cwd[PATH_MAX];
auto ret_val = getcwd(cwd, sizeof(cwd));
CHECK_AS_EXPECTED(nullptr != ret_val, HAILO_FILE_OPERATION_FAILURE, "Failed to get current directory path with errno {}", errno);
return std::string(cwd);
}
std::string Filesystem::get_home_directory()
{
const char *homedir = getenv("HOME");
if (NULL == homedir) {
homedir = getpwuid(getuid())->pw_dir;
}
#ifdef __QNX__
const std::string root_dir = "/";
std::string homedir_str = std::string(homedir);
if (homedir_str == root_dir) {
return homedir_str + "home";
}
#endif
return homedir;
}
bool Filesystem::is_path_accesible(const std::string &path)
{
auto ret = access(path.c_str(), W_OK);
if (ret == 0) {
return true;
}
else if (EACCES == errno) {
return false;
} else {
std::cerr << "Failed checking path " << path << " access permissions, errno = " << errno << std::endl;
return false;
}
}
bool Filesystem::does_file_exists(const std::string &path)
{
// From https://stackoverflow.com/a/12774387
struct stat buffer;
return (0 == stat(path.c_str(), &buffer));
}
Expected<TempFile> TempFile::create(const std::string &file_name, const std::string &file_directory)
{
if (!file_directory.empty()) {
@@ -211,12 +266,18 @@ LockedFile::LockedFile(FILE *fp, int fd) : m_fp(fp), m_fd(fd)
LockedFile::~LockedFile()
{
if (-1 == flock(m_fd, LOCK_UN)) {
LOGGER__ERROR("Failed to unlock file with errno {}", errno);
if (m_fp != nullptr) {
// The lock is released when all descriptors are closed.
// Since we use LOCK_EX, this is the only fd open and the lock will be release after d'tor.
fclose(m_fp);
}
}
LockedFile::LockedFile(LockedFile &&other) :
m_fp(std::exchange(other.m_fp, nullptr)),
m_fd(other.m_fd)
{}
int LockedFile::get_fd() const
{
return m_fd;

View File

@@ -230,7 +230,7 @@ hailo_status Socket::send_to(const uint8_t *src_buffer, size_t src_buffer_size,
} else if (EPIPE == errno) {
// When socket is aborted from another thread sendto will return errno EPIPE
LOGGER__INFO("Udp send aborted!");
return HAILO_STREAM_INTERNAL_ABORT;
return HAILO_STREAM_ABORTED_BY_USER;
} else {
LOGGER__ERROR("Udp failed to send data, errno:{}.", errno);
return HAILO_ETH_SEND_FAILURE;
@@ -272,7 +272,7 @@ hailo_status Socket::recv_from(uint8_t *dest_buffer, size_t dest_buffer_size, in
}
else if ((0 == number_of_received_bytes) && (0 != dest_buffer_size)) {
LOGGER__INFO("Udp socket was aborted");
return HAILO_STREAM_INTERNAL_ABORT;
return HAILO_STREAM_ABORTED_BY_USER;
}
if (result_src_addr_size > src_addr_size) {

View File

@@ -11,6 +11,9 @@
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include <iostream>
#include <io.h>
#include <AclAPI.h>
#include <shlwapi.h>
namespace hailort
@@ -145,4 +148,93 @@ Expected<bool> Filesystem::is_directory(const std::string &path)
return PathIsDirectoryA(path.c_str());
}
Expected<std::string> Filesystem::get_current_dir()
{
char cwd[MAX_PATH];
auto ret_val = GetCurrentDirectoryA(MAX_PATH, cwd);
CHECK_AS_EXPECTED(0 != ret_val, HAILO_FILE_OPERATION_FAILURE, "Failed to get current directory path with error: {}", WSAGetLastError());
return std::string(cwd);
}
hailo_status Filesystem::create_directory(const std::string &dir_path)
{
auto ret_val = CreateDirectory(dir_path.c_str(), nullptr);
CHECK((0 != ret_val) || (GetLastError() == ERROR_ALREADY_EXISTS), HAILO_FILE_OPERATION_FAILURE, "Failed to create directory {}", dir_path);
return HAILO_SUCCESS;
}
bool Filesystem::is_path_accesible(const std::string &path)
{
// The code is based on examples from: https://cpp.hotexamples.com/examples/-/-/AccessCheck/cpp-accesscheck-function-examples.html
bool return_val = false;
SECURITY_INFORMATION security_Info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION;
PSECURITY_DESCRIPTOR security_desc = NULL;
DWORD access_mask = GENERIC_WRITE;
GENERIC_MAPPING mapping = {0xFFFFFFFF};
mapping.GenericRead = FILE_GENERIC_READ;
mapping.GenericWrite = FILE_GENERIC_WRITE;
mapping.GenericExecute = FILE_GENERIC_EXECUTE;
mapping.GenericAll = FILE_ALL_ACCESS;
HANDLE h_token = NULL;
HANDLE h_impersonated_token = NULL;
PRIVILEGE_SET privilege_set = {0};
DWORD privilege_set_size = sizeof(privilege_set);
DWORD granted_access = 0;
BOOL access_status = FALSE;
// Retrieves a copy of the security descriptor for the path
DWORD result = GetNamedSecurityInfo(path.c_str(), SE_FILE_OBJECT, security_Info, NULL, NULL, NULL, NULL, &security_desc);
if (result != ERROR_SUCCESS) {
std::cerr << "Failed to get security information for path " << path << " with error = " << result << std::endl;
return_val = false;
goto l_exit;
}
MapGenericMask(&access_mask, &mapping);
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &h_token) == 0) {
return_val = false;
std::cerr << "OpenProcessToken() Failed. Cannot check path " << path << " access permissions, last_error = " << GetLastError() << std::endl;
goto l_release_security_desc;
}
// Getting a handle to an impersonation token. It will represent the client that is attempting to gain access.
if (DuplicateToken(h_token, SecurityImpersonation, &h_impersonated_token) == 0) {
std::cerr << "DuplicateToken() Failed. Cannot check path " << path << " access permissions, last_error = " << GetLastError() << std::endl;
return_val = false;
goto l_close_token;
}
if (AccessCheck(security_desc, h_impersonated_token, access_mask, &mapping, &privilege_set, &privilege_set_size, &granted_access, &access_status) == 0) {
std::cerr << "AccessCheck Failed. Cannot check path " << path << " access permissions, last_error = " << GetLastError() << std::endl;
return_val = false;
goto l_close_impersonated_token;
}
return_val = (access_status == TRUE);
l_close_impersonated_token:
if (NULL != h_impersonated_token) {
(void)CloseHandle(h_impersonated_token);
}
l_close_token:
if (NULL != h_token) {
(void)CloseHandle(h_token);
}
l_release_security_desc:
if (NULL != security_desc) {
(void)LocalFree(security_desc);
}
l_exit:
return return_val;
}
bool Filesystem::does_file_exists(const std::string &path)
{
// From https://stackoverflow.com/a/2112304
return ((GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES) && (GetLastError() == ERROR_FILE_NOT_FOUND));
}
} /* namespace hailort */

View File

@@ -26,8 +26,6 @@ namespace hailort
#define IS_FIT_IN_UINT8(number) ((std::numeric_limits<uint8_t>::max() >= ((int32_t)(number))) && (std::numeric_limits<uint8_t>::min() <= ((int32_t)(number))))
#define IS_FIT_IN_UINT16(number) ((std::numeric_limits<uint16_t>::max() >= ((int32_t)(number))) && (std::numeric_limits<uint16_t>::min() <= ((int32_t)(number))))
#define IS_FIT_IN_UINT16(number) ((std::numeric_limits<uint16_t>::max() >= ((int32_t)(number))) && (std::numeric_limits<uint16_t>::min() <= ((int32_t)(number))))
template <typename T>
static inline bool contains(const std::vector<T> &container, const T &value)
@@ -53,24 +51,6 @@ static inline bool contains(const std::set<T> &container, T value)
return (container.find(value) != container.end());
}
template <class T>
class unlock_guard {
public:
unlock_guard(T &lock) : m_lock(lock) {
m_lock.unlock();
}
~unlock_guard() {
m_lock.lock();
}
unlock_guard(const unlock_guard&) = delete;
unlock_guard& operator=(const unlock_guard&) = delete;
private:
T &m_lock;
};
// From https://stackoverflow.com/questions/57092289/do-stdmake-shared-and-stdmake-unique-have-a-nothrow-version
template <class T, class... Args>
static inline std::unique_ptr<T> make_unique_nothrow(Args&&... args)
@@ -250,16 +230,18 @@ _ISEMPTY( \
} while(0)
#define CHECK_AS_RPC_STATUS(cond, reply, ret_val, ...) _CHECK_AS_RPC_STATUS((cond), (reply), (ret_val), ISEMPTY(__VA_ARGS__), "" __VA_ARGS__)
#define _CHECK_GRPC_STATUS(status, ret_val) \
#define _CHECK_GRPC_STATUS(status, ret_val, warning_msg) \
do { \
if (!status.ok()) { \
LOGGER__ERROR("CHECK_GRPC_STATUS failed with error massage: {}.", status.error_message()); \
LOGGER__WARNING(warning_msg); \
return ret_val; \
} \
} while(0)
#define CHECK_GRPC_STATUS(status) _CHECK_GRPC_STATUS(status, HAILO_RPC_FAILED)
#define CHECK_GRPC_STATUS_AS_EXPECTED(status) _CHECK_GRPC_STATUS(status, make_unexpected(HAILO_RPC_FAILED))
#define SERVICE_WARNING_MSG ("Make sure HailoRT service is enabled and active!")
#define CHECK_GRPC_STATUS(status) _CHECK_GRPC_STATUS(status, HAILO_RPC_FAILED, SERVICE_WARNING_MSG)
#define CHECK_GRPC_STATUS_AS_EXPECTED(status) _CHECK_GRPC_STATUS(status, make_unexpected(HAILO_RPC_FAILED), SERVICE_WARNING_MSG)
#endif
#define _CHECK_EXPECTED(obj, is_default, fmt, ...) \

View File

@@ -6,6 +6,9 @@
#ifndef _HAILO_IOCTL_COMMON_H_
#define _HAILO_IOCTL_COMMON_H_
#define DESCRIPTORS_IN_BUFFER(buffer_size, desc_page_size) (((buffer_size) + (desc_page_size) - 1) / (desc_page_size))
// This value is not easily changeable.
// For example: the channel interrupts ioctls assume we have up to 32 channels
#define MAX_VDMA_CHANNELS_PER_ENGINE (32)
@@ -84,6 +87,11 @@ struct hailo_channel_interrupt_timestamp {
uint16_t desc_num_processed;
};
typedef struct {
uint16_t is_buffer_in_use;
uint16_t buffer_len;
} hailo_d2h_buffer_details_t;
// This struct is the same as `enum dma_data_direction` (defined in linux/dma-direction)
enum hailo_dma_data_direction {
HAILO_DMA_BIDIRECTIONAL = 0,
@@ -145,6 +153,7 @@ struct hailo_desc_list_bind_vdma_buffer_params {
uintptr_t desc_handle; // in
uint16_t desc_page_size; // in
uint8_t channel_index; // in
size_t offset; // in
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_ENABLE */
@@ -152,9 +161,6 @@ struct hailo_vdma_channel_enable_params {
uint8_t engine_index; // in
uint8_t channel_index; // in
enum hailo_dma_data_direction direction; // in
// If desc_list_handle is set to valid handle (different than INVALID_DRIVER_HANDLE_VALUE),
// the driver will start the channel with the given descriptors list.
uintptr_t desc_list_handle; // in
bool enable_timestamps_measure; // in
uint64_t channel_handle; // out
};
@@ -221,9 +227,9 @@ struct hailo_fw_control {
enum hailo_cpu_id cpu_id;
};
/* structure used in ioctl HAILO_BAR_TRANSFER */
/* structure used in ioctl HAILO_MEMORY_TRANSFER */
// Max bar transfer size gotten from ATR0_TABLE_SIZE
#define MAX_BAR_TRANSFER_LENGTH (4096)
#define MAX_MEMORY_TRANSFER_LENGTH (4096)
enum hailo_transfer_direction {
TRANSFER_READ = 0,
@@ -233,12 +239,34 @@ enum hailo_transfer_direction {
TRANSFER_MAX_ENUM = INT_MAX,
};
struct hailo_bar_transfer_params {
enum hailo_transfer_memory_type {
HAILO_TRANSFER_DEVICE_DIRECT_MEMORY,
// vDMA memories
HAILO_TRANSFER_MEMORY_VDMA0 = 0x100,
HAILO_TRANSFER_MEMORY_VDMA1,
HAILO_TRANSFER_MEMORY_VDMA2,
// PCIe driver memories
HAILO_TRANSFER_MEMORY_PCIE_BAR0 = 0x200,
HAILO_TRANSFER_MEMORY_PCIE_BAR2 = 0x202,
HAILO_TRANSFER_MEMORY_PCIE_BAR4 = 0x204,
// DRAM DMA driver memories
HAILO_TRANSFER_MEMORY_DMA_ENGINE0 = 0x300,
HAILO_TRANSFER_MEMORY_DMA_ENGINE1,
HAILO_TRANSFER_MEMORY_DMA_ENGINE2,
/** Max enum value to maintain ABI Integrity */
HAILO_TRANSFER_MEMORY_MAX_ENUM = INT_MAX,
};
struct hailo_memory_transfer_params {
enum hailo_transfer_direction transfer_direction; // in
uint32_t bar_index; // in
off_t offset; // in
enum hailo_transfer_memory_type memory_type; // in
uint64_t address; // in
size_t count; // in
uint8_t buffer[MAX_BAR_TRANSFER_LENGTH]; // in/out
uint8_t buffer[MAX_MEMORY_TRANSFER_LENGTH]; // in/out
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_READ_REGISTER */
@@ -286,10 +314,12 @@ struct hailo_d2h_notification {
};
enum hailo_board_type {
HAILO8 = 0,
HAILO_MERCURY,
HAILO_BOARD_COUNT,
HAILO_INVALID_BOARD = 0xFFFFFFFF,
HAILO_BOARD_TYPE_HAILO8 = 0,
HAILO_BOARD_TYPE_MERCURY,
HAILO_BOARD_TYPE_COUNT,
/** Max enum value to maintain ABI Integrity */
HAILO_BOARD_TYPE_MAX_ENUM = INT_MAX
};
enum hailo_dma_type {
@@ -306,6 +336,7 @@ struct hailo_device_properties {
enum hailo_allocation_mode allocation_mode;
enum hailo_dma_type dma_type;
size_t dma_engines_count;
bool is_fw_loaded;
#ifdef __QNX__
pid_t resource_manager_pid;
#endif // __QNX__
@@ -345,7 +376,7 @@ struct hailo_allocate_continuous_buffer_params {
#pragma pack(pop)
enum hailo_general_ioctl_code {
HAILO_BAR_TRANSFER_CODE,
HAILO_MEMORY_TRANSFER_CODE,
HAILO_FW_CONTROL_CODE,
HAILO_READ_NOTIFICATION_CODE,
HAILO_DISABLE_NOTIFICATION_CODE,
@@ -358,7 +389,7 @@ enum hailo_general_ioctl_code {
HAILO_GENERAL_IOCTL_MAX_NR,
};
#define HAILO_BAR_TRANSFER _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_BAR_TRANSFER_CODE, struct hailo_bar_transfer_params)
#define HAILO_MEMORY_TRANSFER _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_MEMORY_TRANSFER_CODE, struct hailo_memory_transfer_params)
#define HAILO_FW_CONTROL _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_FW_CONTROL_CODE, struct hailo_fw_control)
#define HAILO_READ_NOTIFICATION _IOW_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_READ_NOTIFICATION_CODE, struct hailo_d2h_notification)
#define HAILO_DISABLE_NOTIFICATION _IO_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_DISABLE_NOTIFICATION_CODE)
@@ -393,7 +424,7 @@ enum hailo_vdma_ioctl_code {
#define HAILO_VDMA_CHANNEL_ENABLE _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_ENABLE_CODE, struct hailo_vdma_channel_enable_params)
#define HAILO_VDMA_CHANNEL_DISABLE _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_DISABLE_CODE, struct hailo_vdma_channel_disable_params)
#define HAILO_VDMA_CHANNEL_WAIT_INT _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_WAIT_INT_CODE, struct hailo_vdma_channel_wait_params)
#define HAILO_VDMA_CHANNEL_WAIT_INT _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_WAIT_INT_CODE, struct hailo_vdma_channel_wait_params)
#define HAILO_VDMA_CHANNEL_ABORT _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_ABORT_CODE, struct hailo_vdma_channel_abort_params)
#define HAILO_VDMA_CHANNEL_CLEAR_ABORT _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_CLEAR_ABORT_CODE, struct hailo_vdma_channel_clear_abort_params)
#define HAILO_VDMA_CHANNEL_READ_REGISTER _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_READ_REGISTER_CODE, struct hailo_vdma_channel_read_register_params)

View File

@@ -102,7 +102,7 @@ struct tCompatibleHailoIoctlData
tCompatibleHailoIoctlParam Parameters;
ULONG_PTR Value;
union {
hailo_bar_transfer_params BarTransfer;
hailo_memory_transfer_params MemoryTransfer;
hailo_vdma_channel_enable_params ChannelEnable;
hailo_vdma_channel_disable_params ChannelDisable;
hailo_vdma_channel_wait_params ChannelWait;

View File

@@ -4,6 +4,7 @@ add_executable(hailort_service
hailort_rpc_service.cpp
hailort_service.cpp
service_resource_manager.hpp
${HAILORT_COMMON_CPP_SOURCES}
)
target_compile_options(hailort_service PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailort_service PROPERTY CXX_STANDARD 14)
@@ -15,17 +16,28 @@ target_link_libraries(hailort_service
target_include_directories(hailort_service
PRIVATE
${HAILORT_INC_DIR}
${HAILORT_COMMON_DIR}
${COMMON_INC_DIR}
${RPC_DIR}
)
disable_exceptions(hailort_service)
# Install systemd unit file
set(SYSTEMD_UNIT_DIR "/lib/systemd/system/")
set(SYSTEMD_UNIT_DIR "lib/systemd/system/")
if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(SYSTEMD_UNIT_DIR ${CMAKE_INSTALL_PREFIX}/${SYSTEMD_UNIT_DIR})
endif()
# Install service's environment variables file
set(ENV_VARS_FILE_DIR ${CMAKE_INSTALL_SYSCONFDIR}/default/)
set(HAILORT_SERVICE_ENV_VARS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/hailort_service)
install(
FILES "${HAILORT_SERVICE_ENV_VARS_FILE}"
DESTINATION "${ENV_VARS_FILE_DIR}"
CONFIGURATIONS Release
COMPONENT hailort_service
)
# Install systemd unit file
set(HAILORT_SERVICE_UNIT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/hailort.service)
install(
FILES "${HAILORT_SERVICE_UNIT_FILE}"
@@ -40,8 +52,15 @@ install(
CONFIGURATIONS Release
)
# Create empty directory for hailort log file
set(DAEMON_PID_DIR "/run/hailo")
add_definitions(-DHAILO_DAEMON_PID_DIR="${DAEMON_PID_DIR}")
add_definitions(-DHAILO_DAEMON_PID_FILE="${DAEMON_PID_DIR}/hailort_service.pid")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# Create empty directory for hailort log file
set(HAILORT_LOG_DIR "/var/log/hailo")
install(DIRECTORY DESTINATION ${HAILORT_LOG_DIR})
# Create empty directory for default PID file
install(DIRECTORY DESTINATION ${DAEMON_PID_DIR})
endif()

View File

@@ -4,10 +4,13 @@ Documentation=https://github.com/hailo-ai/hailort
[Service]
Type=forking
EnvironmentFile=/etc/default/hailort_service
ExecStart=/usr/local/bin/hailort_service
Restart=on-failure
RemainAfterExit=yes
Environment="HAILORT_LOGGER_PATH=/var/log/hailo"
PIDFile=/run/hailo/hailort_service.pid
ExecReload=/bin/kill -HUP $MAINPID
ExecStartPost=/bin/sleep 0.1
[Install]
WantedBy=multi-user.target

View File

@@ -65,7 +65,6 @@ grpc::Status HailoRtRpcService::VDevice_create(grpc::ServerContext *, const VDev
hailo_vdevice_params_t params = {
.device_count = params_proto.device_count(),
.device_infos = nullptr,
.device_ids = device_ids.data(),
.scheduling_algorithm = static_cast<hailo_scheduling_algorithm_e>(params_proto.scheduling_algorithm()),
.group_id = params_proto.group_id().c_str(),
@@ -180,6 +179,19 @@ grpc::Status HailoRtRpcService::VDevice_get_physical_devices_ids(grpc::ServerCon
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_get_default_streams_interface(grpc::ServerContext*,
const VDevice_get_default_streams_interface_Request* request, VDevice_get_default_streams_interface_Reply* reply)
{
auto lambda = [](std::shared_ptr<VDevice> vdevice) {
return vdevice->get_default_streams_interface();
};
auto &vdevice_manager = ServiceResourceManager<VDevice>::get_instance();
auto stream_interface = vdevice_manager.execute<Expected<hailo_stream_interface_t>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(stream_interface, reply);
reply->set_stream_interface(*stream_interface);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
{
@@ -189,6 +201,22 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_release(grpc::ServerConte
return grpc::Status::OK;
}
ProtoNamedVStreamParams get_named_params(const std::string &name, const hailo_vstream_params_t &params)
{
ProtoNamedVStreamParams named_params;
named_params.set_name(name);
auto proto_params = named_params.mutable_params();
auto proto_user_buffer_format = proto_params->mutable_user_buffer_format();
proto_user_buffer_format->set_type(params.user_buffer_format.type);
proto_user_buffer_format->set_order(params.user_buffer_format.order);
proto_user_buffer_format->set_flags(params.user_buffer_format.flags);
proto_params->set_timeout_ms(params.timeout_ms);
proto_params->set_queue_size(params.queue_size);
proto_params->set_vstream_stats_flags(params.vstream_stats_flags);
proto_params->set_pipeline_elements_stats_flags(params.pipeline_elements_stats_flags);
return named_params;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_make_input_vstream_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_input_vstream_params_Request *request,
ConfiguredNetworkGroup_make_input_vstream_params_Reply *reply)
@@ -202,20 +230,10 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_make_input_vstream_params
request->timeout_ms(), request->queue_size(), request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto params_map = reply->mutable_vstream_params_map();
auto params_map_impl = params_map->mutable_vstream_params_map();
for (auto& name_to_params : expected_params.value()) {
NamedVStreamParams named_params;
named_params.set_name(name_to_params.first);
auto params = name_to_params.second;
auto proto_params = named_params.mutable_params();
auto proto_user_buffer_format = proto_params->mutable_user_buffer_format();
proto_user_buffer_format->set_type(params.user_buffer_format.type);
proto_user_buffer_format->set_order(params.user_buffer_format.order);
proto_user_buffer_format->set_flags(params.user_buffer_format.flags);
proto_params->set_timeout_ms(params.timeout_ms);
proto_params->set_queue_size(params.queue_size);
proto_params->set_vstream_stats_flags(params.vstream_stats_flags);
proto_params->set_pipeline_elements_stats_flags(params.pipeline_elements_stats_flags);
params_map->Add(std::move(named_params));
auto named_params = get_named_params(name_to_params.first, name_to_params.second);
params_map_impl->Add(std::move(named_params));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
@@ -235,20 +253,37 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_make_output_vstream_param
request->timeout_ms(), request->queue_size(), request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto params_map = reply->mutable_vstream_params_map();
auto params_map_impl = params_map->mutable_vstream_params_map();
for (auto& name_to_params : expected_params.value()) {
NamedVStreamParams named_params;
named_params.set_name(name_to_params.first);
auto params = name_to_params.second;
auto proto_params = named_params.mutable_params();
auto proto_user_buffer_format = proto_params->mutable_user_buffer_format();
proto_user_buffer_format->set_type(params.user_buffer_format.type);
proto_user_buffer_format->set_order(params.user_buffer_format.order);
proto_user_buffer_format->set_flags(params.user_buffer_format.flags);
proto_params->set_timeout_ms(params.timeout_ms);
proto_params->set_queue_size(params.queue_size);
proto_params->set_vstream_stats_flags(params.vstream_stats_flags);
proto_params->set_pipeline_elements_stats_flags(params.pipeline_elements_stats_flags);
params_map->Add(std::move(named_params));
auto named_params = get_named_params(name_to_params.first, name_to_params.second);
params_map_impl->Add(std::move(named_params));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_make_output_vstream_params_groups(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_output_vstream_params_groups_Request *request,
ConfiguredNetworkGroup_make_output_vstream_params_groups_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, bool quantized,
hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size) {
return cng->make_output_vstream_params_groups(quantized, format_type, timeout_ms, queue_size);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_params = manager.execute<Expected<std::vector<std::map<std::string, hailo_vstream_params_t>>>>(request->handle(),
lambda, request->quantized(), static_cast<hailo_format_type_t>(request->format_type()),
request->timeout_ms(), request->queue_size());
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto params_map_vector = reply->mutable_vstream_params_groups();
for (auto &params_map : expected_params.value()) {
ProtoNamedVStreamParamsMap params_map_proto;
auto params_map_impl_proto = params_map_proto.mutable_vstream_params_map();
for (auto& name_to_params : params_map) {
auto named_params = get_named_params(name_to_params.first, name_to_params.second);
params_map_impl_proto->Add(std::move(named_params));
}
params_map_vector->Add(std::move(params_map_proto));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
@@ -282,7 +317,7 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_output_vstream_groups
auto output_vstream_groups = expected_output_vstream_groups.value();
auto groups_proto = reply->mutable_output_vstream_groups();
for (auto& group : output_vstream_groups) {
VStreamGroup group_proto;
ProtoVStreamGroup group_proto;
for (auto& name : group) {
auto vstream_group_proto = group_proto.mutable_vstream_group();
vstream_group_proto->Add(std::move(name));
@@ -293,34 +328,39 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_output_vstream_groups
return grpc::Status::OK;
}
void serialize_vstream_info(const hailo_vstream_info_t &info, ProtoVStreamInfo *info_proto)
{
info_proto->set_name(std::string(info.name));
info_proto->set_network_name(std::string(info.network_name));
info_proto->set_direction(static_cast<uint32_t>(info.direction));
auto format_proto = info_proto->mutable_format();
format_proto->set_flags(info.format.flags);
format_proto->set_order(info.format.order);
format_proto->set_type(info.format.type);
if (info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
auto nms_shape_proto = info_proto->mutable_nms_shape();
nms_shape_proto->set_number_of_classes(info.nms_shape.number_of_classes);
nms_shape_proto->set_max_bbox_per_class(info.nms_shape.max_bboxes_per_class);
} else {
auto shape_proto = info_proto->mutable_shape();
shape_proto->set_height(info.shape.height);
shape_proto->set_width(info.shape.width);
shape_proto->set_features(info.shape.features);
}
auto quant_info_proto = info_proto->mutable_quant_info();
quant_info_proto->set_qp_zp(info.quant_info.qp_zp);
quant_info_proto->set_qp_scale(info.quant_info.qp_scale);
quant_info_proto->set_limvals_min(info.quant_info.limvals_min);
quant_info_proto->set_limvals_max(info.quant_info.limvals_max);
}
void serialize_vstream_infos(ConfiguredNetworkGroup_get_vstream_infos_Reply *reply,
const std::vector<hailo_vstream_info_t> &infos)
{
auto vstream_infos_proto = reply->mutable_vstream_infos();
for (auto& info : infos) {
VStreamInfo info_proto;
info_proto.set_name(std::string(info.name));
info_proto.set_network_name(std::string(info.network_name));
info_proto.set_direction(static_cast<uint32_t>(info.direction));
auto format_proto = info_proto.mutable_format();
format_proto->set_flags(info.format.flags);
format_proto->set_order(info.format.order);
format_proto->set_type(info.format.type);
if (info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
auto nms_shape_proto = info_proto.mutable_nms_shape();
nms_shape_proto->set_number_of_classes(info.nms_shape.number_of_classes);
nms_shape_proto->set_max_bbox_per_class(info.nms_shape.max_bboxes_per_class);
} else {
auto shape_proto = info_proto.mutable_shape();
shape_proto->set_height(info.shape.height);
shape_proto->set_width(info.shape.width);
shape_proto->set_features(info.shape.features);
}
auto quant_info_proto = info_proto.mutable_quant_info();
quant_info_proto->set_qp_zp(info.quant_info.qp_zp);
quant_info_proto->set_qp_scale(info.quant_info.qp_scale);
quant_info_proto->set_limvals_min(info.quant_info.limvals_min);
quant_info_proto->set_limvals_max(info.quant_info.limvals_max);
ProtoVStreamInfo info_proto;
serialize_vstream_info(info, &info_proto);
vstream_infos_proto->Add(std::move(info_proto));
}
}
@@ -397,6 +437,42 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_scheduler_threshold(g
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_config_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_config_params_Request *request,
ConfiguredNetworkGroup_get_config_params_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->get_config_params();
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_params = net_group_manager.execute<Expected<ConfigureNetworkParams>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto net_configure_params = expected_params.value();
auto proto_network_configure_params = reply->mutable_params();
proto_network_configure_params->set_batch_size(net_configure_params.batch_size);
proto_network_configure_params->set_power_mode(net_configure_params.power_mode);
proto_network_configure_params->set_latency(net_configure_params.latency);
for (const auto &name_stream_params_pair : net_configure_params.stream_params_by_name) {
auto proto_name_streams_params = proto_network_configure_params->add_stream_params_map();
proto_name_streams_params->set_name(name_stream_params_pair.first);
auto proto_stream_params = proto_name_streams_params->mutable_params();
auto stream_params = name_stream_params_pair.second;
proto_stream_params->set_stream_interface(stream_params.stream_interface);
proto_stream_params->set_direction(stream_params.direction);
}
for (const auto &name_network_params_pair : net_configure_params.network_params_by_name) {
auto proto_name_network_params = proto_network_configure_params->add_network_params_map();
proto_name_network_params->set_name(name_network_params_pair.first);
auto proto_network_params = proto_name_network_params->mutable_params();
auto network_params = name_network_params_pair.second;
proto_network_params->set_batch_size(network_params.batch_size);
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply)
{
@@ -493,9 +569,9 @@ grpc::Status HailoRtRpcService::OutputVStream_release(grpc::ServerContext *, con
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_name(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_name_Request *request,
ConfiguredNetworkGroup_get_name_Reply *reply)
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_name(grpc::ServerContext*,
const ConfiguredNetworkGroup_name_Request *request,
ConfiguredNetworkGroup_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->name();
@@ -568,7 +644,7 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_all_stream_infos(grpc
CHECK_EXPECTED_AS_RPC_STATUS(expected_stream_infos, reply);
auto proto_stream_infos = reply->mutable_stream_infos();
for (auto& stream_info : expected_stream_infos.value()) {
StreamInfo proto_stream_info;
ProtoStreamInfo proto_stream_info;
if (stream_info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
auto proto_nms_info = proto_stream_info.mutable_nms_info();
proto_nms_info->set_number_of_classes(stream_info.nms_info.number_of_classes);
@@ -626,6 +702,20 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_latency_measurement(g
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_is_multi_context(grpc::ServerContext*,
const ConfiguredNetworkGroup_is_multi_context_Request *request,
ConfiguredNetworkGroup_is_multi_context_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->is_multi_context();
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto is_multi_context = manager.execute<bool>(request->handle(), lambda);
reply->set_is_multi_context(static_cast<bool>(is_multi_context));
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_get_frame_size(grpc::ServerContext*, const VStream_get_frame_size_Request *request,
VStream_get_frame_size_Reply *reply)
{
@@ -673,7 +763,7 @@ grpc::Status HailoRtRpcService::InputVStream_name(grpc::ServerContext*, const VS
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_name(name);
reply->set_status(HAILO_SUCCESS);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
@@ -686,7 +776,33 @@ grpc::Status HailoRtRpcService::OutputVStream_name(grpc::ServerContext*, const V
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_name(name);
reply->set_status(HAILO_SUCCESS);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_network_name(grpc::ServerContext*, const VStream_network_name_Request *request,
VStream_network_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->network_name();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_network_name(name);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_network_name(grpc::ServerContext*, const VStream_network_name_Request *request,
VStream_network_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->network_name();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_network_name(name);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
@@ -714,29 +830,91 @@ grpc::Status HailoRtRpcService::OutputVStream_abort(grpc::ServerContext*, const
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *,
VStream_resume_Reply *)
grpc::Status HailoRtRpcService::InputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *request,
VStream_resume_Reply *reply)
{
// TODO - HRT-7892
// auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
// return input_vstream->resume();
// };
// auto &manager = ServiceResourceManager<InputVStream>::get_instance();
// auto status = manager.execute<hailo_status>(request->handle(), lambda);
// reply->set_status(status);
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->resume();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto status = manager.execute<hailo_status>(request->handle(), lambda);
reply->set_status(status);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *,
VStream_resume_Reply *)
grpc::Status HailoRtRpcService::OutputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *request,
VStream_resume_Reply *reply)
{
// TODO - HRT-7892
// auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
// return output_vstream->resume();
// };
// auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
// auto status = manager.execute<hailo_status>(request->handle(), lambda);
// reply->set_status(status);
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->resume();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto status = manager.execute<hailo_status>(request->handle(), lambda);
reply->set_status(status);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_get_user_buffer_format(grpc::ServerContext*, const VStream_get_user_buffer_format_Request *request,
VStream_get_user_buffer_format_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->get_user_buffer_format();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto format = manager.execute<hailo_format_t>(request->handle(), lambda);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
auto proto_user_buffer_format = reply->mutable_user_buffer_format();
proto_user_buffer_format->set_type(format.type);
proto_user_buffer_format->set_order(format.order);
proto_user_buffer_format->set_flags(format.flags);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_get_user_buffer_format(grpc::ServerContext*, const VStream_get_user_buffer_format_Request *request,
VStream_get_user_buffer_format_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->get_user_buffer_format();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto format = manager.execute<hailo_format_t>(request->handle(), lambda);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
auto proto_user_buffer_format = reply->mutable_user_buffer_format();
proto_user_buffer_format->set_type(format.type);
proto_user_buffer_format->set_order(format.order);
proto_user_buffer_format->set_flags(format.flags);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_get_info(grpc::ServerContext*, const VStream_get_info_Request *request,
VStream_get_info_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->get_info();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto info = manager.execute<hailo_vstream_info_t>(request->handle(), lambda);
auto info_proto = reply->mutable_vstream_info();
serialize_vstream_info(info, info_proto);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_get_info(grpc::ServerContext*, const VStream_get_info_Request *request,
VStream_get_info_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->get_info();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto info = manager.execute<hailo_vstream_info_t>(request->handle(), lambda);
auto info_proto = reply->mutable_vstream_info();
serialize_vstream_info(info, info_proto);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}

View File

@@ -28,7 +28,7 @@
namespace hailort
{
class HailoRtRpcService final : public HailoRtRpc::Service {
class HailoRtRpcService final : public ProtoHailoRtRpc::Service {
public:
virtual grpc::Status client_keep_alive(grpc::ServerContext *ctx, const keepalive_Request *request,
@@ -45,6 +45,8 @@ public:
VDevice_configure_Reply* reply) override;
virtual grpc::Status VDevice_get_physical_devices_ids(grpc::ServerContext*, const VDevice_get_physical_devices_ids_Request* request,
VDevice_get_physical_devices_ids_Reply* reply) override;
virtual grpc::Status VDevice_get_default_streams_interface(grpc::ServerContext*, const VDevice_get_default_streams_interface_Request* request,
VDevice_get_default_streams_interface_Reply* reply) override;
virtual grpc::Status InputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply) override;
@@ -68,6 +70,10 @@ public:
VStream_name_Reply *reply) override;
virtual grpc::Status OutputVStream_name(grpc::ServerContext*, const VStream_name_Request *request,
VStream_name_Reply *reply) override;
virtual grpc::Status InputVStream_network_name(grpc::ServerContext*, const VStream_network_name_Request *request,
VStream_network_name_Reply *reply) override;
virtual grpc::Status OutputVStream_network_name(grpc::ServerContext*, const VStream_network_name_Request *request,
VStream_network_name_Reply *reply) override;
virtual grpc::Status InputVStream_abort(grpc::ServerContext*, const VStream_abort_Request *request,
VStream_abort_Reply *reply) override;
virtual grpc::Status OutputVStream_abort(grpc::ServerContext*, const VStream_abort_Request *request,
@@ -76,7 +82,14 @@ public:
VStream_resume_Reply *reply) override;
virtual grpc::Status OutputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *request,
VStream_resume_Reply *reply) override;
virtual grpc::Status InputVStream_get_user_buffer_format(grpc::ServerContext*, const VStream_get_user_buffer_format_Request *request,
VStream_get_user_buffer_format_Reply *reply) override;
virtual grpc::Status OutputVStream_get_user_buffer_format(grpc::ServerContext*, const VStream_get_user_buffer_format_Request *request,
VStream_get_user_buffer_format_Reply *reply) override;
virtual grpc::Status InputVStream_get_info(grpc::ServerContext*, const VStream_get_info_Request *request,
VStream_get_info_Reply *reply) override;
virtual grpc::Status OutputVStream_get_info(grpc::ServerContext*, const VStream_get_info_Request *request,
VStream_get_info_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request* request,
Release_Reply* reply) override;
virtual grpc::Status ConfiguredNetworkGroup_make_input_vstream_params(grpc::ServerContext*,
@@ -85,9 +98,12 @@ public:
virtual grpc::Status ConfiguredNetworkGroup_make_output_vstream_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_output_vstream_params_Request *request,
ConfiguredNetworkGroup_make_output_vstream_params_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_name(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_name_Request *request,
ConfiguredNetworkGroup_get_name_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_make_output_vstream_params_groups(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_output_vstream_params_groups_Request *request,
ConfiguredNetworkGroup_make_output_vstream_params_groups_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_name(grpc::ServerContext*,
const ConfiguredNetworkGroup_name_Request *request,
ConfiguredNetworkGroup_name_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_network_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_network_infos_Request *request,
ConfiguredNetworkGroup_get_network_infos_Reply *reply) override;
@@ -118,6 +134,12 @@ public:
virtual grpc::Status ConfiguredNetworkGroup_get_latency_measurement(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_latency_measurement_Request *request,
ConfiguredNetworkGroup_get_latency_measurement_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_is_multi_context(grpc::ServerContext*,
const ConfiguredNetworkGroup_is_multi_context_Request *request,
ConfiguredNetworkGroup_is_multi_context_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_config_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_config_params_Request *request,
ConfiguredNetworkGroup_get_config_params_Reply *reply) override;
};
}

View File

@@ -0,0 +1,12 @@
# This file contains HailoRT's configurable environment variables for HailoRT Service.
# The environment variables are set to their default values.
# To change an environment variable's value, follow the steps:
# 1. Change the value of the selected environemt variable in this file
# 2. Reload systemd unit files by running: `sudo systemctl daemon-reload`
# 3. Enable and start service by running: `sudo systemctl enable --now hailort.service`
[Service]
HAILORT_LOGGER_PATH="/var/log/hailo"
HAILO_DISABLE_MULTIPLEXER=0
HAILO_ENABLE_MULTI_DEVICE_SCHEDULER=0
SCHEDULER_MONITOR=0

View File

@@ -4,12 +4,11 @@
*
* @file hailort_service.cpp
* @brief main for hailort service
* TODO: move to user guide (HRT-7559)
* * To run as without daemonize the executable:
* To run as without daemonize the executable:
* 1) Compile with `./build.sh`
* 2) Run `./bin/linux.x86_64.debug/hailort_service standalone`
*
* * To run as daemon service please follow the steps:
* To run as daemon service please follow the steps:
* 1) Install the HailoRT:
* cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release -DHAILO_BUILD_SERVICE=1 && sudo cmake --build build --target install
*
@@ -26,6 +25,7 @@
#include "hailort_rpc_service.hpp"
#include "rpc/rpc_definitions.hpp"
#include "common/utils.hpp"
#include "common/filesystem.hpp"
#include "hailo/hailort_common.hpp"
#include <syslog.h>
@@ -44,6 +44,28 @@ void RunService() {
server->Wait();
}
void write_pid_to_lock_file()
{
auto status = hailort::Filesystem::create_directory(HAILO_DAEMON_PID_DIR);
if (status != HAILO_SUCCESS) {
syslog(LOG_ERR, "Cannot create directory at path, status=%i", status);
return;
}
auto locked_file = hailort::LockedFile::create(HAILO_DAEMON_PID_FILE, "wx");
if (HAILO_SUCCESS != locked_file.status()) {
syslog(LOG_ERR, "Failed to lock pid file for hailort service, status=%i", locked_file.status());
return;
}
std::string pid = std::to_string(getpid());
auto ret = write(locked_file->get_fd(), pid.c_str(), pid.size());
if (-1 == ret) {
syslog(LOG_ERR, "Failed to write pid to lock file for hailort service, errno=%i", errno);
return;
}
}
int main(int argc, char *argv[])
{
bool is_standalone = ((1 < argc) && (strcmp("standalone", argv[1]) == 0));
@@ -53,8 +75,9 @@ int main(int argc, char *argv[])
syslog(LOG_ERR, "Failed to create daemon with errno %i", errno);
exit(EXIT_FAILURE);
}
}
write_pid_to_lock_file();
}
RunService();
return 0;
}

View File

@@ -24,6 +24,12 @@ set(HAILORTCLI_CPP_FILES
parse_hef_command.cpp
graph_printer.cpp
mon_command.cpp
run2/run2_command.cpp
run2/network_runner.cpp
run2/live_printer.cpp
run2/timer_live_track.cpp
run2/network_live_track.cpp
)
if(UNIX)
@@ -61,8 +67,6 @@ target_link_libraries(hailortcli
readerwriterqueue
DotWriter
scheduler_mon_proto)
# TODO: Remove microprofile after removing pipeline.cpp from hailortcli sources
target_link_libraries(hailortcli microprofile)
if(WIN32)
target_link_libraries(hailortcli Ws2_32 Iphlpapi Shlwapi)

View File

@@ -31,6 +31,10 @@ BoardConfigReadSubcommand::BoardConfigReadSubcommand(CLI::App &parent_app) :
hailo_status BoardConfigReadSubcommand::execute_on_device(Device &device)
{
auto status = validate_specific_device_is_given();
CHECK_SUCCESS(status,
"'board-config read' command should get a specific device-id.");
auto buffer = device.read_board_config();
CHECK_EXPECTED_AS_STATUS(buffer, "Failed reading board config from device");

View File

@@ -61,3 +61,16 @@ hailo_status DeviceCommand::execute_on_devices(std::vector<std::unique_ptr<Devic
}
return status;
}
hailo_status DeviceCommand::validate_specific_device_is_given()
{
if ((1 != m_device_params.device_ids.size()) || contains(m_device_params.device_ids, std::string("*"))) {
// No specific device-id given, make sure there is only 1 device on the machine.
auto scan_res = Device::scan();
CHECK_EXPECTED_AS_STATUS(scan_res, "Failed to scan for devices");
if (1 != scan_res->size()) {
return HAILO_INVALID_OPERATION;
}
}
return HAILO_SUCCESS;
}

View File

@@ -64,11 +64,12 @@ public:
virtual hailo_status execute() override final;
protected:
hailo_device_params m_device_params;
virtual hailo_status execute_on_device(Device &device) = 0;
hailo_status execute_on_devices(std::vector<std::unique_ptr<Device>> &devices);
hailo_status validate_specific_device_is_given();
private:
hailo_device_params m_device_params;
};
#endif /* _HAILO_COMMAND_HPP_ */

View File

@@ -72,3 +72,22 @@ void CliCommon::reset_cursor(size_t lines_count)
std::cout << FORMAT_CURSOR_UP_LINE;
}
}
void CliCommon::clear_lines_down(size_t lines_count)
{
for (size_t i = 0; i < lines_count; i++) {
std::cout << FORMAT_CURSOR_DOWN_CLEAR_LINE;
}
}
bool CliCommon::is_positive_number(const std::string &s)
{
bool is_number = (!s.empty()) && (std::all_of(s.begin(), s.end(), ::isdigit));
return is_number && (0 < std::stoi(s));
}
bool CliCommon::is_non_negative_number(const std::string &s)
{
bool is_number = (!s.empty()) && (std::all_of(s.begin(), s.end(), ::isdigit));
return is_number && (0 <= std::stoi(s));
}

View File

@@ -22,6 +22,7 @@ using namespace hailort;
// http://www.climagic.org/mirrors/VT100_Escape_Codes.html
#define FORMAT_CLEAR_LINE "\033[2K\r"
#define FORMAT_CURSOR_UP_LINE "\033[F"
#define FORMAT_CURSOR_DOWN_CLEAR_LINE "\033[B\33[2K\r"
class CliCommon final
{
@@ -31,6 +32,9 @@ public:
static std::string duration_to_string(std::chrono::seconds secs);
static Expected<std::string> current_time_to_string();
static void reset_cursor(size_t number_of_lines);
static void clear_lines_down(size_t number_of_lines);
static bool is_positive_number(const std::string &s);
static bool is_non_negative_number(const std::string &s);
};
// Validators

View File

@@ -20,6 +20,7 @@
// TODO - HRT-7364 - add CPU subsystem frequency into the device extended info control
// and use it for get the timer's frequency
#define NN_CORE_TO_TIMER_FREQ_FACTOR (2)
#define MERCURY_VPU_CORE_CPU_DEFAULT_FREQ_MHZ (200)
constexpr int DownloadActionListCommand::INVALID_NUMERIC_VALUE;
@@ -40,9 +41,17 @@ hailo_status DownloadActionListCommand::execute(Device &device, const std::strin
auto curr_time = CliCommon::current_time_to_string();
CHECK_EXPECTED_AS_STATUS(curr_time);
auto chip_arch = device.get_architecture();
CHECK_EXPECTED_AS_STATUS(chip_arch);
unsigned int clock_cycle = 0;
// TODO - HRT-8046 Implement extended device info for mercury
if (HAILO_ARCH_MERCURY_VPU == chip_arch.value()) {
clock_cycle = MERCURY_VPU_CORE_CPU_DEFAULT_FREQ_MHZ;
} else {
auto extended_info = device.get_extended_device_information();
CHECK_EXPECTED_AS_STATUS(extended_info);
const auto clock_cycle = (extended_info->neural_network_core_clock_rate / NN_CORE_TO_TIMER_FREQ_FACTOR) / MHz;
clock_cycle = (extended_info->neural_network_core_clock_rate / NN_CORE_TO_TIMER_FREQ_FACTOR) / MHz;
}
ordered_json action_list_json = {
{"version", ACTION_LIST_FORMAT_VERSION()},
@@ -75,6 +84,10 @@ hailo_status DownloadActionListCommand::set_batch_to_measure(Device &device, uin
hailo_status DownloadActionListCommand::execute_on_device(Device &device)
{
auto status = validate_specific_device_is_given();
CHECK_SUCCESS(status,
"'fw-control action-list' command should get a specific device-id.");
return execute(device, m_output_file_path);
}
@@ -179,9 +192,9 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__wait_dma_idle_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__wait_dma_idle_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS_IDLE:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__wait_nms_idle_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__wait_nms_idle_data_t);
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__wait_nms_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__wait_nms_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_OUTPUT_CHANNEL_TRANSFER_DONE_INTERRUPT:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t *>(action);
@@ -192,8 +205,8 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__module_config_done_interrupt_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_APPLICATION_CHANGE_INTERRUPT:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t);
data_json = json({});
action_length_local = 0;
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t *>(action);
@@ -283,6 +296,18 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = json({});
action_length_local = 0;
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_INPUT_CHANNEL:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__open_boundary_input_channel_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__open_boundary_input_channel_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_OUTPUT_CHANNEL:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__open_boundary_output_channel_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__open_boundary_output_channel_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_NMS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__enable_nms_action_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__enable_nms_action_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT:
// Fallthrough
// Handling CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT is needed because we compile this file with -Wswitch-enum
@@ -326,24 +351,35 @@ Expected<ordered_json> DownloadActionListCommand::parse_single_action(uint32_t b
return json.release();
}
Expected<ordered_json> DownloadActionListCommand::parse_context(uint32_t action_list_base_address,
uint8_t *context_action_list, uint16_t action_list_size, uint32_t batch_counter)
Expected<ordered_json> DownloadActionListCommand::parse_context(Device &device, uint32_t network_group_id,
CONTROL_PROTOCOL__context_switch_context_type_t context_type, uint8_t context_index, const std::string &context_name)
{
uint32_t action_list_base_address = 0;
uint32_t batch_counter = 0;
auto action_list = device.download_context_action_list(network_group_id, context_type, context_index,
&action_list_base_address, &batch_counter);
CHECK_EXPECTED(action_list);
// Needs to fit in 2 bytes due to firmware limitation of action list size
CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(action_list->size()), HAILO_INTERNAL_FAILURE,
"Action list size is expected to fit in 2B. actual size is {}", action_list->size());
ordered_json context_json {
{"action_list_base_address", action_list_base_address},
{"action_list_size", action_list_size },
{"batch_counter", batch_counter}
{"action_list_size", action_list->size() },
{"batch_counter", batch_counter},
{"context_name", context_name},
};
ordered_json action_list_json;
uint16_t current_buffer_offset = 0;
while (current_buffer_offset < action_list_size) {
while (current_buffer_offset < action_list->size()) {
bool is_repeated = false;
uint8_t num_repeated = 0;
CONTEXT_SWITCH_DEFS__ACTION_TYPE_t sub_action_type = CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT;
uint32_t single_action_length = 0;
uint32_t timestamp = 0;
auto action_json = parse_single_action(action_list_base_address, context_action_list,
auto action_json = parse_single_action(action_list_base_address, action_list->data(),
current_buffer_offset, &single_action_length, &is_repeated, &num_repeated, &sub_action_type, &timestamp);
CHECK_EXPECTED(action_json);
current_buffer_offset = (uint16_t)(current_buffer_offset + single_action_length);
@@ -353,7 +389,7 @@ Expected<ordered_json> DownloadActionListCommand::parse_context(uint32_t action_
for (uint8_t index_in_repeated_block = 0; index_in_repeated_block < num_repeated; index_in_repeated_block++) {
uint32_t sub_action_length = 0;
auto repeated_action_json = parse_single_repeated_action(action_list_base_address,
context_action_list + current_buffer_offset, current_buffer_offset, &sub_action_length,
action_list->data() + current_buffer_offset, current_buffer_offset, &sub_action_length,
sub_action_type, timestamp, index_in_repeated_block);
CHECK_EXPECTED(repeated_action_json);
current_buffer_offset = (uint16_t)(current_buffer_offset + sub_action_length);
@@ -361,7 +397,7 @@ Expected<ordered_json> DownloadActionListCommand::parse_context(uint32_t action_
}
}
}
CHECK_AS_EXPECTED(current_buffer_offset == action_list_size, HAILO_INTERNAL_FAILURE,
CHECK_AS_EXPECTED(current_buffer_offset == action_list->size(), HAILO_INTERNAL_FAILURE,
"PARSING ERROR ! Reached forbidden memory space");
context_json["actions"] = action_list_json;
@@ -377,16 +413,19 @@ double DownloadActionListCommand::get_accumulator_mean_value(const AccumulatorPt
Expected<ordered_json> DownloadActionListCommand::parse_network_groups(Device &device, const ConfiguredNetworkGroupVector &network_groups)
{
const auto number_of_contexts_per_network_group = device.get_number_of_contexts_per_network_group();
CHECK_EXPECTED(number_of_contexts_per_network_group);
const auto number_of_dynamic_contexts_per_network_group = device.get_number_of_dynamic_contexts_per_network_group();
CHECK_EXPECTED(number_of_dynamic_contexts_per_network_group);
ordered_json network_group_list_json;
uint8_t global_context_index = 0;
for (uint32_t network_group_index = 0; network_group_index < number_of_contexts_per_network_group->size(); network_group_index++) {
for (uint32_t network_group_index = 0; network_group_index < number_of_dynamic_contexts_per_network_group->size(); network_group_index++) {
// TODO: HRT-8147 use the real network_group_id instead of network_group_index
const uint32_t network_group_id = network_group_index;
// TODO: network_group_name via Hef::get_network_groups_names (HRT-5997)
ordered_json network_group_json = {
{"mean_activation_time_ms", INVALID_NUMERIC_VALUE},
{"mean_deactivation_time_ms", INVALID_NUMERIC_VALUE},
{"network_group_id", network_group_id},
{"contexts", json::array()}
};
// We assume the the order of the network_groups in the ConfiguredNetworkGroupVector and in the action_list
@@ -399,25 +438,31 @@ Expected<ordered_json> DownloadActionListCommand::parse_network_groups(Device &d
network_groups[network_group_index]->get_deactivation_time_accumulator());
}
const auto num_contexts_in_network_group = number_of_contexts_per_network_group.value()[network_group_index];
for (uint8_t i = 0; i < num_contexts_in_network_group; i++) {
uint32_t batch_counter = 0;
uint32_t base_address = 0;
auto action_list = device.download_context_action_list(global_context_index, &base_address, &batch_counter);
CHECK_EXPECTED(action_list);
// Needs to fit in 2 bytes due to firmware limitation of action list size
CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(action_list->size()), HAILO_INTERNAL_FAILURE,
"Action list size is expected to fit in 2B. actual size is {}", action_list->size());
auto activation_context_json = parse_context(device, network_group_id,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_ACTIVATION, 0, "activation");
CHECK_EXPECTED(activation_context_json);
network_group_json["contexts"].emplace_back(activation_context_json.release());
auto context_json = parse_context(base_address, action_list->data(),
static_cast<uint16_t>(action_list->size()), batch_counter);
auto preliminary_context_json = parse_context(device, network_group_id,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_PRELIMINARY, 0, "preliminary");
CHECK_EXPECTED(preliminary_context_json);
network_group_json["contexts"].emplace_back(preliminary_context_json.release());
const auto dynamic_contexts_count = number_of_dynamic_contexts_per_network_group.value()[network_group_index];
for (uint8_t context_index = 0; context_index < dynamic_contexts_count; context_index++) {
auto context_json = parse_context(device, network_group_id,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_DYNAMIC, context_index,
fmt::format("dynamic_{}", context_index));
CHECK_EXPECTED(context_json);
network_group_json["contexts"].emplace_back(context_json.release());
// Device::get_number_of_contexts_per_network_group guarantees no overflow
global_context_index++;
}
auto batch_switching_context_json = parse_context(device, network_group_id,
CONTROL_PROTOCOL__CONTEXT_SWITCH_CONTEXT_TYPE_BATCH_SWITCHING, 0, "batch_switching");
CHECK_EXPECTED(batch_switching_context_json);
network_group_json["contexts"].emplace_back(batch_switching_context_json.release());
network_group_list_json.emplace_back(network_group_json);
}
@@ -567,3 +612,13 @@ void to_json(json &j, const CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t
j = json{{"h2d_engine_index", h2d_engine_index}, {"h2d_vdma_channel_index", h2d_vdma_channel_index},
{"d2h_engine_index", d2h_engine_index}, {"d2h_vdma_channel_index", d2h_vdma_channel_index}};
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__open_boundary_input_channel_data_t &data)
{
j = unpack_vdma_channel_id(data);
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__open_boundary_output_channel_data_t &data)
{
j = unpack_vdma_channel_id(data);
}

View File

@@ -56,8 +56,9 @@ private:
static Expected<ordered_json> parse_single_action(uint32_t base_address, uint8_t *context_action_list,
uint32_t current_buffer_offset, uint32_t *action_length, bool *is_repeated, uint8_t *num_repeated,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_t *sub_action_type, uint32_t *time_stamp);
static Expected<ordered_json> parse_context(uint32_t action_list_base_address, uint8_t *context_action_list,
uint16_t action_list_size, uint32_t batch_counter);
static Expected<ordered_json> parse_context(Device &device, uint32_t network_group_id,
CONTROL_PROTOCOL__context_switch_context_type_t context_type, uint8_t context_index,
const std::string &context_name);
static double get_accumulator_mean_value(const AccumulatorPtr &accumulator, double default_value = INVALID_NUMERIC_VALUE);
static Expected<ordered_json> parse_network_groups(Device &device, const ConfiguredNetworkGroupVector &network_groups);
};
@@ -93,9 +94,12 @@ static std::pair<CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, std::string> mapping[] = {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DEACTIVATE_CFG_CHANNEL, "deactivate_cfg_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_REPEATED_ACTION, "repeated_action"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_DMA_IDLE_ACTION, "wait_for_dma_idle_action"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS_IDLE, "wait_for_nms_idle"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS, "wait_for_nms_idle"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CCW_BURSTS, "fetch_ccw_bursts"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_RESET, "ddr_buffering_reset"}
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_RESET, "ddr_buffering_reset"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_INPUT_CHANNEL, "open_boundary_input_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_OPEN_BOUNDARY_OUTPUT_CHANNEL, "open_boundary_output_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_NMS, "enable_nms"},
};
static_assert(ARRAY_ENTRIES(mapping) == CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT,
"Missing a mapping from a CONTEXT_SWITCH_DEFS__ACTION_TYPE_t to it's string value");
@@ -106,10 +110,10 @@ NLOHMANN_JSON_SERIALIZE_ENUM2(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, mapping);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__repeated_action_header_t, count, last_executed, sub_action_type);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__trigger_sequencer_action_data_t, cluster_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__sequencer_interrupt_data_t, sequencer_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__wait_nms_idle_data_t, aggregator_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__wait_nms_data_t, aggregator_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__module_config_done_interrupt_data_t, module_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t, application_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t, config_stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__enable_nms_action_t, nms_unit_index, network_index);
// Non-default implementations
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t &data);
@@ -132,5 +136,7 @@ void to_json(json &j, const CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_cfg_channel_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__open_boundary_input_channel_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__open_boundary_output_channel_data_t &data);
#endif /* _HAILO_DOWNLOAD_ACTION_LIST_COMMAND_HPP_ */

View File

@@ -18,10 +18,14 @@ FwConfigReadSubcommand::FwConfigReadSubcommand(CLI::App &parent_app) :
hailo_status FwConfigReadSubcommand::execute_on_device(Device &device)
{
auto status = validate_specific_device_is_given();
CHECK_SUCCESS(status,
"'fw-config read' command should get a specific device-id.");
auto user_config_buffer = device.read_user_config();
CHECK_EXPECTED_AS_STATUS(user_config_buffer, "Failed reading user config from device");
auto status = FwConfigJsonSerializer::deserialize_config(
status = FwConfigJsonSerializer::deserialize_config(
*reinterpret_cast<USER_CONFIG_header_t*>(user_config_buffer->data()),
user_config_buffer->size(), m_output_file);
CHECK_SUCCESS(status);

View File

@@ -114,7 +114,7 @@ static std::string fw_version_string(const hailo_device_identity_t &identity)
{
std::stringstream os;
const auto fw_mode = ((identity.is_release) ? "release" : "develop");
// Currently will always return FW_BINARY_TYPE_APP_FIRMWARE as version bit is cleared in HailoRT
// TODO: Currently will always return FW_BINARY_TYPE_APP_FIRMWARE as version bit is cleared in HailoRT
FW_BINARY_TYPE_t fw_binary_type = FIRMWARE_HEADER_UTILS__get_fw_binary_type(identity.fw_version.revision);
auto fw_type = "invalid";
if (FW_BINARY_TYPE_CORE_FIRMWARE == fw_binary_type) {
@@ -123,7 +123,11 @@ static std::string fw_version_string(const hailo_device_identity_t &identity)
fw_type = "app";
}
os << identity.fw_version.major << "." << identity.fw_version.minor << "."
<< identity.fw_version.revision << " (" << fw_mode << "," << fw_type << ")";
<< identity.fw_version.revision << " (" << fw_mode << "," << fw_type;
if (identity.extended_context_switch_buffer) {
os << ",extended context switch buffer";
}
os << ")";
return os.str();
}

View File

@@ -49,8 +49,11 @@ hailo_status write_logs_to_file(Device &device, std::ofstream &ofs, hailo_cpu_id
hailo_status FwLoggerCommand::execute_on_device(Device &device)
{
auto status = validate_specific_device_is_given();
CHECK_SUCCESS(status,
"'fw-logger' command should get a specific device-id");
auto ofs_flags = std::ios::out | std::ios::binary;
hailo_status status = HAILO_UNINITIALIZED;
if (!m_should_overwrite){
ofs_flags |= std::ios::app;

View File

@@ -8,6 +8,7 @@
*
* HailoRT command line interface.
**/
#include "run2/run2_command.hpp"
#include "hailortcli.hpp"
#include "scan_command.hpp"
#include "power_measurement_command.hpp"
@@ -96,9 +97,9 @@ void add_vdevice_options(CLI::App *app, hailo_vdevice_params &vdevice_params)
auto group = app->add_option_group("VDevice Options");
auto device_count_option = group->add_option("--device-count", vdevice_params.device_count, "VDevice device count")
->check(CLI::PositiveNumber);
auto multi_process_option = group->add_flag("--multi-process-service", vdevice_params.multi_process_service,
group->add_flag("--multi-process-service", vdevice_params.multi_process_service,
"VDevice multi process service");
group->add_option("--group-id", vdevice_params.group_id, "VDevice group id")->needs(multi_process_option);
group->add_option("--group-id", vdevice_params.group_id, "VDevice group id");
group->parse_complete_callback([&vdevice_params, device_count_option](){
if (vdevice_params.device_params.device_ids.size() > 0) {
// Check either device_count or device_id
@@ -136,13 +137,6 @@ void add_device_options(CLI::App *app, hailo_device_params &device_params, bool
auto *ip_option = group->add_option("--ip", device_params.device_ids, "IP address of the target")
->check(CLI::ValidIPV4);
auto *device_type_option = group->add_option("-d,--device-type,--target", "ignored.");
std::vector<DeprecationActionPtr> actions{
std::make_shared<OptionDeprecation>(device_type_option),
};
hailo_deprecate_options(app, actions, false);
group->parse_complete_callback([&device_params, device_id_option, pcie_bdf_option, ip_option, support_asterisk]()
{
// Check that only one device id param is given
@@ -190,18 +184,10 @@ class HailoRTCLI : public ContainerCommand {
public:
HailoRTCLI(CLI::App *app) : ContainerCommand(app)
{
m_app->add_flag_callback("-v,--version",
[] () {
std::cout << "HailoRT-CLI version " <<
HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << std::endl;
// throw CLI::Success to stop parsing and not failing require_subcommand(1) we set earlier
throw (CLI::Success{});
},
"Print program version and exit"
);
m_app->set_version_flag("-v,--version", fmt::format("HailoRT-CLI version {}.{}.{}", HAILORT_MAJOR_VERSION, HAILORT_MINOR_VERSION, HAILORT_REVISION_VERSION));
add_subcommand<RunCommand>();
add_subcommand<Run2Command>();
add_subcommand<ScanSubcommand>();
add_subcommand<BenchmarkCommand>();
add_subcommand<PowerMeasurementSubcommand>();

View File

@@ -13,6 +13,9 @@
#include "common/filesystem.hpp"
#include <iostream>
#if defined(__GNUC__)
#include <sys/ioctl.h>
#endif
namespace hailort
{
@@ -20,8 +23,11 @@ namespace hailort
// TODO: Deal with longer networks names - should use HAILO_MAX_NETWORK_NAME_SIZE but its too long for one line
constexpr size_t NETWORK_NAME_WIDTH = 40;
constexpr size_t STREAM_NAME_WIDTH = 60;
constexpr size_t ACTIVE_TIME_WIDTH = 25;
constexpr size_t NUMBER_WIDTH = 15;
constexpr size_t TERMINAL_DEFAULT_WIDTH = 80;
constexpr size_t LINE_LENGTH = 125;
constexpr std::chrono::milliseconds EPSILON_TIME(500);
MonCommand::MonCommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("monitor", "Monitor of networks - Presents information about the running networks. " \
@@ -43,7 +49,7 @@ size_t MonCommand::print_networks_info_header()
std::cout <<
std::setw(NETWORK_NAME_WIDTH) << std::left << "Network" <<
std::setw(NUMBER_WIDTH) << std::left << "FPS" <<
std::setw(NUMBER_WIDTH) << std::left << "Core%" <<
std::setw(ACTIVE_TIME_WIDTH) << std::left << "Active Time (%) " <<
std::setw(NUMBER_WIDTH) << std::left << "PID" <<
"\n" << std::left << std::string(LINE_LENGTH, '-') << "\n";
static const uint32_t header_lines_count = 2;
@@ -53,17 +59,21 @@ size_t MonCommand::print_networks_info_header()
size_t MonCommand::print_networks_info_table(const ProtoMon &mon_message)
{
const uint32_t NUMBER_OBJECTS_COUNT = 3;
auto data_line_len = (NUMBER_WIDTH * NUMBER_OBJECTS_COUNT) + NETWORK_NAME_WIDTH;
auto rest_line_len = LINE_LENGTH - data_line_len;
const std::string &pid = mon_message.pid();
for (auto net_info : mon_message.networks_infos()) {
auto &net_name = net_info.network_name();
auto fps = net_info.fps();
auto core = net_info.core_utilization();
auto active_time = net_info.active_time();
std::cout << std::setprecision(1) << std::fixed <<
std::setw(NETWORK_NAME_WIDTH) << std::left << net_name <<
std::setw(NUMBER_WIDTH) << std::left << fps <<
std::setw(NUMBER_WIDTH) << std::left << core <<
std::setw(NUMBER_WIDTH) << std::left << pid << "\n";
std::setw(ACTIVE_TIME_WIDTH) << std::left << active_time <<
std::setw(NUMBER_WIDTH) << std::left << pid << std::string(rest_line_len, ' ') << "\n";
}
return mon_message.networks_infos().size();
@@ -110,50 +120,93 @@ size_t MonCommand::print_frames_table(const ProtoMon &mon_message)
}
#if defined(__GNUC__)
hailo_status MonCommand::print_table()
Expected<uint16_t> get_terminal_line_width()
{
while (true) {
auto epsilon = std::chrono::milliseconds(500);
std::chrono::milliseconds time_interval = DEFAULT_SCHEDULER_MON_INTERVAL + epsilon;
auto scheduler_mon_files = Filesystem::get_latest_files_in_dir_flat(SCHEDULER_MON_TMP_DIR, time_interval);
if (HAILO_SUCCESS != scheduler_mon_files.status() || scheduler_mon_files->empty()) {
LOGGER__WARNING("Getting scheduler monitor files failed. Please check the application is running and environment variable '{}' is set to 1.",
SCHEDULER_MON_ENV_VAR);
return HAILO_NOT_FOUND;
struct winsize w;
int ret = ioctl(0, TIOCGWINSZ, &w);
if (ret != 0) {
LOGGER__DEBUG("Failed to get_terminal_line_width, with errno: {}, using default value: {}", errno);
return TERMINAL_DEFAULT_WIDTH;
}
uint16_t terminal_line_width = w.ws_col;
return terminal_line_width;
}
hailo_status MonCommand::print_table()
{
std::chrono::milliseconds time_interval = DEFAULT_SCHEDULER_MON_INTERVAL + EPSILON_TIME;
auto terminal_line_width_expected = get_terminal_line_width();
CHECK_EXPECTED_AS_STATUS(terminal_line_width_expected);
auto terminal_line_width = terminal_line_width_expected.release();
size_t last_run_total_lines_count = 0;
bool data_was_printed = false;
while (true) {
size_t total_lines_count = 0;
bool print_warning_msg = true; // Will change to false only if mon directory is valid and there are updated files in it.
auto mon_dir_valid = Filesystem::is_directory(SCHEDULER_MON_TMP_DIR);
CHECK_EXPECTED_AS_STATUS(mon_dir_valid);
std::vector<ProtoMon> mon_messages;
if (mon_dir_valid.value()) {
auto scheduler_mon_files = Filesystem::get_latest_files_in_dir_flat(SCHEDULER_MON_TMP_DIR, time_interval);
CHECK_EXPECTED_AS_STATUS(scheduler_mon_files);
print_warning_msg = scheduler_mon_files->empty();
mon_messages.reserve(scheduler_mon_files->size());
for (const auto &mon_file : scheduler_mon_files.value()) {
auto file = LockedFile::create(mon_file, "r");
if (HAILO_SUCCESS != file.status()) {
LOGGER__ERROR("Failed to open and lock file {}, with status: {}", mon_file, file.status());
total_lines_count++;
continue;
}
ProtoMon mon_message;
if (!mon_message.ParseFromFileDescriptor(file->get_fd())) {
LOGGER__WARNING("Failed to ParseFromFileDescriptor monitor file {} with errno {}", mon_file, errno);
total_lines_count++;
continue;
}
mon_messages.emplace_back(std::move(mon_message));
}
}
size_t total_lines_count = print_networks_info_header();
total_lines_count += print_networks_info_header();
for (auto &mon_message : mon_messages) {
total_lines_count += print_networks_info_table(mon_message);
}
std::cout << "\n\n";
std::cout << std::string(terminal_line_width, ' ') << "\n";
std::cout << std::string(terminal_line_width, ' ') << "\n";
total_lines_count += 2;
total_lines_count += print_frames_header();
for (auto &mon_message : mon_messages) {
total_lines_count += print_frames_table(mon_message);
}
CliCommon::reset_cursor(total_lines_count);
if (print_warning_msg) {
std::cout << "Monitor did not retrieve any files. This occurs when there is no application currently running. If this is not the case, verify that environment variable '" <<
SCHEDULER_MON_ENV_VAR << "' is set to 1.\n";
total_lines_count++;
if (data_was_printed) {
auto lines_to_clear = last_run_total_lines_count - total_lines_count;
CliCommon::clear_lines_down(lines_to_clear);
total_lines_count += lines_to_clear;
data_was_printed = false;
}
}
else {
data_was_printed = true;
last_run_total_lines_count = total_lines_count;
}
CliCommon::reset_cursor(total_lines_count);
std::this_thread::sleep_for(DEFAULT_SCHEDULER_MON_INTERVAL);
}

View File

@@ -0,0 +1,69 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file live_printer.cpp
* @brief Live printer
**/
#include "live_printer.hpp"
#include "../common.hpp"
#include <sstream>
#include <iostream>
using namespace hailort;
LivePrinter::LivePrinter(std::chrono::milliseconds interval) :
m_interval(interval),
m_stop_event(Event::create_shared(Event::State::not_signalled)),
m_tracks(),
m_mutex()
{
}
LivePrinter::~LivePrinter()
{
(void)m_stop_event->signal();
if (m_thread.joinable()) {
m_thread.join();
}
print(false);
}
void LivePrinter::add(std::shared_ptr<Track> track)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_tracks.emplace_back(track);
}
void LivePrinter::print(bool reset)
{
std::stringstream ss;
uint32_t count = 0;
{
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &track : m_tracks) {
count += track->get_text(ss);
}
}
std::cout << ss.str() << std::flush;
if (reset) {
CliCommon::reset_cursor(count);
//TODO: what aout leftovers from prev line?
}
}
void LivePrinter::start()
{
m_thread = std::thread([this] () {
while (true) {
print(true);
auto status = m_stop_event->wait(m_interval);
if (HAILO_TIMEOUT != status) {
break;
}
}
});
}

View File

@@ -0,0 +1,43 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file live_printer.hpp
* @brief Live printer
**/
#ifndef _HAILO_HAILORTCLI_RUN2_LIVE_PRINTER_HPP_
#define _HAILO_HAILORTCLI_RUN2_LIVE_PRINTER_HPP_
#include "hailo/event.hpp"
#include <stdint.h>
#include <chrono>
#include <mutex>
#include <thread>
#include <atomic>
class LivePrinter final
{
public:
class Track
{
public:
virtual uint32_t get_text(std::stringstream &ss) = 0;
};
LivePrinter(std::chrono::milliseconds interval);
~LivePrinter();
void add(std::shared_ptr<Track> track);
void print(bool reset);
void start();
private:
std::chrono::milliseconds m_interval;
hailort::EventPtr m_stop_event;
std::vector<std::shared_ptr<Track>> m_tracks;
std::thread m_thread;
std::mutex m_mutex;
};
#endif /* _HAILO_HAILORTCLI_RUN2_LIVE_PRINTER_HPP_ */

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file network_live_track.cpp
* @brief Network live track
**/
#include "network_live_track.hpp"
#include <spdlog/fmt/fmt.h>
#include <sstream>
NetworkLiveTrack::NetworkLiveTrack(const std::string &name) :
m_name(name), m_count(0), m_last_get_time(std::chrono::steady_clock::now())
{
}
uint32_t NetworkLiveTrack::get_text(std::stringstream &ss)
{
auto elapsed_time = std::chrono::steady_clock::now() - m_last_get_time;
auto count = m_count.load();
auto fps = count / std::chrono::duration<double>(elapsed_time).count();
ss << fmt::format("{} - fps: {:.2f}\n", m_name, fps);
return 1;
}
void NetworkLiveTrack::progress()
{
m_count++;
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file network_live_track.hpp
* @brief Network live track
**/
#include "live_printer.hpp"
#ifndef _HAILO_HAILORTCLI_RUN2_NETWORK_LIVE_TRACK_HPP_
#define _HAILO_HAILORTCLI_RUN2_NETWORK_LIVE_TRACK_HPP_
class NetworkLiveTrack : public LivePrinter::Track
{
public:
NetworkLiveTrack(const std::string &name);
virtual ~NetworkLiveTrack() = default;
uint32_t get_text(std::stringstream &ss);
void progress();
private:
std::string m_name;
std::atomic<uint32_t> m_count;
std::chrono::time_point<std::chrono::steady_clock> m_last_get_time;
};
#endif /* _HAILO_HAILORTCLI_RUN2_NETWORK_LIVE_TRACK_HPP_ */

View File

@@ -0,0 +1,197 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file network_runner.cpp
* @brief Run network on hailo device
**/
#include "network_runner.hpp"
#include "common/async_thread.hpp"
#include "hailort_defaults.hpp" //TODO: not API
using namespace hailort;
//TODO: duplicated
static hailo_status wait_for_threads(std::vector<AsyncThreadPtr<hailo_status>> &threads)
{
auto last_error_status = HAILO_SUCCESS;
for (auto &thread : threads) {
auto thread_status = thread->get();
if ((HAILO_SUCCESS != thread_status) && (HAILO_STREAM_ABORTED_BY_USER != thread_status)) {
last_error_status = thread_status;
LOGGER__ERROR("Thread failed with with status {}", thread_status);
}
}
return last_error_status;
}
VStreamParams::VStreamParams() : name(), params(HailoRTDefaults::get_vstreams_params())
{
}
NetworkRunner::NetworkRunner(const NetworkParams &params, const std::string &name,
std::vector<InputVStream> &&input_vstreams, std::vector<OutputVStream> &&output_vstreams)
: m_params(params), m_name(name), m_input_vstreams(std::move(input_vstreams)),
m_output_vstreams(std::move(output_vstreams))
{
}
Expected<std::shared_ptr<NetworkRunner>> NetworkRunner::create_shared(VDevice &vdevice, const NetworkParams &params)
{
auto hef = Hef::create(params.hef_path);
CHECK_EXPECTED(hef);
// Get NG's name if single
auto net_group_name = params.net_group_name;
if (net_group_name.empty()) {
auto net_groups_names = hef->get_network_groups_names();
CHECK_AS_EXPECTED(net_groups_names.size() == 1, HAILO_INVALID_ARGUMENT, "HEF {} doesn't contain a single NetworkGroup. Pass --name", params.hef_path);
net_group_name = net_groups_names[0];
}
auto interface = vdevice.get_default_streams_interface();
CHECK_EXPECTED(interface, "Failed to get default streams interface");
auto cfg_params = hef->create_configure_params(*interface, net_group_name);
CHECK_EXPECTED(cfg_params);
cfg_params->batch_size = params.batch_size;
auto cfgr_net_groups = vdevice.configure(hef.value(), {{net_group_name, cfg_params.value()}});
CHECK_EXPECTED(cfgr_net_groups);
assert(1 == cfgr_net_groups->size());
auto cfgr_net_group = cfgr_net_groups.value()[0];
CHECK_SUCCESS_AS_EXPECTED(cfgr_net_group->set_scheduler_threshold(params.scheduler_threshold));
CHECK_SUCCESS_AS_EXPECTED(cfgr_net_group->set_scheduler_timeout(std::chrono::milliseconds(params.scheduler_timeout_ms)));
std::map<std::string, hailo_vstream_params_t> vstreams_params;
for (auto &vstream_params : params.vstream_params) {
vstreams_params.emplace(vstream_params.name, vstream_params.params);
}
auto vstreams = create_vstreams(*cfgr_net_group, vstreams_params);
CHECK_EXPECTED(vstreams);
auto net_runner = make_shared_nothrow<NetworkRunner>(params, net_group_name, std::move(vstreams->first), std::move(vstreams->second));
CHECK_NOT_NULL_AS_EXPECTED(net_runner, HAILO_OUT_OF_HOST_MEMORY);
return net_runner;
}
hailo_status NetworkRunner::run_input_vstream(InputVStream &vstream)
{
auto dataset = Buffer::create(vstream.get_frame_size(), 0xAB);
CHECK_EXPECTED_AS_STATUS(dataset);
auto last_write_time = std::chrono::steady_clock::now();
auto framerate_interval = std::chrono::duration<double>(1) / m_params.framerate;
while(true) {
auto status = vstream.write(MemoryView(dataset.value()));
if (status == HAILO_STREAM_ABORTED_BY_USER) {
return status;
}
CHECK_SUCCESS(status);
if (m_params.framerate != UNLIMITED_FRAMERATE) {
auto elapsed_time = std::chrono::steady_clock::now() - last_write_time;
std::this_thread::sleep_for(framerate_interval - elapsed_time);
last_write_time = std::chrono::steady_clock::now();
}
}
return HAILO_SUCCESS;
}
hailo_status NetworkRunner::run_output_vstream(OutputVStream &vstream, bool first, std::shared_ptr<NetworkLiveTrack> net_live_track)
{
auto result = Buffer::create(vstream.get_frame_size());
CHECK_EXPECTED_AS_STATUS(result);
while(true) {
auto status = vstream.read(MemoryView(result.value()));
if (status == HAILO_STREAM_ABORTED_BY_USER) {
return status;
}
CHECK_SUCCESS(status);
if (first) {
net_live_track->progress();
}
}
return HAILO_SUCCESS;
}
hailo_status NetworkRunner::run(Event &shutdown_event, LivePrinter &live_printer)
{
std::vector<AsyncThreadPtr<hailo_status>> threads;
for (auto &input_vstream : m_input_vstreams) {
threads.emplace_back(std::make_unique<AsyncThread<hailo_status>>([this, &input_vstream](){
return run_input_vstream(input_vstream);
}));
}
auto net_live_track = std::make_shared<NetworkLiveTrack>(m_name);
live_printer.add(net_live_track);//support progress over multiple outputs
bool first = true;//TODO: check with multiple outputs
for (auto &output_vstream : m_output_vstreams) {
threads.emplace_back(std::make_unique<AsyncThread<hailo_status>>([&output_vstream, first, net_live_track](){
return run_output_vstream(output_vstream, first, net_live_track);
}));
first = false;
}
//TODO: signal a barrier that we should start infer and timer. return threads and move stop outside?
CHECK_SUCCESS(shutdown_event.wait(HAILO_INFINITE_TIMEOUT));
stop();
return wait_for_threads(threads);
}
void NetworkRunner::stop()
{
for (auto &input_vstream : m_input_vstreams) {
(void) input_vstream.abort();
}
for (auto &output_vstream : m_output_vstreams) {
(void) output_vstream.abort();
}
}
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> NetworkRunner::create_vstreams(
ConfiguredNetworkGroup &net_group, const std::map<std::string, hailo_vstream_params_t> &params)
{//TODO: support network name
size_t match_count = 0;
std::map<std::string, hailo_vstream_params_t> input_vstreams_params;
auto input_vstreams_info = net_group.get_input_vstream_infos();
CHECK_EXPECTED(input_vstreams_info);
for (auto &input_vstream_info : input_vstreams_info.value()) {
auto elem_it = params.find(input_vstream_info.name);
if (elem_it != params.end()) {
input_vstreams_params.emplace(input_vstream_info.name, elem_it->second);
match_count++;
}
else {
input_vstreams_params.emplace(input_vstream_info.name, HailoRTDefaults::get_vstreams_params());
}
}
std::map<std::string, hailo_vstream_params_t> output_vstreams_params;
auto output_vstreams_info = net_group.get_output_vstream_infos();
CHECK_EXPECTED(output_vstreams_info);
for (auto &output_vstream_info : output_vstreams_info.value()) {
auto elem_it = params.find(output_vstream_info.name);
if (elem_it != params.end()) {
output_vstreams_params.emplace(output_vstream_info.name, elem_it->second);
match_count++;
}
else {
output_vstreams_params.emplace(output_vstream_info.name, HailoRTDefaults::get_vstreams_params());
}
}
CHECK(match_count == params.size(), make_unexpected(HAILO_INVALID_ARGUMENT), "One of the params has an invalid vStream name");
auto input_vstreams = VStreamsBuilder::create_input_vstreams(net_group, input_vstreams_params);
CHECK_EXPECTED(input_vstreams);
auto output_vstreams = VStreamsBuilder::create_output_vstreams(net_group, output_vstreams_params);
CHECK_EXPECTED(output_vstreams);
return {{input_vstreams.release(), output_vstreams.release()}};//TODO: move? copy elision?
}

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file network_runner.hpp
* @brief Run network on hailo device
**/
#ifndef _HAILO_HAILORTCLI_RUN2_NETWORK_RUNNER_HPP_
#define _HAILO_HAILORTCLI_RUN2_NETWORK_RUNNER_HPP_
#include "hailo/vdevice.hpp"
#include "hailo/vstream.hpp"
#include "hailo/event.hpp"
#include "hailo/network_group.hpp"
#include "hailo/expected.hpp"
#include "live_printer.hpp"
#include "network_live_track.hpp"
#include <string>
#include <vector>
constexpr uint32_t UNLIMITED_FRAMERATE = 0;
struct VStreamParams
{
VStreamParams();
std::string name;
hailo_vstream_params_t params;
};
struct NetworkParams
{
std::string hef_path;
std::string net_group_name;
std::vector<VStreamParams> vstream_params;
// Network parameters
uint16_t batch_size;
uint32_t scheduler_threshold;
uint32_t scheduler_timeout_ms;
// Run parameters
uint32_t framerate;
};
class NetworkRunner
{
public:
NetworkRunner(const NetworkParams &params, const std::string &name,
std::vector<hailort::InputVStream> &&input_vstreams, std::vector<hailort::OutputVStream> &&output_vstreams);
static hailort::Expected<std::shared_ptr<NetworkRunner>> create_shared(hailort::VDevice &vdevice, const NetworkParams &params);
hailo_status run(hailort::Event &shutdown_event, LivePrinter &live_printer);
void stop();
private:
static hailort::Expected<std::pair<std::vector<hailort::InputVStream>, std::vector<hailort::OutputVStream>>> create_vstreams(
hailort::ConfiguredNetworkGroup &net_group, const std::map<std::string, hailo_vstream_params_t> &params);
hailo_status run_input_vstream(hailort::InputVStream &vstream);
static hailo_status run_output_vstream(hailort::OutputVStream &vstream, bool first, std::shared_ptr<NetworkLiveTrack> net_live_track);
const NetworkParams &m_params;//TODO: copy instead of ref?
std::string m_name;
std::vector<hailort::InputVStream> m_input_vstreams;
std::vector<hailort::OutputVStream> m_output_vstreams;
};
#endif /* _HAILO_HAILORTCLI_RUN2_NETWORK_RUNNER_HPP_ */

View File

@@ -0,0 +1,348 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file run2_command.cpp
* @brief Run inference on hailo device
**/
#include "run2_command.hpp"
#include "live_printer.hpp"
#include "timer_live_track.hpp"
#include "network_runner.hpp"
#include "common/async_thread.hpp"
#include "hailo/vdevice.hpp"
#include "hailo/hef.hpp"
#include <memory>
#include <vector>
using namespace hailort;
constexpr uint32_t DEFAULT_TIME_TO_RUN_SECONDS = 5;
/** VStreamNameValidator */
class VStreamNameValidator : public CLI::Validator {
public:
VStreamNameValidator(const CLI::Option *hef_path_option, const CLI::Option *net_group_name_option);
private:
static std::vector<std::string> get_values(const std::string &hef_path, const std::string &net_group_name);
};
VStreamNameValidator::VStreamNameValidator(const CLI::Option *hef_path_option, const CLI::Option *net_group_name_option) : Validator("VSTREAM") {
func_ = [](std::string&) {
//TODO: support?
return std::string();
};
autocomplete_func_ = [hef_path_option, net_group_name_option](const std::string&) {
// TODO: remove existing names from prev user input
return get_values(hef_path_option->as<std::string>(), net_group_name_option->as<std::string>());
};
}
std::vector<std::string> VStreamNameValidator::get_values(const std::string &hef_path, const std::string &net_group_name)
{
auto hef = Hef::create(hef_path);
if (!hef.has_value()) {
return {};
}
// TODO: duplicate
auto actual_net_group_name = net_group_name;
if (actual_net_group_name.empty()) {
auto net_groups_names = hef->get_network_groups_names();
if (net_groups_names.size() != 1) {
return {};
}
actual_net_group_name = net_groups_names[0];
}
auto vstreams_info = hef->get_all_vstream_infos(actual_net_group_name);
if (!vstreams_info.has_value()) {
return {};
}
std::vector<std::string> names;
for (auto &vstream_info : vstreams_info.value()) {
names.emplace_back(vstream_info.name);
}
return names;
}
/** VStreamApp */
class VStreamApp : public CLI::App
{
public:
VStreamApp(const std::string &description, const std::string &name, CLI::Option *hef_path_option, CLI::Option *net_group_name_option);
const VStreamParams& get_params();
private:
CLI::Option* add_flag_callback(CLI::App *app, const std::string &name, const std::string &description,
std::function<void(bool)> function);
VStreamParams m_params;
};
VStreamApp::VStreamApp(const std::string &description, const std::string &name, CLI::Option *hef_path_option,
CLI::Option *net_group_name_option) : CLI::App(description, name), m_params()
{
add_option("name", m_params.name, "vStream name")
->check(VStreamNameValidator(hef_path_option, net_group_name_option));
auto format_opt_group = add_option_group("Format");
format_opt_group->add_option("--type", m_params.params.user_buffer_format.type, "Format type")
->transform(HailoCheckedTransformer<hailo_format_type_t>({
{ "auto", HAILO_FORMAT_TYPE_AUTO },
{ "uint8", HAILO_FORMAT_TYPE_UINT8 },
{ "uint16", HAILO_FORMAT_TYPE_UINT16 },
{ "float32", HAILO_FORMAT_TYPE_FLOAT32 }
}))
->default_val("auto");
format_opt_group->add_option("--order", m_params.params.user_buffer_format.order, "Format order")
->transform(HailoCheckedTransformer<hailo_format_order_t>({
{ "auto", HAILO_FORMAT_ORDER_AUTO },
{ "nhwc", HAILO_FORMAT_ORDER_NHWC },
{ "nhcw",HAILO_FORMAT_ORDER_NHCW },
{ "fcr", HAILO_FORMAT_ORDER_FCR },
{ "f8cr", HAILO_FORMAT_ORDER_F8CR },
{ "nhw", HAILO_FORMAT_ORDER_NHW },
{ "nc", HAILO_FORMAT_ORDER_NC },
{ "bayer_rgb", HAILO_FORMAT_ORDER_BAYER_RGB },
{ "12_bit_bayer_rgb", HAILO_FORMAT_ORDER_12_BIT_BAYER_RGB },
{ "hailo_nms", HAILO_FORMAT_ORDER_HAILO_NMS },
{ "nchw", HAILO_FORMAT_ORDER_NCHW },
{ "yuy2", HAILO_FORMAT_ORDER_YUY2 },
{ "nv12", HAILO_FORMAT_ORDER_NV12 },
{ "nv21", HAILO_FORMAT_ORDER_NV21 }
}))
->default_val("auto");
add_flag_callback(format_opt_group, "-q,--quantized,!--no-quantized", "Whether or not data is quantized",
[this](bool result){
m_params.params.user_buffer_format.flags = result ?
m_params.params.user_buffer_format.flags | HAILO_FORMAT_FLAGS_QUANTIZED :
static_cast<hailo_format_flags_t>(m_params.params.user_buffer_format.flags & (~HAILO_FORMAT_FLAGS_QUANTIZED));})
->run_callback_for_default()
->default_val(true); // default_val() must be after run_callback_for_default()
}
const VStreamParams& VStreamApp::get_params()
{
//TODO: instead of copy do a move + call reset()? change func name to move_params? same for NetworkParams/NetworkApp class
return m_params;
}
CLI::Option* VStreamApp::add_flag_callback(CLI::App *app, const std::string &name, const std::string &description,
std::function<void(bool)> function)
{
// get_option doesn't support multiple names so taking the first one
auto first_name = name.substr(0, name.find(','));
auto wrap_function = [app, function, first_name](std::int64_t){function(app->get_option(first_name)->as<bool>());};
return app->add_flag_function(name, wrap_function, description);
}
/** NetworkGroupNameValidator */
class NetworkGroupNameValidator : public CLI::Validator {
public:
NetworkGroupNameValidator(const CLI::Option *hef_path_option);
};
NetworkGroupNameValidator::NetworkGroupNameValidator(const CLI::Option *hef_path_option) : Validator("NETWORK_GROUP") {
func_ = [](std::string&) {
//TODO: support?
return std::string();
};
autocomplete_func_ = [hef_path_option](const std::string&) -> std::vector<std::string>{
auto hef = Hef::create(hef_path_option->as<std::string>());
if (!hef.has_value()) {
return {};
}
return hef->get_network_groups_names();
};
}
/** NetworkApp */
class NetworkApp : public CLI::App
{
public:
NetworkApp(const std::string &description, const std::string &name);
const NetworkParams& get_params();
private:
void add_vstream_app_subcom(CLI::Option *hef_path_option, CLI::Option *net_group_name_option);
NetworkParams m_params;
};
NetworkApp::NetworkApp(const std::string &description, const std::string &name) : CLI::App(description, name), m_params()
{
auto hef_path_option = add_option("hef", m_params.hef_path, "HEF file path")->check(CLI::ExistingFile);
auto net_group_name_option = add_option("--name", m_params.net_group_name, "Network group name")
->default_val("")
->needs(hef_path_option)
->check(NetworkGroupNameValidator(hef_path_option));
// NOTE: callbacks/params aren't called/updated before auto-completion (even after changing the order in App.hpp - at least for 2 jumps)
auto net_params = add_option_group("Network Group Parameters");
net_params->add_option("--batch-size", m_params.batch_size, "Batch size")->default_val(HAILO_DEFAULT_BATCH_SIZE);
net_params->add_option("--scheduler-threshold", m_params.scheduler_threshold, "Scheduler threshold")->default_val(0);
net_params->add_option("--scheduler-timeout", m_params.scheduler_timeout_ms, "Scheduler timeout in milliseconds")->default_val(0);
auto run_params = add_option_group("Run Parameters");
run_params->add_option("--framerate", m_params.framerate, "Input vStreams framerate")->default_val(UNLIMITED_FRAMERATE);
add_vstream_app_subcom(hef_path_option, net_group_name_option);
}
void NetworkApp::add_vstream_app_subcom(CLI::Option *hef_path_option, CLI::Option *net_group_name_option)
{
auto vstream_app = std::make_shared<VStreamApp>("Set vStream", "set-vstream", hef_path_option, net_group_name_option);
vstream_app->immediate_callback();
vstream_app->callback([this, vstream_app, hef_path_option, net_group_name_option]() {
m_params.vstream_params.push_back(vstream_app->get_params());
// Throw an error if anything is left over and should not be.
_process_extras();
// NOTE: calling "net_app->clear(); m_params = NetworkParams();" is not sufficient because default values
// need to be re-set. we can override clear and reset them but there might be other issues as well
// and this one feels less hacky ATM
remove_subcommand(vstream_app.get());
// Remove from parsed_subcommands_ as well (probably a bug in CLI11)
parsed_subcommands_.erase(std::remove_if(
parsed_subcommands_.begin(), parsed_subcommands_.end(),
[vstream_app](auto x){return x == vstream_app.get();}),
parsed_subcommands_.end());
add_vstream_app_subcom(hef_path_option, net_group_name_option);
});
// Must set fallthrough to support nested repeated subcommands.
vstream_app->fallthrough();
add_subcommand(vstream_app);
}
const NetworkParams& NetworkApp::get_params()
{
return m_params;
}
/** Run2 */
class Run2 : public CLI::App
{
public:
Run2();
const std::vector<NetworkParams>& get_network_params();
std::chrono::seconds get_time_to_run();
private:
void add_net_app_subcom();
std::vector<NetworkParams> m_network_params;
uint32_t m_time_to_run;
};
Run2::Run2() : CLI::App("Run networks (preview)", "run2")
{
add_net_app_subcom();
add_option("-t,--time-to-run", m_time_to_run, "Time to run (seconds)")
->default_val(DEFAULT_TIME_TO_RUN_SECONDS)
->check(CLI::PositiveNumber);
}
void Run2::add_net_app_subcom()
{
auto net_app = std::make_shared<NetworkApp>("Set network", "set-net");
net_app->immediate_callback();
net_app->callback([this, net_app]() {
m_network_params.push_back(net_app->get_params());
// Throw an error if anything is left over and should not be.
_process_extras();
// NOTE: calling "net_app->clear(); m_params = NetworkParams();" is not sufficient because default values
// need to be re-set. we can override clear and reset them but there might be other issues as well
// and this one feels less hacky ATM
remove_subcommand(net_app.get());
// Remove from parsed_subcommands_ as well (probably a bug in CLI11)
parsed_subcommands_.erase(std::remove_if(
parsed_subcommands_.begin(), parsed_subcommands_.end(),
[net_app](auto x){return x == net_app.get();}),
parsed_subcommands_.end());
add_net_app_subcom();
});
// NOTE: fallthrough() is not a must here but it is also not working (causing only a single vstream param
// instead of >1). Debug - App.hpp::void _parse(std::vector<std::string> &args)
add_subcommand(net_app);
}
const std::vector<NetworkParams>& Run2::get_network_params()
{
return m_network_params;
}
std::chrono::seconds Run2::get_time_to_run()
{
return std::chrono::seconds(m_time_to_run);
}
/** Run2Command */
Run2Command::Run2Command(CLI::App &parent_app) : Command(parent_app.add_subcommand(std::make_shared<Run2>()))
{
}
static hailo_status wait_for_threads(std::vector<AsyncThreadPtr<hailo_status>> &threads)
{
auto last_error_status = HAILO_SUCCESS;
for (auto& thread : threads) {
auto thread_status = thread->get();
if ((HAILO_SUCCESS != thread_status) && (HAILO_STREAM_ABORTED_BY_USER != thread_status)) {
last_error_status = thread_status;
LOGGER__ERROR("Thread failed with with status {}", thread_status);
}
}
return last_error_status;
}
hailo_status Run2Command::execute()
{
Run2 *app = reinterpret_cast<Run2*>(m_app);
if (0 == app->get_network_params().size()) {
LOGGER__ERROR("Nothing to run");
return HAILO_INVALID_OPERATION;
}
if (1 == app->get_network_params().size()) {
LOGGER__WARN("\"hailortcli run2\" is in preview. It is recommended to use \"hailortcli run\" command for a single network group");
}
// TODO: support multi-device. maybe get all by default?
hailo_vdevice_params_t vdevice_params = {};
CHECK_SUCCESS(hailo_init_vdevice_params(&vdevice_params));
auto vdevice = VDevice::create(vdevice_params);
CHECK_EXPECTED_AS_STATUS(vdevice);
// create network runners
std::vector<std::shared_ptr<NetworkRunner>> net_runners;
for (auto &net_params : app->get_network_params()) {
auto net_runner = NetworkRunner::create_shared(*vdevice->get(), net_params);
CHECK_EXPECTED_AS_STATUS(net_runner);
net_runners.emplace_back(net_runner.release());
}
LivePrinter live_printer(std::chrono::seconds(1));
live_printer.add(std::make_shared<TimerLiveTrack>(app->get_time_to_run()));
auto shutdown_event = Event::create(Event::State::not_signalled);
CHECK_EXPECTED_AS_STATUS(shutdown_event);
std::vector<AsyncThreadPtr<hailo_status>> threads;
for (auto &net_runner : net_runners) {
threads.emplace_back(std::make_unique<AsyncThread<hailo_status>>([&net_runner, &shutdown_event, &live_printer](){
return net_runner->run(shutdown_event.value(), live_printer);
}));
}
// TODO: wait for all nets before starting timer. start() should update TimerLiveTrack to start. or maybe append here but first in vector...
live_printer.start();
std::this_thread::sleep_for(app->get_time_to_run());
shutdown_event->signal();
return wait_for_threads(threads);
}

View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file run2_command.hpp
* @brief Run inference on hailo device
**/
#ifndef _HAILO_HAILORTCLI_RUN2_RUN2_COMMAND_HPP_
#define _HAILO_HAILORTCLI_RUN2_RUN2_COMMAND_HPP_
#include "../command.hpp"
class Run2Command : public Command {
public:
explicit Run2Command(CLI::App &parent_app);
hailo_status execute() override;
private:
};
#endif /* _HAILO_HAILORTCLI_RUN2_RUN2_COMMAND_HPP_ */

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file timer_live_track.cpp
* @brief Timer live track
**/
#include "timer_live_track.hpp"
#include "../common.hpp"
#include <spdlog/fmt/fmt.h>
#include <sstream>
TimerLiveTrack::TimerLiveTrack(std::chrono::milliseconds duration) :
m_duration(duration), m_start(std::chrono::steady_clock::now())
{
}
uint32_t TimerLiveTrack::get_text(std::stringstream &ss)
{
static const uint32_t MAX_PROGRESS_BAR_WIDTH = 20;
auto elapsed_time = std::chrono::steady_clock::now() - m_start;
auto eta = std::chrono::seconds(std::max<int32_t>(0, static_cast<int32_t>(std::round(std::chrono::duration<double>(m_duration - elapsed_time).count())))); // std::chrono::round is from C++17
auto elapsed_percentage = std::min<uint32_t>(100, static_cast<uint32_t>(std::round(std::chrono::duration<double>(100 * elapsed_time / m_duration).count())));
auto progress_bar_width = std::max<uint32_t>(1, std::min<uint32_t>(MAX_PROGRESS_BAR_WIDTH,
static_cast<uint32_t>(std::round(std::chrono::duration<double>(MAX_PROGRESS_BAR_WIDTH * elapsed_time / m_duration).count()))));
ss << fmt::format("[{:=>{}}{:{}}] {:>3}% {}\n", '>', progress_bar_width, "", MAX_PROGRESS_BAR_WIDTH - progress_bar_width, elapsed_percentage, CliCommon::duration_to_string(eta));
return 1;
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file timer_live_track.hpp
* @brief Timer live track
**/
#include "live_printer.hpp"
#ifndef _HAILO_HAILORTCLI_RUN2_TIMER_LIVE_TRACK_HPP_
#define _HAILO_HAILORTCLI_RUN2_TIMER_LIVE_TRACK_HPP_
class TimerLiveTrack : public LivePrinter::Track
{
public:
TimerLiveTrack(std::chrono::milliseconds duration);
virtual ~TimerLiveTrack() = default;
virtual uint32_t get_text(std::stringstream &ss) override;
private:
std::chrono::milliseconds m_duration;
std::chrono::time_point<std::chrono::steady_clock> m_start;
};
#endif /* _HAILO_HAILORTCLI_RUN2_TIMER_LIVE_TRACK_HPP_ */

View File

@@ -19,6 +19,7 @@
#endif
#include "common.hpp"
#include "common/string_utils.hpp"
#include "common/file_utils.hpp"
#include "common/async_thread.hpp"
#include "common/barrier.hpp"
@@ -29,8 +30,11 @@
#include "hailo/vstream.hpp"
#include "hailo/vdevice.hpp"
#include "spdlog/fmt/fmt.h"
#include <vector>
#include <algorithm>
#include <regex>
#include <signal.h>
#include <condition_variable>
std::condition_variable wait_for_exit_cv;
@@ -48,6 +52,9 @@ constexpr std::chrono::milliseconds TIME_TO_WAIT_FOR_CONFIG(300);
constexpr std::chrono::milliseconds TIME_TO_WAIT_FOR_CONFIG(30000);
#define HAILORTCLI_DEFAULT_VSTREAM_TIMEOUT_MS (HAILO_DEFAULT_VSTREAM_TIMEOUT_MS * 100)
#endif /* ifndef HAILO_EMULATOR */
static const char *RUNTIME_DATA_OUTPUT_PATH_HEF_PLACE_HOLDER = "<hef>";
static const char *RUNTIME_DATA_BATCH_TO_MEASURE_OPT_LAST = "last";
static const char *RUNTIME_DATA_BATCH_TO_MEASURE_OPT_DEFAULT = "2";
#ifndef _MSC_VER
void user_signal_handler_func(int signum)
@@ -86,7 +93,17 @@ bool should_measure_pipeline_stats(const inference_runner_params& params)
bool use_batch_to_measure_opt(const inference_runner_params& params)
{
return params.runtime_data.collect_runtime_data &&
(params.runtime_data.batch_to_measure != RUNTIME_DATA_IGNORE_BATCH_TO_MEASURE_OPT);
(params.runtime_data.batch_to_measure_str != RUNTIME_DATA_BATCH_TO_MEASURE_OPT_LAST);
}
// We assume that hef_place_holder_regex is valid
std::string format_runtime_data_output_path(const std::string &base_output_path, const std::string &hef_path,
const std::string &hef_place_holder_regex = RUNTIME_DATA_OUTPUT_PATH_HEF_PLACE_HOLDER,
const std::string &hef_suffix = ".hef")
{
const auto hef_basename = Filesystem::basename(hef_path);
const auto hef_no_suffix = Filesystem::remove_suffix(hef_basename, hef_suffix);
return std::regex_replace(base_output_path, std::regex(hef_place_holder_regex), hef_no_suffix);
}
static void add_run_command_params(CLI::App *run_subcommand, inference_runner_params& params)
@@ -118,7 +135,7 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
auto total_batch_size = run_subcommand->add_option("--batch-size", params.batch_size,
"Inference batch (should be a divisor of --frames-count if provided).\n"
"This batch applies to the whole network_group. for differential batch per network, see --net-batch-size")
->check(CLI::PositiveNumber)
->check(CLI::NonNegativeNumber)
->default_val(HAILO_DEFAULT_BATCH_SIZE);
run_subcommand->add_option("--net-batch-size", params.batch_per_network,
@@ -208,16 +225,16 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
auto *collect_runtime_data_subcommand = run_subcommand->add_subcommand("collect-runtime-data",
"Collect runtime data to be used by the Profiler");
static const char *JSON_SUFFIX = ".json";
collect_runtime_data_subcommand->add_option("--output-path",
params.runtime_data.runtime_data_output_path, "Runtime data output file path")
->default_val("runtime_data.json")
collect_runtime_data_subcommand->add_option("--output-path", params.runtime_data.runtime_data_output_path,
fmt::format("Runtime data output file path\n'{}' will be replaced with the current running hef",
RUNTIME_DATA_OUTPUT_PATH_HEF_PLACE_HOLDER))
->default_val(fmt::format("runtime_data_{}.json", RUNTIME_DATA_OUTPUT_PATH_HEF_PLACE_HOLDER))
->check(FileSuffixValidator(JSON_SUFFIX));
std::stringstream batch_to_measure_help;
batch_to_measure_help << "Batch to be measured " << std::endl
<< "The last batch will be measured if " << RUNTIME_DATA_IGNORE_BATCH_TO_MEASURE_OPT << " is provided";
collect_runtime_data_subcommand->add_option("--batch-to-measure",
params.runtime_data.batch_to_measure, batch_to_measure_help.str())
->default_val(RUNTIME_DATA_DEFAULT_BATCH_TO_MEASURE_OPT);
collect_runtime_data_subcommand->add_option("--batch-to-measure", params.runtime_data.batch_to_measure_str,
fmt::format("Batch to be measured (non-negative integer)\nThe last batch will be measured if '{}' is provided",
RUNTIME_DATA_BATCH_TO_MEASURE_OPT_LAST))
->default_val(RUNTIME_DATA_BATCH_TO_MEASURE_OPT_DEFAULT)
->check(UintOrKeywordValidator(RUNTIME_DATA_BATCH_TO_MEASURE_OPT_LAST));
collect_runtime_data_subcommand->parse_complete_callback([&params]() {
// If this subcommand was parsed, then we need to download runtime_data
params.runtime_data.collect_runtime_data = true;
@@ -257,7 +274,7 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
"--sampling-period requires --measure-power or --measure-current");
PARSE_CHECK(power_averaging_factor->empty() || has_oneof_measure_flags,
"--averaging-period factor --measure-power or --measure-current");
PARSE_CHECK(((0 != params.time_to_run) || (0 == (params.frames_count % params.batch_size))),
PARSE_CHECK(((0 != params.time_to_run) || (HAILO_DEFAULT_BATCH_SIZE == params.batch_size) || (0 == (params.frames_count % params.batch_size))),
"--batch-size should be a divisor of --frames-count if provided");
// TODO HRT-5363 support multiple devices
PARSE_CHECK((params.vdevice_params.device_count == 1) || params.csv_output.empty() ||
@@ -278,12 +295,15 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
PARSE_CHECK(!(params.vdevice_params.multi_process_service && is_hw_only),
"--hw-only mode is not supported for multi process service");
if (use_batch_to_measure_opt(params) &&
(0 != params.frames_count) && (params.frames_count < params.runtime_data.batch_to_measure)) {
if (use_batch_to_measure_opt(params)) {
// This cast is ok because we validate params.runtime_data.batch_to_measure_str with UintOrKeywordValidator
params.runtime_data.batch_to_measure = static_cast<uint16_t>(std::stoi(params.runtime_data.batch_to_measure_str));
if ((0 != params.frames_count) && (params.frames_count < params.runtime_data.batch_to_measure)) {
LOGGER__WARNING("--frames-count ({}) is smaller than --batch-to-measure ({}), "
"hence timestamps will not be updated in runtime data", params.frames_count,
params.runtime_data.batch_to_measure);
}
}
});
}
@@ -385,7 +405,7 @@ hailo_status send_loop(const inference_runner_params &params, SendObject &send_o
auto status = send_object.write(MemoryView(
const_cast<uint8_t*>(input_buffer->data()) + offset,
send_object.get_frame_size()));
if (HAILO_STREAM_INTERNAL_ABORT == status) {
if (HAILO_STREAM_ABORTED_BY_USER == status) {
LOGGER__DEBUG("Input stream was aborted!");
return status;
}
@@ -401,7 +421,7 @@ hailo_status send_loop(const inference_runner_params &params, SendObject &send_o
template<typename RecvObject>
hailo_status recv_loop(const inference_runner_params &params, RecvObject &recv_object,
std::shared_ptr<NetworkProgressBar> progress_bar, Barrier &barrier, LatencyMeter &overall_latency_meter,
std::map<std::string, BufferPtr> &dst_data, std::atomic_size_t &received_frames_count, uint32_t output_idx, bool show_progress,
std::map<std::string, BufferPtr> &dst_data, std::atomic_size_t &received_frames_count, bool show_progress,
uint16_t batch_size)
{
uint32_t num_of_batches = ((0 == params.time_to_run) ? (params.frames_count / batch_size) : UINT32_MAX);
@@ -410,13 +430,14 @@ hailo_status recv_loop(const inference_runner_params &params, RecvObject &recv_o
barrier.arrive_and_wait();
}
for (int j = 0; j < batch_size; j++) {
auto status = recv_object.read(MemoryView(*dst_data[recv_object.name()]));
auto dst_buffer = MemoryView(*dst_data[recv_object.name()]);
auto status = recv_object.read(dst_buffer);
if (HAILO_SUCCESS != status) {
return status;
}
if (params.measure_overall_latency) {
overall_latency_meter.add_end_sample(output_idx, std::chrono::steady_clock::now().time_since_epoch());
overall_latency_meter.add_end_sample(recv_object.name(), std::chrono::steady_clock::now().time_since_epoch());
}
if (show_progress && params.show_progress) {
@@ -433,13 +454,6 @@ hailo_status abort_streams(std::vector<std::reference_wrapper<SendObject>> &send
std::vector<std::reference_wrapper<RecvObject>> &recv_objects)
{
auto status = HAILO_SUCCESS; // Best effort
for (auto &input_stream : send_objects) {
auto abort_status = input_stream.get().abort();
if (HAILO_SUCCESS != abort_status) {
LOGGER__ERROR("Failed to abort input stream {}", input_stream.get().name());
status = abort_status;
}
}
for (auto &output_stream : recv_objects) {
auto abort_status = output_stream.get().abort();
if (HAILO_SUCCESS != abort_status) {
@@ -447,6 +461,13 @@ hailo_status abort_streams(std::vector<std::reference_wrapper<SendObject>> &send
status = abort_status;
}
}
for (auto &input_stream : send_objects) {
auto abort_status = input_stream.get().abort();
if (HAILO_SUCCESS != abort_status) {
LOGGER__ERROR("Failed to abort input stream {}", input_stream.get().name());
status = abort_status;
}
}
return status;
}
@@ -549,15 +570,18 @@ std::pair<std::string, uint16_t> get_network_to_batch(const std::string &name_to
uint16_t get_batch_size(const inference_runner_params &params, const std::string &network_name)
{
uint16_t batch_size = params.batch_size;
/* params.batch_per_network is a partial list of networks.
If a network is not in it, it gets the network_group_batch (params.batch_size) */
for (auto &name_to_batch_str : params.batch_per_network) {
auto name_to_batch = get_network_to_batch(name_to_batch_str);
if (network_name == name_to_batch.first) {
return name_to_batch.second;
batch_size = name_to_batch.second;
break;
}
}
return params.batch_size;
return (HAILO_DEFAULT_BATCH_SIZE == batch_size ? 1 : batch_size);
}
Expected<std::map<std::string, ConfigureNetworkParams>> get_configure_params(const inference_runner_params &params, hailort::Hef &hef, hailo_stream_interface_t interface)
@@ -620,12 +644,12 @@ static hailo_status run_streaming_impl(std::shared_ptr<ConfiguredNetworkGroup> c
if (params.measure_overall_latency) {
CHECK((send_objects.size() == 1), HAILO_INVALID_OPERATION, "Overall latency measurement not support multiple inputs network");
}
std::set<uint32_t> output_channels;
for (uint32_t output_channel_index = 0; output_channel_index < recv_objects.size(); output_channel_index++) {
output_channels.insert(output_channel_index);
std::set<std::string> output_names;
for (auto &output : recv_objects) {
output_names.insert(output.get().name());
}
LatencyMeter overall_latency_meter(output_channels, OVERALL_LATENCY_TIMESTAMPS_LIST_LENGTH);
LatencyMeter overall_latency_meter(output_names, OVERALL_LATENCY_TIMESTAMPS_LIST_LENGTH);
Barrier barrier(send_objects.size() + recv_objects.size());
std::vector<std::atomic_size_t> frames_recieved_per_output(recv_objects.size());
@@ -648,9 +672,9 @@ static hailo_status run_streaming_impl(std::shared_ptr<ConfiguredNetworkGroup> c
auto &frames_recieved = frames_recieved_per_output[output_index];
results.emplace_back(std::make_unique<AsyncThread<hailo_status>>(
[network_progress_bar, params, &recv_object, &output_buffers, first, &barrier, &overall_latency_meter,
&frames_recieved, output_index, batch_size]() {
&frames_recieved, batch_size]() {
auto res = recv_loop(params, recv_object.get(), network_progress_bar, barrier, overall_latency_meter,
output_buffers, frames_recieved, output_index, first, batch_size);
output_buffers, frames_recieved, first, batch_size);
if (HAILO_SUCCESS != res) {
barrier.terminate();
}
@@ -685,7 +709,7 @@ static hailo_status run_streaming_impl(std::shared_ptr<ConfiguredNetworkGroup> c
auto error_status = HAILO_SUCCESS;
for (auto& result : results) {
auto status = result->get();
if (HAILO_STREAM_INTERNAL_ABORT == status) {
if (HAILO_STREAM_ABORTED_BY_USER == status) {
continue;
}
if (HAILO_SUCCESS != status) {
@@ -1051,7 +1075,7 @@ static Expected<std::vector<std::map<std::string, BufferPtr>>> create_dataset(
return results;
}
Expected<InferResult> activate_network_group_and_run(
Expected<InferResult> activate_and_run_single_device(
Device &device,
const std::vector<std::shared_ptr<ConfiguredNetworkGroup>> &network_groups,
const inference_runner_params &params)
@@ -1164,7 +1188,7 @@ Expected<InferResult> run_command_hef_single_device(const inference_runner_param
}
#endif
auto inference_result = activate_network_group_and_run(*device, network_group_list.value(), params);
auto inference_result = activate_and_run_single_device(*device, network_group_list.value(), params);
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
@@ -1179,8 +1203,10 @@ Expected<InferResult> run_command_hef_single_device(const inference_runner_param
}
if (params.runtime_data.collect_runtime_data) {
DownloadActionListCommand::execute(*device, params.runtime_data.runtime_data_output_path,
network_group_list.value(), params.hef_path);
const auto runtime_data_output_path = format_runtime_data_output_path(
params.runtime_data.runtime_data_output_path, params.hef_path);
DownloadActionListCommand::execute(*device, runtime_data_output_path, network_group_list.value(),
params.hef_path);
}
#endif
@@ -1188,6 +1214,100 @@ Expected<InferResult> run_command_hef_single_device(const inference_runner_param
return inference_result;
}
Expected<InferResult> activate_and_run_vdevice(
std::vector<std::reference_wrapper<Device>> &physical_devices,
bool scheduler_is_used,
const std::vector<std::shared_ptr<ConfiguredNetworkGroup>> &network_groups,
const inference_runner_params &params)
{
std::unique_ptr<ActivatedNetworkGroup> activated_network_group;
if (!scheduler_is_used) {
auto activated_net_group_exp = activate_network_group(*network_groups[0]);
CHECK_EXPECTED(activated_net_group_exp, "Failed activate network_group");
activated_network_group = activated_net_group_exp.release();
}
auto input_dataset = create_dataset(network_groups, params);
CHECK_EXPECTED(input_dataset, "Failed creating input dataset");
hailo_power_measurement_types_t measurement_type = HAILO_POWER_MEASUREMENT_TYPES__MAX_ENUM;
bool should_measure_power = false;
if (params.power_measurement.measure_power) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
should_measure_power = true;
} else if (params.power_measurement.measure_current) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__CURRENT;
should_measure_power = true;
}
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> power_measurements;
if (should_measure_power) {
for (auto &device : physical_devices) {
auto long_power_measurement_exp = PowerMeasurementSubcommand::start_power_measurement(device,
HAILO_DVM_OPTIONS_AUTO,
measurement_type, params.power_measurement.sampling_period, params.power_measurement.averaging_factor);
CHECK_EXPECTED(long_power_measurement_exp, "Failed starting power measurement on device {}", device.get().get_dev_id());
auto long_power_measurement_p = make_shared_nothrow<LongPowerMeasurement>(long_power_measurement_exp.release());
CHECK_NOT_NULL_AS_EXPECTED(long_power_measurement_p, HAILO_OUT_OF_HOST_MEMORY);
power_measurements.emplace(device.get().get_dev_id(), std::move(long_power_measurement_p));
}
}
std::map<std::string, std::shared_ptr<TemperatureMeasurement>> temp_measurements;
if (params.measure_temp) {
for (auto &device : physical_devices) {
auto temp_measure = make_shared_nothrow<TemperatureMeasurement>(device);
CHECK_NOT_NULL_AS_EXPECTED(temp_measure, HAILO_OUT_OF_HOST_MEMORY);
auto status = temp_measure->start_measurement();
CHECK_SUCCESS_AS_EXPECTED(status, "Failed starting temperature measurement on device {}", device.get().get_dev_id());
temp_measurements.emplace(device.get().get_dev_id(), std::move(temp_measure));
}
}
auto infer_result = run_inference(network_groups, input_dataset.value(), params);
CHECK_EXPECTED(infer_result, "Error failed running inference");
InferResult inference_result(infer_result.release());
inference_result.initialize_measurements(physical_devices);
if (should_measure_power) {
auto status = HAILO_SUCCESS;
for (auto &power_measure_pair : power_measurements) {
auto measurement_status = power_measure_pair.second->stop();
if (HAILO_SUCCESS != measurement_status) {
// The returned status will be the last non-success status.
status = measurement_status;
LOGGER__ERROR("Failed stopping power measurement on device {} with status {}", power_measure_pair.first, measurement_status);
} else {
auto set_measurement_status = HAILO_UNINITIALIZED;
if (params.power_measurement.measure_current) {
set_measurement_status = inference_result.set_current_measurement(power_measure_pair.first, std::move(power_measure_pair.second));
} else {
set_measurement_status = inference_result.set_power_measurement(power_measure_pair.first, std::move(power_measure_pair.second));
}
if (HAILO_SUCCESS != set_measurement_status) {
status = set_measurement_status;
LOGGER__ERROR("Failed setting power measurement to inference result with status {}", set_measurement_status);
}
}
}
CHECK_SUCCESS_AS_EXPECTED(status);
}
if (params.measure_temp) {
for(const auto &temp_measure_pair : temp_measurements) {
temp_measure_pair.second->stop_measurement();
auto temp_measure_p = make_shared_nothrow<TempMeasurementData>(temp_measure_pair.second->get_data());
CHECK_NOT_NULL_AS_EXPECTED(temp_measure_p, HAILO_OUT_OF_HOST_MEMORY);
auto status = inference_result.set_temp_measurement(temp_measure_pair.first, std::move(temp_measure_p));
CHECK_SUCCESS_AS_EXPECTED(status);
}
}
return inference_result;
}
Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &params)
{
auto hef = Hef::create(params.hef_path.c_str());
@@ -1221,33 +1341,6 @@ Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &par
auto vdevice = VDevice::create(vdevice_params);
CHECK_EXPECTED(vdevice, "Failed creating vdevice");
// VDevice always has Pcie devices
auto configure_params = get_configure_params(params, hef.value(), hailo_stream_interface_t::HAILO_STREAM_INTERFACE_PCIE);
CHECK_EXPECTED(configure_params);
auto network_group_list = vdevice.value()->configure(hef.value(), configure_params.value());
CHECK_EXPECTED(network_group_list, "Failed configure vdevice from hef");
std::unique_ptr<ActivatedNetworkGroup> activated_network_group;
if (!scheduler_is_used) {
auto activated_net_group_exp = activate_network_group(*network_group_list.value()[0]);
CHECK_EXPECTED(activated_net_group_exp, "Failed activate network_group");
activated_network_group = activated_net_group_exp.release();
}
auto input_dataset = create_dataset(network_group_list.value(), params);
CHECK_EXPECTED(input_dataset, "Failed creating input dataset");
hailo_power_measurement_types_t measurement_type = HAILO_POWER_MEASUREMENT_TYPES__MAX_ENUM;
bool should_measure_power = false;
if (params.power_measurement.measure_power) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
should_measure_power = true;
} else if (params.power_measurement.measure_current) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__CURRENT;
should_measure_power = true;
}
std::vector<std::reference_wrapper<Device>> physical_devices;
if (!params.vdevice_params.multi_process_service) {
auto expected_physical_devices = vdevice.value()->get_physical_devices();
@@ -1255,29 +1348,14 @@ Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &par
physical_devices = expected_physical_devices.value();
}
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> power_measurements;
if (should_measure_power) {
for (auto &device : physical_devices) {
auto long_power_measurement_exp = PowerMeasurementSubcommand::start_power_measurement(device,
HAILO_DVM_OPTIONS_AUTO,
measurement_type, params.power_measurement.sampling_period, params.power_measurement.averaging_factor);
CHECK_EXPECTED(long_power_measurement_exp, "Failed starting power measurement on device {}", device.get().get_dev_id());
auto long_power_measurement_p = make_shared_nothrow<LongPowerMeasurement>(long_power_measurement_exp.release());
CHECK_NOT_NULL_AS_EXPECTED(long_power_measurement_p, HAILO_OUT_OF_HOST_MEMORY);
power_measurements.emplace(device.get().get_dev_id(), std::move(long_power_measurement_p));
}
}
auto interface = vdevice.value()->get_default_streams_interface();
CHECK_EXPECTED(interface, "Failed to get default streams interface");
std::map<std::string, std::shared_ptr<TemperatureMeasurement>> temp_measurements;
if (params.measure_temp) {
for (auto &device : physical_devices) {
auto temp_measure = make_shared_nothrow<TemperatureMeasurement>(device);
CHECK_NOT_NULL_AS_EXPECTED(temp_measure, HAILO_OUT_OF_HOST_MEMORY);
status = temp_measure->start_measurement();
CHECK_SUCCESS_AS_EXPECTED(status, "Failed starting temperature measurement on device {}", device.get().get_dev_id());
temp_measurements.emplace(device.get().get_dev_id(), std::move(temp_measure));
}
}
auto configure_params = get_configure_params(params, hef.value(), *interface);
CHECK_EXPECTED(configure_params);
auto network_group_list = vdevice.value()->configure(hef.value(), configure_params.value());
CHECK_EXPECTED(network_group_list, "Failed configure vdevice from hef");
#if defined(__GNUC__)
for (auto &device : physical_devices) {
@@ -1289,7 +1367,8 @@ Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &par
}
#endif
auto infer_result = run_inference(network_group_list.value(), input_dataset.value(), params);
auto infer_result = activate_and_run_vdevice(physical_devices, scheduler_is_used, network_group_list.value(), params);
CHECK_EXPECTED(infer_result, "Error failed running inference");
#if defined(__GNUC__)
for (auto &device : physical_devices) {
@@ -1305,51 +1384,15 @@ Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &par
}
if (params.runtime_data.collect_runtime_data) {
DownloadActionListCommand::execute(device.get(), params.runtime_data.runtime_data_output_path,
network_group_list.value(), params.hef_path);
const auto runtime_data_output_path = format_runtime_data_output_path(
params.runtime_data.runtime_data_output_path, params.hef_path);
DownloadActionListCommand::execute(device.get(), runtime_data_output_path, network_group_list.value(),
params.hef_path);
}
}
#endif
CHECK_EXPECTED(infer_result, "Error failed running inference");
InferResult inference_result(infer_result.release());
inference_result.initialize_measurements(physical_devices);
if (should_measure_power) {
for (auto &power_measure_pair : power_measurements) {
auto measurement_status = power_measure_pair.second->stop();
if (HAILO_SUCCESS != measurement_status) {
// The returned status will be the last non-success status.
status = measurement_status;
LOGGER__ERROR("Failed stopping power measurement on device {} with status {}", power_measure_pair.first, measurement_status);
} else {
auto set_measurement_status = HAILO_UNINITIALIZED;
if (params.power_measurement.measure_current) {
set_measurement_status = inference_result.set_current_measurement(power_measure_pair.first, std::move(power_measure_pair.second));
} else {
set_measurement_status = inference_result.set_power_measurement(power_measure_pair.first, std::move(power_measure_pair.second));
}
if (HAILO_SUCCESS != set_measurement_status) {
status = set_measurement_status;
LOGGER__ERROR("Failed setting power measurement to inference result with status {}", set_measurement_status);
}
}
}
CHECK_SUCCESS_AS_EXPECTED(status);
}
if (params.measure_temp) {
for(const auto &temp_measure_pair : temp_measurements) {
temp_measure_pair.second->stop_measurement();
auto temp_measure_p = make_shared_nothrow<TempMeasurementData>(temp_measure_pair.second->get_data());
CHECK_NOT_NULL_AS_EXPECTED(temp_measure_p, HAILO_OUT_OF_HOST_MEMORY);
status = inference_result.set_temp_measurement(temp_measure_pair.first, std::move(temp_measure_p));
CHECK_SUCCESS_AS_EXPECTED(status);
}
}
return inference_result;
return infer_result;
}
Expected<bool> use_vdevice(const hailo_vdevice_params &params)

View File

@@ -11,6 +11,7 @@
#define _HAILO_RUN_COMMAND_HPP_
#include "hailortcli.hpp"
#include "common.hpp"
#include "power_measurement_command.hpp"
#include "temp_measurement.hpp"
#include "CLI/CLI.hpp"
@@ -44,12 +45,10 @@ struct pipeline_stats_measurement_params {
std::string pipeline_stats_output_path;
};
static constexpr uint16_t RUNTIME_DATA_IGNORE_BATCH_TO_MEASURE_OPT = std::numeric_limits<uint16_t>::max();
static constexpr uint16_t RUNTIME_DATA_DEFAULT_BATCH_TO_MEASURE_OPT = 2;
struct runtime_data_params {
bool collect_runtime_data;
std::string runtime_data_output_path;
std::string batch_to_measure_str;
uint16_t batch_to_measure;
};
@@ -91,6 +90,26 @@ private:
inference_runner_params m_params;
};
class UintOrKeywordValidator : public CLI::Validator {
public:
UintOrKeywordValidator(const std::string &keyword) {
name_ = "UINT_OR_KEYWORD";
func_ = [keyword](const std::string &s) {
if (s == keyword) {
// s is the allowed keyword
return std::string(); // Success
}
if (CliCommon::is_non_negative_number(s)) {
// s is an int
return std::string(); // Success
}
return std::string("should be a positive integer or '" + keyword + "'.");
};
}
};
class InputNameToFilePairValidator : public CLI::Validator {
public:
InputNameToFilePairValidator() : CLI::Validator("InputNameToFilePair"), m_first_run(true), m_must_fail(false) {
@@ -143,7 +162,7 @@ public:
auto batch_size = key_value_pair_str.substr(first_delimiter + 1);
auto network_name = key_value_pair_str.substr(0, first_delimiter);
// Batch size must be a positive number
if (!is_positive_number(batch_size)) {
if (!CliCommon::is_positive_number(batch_size)) {
m_must_fail = true;
return std::string("Failed parsing batch size (" + batch_size + ") for network (" + network_name + "). batch should be a positive number.");
}
@@ -151,13 +170,8 @@ public:
};
}
private:
bool is_positive_number(const std::string &s)
{
bool is_number = (!s.empty()) && (std::all_of(s.begin(), s.end(), ::isdigit));
return is_number && (0 < std::stoi(s));
}
private:
bool m_must_fail;
};

View File

@@ -16,12 +16,6 @@
ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("scan", "Shows all available devices"))
{
auto *device_type_option = m_app->add_option("-d,--device-type,--target", "ignored.");
std::vector<DeprecationActionPtr> actions{
std::make_shared<OptionDeprecation>(device_type_option),
};
hailo_deprecate_options(m_app, actions, false);
// Ethernet options
auto *eth_options_group = m_app->add_option_group("Ethernet Device Options");
auto *interface_ip_option = eth_options_group->add_option("--interface-ip", m_interface_ip_addr,

View File

@@ -157,6 +157,10 @@ SensorDumpConfigSubcommand::SensorDumpConfigSubcommand(CLI::App &parent_app) :
hailo_status SensorDumpConfigSubcommand::execute_on_device(Device &device)
{
auto status = validate_specific_device_is_given();
CHECK_SUCCESS(status,
"'sensor-config get-config' command should get a specific device-id.");
return device.sensor_dump_config(m_section_index, m_output_file_path);
}

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
set(HAILORT_MINOR_VERSION 10)
set(HAILORT_MINOR_VERSION 12)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found
@@ -25,6 +25,10 @@ target_include_directories(hef_proto
$<BUILD_INTERFACE: ${Protobuf_INCLUDE_DIRS}>
)
if(HAILO_BUILD_PROFILER)
add_definitions( -DHAILO_ENABLE_PROFILER_BUILD )
endif()
protobuf_generate_cpp(PROTO_SCHEDULER_MON_SRC PROTO_SCHEDULER_MON_HEADR scheduler_mon.proto)
add_library(scheduler_mon_proto ${PROTO_SCHEDULER_MON_SRC} ${PROTO_SCHEDULER_MON_HEADR})
target_link_libraries(scheduler_mon_proto libprotobuf-lite)

View File

@@ -8,7 +8,7 @@ if(NOT CMAKE_HOST_UNIX)
message(FATAL_ERROR "Only unix hosts are supported, stopping build")
endif()
find_package(HailoRT 4.10.0 EXACT REQUIRED)
find_package(HailoRT 4.12.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")
@@ -37,7 +37,7 @@ set_target_properties(gsthailo PROPERTIES
)
target_compile_options(gsthailo PRIVATE
-Werror -Wall -Wextra -Wconversion -O3 -DNDEBUG # TODO support debug/release builds
-Werror -Wall -Wextra -Wconversion
-DVERSION="${GST_HAILO_VERSION}"
-DPACKAGE="${GST_HAILO_PACKAGE_NAME}")

View File

@@ -1,6 +1,6 @@
Compiling the plugin:
cmake -H. -Bbuild
cmake --build build
cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
cmake --build build --config release
Using the plugin:
The plugin is dependent on libhailort which is included in the `hailort/lib/` directory.

View File

@@ -48,11 +48,13 @@ using namespace hailort;
#define DEFAULT_VDEVICE_KEY (0)
#define MIN_VALID_VDEVICE_KEY (1)
#define HAILO_SUPPORTED_FORMATS "{ RGB, RGBA, YUY2 }"
#define HAILO_SUPPORTED_FORMATS "{ RGB, RGBA, YUY2, NV12, NV21 }"
#define HAILO_VIDEO_CAPS GST_VIDEO_CAPS_MAKE(HAILO_SUPPORTED_FORMATS)
#define HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS (0)
#define HAILO_DEFAULT_SCHEDULER_THRESHOLD (1)
#define HAILO_DEFAULT_SCHEDULER_THRESHOLD (0)
#define HAILO_DEFAULT_MULTI_PROCESS_SERVICE (false)
#define GST_CHECK(cond, ret_val, element, domain, ...) \
do { \

View File

@@ -79,6 +79,7 @@ enum
PROP_SCHEDULING_ALGORITHM,
PROP_SCHEDULER_TIMEOUT_MS,
PROP_SCHEDULER_THRESHOLD,
PROP_MULTI_PROCESS_SERVICE,
};
G_DEFINE_TYPE(GstHailoNet, gst_hailonet, GST_TYPE_BIN);
@@ -150,8 +151,8 @@ static void gst_hailonet_class_init(GstHailoNetClass *klass)
"Gets values from the enum GstHailoSchedulingAlgorithms. "
"Using Model Scheduler algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE, excludes the property 'is-active'. "
"When using the same VDevice across multiple hailonets, all should have the same 'scheduling-algorithm'. "
"Currently only supported with 1 device (e.g. device-count=1).",
GST_TYPE_SCHEDULING_ALGORITHM, HAILO_SCHEDULING_ALGORITHM_NONE,
"To run with more than one device, set env variable 'HAILO_ENABLE_MULTI_DEVICE_SCHEDULER' to 1.",
GST_TYPE_SCHEDULING_ALGORITHM, HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_SCHEDULER_TIMEOUT_MS,
g_param_spec_uint("scheduler-timeout-ms", "Timeout for for scheduler in ms", "The maximum time period that may pass before getting run time from the scheduler,"
@@ -160,7 +161,10 @@ static void gst_hailonet_class_init(GstHailoNetClass *klass)
g_object_class_install_property(gobject_class, PROP_SCHEDULER_THRESHOLD,
g_param_spec_uint("scheduler-threshold", "Frames threshold for scheduler", "The minimum number of send requests required before the hailonet is considered ready to get run time from the scheduler.",
HAILO_DEFAULT_SCHEDULER_THRESHOLD, std::numeric_limits<uint32_t>::max(), HAILO_DEFAULT_SCHEDULER_THRESHOLD, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_MULTI_PROCESS_SERVICE,
g_param_spec_boolean("multi-process-service", "Should run over HailoRT service", "Controls wether to run HailoRT over its service. "
"To use this property, the service should be active and scheduling-algorithm should be set. Defaults to false.",
HAILO_DEFAULT_MULTI_PROCESS_SERVICE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
// See information about the "flush" signal in the element description
g_signal_new(
"flush",
@@ -170,13 +174,19 @@ static void gst_hailonet_class_init(GstHailoNetClass *klass)
);
}
std::string create_name(std::string prefix, uint32_t id)
{
return prefix + std::to_string(id);
}
Expected<std::unique_ptr<HailoNetImpl>> HailoNetImpl::create(GstHailoNet *element)
{
if (nullptr == element) {
return make_unexpected(HAILO_INVALID_ARGUMENT);
}
GstElement *hailosend = gst_element_factory_make("hailosend", "hailosend");
auto hailosend_name = create_name("hailosend", HailoNetImpl::m_hailonet_count);
GstElement *hailosend = gst_element_factory_make("hailosend", hailosend_name.c_str());
if (nullptr == hailosend) {
GST_ELEMENT_ERROR(element, RESOURCE, FAILED, ("Failed creating hailosend element in bin!"), (NULL));
return make_unexpected(HAILO_INTERNAL_FAILURE);
@@ -184,7 +194,8 @@ Expected<std::unique_ptr<HailoNetImpl>> HailoNetImpl::create(GstHailoNet *elemen
g_object_set(hailosend, "qos", FALSE, NULL);
GstElement *queue = gst_element_factory_make("queue", "hailo_infer_q_0");
auto hailoqueue_name = create_name("hailoqueue", HailoNetImpl::m_hailonet_count);
GstElement *queue = gst_element_factory_make("queue", hailoqueue_name.c_str());
if (nullptr == queue) {
GST_ELEMENT_ERROR(element, RESOURCE, FAILED, ("Failed creating queue element in bin!"), (NULL));
gst_object_unref(hailosend);
@@ -192,12 +203,13 @@ Expected<std::unique_ptr<HailoNetImpl>> HailoNetImpl::create(GstHailoNet *elemen
}
// Passing 0 disables the features here
g_object_set(queue, "max-size-time", 0, NULL);
g_object_set(queue, "max-size-bytes", 0, NULL);
g_object_set(queue, "max-size-time", (guint64)0, NULL);
g_object_set(queue, "max-size-bytes", (guint)0, NULL);
g_signal_connect(queue, "overrun", G_CALLBACK(gst_hailonet_inner_queue_overrun_callback), nullptr);
g_signal_connect(queue, "underrun", G_CALLBACK(gst_hailonet_inner_queue_underrun_callback), nullptr);
GstElement *hailorecv = gst_element_factory_make("hailorecv", "hailorecv");
auto hailorecv_name = create_name("hailorecv", HailoNetImpl::m_hailonet_count);
GstElement *hailorecv = gst_element_factory_make("hailorecv", hailorecv_name.c_str());
if (nullptr == hailorecv) {
GST_ELEMENT_ERROR(element, RESOURCE, FAILED, ("Failed creating hailorecv element in bin!"), (NULL));
gst_object_unref(hailosend);
@@ -375,7 +387,7 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
{
gboolean new_is_active = g_value_get_boolean(value);
if (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get()) {
if (m_props.m_scheduling_algorithm.was_changed() && (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get())) {
g_error("scheduling-algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE in combination with 'is-active' is not supported.");
break;
}
@@ -438,6 +450,13 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
}
m_props.m_scheduler_threshold = g_value_get_uint(value);
break;
case PROP_MULTI_PROCESS_SERVICE:
if (m_was_configured) {
g_warning("The network was already configured so changing the multi-process-service property will not take place!");
break;
}
m_props.m_multi_process_service = g_value_get_boolean(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -505,6 +524,9 @@ void HailoNetImpl::get_property(GObject *object, guint property_id, GValue *valu
case PROP_SCHEDULER_THRESHOLD:
g_value_set_uint(value, m_props.m_scheduler_threshold.get());
break;
case PROP_MULTI_PROCESS_SERVICE:
g_value_set_boolean(value, m_props.m_multi_process_service.get());
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -516,12 +538,18 @@ hailo_status HailoNetImpl::set_hef()
m_net_group_handle = make_unique_nothrow<NetworkGroupHandle>(GST_ELEMENT(m_element));
GST_CHECK(nullptr != m_net_group_handle, HAILO_OUT_OF_HOST_MEMORY, m_element, RESOURCE, "Failed allocating memory for network handle!");
hailo_status status = m_net_group_handle->set_hef(m_props.m_device_id.get(), m_props.m_device_count.get(), m_props.m_vdevice_key.get(),
m_props.m_scheduling_algorithm.get(), m_props.m_hef_path.get());
hailo_status status = m_net_group_handle->set_hef(m_props.m_device_id.get(), m_props.m_device_count.get(),
m_props.m_vdevice_key.get(), m_props.m_scheduling_algorithm.get(), static_cast<bool>(m_props.m_multi_process_service.get()),
m_props.m_hef_path.get());
if (HAILO_SUCCESS != status) {
return status;
}
if (m_props.m_multi_process_service.get()) {
GST_CHECK(m_props.m_scheduling_algorithm.get() != HAILO_SCHEDULING_ALGORITHM_NONE,
HAILO_INVALID_OPERATION, m_element, RESOURCE, "To use multi-process-service please set scheduling-algorithm.");
}
if (nullptr == m_props.m_network_name.get()) {
// TODO: HRT-4957
GST_CHECK(m_net_group_handle->hef()->get_network_groups_names().size() == 1, HAILO_INVALID_ARGUMENT, m_element, RESOURCE,
@@ -541,7 +569,7 @@ hailo_status HailoNetImpl::set_hef()
GST_CHECK(1 == input_vstream_infos->size(), HAILO_INVALID_OPERATION, m_element, RESOURCE, "hailonet element supports only HEFs with one input for now!");
auto input_vstream_info = input_vstream_infos.value()[0];
GST_HAILOSEND(m_hailosend)->impl->set_input_vstream_infos(std::move(input_vstream_infos.release()));
GST_HAILOSEND(m_hailosend)->impl->set_input_vstream_infos(input_vstream_infos.release());
GST_HAILOSEND(m_hailosend)->impl->set_batch_size(m_props.m_batch_size.get());
GstBufferPool *pool = gst_buffer_pool_new();
@@ -661,7 +689,11 @@ hailo_status HailoNetImpl::abort_streams()
return HAILO_SUCCESS;
}
return m_net_group_handle->abort_streams();
auto status = GST_HAILOSEND(m_hailosend)->impl->abort_vstreams();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed aborting input VStreams of hailosend, status = %d", status);
status = GST_HAILORECV(m_hailorecv)->impl->abort_vstreams();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed aborting output VStreams of hailorecv, status = %d", status);
return HAILO_SUCCESS;
}
hailo_status HailoNetImpl::deactivate_network_group()
@@ -834,13 +866,8 @@ static GstStateChangeReturn gst_hailonet_change_state(GstElement *element, GstSt
}
case GST_STATE_CHANGE_READY_TO_NULL:
{
// VStreams are destructed in hailosend's/hailorecv's GST_STATE_CHANGE_READY_TO_NULL (which calls 'clear_abort' on low-level streams)
// We abort streams again because deactivation of the activated network group calls flush, and it can fail on timeout unless we call abort
hailo_status status = hailonet->abort_streams();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Aborting streams has failed, status = %d\n", status);
if (HAILO_SCHEDULING_ALGORITHM_NONE == hailonet->get_props().m_scheduling_algorithm.get()) {
status = hailonet->deactivate_network_group();
auto status = hailonet->deactivate_network_group();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Deactivating network group failed, status = %d\n", status);
}

View File

@@ -52,8 +52,9 @@ struct HailoNetProperties final
{
public:
HailoNetProperties() : m_device_id(nullptr), m_hef_path(nullptr), m_network_name(nullptr), m_batch_size(HAILO_DEFAULT_BATCH_SIZE),
m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY), m_scheduling_algorithm(HAILO_SCHEDULING_ALGORITHM_NONE),
m_scheduler_timeout_ms(HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS), m_scheduler_threshold(HAILO_DEFAULT_SCHEDULER_THRESHOLD)
m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY), m_scheduling_algorithm(HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN),
m_scheduler_timeout_ms(HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS), m_scheduler_threshold(HAILO_DEFAULT_SCHEDULER_THRESHOLD),
m_multi_process_service(HAILO_DEFAULT_MULTI_PROCESS_SERVICE)
{}
HailoElemProperty<gchar*> m_device_id;
@@ -66,6 +67,7 @@ public:
HailoElemProperty<hailo_scheduling_algorithm_t> m_scheduling_algorithm;
HailoElemProperty<guint32> m_scheduler_timeout_ms;
HailoElemProperty<guint32> m_scheduler_threshold;
HailoElemProperty<gboolean> m_multi_process_service;
};
class HailoNetImpl final

View File

@@ -308,6 +308,15 @@ hailo_status HailoRecvImpl::clear_vstreams()
return OutputVStream::clear(m_output_vstreams);
}
hailo_status HailoRecvImpl::abort_vstreams()
{
for (auto& output_vstream : m_output_vstreams) {
auto status = output_vstream.abort();
GST_CHECK_SUCCESS(status, m_element, STREAM, "Failed aborting output vstream %s, status = %d", output_vstream.name().c_str(), status);
}
return HAILO_SUCCESS;
}
static void gst_hailorecv_init(GstHailoRecv *self)
{
auto hailorecv_impl = HailoRecvImpl::create(self);
@@ -343,6 +352,8 @@ static GstStateChangeReturn gst_hailorecv_change_state(GstElement *element, GstS
}
if (GST_STATE_CHANGE_READY_TO_NULL == transition) {
auto status = GST_HAILORECV(element)->impl->abort_vstreams();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, STREAM, "Aborting output vstreams failed, status = %d\n", status);
// Cleanup all of hailorecv memory
GST_HAILORECV(element)->impl.reset();
}

View File

@@ -92,6 +92,7 @@ public:
GstFlowReturn handle_frame(GstVideoFilter *filter, GstVideoFrame *frame);
hailo_status set_output_vstreams(std::vector<OutputVStream> &&output_vstreams, uint32_t batch_size);
hailo_status clear_vstreams();
hailo_status abort_vstreams();
private:
hailo_status read_from_vstreams(bool should_print_latency);

View File

@@ -176,6 +176,19 @@ hailo_status HailoSendImpl::write_to_vstreams(void *buf, size_t size)
return HAILO_SUCCESS;
}
uint32_t get_height_by_order(const hailo_vstream_info_t &input_vstream_info)
{
auto original_height = input_vstream_info.shape.height;
switch (input_vstream_info.format.order) {
case HAILO_FORMAT_ORDER_NV12:
case HAILO_FORMAT_ORDER_NV21:
return original_height * 2;
default:
break;
}
return original_height;
}
GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*direction*/, GstCaps *caps, GstCaps */*filter*/)
{
GST_DEBUG_OBJECT(m_element, "transform_caps");
@@ -192,6 +205,7 @@ GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*
const gchar *format = nullptr;
switch (m_input_vstream_infos[0].format.order) {
case HAILO_FORMAT_ORDER_RGB4:
case HAILO_FORMAT_ORDER_NHWC:
if (m_input_vstream_infos[0].shape.features == RGBA_FEATURES_SIZE) {
format = "RGBA";
@@ -234,7 +248,7 @@ GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*
GstCaps *new_caps = gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, format,
"width", G_TYPE_INT, m_input_vstream_infos[0].shape.width,
"height", G_TYPE_INT, m_input_vstream_infos[0].shape.height,
"height", G_TYPE_INT, get_height_by_order(m_input_vstream_infos[0]),
NULL);
return gst_caps_intersect(caps, new_caps);
}
@@ -254,6 +268,15 @@ hailo_status HailoSendImpl::clear_vstreams()
return InputVStream::clear(m_input_vstreams);
}
hailo_status HailoSendImpl::abort_vstreams()
{
for (auto& input_vstream : m_input_vstreams) {
auto status = input_vstream.abort();
GST_CHECK_SUCCESS(status, m_element, STREAM, "Failed aborting input vstream %s, status = %d", input_vstream.name().c_str(), status);
}
return HAILO_SUCCESS;
}
static void gst_hailosend_init(GstHailoSend *self)
{
auto hailosend_impl = HailoSendImpl::create(self);
@@ -303,6 +326,8 @@ static GstStateChangeReturn gst_hailosend_change_state(GstElement *element, GstS
}
if (GST_STATE_CHANGE_READY_TO_NULL == transition) {
auto status = GST_HAILOSEND(element)->impl->abort_vstreams();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, STREAM, "Aborting input vstreams failed, status = %d\n", status);
// Cleanup all of hailosend memory
GST_HAILOSEND(element)->impl.reset();
}

View File

@@ -71,6 +71,7 @@ public:
void set_input_vstream_infos(std::vector<hailo_vstream_info_t> &&input_vstream_infos);
void set_input_vstreams(std::vector<InputVStream> &&input_vstreams);
hailo_status clear_vstreams();
hailo_status abort_vstreams();
void set_batch_size(uint32_t batch_size)
{

View File

@@ -28,7 +28,7 @@ NetworkGroupActivationManager NetworkGroupHandle::m_net_group_activation_manager
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id,
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm)
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service)
{
// If passing device_id, than device_count must be 1
const auto device_count = 1;
@@ -43,6 +43,7 @@ Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, co
params.device_count = device_count;
params.device_ids = &(device_id_expected.value());
params.scheduling_algorithm = scheduling_algorithm;
params.multi_process_service = multi_process_service;
if (vdevice_key == DEFAULT_VDEVICE_KEY) {
params.group_id = HAILO_UNIQUE_VDEVICE_GROUP_ID;
} else {
@@ -51,12 +52,12 @@ Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, co
}
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
std::shared_ptr<VDevice> vdevice_ptr = vdevice.release();
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm)
hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service)
{
auto device_id = std::to_string(vdevice_key);
hailo_vdevice_params_t params = {};
@@ -65,14 +66,15 @@ Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, ui
params.device_count = device_count;
params.scheduling_algorithm = scheduling_algorithm;
params.group_id = device_id.c_str();
params.multi_process_service = multi_process_service;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
std::shared_ptr<VDevice> vdevice_ptr = vdevice.release();
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count,
hailo_scheduling_algorithm_t scheduling_algorithm)
hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service)
{
hailo_vdevice_params_t params = {};
auto status = hailo_init_vdevice_params(&params);
@@ -81,43 +83,44 @@ Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, ui
params.device_count = device_count;
params.scheduling_algorithm = scheduling_algorithm;
params.group_id = HAILO_UNIQUE_VDEVICE_GROUP_ID;
params.multi_process_service = multi_process_service;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
std::shared_ptr<VDevice> vdevice_ptr = vdevice.release();
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const void *element, const std::string &device_id, uint16_t device_count,
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm)
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service)
{
if (!device_id.empty()) {
auto result = create_shared_vdevice(element, device_id, vdevice_key, scheduling_algorithm);
auto result = create_shared_vdevice(element, device_id, vdevice_key, scheduling_algorithm, multi_process_service);
GST_CHECK_EXPECTED(result, element, RESOURCE, "Failed creating vdevice, status = %d", result.status());
m_vdevices.insert(result.value());
return result;
}
if (DEFAULT_VDEVICE_KEY != vdevice_key) {
auto result = create_shared_vdevice(element, device_count, vdevice_key, scheduling_algorithm);
auto result = create_shared_vdevice(element, device_count, vdevice_key, scheduling_algorithm, multi_process_service);
GST_CHECK_EXPECTED(result, element, RESOURCE, "Failed creating vdevice, status = %d", result.status());
m_vdevices.insert(result.value());
return result;
}
auto result = create_unique_vdevice(element, device_count, scheduling_algorithm);
auto result = create_unique_vdevice(element, device_count, scheduling_algorithm, multi_process_service);
GST_CHECK_EXPECTED(result, element, RESOURCE, "Failed creating vdevice, status = %d", result.status());
m_vdevices.insert(result.value());
return result;
}
Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm)
hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service)
{
auto expected_device = create_vdevice(m_element, device_id, device_count, vdevice_key, scheduling_algorithm);
auto expected_device = create_vdevice(m_element, device_id, device_count, vdevice_key, scheduling_algorithm, multi_process_service);
GST_CHECK_EXPECTED(expected_device, m_element, RESOURCE, "Failed creating vdevice, status = %d", expected_device.status());
return expected_device;
}
hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm, const char *hef_path)
hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service, const char *hef_path)
{
if (0 == device_count) {
device_count = HAILO_DEFAULT_DEVICE_COUNT;
@@ -125,7 +128,7 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
std::string device_id_str = (nullptr == device_id) ? "" : device_id;
auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key, scheduling_algorithm);
auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key, scheduling_algorithm, multi_process_service);
GST_CHECK_EXPECTED_AS_STATUS(vdevice, m_element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
m_vdevice = vdevice.release();
@@ -141,7 +144,7 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
auto hef = Hef::create(hef_path);
GST_CHECK_EXPECTED_AS_STATUS(hef, m_element, RESOURCE, "Failed reading hef file %s, status = %d", hef_path, hef.status());
m_hef = make_shared_nothrow<Hef>(std::move(hef.release()));
m_hef = make_shared_nothrow<Hef>(hef.release());
GST_CHECK(nullptr != m_hef, HAILO_OUT_OF_HOST_MEMORY, m_element, RESOURCE, "Allocating memory for HEF has failed!");
return HAILO_SUCCESS;
@@ -149,7 +152,7 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
hailo_status NetworkGroupHandle::configure_network_group(const char *net_group_name, hailo_scheduling_algorithm_t scheduling_algorithm, uint16_t batch_size)
{
auto net_groups_params_map = get_configure_params(*m_hef, net_group_name, batch_size);
auto net_groups_params_map = get_configure_params(*m_hef, *m_vdevice, net_group_name, batch_size);
GST_CHECK_EXPECTED_AS_STATUS(net_groups_params_map, m_element, RESOURCE, "Failed getting configure params, status = %d", net_groups_params_map.status());
auto expected_cng = m_net_group_config_manager.configure_network_group(m_element, m_shared_device_id, scheduling_algorithm,
@@ -185,12 +188,27 @@ Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> Netwo
"Inserting network name to configured networks has failed, status = %d", status);
}
auto input_params_map = m_cng->make_input_vstream_params(true, HAILO_FORMAT_TYPE_AUTO, HAILO_DEFAULT_VSTREAM_TIMEOUT_MS,
auto expected_input_vstream_infos = hef()->get_input_vstream_infos(network_name);
GST_CHECK_EXPECTED(expected_input_vstream_infos, m_element, RESOURCE, "Failed getting input vstream infos, status = %d",
expected_input_vstream_infos.status());
auto expected_input_params_map = m_cng->make_input_vstream_params(true, HAILO_FORMAT_TYPE_AUTO, HAILO_DEFAULT_VSTREAM_TIMEOUT_MS,
HAILO_DEFAULT_VSTREAM_QUEUE_SIZE, m_network_name);
GST_CHECK_EXPECTED(input_params_map, m_element, RESOURCE, "Failed making input vstream params, status = %d",
input_params_map.status());
GST_CHECK_EXPECTED(expected_input_params_map, m_element, RESOURCE, "Failed making input vstream params, status = %d",
expected_input_params_map.status());
auto input_vstreams = VStreamsBuilder::create_input_vstreams(*m_cng, input_params_map.release());
// In RGB formats, Gstreamer is padding each row to 4.
auto &&input_params_map = expected_input_params_map.release();
auto &&input_infos = expected_input_vstream_infos.release();
for (auto &input_info : input_infos) {
if (input_params_map.count(input_info.name)) {
auto &input_params = input_params_map[input_info.name];
if (input_info.format.order == HAILO_FORMAT_ORDER_NHWC) {
input_params.user_buffer_format.order = HAILO_FORMAT_ORDER_RGB4;
}
}
}
auto input_vstreams = VStreamsBuilder::create_input_vstreams(*m_cng, input_params_map);
GST_CHECK_EXPECTED(input_vstreams, m_element, RESOURCE, "Failed creating input vstreams, status = %d", input_vstreams.status());
// TODO: HRT-4095
@@ -220,17 +238,22 @@ Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> Netwo
GST_CHECK_EXPECTED(output_vstreams, m_element, RESOURCE, "Failed creating output vstreams, status = %d", output_vstreams.status());
return std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>(
std::move(input_vstreams.release()), std::move(output_vstreams.release()));
input_vstreams.release(), output_vstreams.release());
}
Expected<NetworkGroupsParamsMap> NetworkGroupHandle::get_configure_params(Hef &hef, const char *net_group_name, uint16_t batch_size)
Expected<NetworkGroupsParamsMap> NetworkGroupHandle::get_configure_params(Hef &hef, const VDevice &vdevice,
const char *net_group_name, uint16_t batch_size)
{
auto params = hef.create_configure_params(HAILO_STREAM_INTERFACE_PCIE, net_group_name);
auto stream_interface = vdevice.get_default_streams_interface();
GST_CHECK_EXPECTED(stream_interface, m_element, RESOURCE,
"Failed default stream interface configure params, status = %d", stream_interface.status());
auto params = hef.create_configure_params(*stream_interface, net_group_name);
GST_CHECK_EXPECTED(params, m_element, RESOURCE, "Failed creating configure params, status = %d", params.status());
params->batch_size = batch_size;
NetworkGroupsParamsMap net_groups_params_map;
net_groups_params_map[net_group_name] = std::move(params.release());
net_groups_params_map[net_group_name] = params.release();
return net_groups_params_map;
}
@@ -243,39 +266,6 @@ hailo_status NetworkGroupHandle::activate_network_group()
return HAILO_SUCCESS;
}
hailo_status NetworkGroupHandle::abort_streams()
{
if (nullptr == m_cng) {
return HAILO_SUCCESS;
}
hailo_status final_status = HAILO_SUCCESS;
auto input_streams = m_cng->get_input_streams_by_network(m_network_name);
GST_CHECK_EXPECTED_AS_STATUS(input_streams, m_element, RESOURCE, "Getting input streams by network name %s failed, status = %d",
m_network_name.c_str(), input_streams.status());
for (auto &input_stream : input_streams.value()) {
hailo_status status = input_stream.get().abort();
if (HAILO_SUCCESS != status) {
g_warning("Abort of input stream %s has failed, status = %d", input_stream.get().name().c_str(), status);
final_status = status;
}
}
auto output_streams = m_cng->get_output_streams_by_network(m_network_name);
GST_CHECK_EXPECTED_AS_STATUS(output_streams, m_element, RESOURCE, "Getting output streams by network name %s failed, status = %d",
m_network_name.c_str(), output_streams.status());
for (auto &output_stream : output_streams.value()) {
hailo_status status = output_stream.get().abort();
if (HAILO_SUCCESS != status) {
g_warning("Abort of output stream %s has failed, status = %d", output_stream.get().name().c_str(), status);
final_status = status;
}
}
return final_status;
}
Expected<bool> NetworkGroupHandle::remove_network_group()
{
bool was_network_deactivated = false;
@@ -407,7 +397,7 @@ Expected<std::shared_ptr<ActivatedNetworkGroup>> NetworkGroupActivationManager::
GST_CHECK_EXPECTED(activated_network_group, element, RESOURCE, "Failed activating network group, status = %d",
activated_network_group.status());
std::shared_ptr<ActivatedNetworkGroup> ang = std::move(activated_network_group.release());
std::shared_ptr<ActivatedNetworkGroup> ang = activated_network_group.release();
m_activated_net_groups[NetworkGroupConfigManager::get_configure_string(device_id, hef_hash, net_group_name, batch_size)] = ang;
return ang;

View File

@@ -80,12 +80,11 @@ public:
m_vdevice(nullptr), m_hef(nullptr), m_cng(nullptr), m_ang(nullptr) {}
hailo_status set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm,
const char *hef_path);
bool multi_process_service, const char *hef_path);
hailo_status configure_network_group(const char *net_group_name, hailo_scheduling_algorithm_t scheduling_algorithm, uint16_t batch_size);
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> create_vstreams(const char *network_name,
hailo_scheduling_algorithm_t scheduling_algorithm, const std::vector<hailo_format_with_name_t> &output_formats);
hailo_status activate_network_group();
hailo_status abort_streams();
Expected<bool> remove_network_group();
hailo_status set_scheduler_timeout(const char *network_name, uint32_t timeout_ms);
@@ -98,11 +97,12 @@ public:
}
private:
Expected<NetworkGroupsParamsMap> get_configure_params(Hef &hef, const char *net_group_name, uint16_t batch_size);
Expected<NetworkGroupsParamsMap> get_configure_params(Hef &hef, const VDevice &vdevice, const char *net_group_name,
uint16_t batch_size);
static Expected<std::shared_ptr<VDevice>> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count,
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm);
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service);
Expected<std::shared_ptr<VDevice>> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm);
hailo_scheduling_algorithm_t scheduling_algorithm, bool multi_process_service);
static std::unordered_set<std::shared_ptr<VDevice>> m_vdevices;
static NetworkGroupConfigManager m_net_group_config_manager;

View File

@@ -1,9 +1 @@
add_subdirectory(src)
# copy files to venv
if(HAILO_BUILD_PYHAILORT_VENV)
add_custom_target(pyhailort_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:_pyhailort> ${CMAKE_CURRENT_LIST_DIR}/platform/hailo_platform/pyhailort/
)
add_dependencies(pyhailort_venv _pyhailort)
endif()

View File

@@ -1,4 +1,4 @@
from hailo_platform import (HEF, PcieDevice, ConfigureParams, InferVStreams, InputVStreamParams,
from hailo_platform import (HEF, VDevice, ConfigureParams, InferVStreams, InputVStreamParams,
OutputVStreamParams, FormatType)
from hailo_platform.pyhailort.pyhailort import HailoStreamInterface
import numpy as np
@@ -12,7 +12,7 @@ def parse_args():
def main():
args = parse_args()
with PcieDevice() as target:
with VDevice() as target:
hef = HEF(args.hef_path)
configure_params = ConfigureParams.create_from_hef(hef, interface=HailoStreamInterface.PCIe)
network_groups = target.configure(hef, configure_params)

View File

@@ -1,8 +1,9 @@
import argparse
from multiprocessing import Process
import time
import numpy as np
from hailo_platform import (HEF, PcieDevice, HailoStreamInterface, ConfigureParams, InputVStreamParams, InputVStreams,
from multiprocessing import Process
from hailo_platform import (HEF, VDevice, HailoStreamInterface, ConfigureParams, InputVStreamParams, InputVStreams,
OutputVStreamParams, OutputVStreams)
def send(configured_network, num_frames):
@@ -45,17 +46,24 @@ def main():
args = parse_args()
hef = HEF(args.hef_path)
with PcieDevice() as device:
with VDevice() as device:
configure_params = ConfigureParams.create_from_hef(hef, interface=HailoStreamInterface.PCIe)
network_group = device.configure(hef, configure_params)[0]
network_group_params = network_group.create_params()
send_process = Process(target=send, args=(network_group, args.num_frames))
recv_process = Process(target=recv_all, args=(network_group, args.num_frames))
time_before = time.time()
recv_process.start()
send_process.start()
with network_group.activate(network_group_params):
send_process.join()
recv_process.join()
fps = args.num_frames / (time.time() - time_before)
print('Inference ran successfully')
print(f'FPS: {fps}')
if __name__ == '__main__':
main()

View File

@@ -26,7 +26,7 @@ from hailo_platform.pyhailort.pyhailort import (HEF, ConfigureParams,
InputVStreams, OutputVStreams,
InferVStreams, HailoStreamDirection, HailoFormatFlags, HailoCpuId, Device, VDevice,
DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex,
HailoRTException)
HailoRTException, YOLOv5PostProcessingOp)
def _verify_pyhailort_lib_exists():
python_version = "".join(str(i) for i in sys.version_info[:2])
@@ -62,4 +62,4 @@ __all__ = ['EthernetDevice', 'DvmTypes', 'PowerMeasurementTypes',
'MipiIspImageInOrder', 'MipiIspImageOutDataType', 'join_drivers_path', 'IspLightFrequency', 'HailoPowerMode',
'Endianness', 'HailoStreamInterface', 'InputVStreamParams', 'OutputVStreamParams',
'InputVStreams', 'OutputVStreams', 'InferVStreams', 'HailoStreamDirection', 'HailoFormatFlags', 'HailoCpuId',
'Device', 'VDevice', 'HailoRTException']
'Device', 'VDevice', 'HailoRTException', 'YOLOv5PostProcessingOp']

View File

@@ -50,17 +50,19 @@ class HailoHWObject(object):
@property
def name(self):
"""str: The name of this target. Valid values are defined by :class:`~hailo_platform.pyhailort.hw_object.InferenceTargets`"""
# self._logger.warning("HailoHWObject name property is deprecated! Please use VDevice object with device_id.")
return type(self).NAME
@property
def is_hardware(self):
"""bool: Indicates this target runs on a physical hardware device."""
# TODO: SDK should implement in Target
# self._logger.warning("HailoHWObject is_hardware property is deprecated! Please use VDevice object, or derive from it.")
return type(self).IS_HARDWARE
@property
def device_id(self):
"""Getter for the device_id.
Returns:
str: A string ID of the device. BDF for PCIe devices, IP address for Ethernet devices, "Core" for core devices.
"""
@@ -72,12 +74,14 @@ class HailoHWObject(object):
Returns:
list of str: Sorted list of the output layer names.
"""
# self._logger.warning("HailoHWObject sorted_output_layer_names property is deprecated! Please use ConfiguredNetwork get_sorted_output_names.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to sorted_output_layer_names is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_sorted_output_names()
@contextmanager
def use_device(self, *args, **kwargs):
# self._logger.warning("HailoHWObject use_device context manager is deprecated! Please use VDevice object.")
"""A context manager that wraps the usage of the device (deprecated)."""
self._is_device_used = True
yield
@@ -89,6 +93,7 @@ class HailoHWObject(object):
Returns:
dict: Keys are device output names and values are lists of layers' names.
"""
# self._logger.warning("HailoHWObject get_output_device_layer_to_original_layer_map function is deprecated!")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {stream_info.name : self._loaded_network_groups[0].get_vstream_names_from_stream_name(stream_info.name)
@@ -100,6 +105,7 @@ class HailoHWObject(object):
Returns:
dict: Keys are the names of the layers and values are device outputs names.
"""
# self._logger.warning("HailoHWObject get_original_layer_to_device_layer_map function is deprecated!")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {vstream_info.name : self._loaded_network_groups[0].get_stream_names_from_vstream_name(vstream_info.name)
@@ -108,24 +114,31 @@ class HailoHWObject(object):
@property
def device_input_layers(self):
"""Get a list of the names of the device's inputs."""
# self._logger.warning("HailoHWObject device_input_layers function is deprecated! Please use ConfiguredNetwork object.")
return [layer.name for layer in self.get_input_stream_infos()]
@property
def device_output_layers(self):
"""Get a list of the names of the device's outputs."""
# self._logger.warning("HailoHWObject device_output_layers function is deprecated! Please use ConfiguredNetwork object.")
return [layer.name for layer in self.get_output_stream_infos()]
def hef_loaded(self):
"""Return True if this object has loaded the model HEF to the hardware device."""
# TODO: SDK should implement in Target
# self._logger.warning("HailoHWObject hef_loaded function is deprecated! Please use VDevice object, or derive from it.")
return self._hef_loaded
def outputs_count(self):
"""Return the amount of output tensors that are returned from the hardware device for every
input image.
"""
# self._logger.warning("HailoHWObject outputs_count function is deprecated! Please use ConfiguredNetwork object.")
return len(self.get_output_vstream_infos())
def _clear_shapes(self):
# TODO: SDK should implement in Target
# self._logger.warning("HailoHWObject _clear_shapes function is deprecated! Please use ConfiguredNetwork object.")
self._hw_consts = None
@property
@@ -135,6 +148,7 @@ class HailoHWObject(object):
Returns:
str: Model name.
"""
# self._logger.warning("HailoHWObject model_name property is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) == 1:
return self._loaded_network_groups[0].name
raise HailoHWObjectException(
@@ -146,6 +160,7 @@ class HailoHWObject(object):
Returns:
Tuple of output shapes, sorted by the output names.
"""
# self._logger.warning("HailoHWObject get_output_shapes function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Calling get_output_shapes is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_shapes()
@@ -166,7 +181,6 @@ class HailoChipObject(HailoHWObject):
def control(self):
""":class:`HailoControl <hailo_platform.pyhailort.control_object.HailoControl>`: Returns
the control object of this device, which implements the control API of the Hailo device.
.. attention:: Use the low level control API with care.
"""
if self._control_object is None:
@@ -181,6 +195,7 @@ class HailoChipObject(HailoHWObject):
Returns:
dict of :obj:'numpy.dtype': where the key is model input_layer name, and the value is dtype as the device expect to get for this input.
"""
# self._logger.warning("HailoChipObject get_all_input_layers_dtype function is deprecated! Please use ConfiguredNetwork object.")
return {stream.name: HailoRTTransformUtils.get_dtype(stream.data_bytes) for stream in self.get_input_stream_infos()}
def get_input_vstream_infos(self, network_name=None):
@@ -193,7 +208,7 @@ class HailoChipObject(HailoHWObject):
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
"""
# self._logger.warning("HailoChipObject get_input_vstream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_vstream_infos(network_name=network_name)
@@ -208,7 +223,7 @@ class HailoChipObject(HailoHWObject):
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
"""
# self._logger.warning("HailoChipObject get_output_vstream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_vstream_infos(network_name=network_name)
@@ -223,7 +238,7 @@ class HailoChipObject(HailoHWObject):
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
"""
# self._logger.warning("HailoChipObject get_all_vstream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_vstream_infos(network_name=network_name)
@@ -239,6 +254,7 @@ class HailoChipObject(HailoHWObject):
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
of all input low-level streams.
"""
# self._logger.warning("HailoChipObject get_input_stream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_stream_infos(network_name=network_name)
@@ -254,6 +270,7 @@ class HailoChipObject(HailoHWObject):
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
of all output low-level streams.
"""
# self._logger.warning("HailoChipObject get_output_stream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_stream_infos(network_name=network_name)
@@ -268,7 +285,7 @@ class HailoChipObject(HailoHWObject):
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
"""
# self._logger.warning("HailoChipObject get_all_stream_infos function is deprecated! Please use ConfiguredNetwork object.")
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_stream_infos(network_name=network_name)
@@ -276,7 +293,6 @@ class HailoChipObject(HailoHWObject):
@property
def loaded_network_groups(self):
"""Getter for the property _loaded_network_groups.
Returns:
list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
"""
@@ -290,7 +306,6 @@ class HailoChipObject(HailoHWObject):
def configure(self, hef, configure_params_by_name={}):
"""Configures target device from HEF object.
Args:
hef (:class:`~hailo_platform.pyhailort.pyhailort.HEF`): HEF to configure the device from
configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
@@ -313,6 +328,7 @@ class HailoChipObject(HailoHWObject):
Returns:
Tuple of integers representing the input_shape.
"""
# self._logger.warning("HailoChipObject get_input_shape function is deprecated! Please use ConfiguredNetwork object.")
if name is None:
name = self.get_input_vstream_infos()[0].name
@@ -332,6 +348,7 @@ class HailoChipObject(HailoHWObject):
Returns:
int: The index of the layer name in the output list.
"""
# self._logger.warning("HailoChipObject get_index_from_name function is deprecated! Please use ConfiguredNetwork object.")
try:
return self.sorted_output_layer_names.index(name)
except ValueError:
@@ -383,7 +400,6 @@ class EthernetDevice(HailoChipObject):
self._control_object = None
self._open_device()
self._id = "{}".format(self._remote_ip)
identity = self._control_object._identify_info
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@@ -398,6 +414,7 @@ class EthernetDevice(HailoChipObject):
Returns:
list of str: IPs of scanned devices.
"""
# default_logger().warning("EthernetDevice scan_devices method is deprecated! Please use scan() of Device object.")
udp_scanner = HailoUdpScan()
return udp_scanner.scan_devices(interface_name, timeout_seconds=timeout_seconds)
@@ -418,6 +435,7 @@ class EthernetDevice(HailoChipObject):
@property
def remote_ip(self):
"""Return the IP of the remote device."""
# self._logger.warning("EthernetDevice remote_ip method is deprecated! Please use Device object.")
return self._remote_ip
@@ -437,6 +455,7 @@ class PcieDevice(HailoChipObject):
:func:`PcieDevice.scan_devices` to get list of all available devices.
"""
super(PcieDevice, self).__init__()
# self._logger.warning("PcieDevice deprecated! Please use VDevice object.")
gc.collect()
# PcieDevice __del__ function tries to release self._device.
@@ -460,6 +479,7 @@ class PcieDevice(HailoChipObject):
Returns:
list of :obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`
"""
# default_logger().warning("PcieDevice scan_devices method is deprecated! Please use scan() of Device object.")
return InternalPcieDevice.scan_devices()
def _open_device(self, device_info):

View File

@@ -1,5 +1,4 @@
from enum import Enum, IntEnum
import re
import signal
import struct
import pkg_resources
@@ -123,7 +122,7 @@ class ExceptionWrapper(object):
raise HailoRTInvalidFrameException("An invalid frame was received")
if string_error_code == "HAILO_TIMEOUT":
raise HailoRTTimeout("Received a timeout - hailort has failed because a timeout had occurred")
if string_error_code == "HAILO_STREAM_ABORTED":
if string_error_code == "HAILO_STREAM_ABORTED_BY_HW":
raise HailoRTStreamAborted("Stream aborted due to an external event")
if string_error_code == "HAILO_INVALID_OPERATION":
@@ -1076,6 +1075,7 @@ class HailoRTTransformUtils(object):
class InternalEthernetDevice(object):
def __init__(self, address, port, response_timeout_seconds=10, max_number_of_attempts=3):
# default_logger().warning("InternalEthernetDevice is deprecated! Please use Device object.")
self.device = None
self._address = address
self._port = port
@@ -1104,6 +1104,7 @@ class PcieDeviceInfo(_pyhailort.PcieDeviceInfo):
def __init__(self, bus, device, func, domain=None):
super(PcieDeviceInfo, self).__init__()
# default_logger().warning("PcieDeviceInfo is deprecated! Please use Device object with device_id.")
self.bus = bus
self.device = device
self.func = func
@@ -1140,6 +1141,7 @@ class PcieDeviceInfo(_pyhailort.PcieDeviceInfo):
class InternalPcieDevice(object):
def __init__(self, device_info=None):
# self._logger.warning("InternalPcieDevice deprecated! Please use Device object.")
self.device = None
if device_info is None:
device_info = InternalPcieDevice.scan_devices()[0]
@@ -1233,7 +1235,7 @@ class HailoFormatFlags(_pyhailort.FormatFlags):
SUPPORTED_PROTOCOL_VERSION = 2
SUPPORTED_FW_MAJOR = 4
SUPPORTED_FW_MINOR = 10
SUPPORTED_FW_MINOR = 12
SUPPORTED_FW_REVISION = 0
MEGA_MULTIPLIER = 1000.0 * 1000.0
@@ -1250,9 +1252,11 @@ class DeviceArchitectureTypes(IntEnum):
class BoardInformation(object):
def __init__(self, protocol_version, fw_version_major, fw_version_minor, fw_version_revision,
logger_version, board_name, is_release, device_architecture, serial_number, part_number, product_name):
logger_version, board_name, is_release, extended_context_switch_buffer, device_architecture,
serial_number, part_number, product_name):
self.protocol_version = protocol_version
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.APP)
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release,
extended_context_switch_buffer, HailoFirmwareType.APP)
self.logger_version = logger_version
self.board_name = board_name
self.is_release = is_release
@@ -1303,8 +1307,9 @@ class BoardInformation(object):
raise HailoRTException("Unsupported device architecture.")
class CoreInformation(object):
def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release):
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.CORE)
def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release, extended_context_switch_buffer):
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release,
extended_context_switch_buffer, HailoFirmwareType.CORE)
self.is_release = is_release
def __str__(self):
@@ -1456,17 +1461,20 @@ class HailoFirmwareType(Enum):
class HailoFirmwareVersion(object):
"""Represents a Hailo chip firmware version."""
DEV_BIT = 0x80000000
CORE_BIT = 0x08000000
EXTENDED_CONTEXT_SWITCH_BUFFER_BIT = 0x40000000
DEV_BIT = 0x80000000
FW_VERSION_FORMAT = '<III'
def __init__(self, firmware_version_buffer, is_release, fw_type):
def __init__(self, firmware_version_buffer, is_release, extended_context_switch_buffer, fw_type):
"""Initialize a new Hailo Firmware Version object.
Args:
firmware_version_buffer (str): A buffer containing the firmware version struct.
is_release (bool, optional): Flag indicating if firmware is at develop/release mode.
None indicates unknown
extended_context_switch_buffer (bool): Flag indicating if firmware has an extended context switch buffer.
fw_type (HailoFirmwareType): Firmware type
"""
self.major, self.minor, self.revision = struct.unpack(
self.FW_VERSION_FORMAT,
@@ -1474,21 +1482,24 @@ class HailoFirmwareVersion(object):
self.fw_type = fw_type
self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
self.extended_context_switch_buffer = extended_context_switch_buffer
self.revision &= ~(self.CORE_BIT | self.DEV_BIT)
self.revision &= ~(self.CORE_BIT | self.EXTENDED_CONTEXT_SWITCH_BUFFER_BIT | self.DEV_BIT)
def __str__(self):
"""Returns:
str: Firmware version in a human readable format.
"""
return '{}.{}.{} ({},{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value)
return '{}.{}.{} ({},{}{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value,
',extended context switch buffer' if self.extended_context_switch_buffer else '')
@classmethod
def construct_from_params(cls, major, minor, revision, is_release, fw_type):
def construct_from_params(cls, major, minor, revision, is_release, extended_context_switch_buffer, fw_type):
"""Returns:
class HailoFirmwareVersion : with the given Firmware version.
"""
return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release, fw_type)
return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release,
extended_context_switch_buffer, fw_type)
@property
def comparable_value(self):
@@ -1538,14 +1549,6 @@ class SupportedFeatures(object):
def _is_feature_enabled(self, feature):
return (self.supported_features & feature) != 0
def _enum_to_dict(enum):
return {k: v for k, v in enum.__dict__.items() if not re.match("__(.*)", str(k)) and isinstance(v, enum)}
def _get_buffer_index_enum_member(index):
for name, member in _enum_to_dict(MeasurementBufferIndex).items():
if int(member) == index:
return member
raise HailoRTException("Invalid index")
class Control:
"""The control object of this device, which implements the control API of the Hailo device.
@@ -1675,11 +1678,10 @@ class Control:
with ExceptionWrapper():
return self._device.power_measurement(dvm, measurement_type)
def start_power_measurement(self, delay=None, averaging_factor=AveragingFactor.AVERAGE_256, sampling_period=SamplingPeriod.PERIOD_1100us):
def start_power_measurement(self, averaging_factor=AveragingFactor.AVERAGE_256, sampling_period=SamplingPeriod.PERIOD_1100us):
"""Start performing a long power measurement.
Args:
delay: Unused parameter. Will be removed in future versions.
averaging_factor (:class:`~hailo_platform.pyhailort.pyhailort.AveragingFactor`):
Number of samples per time period, sensor configuration value.
sampling_period (:class:`~hailo_platform.pyhailort.pyhailort.SamplingPeriod`):
@@ -1691,9 +1693,6 @@ class Control:
calculated by the firmware is "average of averages", because it averages values
that have already been averaged by the sensor.
"""
# TODO: Remove deprecated arg
if delay is not None:
self._logger.warning("Passing 'delay' to 'start_power_measurement()' is deprecated and will be removed in future versions")
with ExceptionWrapper():
return self._device.start_power_measurement(averaging_factor, sampling_period)
@@ -1727,11 +1726,6 @@ class Control:
This function can perform measurements for more than just power. For all supported measurement types
view :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`
"""
# TODO: Remove deprecated arg
if isinstance(buffer_index, int):
self._logger.warning("Passing integer as 'buffer_index' to 'set_power_measurement()' is deprecated. One should pass "
":class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex` as 'buffer_index' instead.")
buffer_index = _get_buffer_index_enum_member(buffer_index)
with ExceptionWrapper():
return self._device.set_power_measurement(buffer_index, dvm, measurement_type)
@@ -1760,11 +1754,6 @@ class Control:
if ((self._identify_info.device_architecture != DeviceArchitectureTypes.HAILO8) and
(self._identify_info.device_architecture != DeviceArchitectureTypes.HAILO8L)):
raise HailoRTException("Invalid device architecture: {}".format(self._identify_info.device_architecture))
# TODO: Remove deprecated arg
if isinstance(buffer_index, int):
self._logger.warning("Passing integer as 'buffer_index' to 'get_power_measurement()' is deprecated. One should pass "
":class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex` as 'buffer_index' instead.")
buffer_index = _get_buffer_index_enum_member(buffer_index)
with ExceptionWrapper():
return self._device.get_power_measurement(buffer_index, should_clear)
@@ -1822,8 +1811,9 @@ class Control:
response = self._device.identify()
board_information = BoardInformation(response.protocol_version, response.fw_version.major,
response.fw_version.minor, response.fw_version.revision, response.logger_version,
response.board_name, response.is_release, int(response.device_architecture), response.serial_number,
response.part_number, response.product_name)
response.board_name, response.is_release, response.extended_context_switch_buffer,
int(response.device_architecture), response.serial_number, response.part_number,
response.product_name)
return board_information
def core_identify(self):
@@ -1835,7 +1825,7 @@ class Control:
with ExceptionWrapper():
response = self._device.core_identify()
core_information = CoreInformation(response.fw_version.major, response.fw_version.minor,
response.fw_version.revision, response.is_release)
response.fw_version.revision, response.is_release, response.extended_context_switch_buffer)
return core_information
def set_fw_logger(self, level, interface_mask):
@@ -2190,7 +2180,6 @@ class Control:
return self._device
# TODO: HRT-7718 - implement more functionalities from hw_object.py
class Device:
""" Hailo device object representation. """
@@ -2213,6 +2202,7 @@ class Device:
"""
gc.collect()
self._logger = default_logger()
# Device __del__ function tries to release self._device.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
@@ -2286,47 +2276,66 @@ class Device:
"""
return self._control_object
def read_log(self, count, cpu_id):
"""
Returns:
Returns buffer with debug log data.
Args:
count (int): bytes count to read
cpu_id (HailoCpuId): cpu id
"""
with ExceptionWrapper():
return self._device.read_log(count, cpu_id)
@property
def loaded_network_groups(self):
"""Getter for the property _loaded_network_groups.
Returns:
list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
"""
return self._loaded_network_groups
@property
def _loaded_network_group(self):
if len(self._loaded_network_groups) != 1:
raise HailoRTException("Access to network group is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0]
class VDevice(object):
"""Hailo virtual device representation."""
def __init__(self, params=None, device_infos=None, *, device_ids=None):
def __init__(self, params=None, *, device_ids=None):
"""Create the Hailo virtual device object.
Args:
params (:obj:`hailo_platform.pyhailort.pyhailort.VDeviceParams`, optional): VDevice params, call
:func:`VDevice.create_params` to get default params. Excludes 'device_ids' and 'device_infos'.
device_infos (list of :obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`, optional):
Deprecated - one should use device_ids instead. If given - pcie devices infos to create VDevice from,
call :func:`PcieDevice.scan_devices` to get list of all available devices. Excludes 'params' and 'device_ids.
device_ids (list of str, optional): devices ids to create VDevice from, call :func:`_Device.scan` to get
list of all available devices. Excludes 'params' and 'device_infos'.
:func:`VDevice.create_params` to get default params. Excludes 'device_ids'.
device_ids (list of str, optional): devices ids to create VDevice from, call :func:`Device.scan` to get
list of all available devices. Excludes 'params'.
"""
gc.collect()
# VDevice __del__ function tries to release self._vdevice.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
self._vdevice = None
self._id = "VDevice"
self._params = params
# Convert device_infos to device_ids
if device_infos is not None:
if device_ids is not None:
raise HailoRTException("VDevice can by ids from either device_ids or device_infos. Both parameters were passed to the c'tor")
logger = default_logger()
logger.warning("Warning - passing device_infos is deprecated. One should pass device_ids.")
device_ids = [str(device_info) for device_info in device_infos]
device_infos = None
self._loaded_network_groups = []
self._creation_pid = os.getpid()
self._device_ids = device_ids
if self._device_ids is not None:
if self._params is not None:
raise HailoRTException("VDevice can be created from params or device ids/infos. Both parameters were passed to the c'tor")
raise HailoRTException("VDevice can be created from params or device ids. Both parameters were passed to the c'tor")
self._vdevice = None
self._loaded_network_groups = []
self._open_vdevice()
self._creation_pid = os.getpid()
def _open_vdevice(self):
if self._device_ids is not None:
with ExceptionWrapper():
@@ -2382,19 +2391,6 @@ class VDevice(object):
phys_dev_infos = self.get_physical_devices_ids()
return [Device(dev_id) for dev_id in phys_dev_infos]
def get_physical_devices_infos(self):
"""Deprecated: :func:`VDevice.get_physical_devices_infos` is deprecated. One should use
(:func:`VDevice.get_physical_devices_ids`) instead.
Gets the physical devices infos.
Return:
list of :obj:`~hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`: The underlying physical devices infos.
"""
logger = default_logger()
logger.warning("Warning - VDevice.get_physical_devices_infos() is deprecated. One should use VDevice.get_physical_devices_ids.")
return [PcieDeviceInfo.from_string(dev_id) for dev_id in self.get_physical_devices_ids()]
def get_physical_devices_ids(self):
"""Gets the physical devices ids.
@@ -2404,6 +2400,22 @@ class VDevice(object):
with ExceptionWrapper():
return self._vdevice.get_physical_devices_ids()
@property
def loaded_network_groups(self):
"""Getter for the property _loaded_network_groups.
Returns:
list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
"""
return self._loaded_network_groups
@property
def _loaded_network_group(self):
if len(self._loaded_network_groups) != 1:
raise HailoRTException("Access to network group is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0]
class InputVStreamParams(object):
"""Parameters of an input virtual stream (host to device)."""
@@ -2883,3 +2895,14 @@ class OutputVStreams(object):
def __iter__(self):
return iter(self._vstreams.values())
class YOLOv5PostProcessingOp(object):
def __init__(self, anchors, shapes, formats, quant_infos, image_height, image_width, confidence_threshold, iou_threshold, num_of_classes,
should_dequantize, max_boxes, should_sigmoid, one_class_per_bbox=True):
self._op = _pyhailort.YOLOv5PostProcessingOp.create(anchors, shapes, formats, quant_infos, image_height, image_width, confidence_threshold,
iou_threshold, num_of_classes, should_dequantize, max_boxes, should_sigmoid, one_class_per_bbox)
def execute(self, net_flow_tensors):
return self._op.execute(net_flow_tensors)

View File

@@ -49,12 +49,6 @@ class HailoDeviceCmdUtil(CmdUtilsBaseUtil):
def validate_args(self, args):
if args.target == HailoCLITargets.udp.value:
if not args.ip:
self._parser.error('When using --target udp, you must supply --ip')
if args.board_location:
self._parser.error("When using --target udp, you must not supply --board-location")
if args.board_location:
all_devices = InternalPcieDevice.scan_devices()
if args.board_location not in all_devices:
@@ -62,8 +56,6 @@ class HailoDeviceCmdUtil(CmdUtilsBaseUtil):
.format(args.board_location))
def add_target_args(self, args_parser):
args_parser.add_argument('--target', type=str, choices=[t.value for t in HailoCLITargets],
default=None, help='Device type to use')
args_parser.add_argument('--ip', type=str, default=None, help='IP address of the target (udp)')
args_parser.add_argument('-s', '--board-location', help=PcieDeviceInfo.BOARD_LOCATION_HELP_STRING,
type=PcieDeviceInfo.argument_type)

View File

@@ -76,6 +76,12 @@ class UDPRateLimiterCLI(HailortCliUtil):
super().__init__(parser, 'udp-rate-limiter')
class VersionCLI(HailortCliUtil):
"""CLI tool for hailort version."""
def __init__(self, parser):
super().__init__(parser, '--version')
class TutorialRequired(Exception):
pass

View File

@@ -9,7 +9,6 @@ from hailo_platform.tools.hailocli.base_utils import HailortCliUtil, Helper, Hai
from hailo_platform.tools.hailocli.hailocli_commands import (FWUpdaterCLI, SSBUpdaterCLI, ControlCommandCLI, ScanCommandCLI,
LoggerCommandCLI, MeasurePowerCommandCLI, RunCommandCLI, SensorConfigCommandCLI,
FWConfigCommandCLI, BenchmarkCommandCLI, UDPRateLimiterCLI, MonitorCommandCLI, ParseHEFCommandCLI, TutorialRunnerCLI)
from hailo_platform.common.logger.logger import default_logger
# Note: PlatformCommands are external dependencies in phase2-sdk/demos repo; don't change!
class PlatformCommands:
@@ -19,8 +18,6 @@ class PlatformCommands:
'fw-update': ('Firmware update tool', FWUpdaterCLI),
'ssb-update': ('Second stage boot update tool', SSBUpdaterCLI),
'fw-config': ('Firmware configuration tool', FWConfigCommandCLI),
'udp-limiter': ('Alias to udp-rate-limiter. Deprecated.', UDPRateLimiterCLI),
'udp': ('Alias to udp-rate-limiter. Deprecated.', UDPRateLimiterCLI),
'udp-rate-limiter': ('Limit UDP rate', UDPRateLimiterCLI),
'fw-control': ('Useful firmware control operations', ControlCommandCLI),
'fw-logger': ('Download fw logs to a file', LoggerCommandCLI),
@@ -32,6 +29,7 @@ class PlatformCommands:
'parse-hef': (' Parse HEF to get information about its components', ParseHEFCommandCLI),
'measure-power': ('Measures power consumption', MeasurePowerCommandCLI),
'tutorial': ('Runs the tutorials in jupyter notebook', TutorialRunnerCLI),
#'--version': ('Print program version and exit', VersionCLI)
}
def __init__(self):
@@ -79,10 +77,6 @@ class PlatformCommands:
return self.INVALID_COMMAND_EXIT_CODE
command_name = argv[0]
# TODO: Remove deprecation warning
if command_name in ['udp', 'udp-limiter']:
logger = default_logger()
logger.warning("Warning - running '{}' command is deprecated, support will be removed in future versions. Use 'udp-rate-limiter' instead.".format(command_name))
if (command_name in commands) and isinstance(commands[command_name], HailortCliUtil):
# HailortCliUtil just passes the rest of the argv to hailortcli
try :

View File

@@ -11,7 +11,9 @@
"\n",
"**Requirements:**\n",
"\n",
"* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```"
"* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```\n",
"\n",
"It is recommended to use the command ``hailo tutorial`` (when inside the virtualenv) to open a Jupyter server that contains the tutorials."
]
},
{

View File

@@ -16,7 +16,9 @@
"\n",
"**Attention:**\n",
"\n",
"* These examples should run in a different process than the one that performs the actual inference.\n"
"* These examples should run in a different process than the one that performs the actual inference.\n",
"\n",
"It is recommended to use the command ``hailo tutorial`` (when inside the virtualenv) to open a Jupyter server that contains the tutorials."
]
},
{

View File

@@ -4,12 +4,11 @@ contextlib2==0.6.0.post1
distlib==0.3.4
filelock==3.4.1
future==0.18.2
importlib-metadata==3.7.3
importlib-metadata==5.1.0
importlib-resources==5.1.2
netaddr==0.8.0
netifaces==0.10.9
numpy==1.19.4
numpy==1.23.3
typing_extensions==4.1.1
verboselogs==1.7
virtualenv==20.4.3
zipp==3.4.1

View File

@@ -23,6 +23,7 @@ def _get_pyhailort_lib_path():
with open(conf_file_path, "r") as conf_file:
content = json.load(conf_file)
# TODO (HRT-8637): change this hard-coded path
return f"../hailo_platform/pyhailort/_pyhailort*{content['py_version']}*{content['arch']}*.{extension}"
def _get_package_paths():
@@ -56,7 +57,7 @@ if __name__ == "__main__":
"netifaces",
"verboselogs",
# Pinned versions
"numpy==1.19.4",
"numpy==1.23.3",
],
name="hailort",
package_data={
@@ -68,6 +69,6 @@ if __name__ == "__main__":
"linux_aarch64",
],
url="https://hailo.ai/",
version="4.10.0",
version="4.12.0",
zip_safe=False,
)

View File

@@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYHAILORT_INTERNAL OFF)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if(NOT DEFINED PYBIND11_PYTHON_VERSION)
message(FATAL_ERROR "PYBIND11_PYTHON_VERSION is not defined. To build _pyhailort, pass python version")
endif()
string(REPLACE "." "" dpython ${PYBIND11_PYTHON_VERSION}) # E.g "3.5" -> "35"
if(${dpython} LESS "38")
set(m_flag "m")
@@ -45,11 +49,24 @@ exclude_archive_libs_symbols(_pyhailort)
if (HAILO_BUILD_PYHAILORT_INTERNAL)
add_subdirectory(internal)
# copy files to venv
if(HAILO_BUILD_PYHAILORT_VENV)
# copy files to a path the venv will look for
add_custom_target(pyhailort_internal_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:_pyhailort_internal> ${PROJECT_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/
)
add_dependencies(pyhailort_internal_venv _pyhailort_internal)
endif()
endif()
# TODO (HRT-8637): change this hard-coded path
set(HAILO_PYHAILORT_TARGET_DIR ${CMAKE_CURRENT_LIST_DIR}/../platform/hailo_platform/pyhailort/)
# copy files to a path the venv and whl will look for
message(STATUS "Copying _pyhailort artifacts into " ${HAILO_PYHAILORT_TARGET_DIR})
add_custom_target(pyhailort_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:_pyhailort> ${HAILO_PYHAILORT_TARGET_DIR}
)
add_dependencies(pyhailort_venv _pyhailort)
install(TARGETS _pyhailort
LIBRARY DESTINATION ${HAILO_PYHAILORT_TARGET_DIR}
CONFIGURATIONS Release
)

View File

@@ -469,6 +469,12 @@ const char *DeviceWrapper::get_dev_id() const
return device().get_dev_id();
}
void DeviceWrapper::set_sleep_state(hailo_sleep_state_t sleep_state)
{
auto status = device().set_sleep_state(sleep_state);
VALIDATE_STATUS(status);
}
void DeviceWrapper::add_to_python_module(py::module &m)
{
py::class_<DeviceWrapper>(m, "Device")
@@ -533,6 +539,7 @@ void DeviceWrapper::add_to_python_module(py::module &m)
.def("set_notification_callback", &DeviceWrapper::set_notification_callback)
.def("remove_notification_callback", &DeviceWrapper::remove_notification_callback)
.def("set_sleep_state", &DeviceWrapper::set_sleep_state)
;
}

View File

@@ -125,6 +125,7 @@ public:
void direct_write_memory(uint32_t address, py::bytes buffer);
py::bytes direct_read_memory(uint32_t address, uint32_t size);
const char *get_dev_id() const;
void set_sleep_state(hailo_sleep_state_t sleep_state);
static void add_to_python_module(py::module &m);

View File

@@ -26,7 +26,6 @@ target_link_libraries(_pyhailort_internal PRIVATE
hef_proto
spdlog::spdlog
readerwriterqueue
microprofile
scheduler_mon_proto)
if(HAILO_BUILD_SERVICE)
target_link_libraries(_pyhailort_internal PRIVATE grpc++_unsecure hailort_rpc_grpc_proto)

View File

@@ -13,10 +13,163 @@
#include "hailo/hailort.h"
#include "transform_internal.hpp"
#include "bindings_common.hpp"
namespace hailort
{
static const uint32_t TEST_NUM_OF_CLASSES2 = 80;
py::array PyhailortInternal::get_yolov5_post_process_expected_buffer()
{
static const uint32_t DETECTION_CLASS_ID_1 = 0;
static const float32_t CLASS_ID_1_DETECTION_COUNT = 5;
static const uint32_t DETECTION_CLASS_ID_3 = 2;
static const float32_t CLASS_ID_3_DETECTION_COUNT = 2;
static const uint32_t DETECTION_CLASS_ID_8 = 7;
static const float32_t CLASS_ID_8_DETECTION_COUNT = 1;
static const uint32_t DETECTION_CLASS_ID_26 = 25;
static const float32_t CLASS_ID_26_DETECTION_COUNT = 1;
static const hailo_bbox_float32_t bbox1_0 = {
/*.y_min =*/ 0.5427529811859131f,
/*.x_min =*/ 0.2485126256942749f,
/*.y_max =*/ 0.6096446067f,
/*.x_max =*/ 0.27035075984f,
/*.score =*/ 0.7761699557304382f,
};
static const hailo_bbox_float32_t bbox1_1 = {
/*.y_min =*/ 0.5454554557800293f,
/*.x_min =*/ 0.33257606625556948f,
/*.y_max =*/ 0.7027952075f,
/*.x_max =*/ 0.40901548415f,
/*.score =*/ 0.7637669444084168f,
};
static const hailo_bbox_float32_t bbox1_2 = {
/*.y_min =*/ 0.5521867275238037f,
/*.x_min =*/ 0.19988654553890229f,
/*.y_max =*/ 0.60256312787f,
/*.x_max =*/ 0.21917282976f,
/*.score =*/ 0.7451231479644775f,
};
static const hailo_bbox_float32_t bbox1_3 = {
/*.y_min =*/ 0.5514537692070007f,
/*.x_min =*/ 0.2693796157836914f,
/*.y_max =*/ 0.60397491604f,
/*.x_max =*/ 0.28537025302f,
/*.score =*/ 0.3756354749202728f,
};
static const hailo_bbox_float32_t bbox1_4 = {
/*.y_min =*/ 0.553998589515686f,
/*.x_min =*/ 0.18612079322338105f,
/*.y_max =*/ 0.58339602686f,
/*.x_max =*/ 0.2008818537f,
/*.score =*/ 0.3166312277317047f,
};
static const hailo_bbox_float32_t bbox3_0 = {
/*.y_min =*/ 0.5026738047599793f,
/*.x_min =*/ -0.005611047148704529f,
/*.y_max =*/ 0.65071095526f,
/*.x_max =*/ 0.13888412714f,
/*.score =*/ 0.5734351277351379f,
};
static const hailo_bbox_float32_t bbox3_1 = {
/*.y_min =*/ 0.5620155334472656f,
/*.x_min =*/ 0.16757474839687348f,
/*.y_max =*/ 0.58410947769f,
/*.x_max =*/ 0.19325175508f,
/*.score =*/ 0.4062519371509552f,
};
static const hailo_bbox_float32_t bbox8_0 = {
/*.y_min =*/ 0.5028372406959534f,
/*.x_min =*/ -0.0017736181616783143f,
/*.y_max =*/ 0.65114967525f,
/*.x_max =*/ 0.13592261821f,
/*.score =*/ 0.4223918318748474f,
};
static const hailo_bbox_float32_t bbox26_0 = {
/*.y_min =*/ 0.5854946374893189f,
/*.x_min =*/ 0.2693060040473938f,
/*.y_max =*/ 0.68259389698f,
/*.x_max =*/ 0.38090330362f,
/*.score =*/ 0.6338639259338379f,
};
static const uint32_t DETECTION_COUNT = 9;
auto buffer_size = (DETECTION_COUNT * sizeof(hailo_bbox_float32_t)) + (TEST_NUM_OF_CLASSES2 * sizeof(float32_t));
auto buffer_expected = hailort::Buffer::create(buffer_size, 0);
// CATCH_REQUIRE_EXPECTED(buffer_expected);
auto buffer = buffer_expected.release();
size_t offset = 0;
for (uint32_t class_index = 0; class_index < TEST_NUM_OF_CLASSES2; class_index++) {
if (DETECTION_CLASS_ID_1 == class_index) {
memcpy(buffer.data() + offset, &CLASS_ID_1_DETECTION_COUNT, sizeof(CLASS_ID_1_DETECTION_COUNT));
offset += sizeof(CLASS_ID_1_DETECTION_COUNT);
memcpy(buffer.data() + offset, &bbox1_0, sizeof(bbox1_0));
offset += sizeof(bbox1_0);
memcpy(buffer.data() + offset, &bbox1_1, sizeof(bbox1_1));
offset += sizeof(bbox1_1);
memcpy(buffer.data() + offset, &bbox1_2, sizeof(bbox1_2));
offset += sizeof(bbox1_2);
memcpy(buffer.data() + offset, &bbox1_3, sizeof(bbox1_3));
offset += sizeof(bbox1_3);
memcpy(buffer.data() + offset, &bbox1_4, sizeof(bbox1_4));
offset += sizeof(bbox1_4);
}
else if (DETECTION_CLASS_ID_3 == class_index) {
memcpy(buffer.data() + offset, &CLASS_ID_3_DETECTION_COUNT, sizeof(CLASS_ID_3_DETECTION_COUNT));
offset += sizeof(CLASS_ID_3_DETECTION_COUNT);
memcpy(buffer.data() + offset, &bbox3_0, sizeof(bbox3_0));
offset += sizeof(bbox3_0);
memcpy(buffer.data() + offset, &bbox3_1, sizeof(bbox3_1));
offset += sizeof(bbox3_1);
}
else if (DETECTION_CLASS_ID_8 == class_index) {
memcpy(buffer.data() + offset, &CLASS_ID_8_DETECTION_COUNT, sizeof(CLASS_ID_8_DETECTION_COUNT));
offset += sizeof(CLASS_ID_8_DETECTION_COUNT);
memcpy(buffer.data() + offset, &bbox8_0, sizeof(bbox8_0));
offset += sizeof(bbox8_0);
}
else if (DETECTION_CLASS_ID_26 == class_index) {
memcpy(buffer.data() + offset, &CLASS_ID_26_DETECTION_COUNT, sizeof(CLASS_ID_26_DETECTION_COUNT));
offset += sizeof(CLASS_ID_26_DETECTION_COUNT);
memcpy(buffer.data() + offset, &bbox26_0, sizeof(bbox26_0));
offset += sizeof(bbox26_0);
}
else {
offset += sizeof(float32_t);
}
}
// Note: The ownership of the buffer is transferred to Python wrapped as a py::array.
// When the py::array isn't referenced anymore in Python and is destructed, the py::capsule's dtor
// is called too (and it deletes the raw buffer)
auto type = py::dtype(HailoRTBindingsCommon::convert_format_type_to_string(HAILO_FORMAT_TYPE_FLOAT32));
auto shape = *py::array::ShapeContainer({buffer.size()});
const auto unmanaged_addr = buffer.release();
return py::array(type, shape, unmanaged_addr,
py::capsule(unmanaged_addr, [](void *p) { delete reinterpret_cast<uint8_t*>(p); }));
}
void PyhailortInternal::demux_output_buffer(
py::bytes src, const hailo_format_t &src_format, const hailo_3d_image_shape_t &src_shape,
std::map<std::string, py::array> dst_buffers, const LayerInfo &mux_layer_info)
@@ -108,17 +261,15 @@ bool PyhailortInternal::is_output_transformation_required(
py::list PyhailortInternal::get_all_layers_info(const HefWrapper &hef, const std::string &net_group_name)
{
auto network_gorup_metadata = hef.hef_ptr()->pimpl->get_network_group_metadata(net_group_name);
VALIDATE_EXPECTED(network_gorup_metadata);
auto network_group_metadata = hef.hef_ptr()->pimpl->get_network_group_metadata(net_group_name);
VALIDATE_EXPECTED(network_group_metadata);
auto layers_info = network_gorup_metadata->get_all_layer_infos();
VALIDATE_EXPECTED(layers_info);
return py::cast(layers_info.release());
return py::cast(network_group_metadata->get_all_layer_infos());
}
PYBIND11_MODULE(_pyhailort_internal, m) {
ControlWrapper::add_to_python_module(m);
m.def("get_yolov5_post_process_expected_buffer", &PyhailortInternal::get_yolov5_post_process_expected_buffer);
m.def("demux_output_buffer", &PyhailortInternal::demux_output_buffer);
m.def("transform_input_buffer", &PyhailortInternal::transform_input_buffer);
m.def("transform_output_buffer", &PyhailortInternal::transform_output_buffer);

View File

@@ -28,6 +28,7 @@ namespace hailort
class PyhailortInternal {
public:
static py::array get_yolov5_post_process_expected_buffer();
static void demux_output_buffer(py::bytes src, const hailo_format_t &src_format, const hailo_3d_image_shape_t &src_shape,
std::map<std::string, py::array> dst_buffers, const LayerInfo &mux_layer_info);
static void transform_input_buffer(py::array src, const hailo_format_t &src_format, const hailo_3d_image_shape_t &src_shape,

View File

@@ -0,0 +1,102 @@
/**
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file net_flow_api.hpp
* @brief Defines binding to a HailoRT++ ops usage over Python.
**/
#ifndef _HAILO_NET_FLOW_API_HPP_
#define _HAILO_NET_FLOW_API_HPP_
#include "utils.hpp"
#include "hailo/hailort.hpp"
#include "bindings_common.hpp"
#include "net_flow/ops/yolo_post_processing.hpp"
namespace hailort
{
namespace net_flow
{
class YOLOv5PostProcessingOpWrapper
{
public:
static YOLOv5PostProcessingOpWrapper create(const std::vector<std::vector<int>> &anchors,
const std::vector<hailo_3d_image_shape_t> &shapes, const std::vector<hailo_format_t> &formats,
const std::vector<hailo_quant_info_t> &quant_infos, float32_t image_height, float32_t image_width, float32_t confidence_threshold,
float32_t iou_threshold, uint32_t num_of_classes, bool should_dequantize, uint32_t max_boxes, bool should_sigmoid,
bool one_class_per_bbox=true)
{
auto op = YOLOv5PostProcessingOp::create(anchors, shapes, formats, quant_infos, image_height, image_width,
confidence_threshold, iou_threshold, num_of_classes, should_dequantize, max_boxes, should_sigmoid, one_class_per_bbox);
VALIDATE_EXPECTED(op);
return YOLOv5PostProcessingOpWrapper(op.release(), num_of_classes, max_boxes);
}
static void add_to_python_module(py::module &m)
{
py::class_<YOLOv5PostProcessingOpWrapper>(m, "YOLOv5PostProcessingOp")
.def("create", &YOLOv5PostProcessingOpWrapper::create)
.def("execute",[](YOLOv5PostProcessingOpWrapper &self, const std::vector<py::array> &tensors)
{
std::vector<MemoryView> data_views;
data_views.reserve(tensors.size());
for (auto &tensor : tensors) {
data_views.push_back(MemoryView(const_cast<void*>(reinterpret_cast<const void*>(tensor.data())), tensor.nbytes()));
}
hailo_nms_info_t nms_info = {
self.m_num_of_classes,
self.m_max_boxes,
sizeof(hailo_bbox_float32_t),
1,
false,
hailo_nms_defuse_info_t()
};
hailo_format_t output_format = {
HAILO_FORMAT_TYPE_FLOAT32,
HAILO_FORMAT_ORDER_HAILO_NMS,
HAILO_FORMAT_FLAGS_QUANTIZED,
};
auto buffer = Buffer::create(HailoRTCommon::get_nms_host_frame_size(nms_info, output_format), 0);
VALIDATE_STATUS(buffer.status());
auto status = self.m_post_processing_op.execute<float32_t>(data_views, MemoryView(buffer.value().data(), buffer.value().size()));
VALIDATE_STATUS(status);
// Note: The ownership of the buffer is transferred to Python wrapped as a py::array.
// When the py::array isn't referenced anymore in Python and is destructed, the py::capsule's dtor
// is called too (and it deletes the raw buffer)
auto type = py::dtype(HailoRTBindingsCommon::convert_format_type_to_string(HAILO_FORMAT_TYPE_FLOAT32));
auto shape = *py::array::ShapeContainer({buffer.value().size()});
const auto unmanaged_addr = buffer.release().release();
return py::array(type, shape, unmanaged_addr,
py::capsule(unmanaged_addr, [](void *p) { delete reinterpret_cast<uint8_t*>(p); }));
})
;
}
private:
YOLOv5PostProcessingOpWrapper(YOLOv5PostProcessingOp &&post_processing_op, uint32_t num_of_classes, uint32_t max_bboxes)
: m_post_processing_op(post_processing_op),
m_num_of_classes(num_of_classes),
m_max_boxes(max_bboxes) {}
YOLOv5PostProcessingOp m_post_processing_op;
uint32_t m_num_of_classes = 0;
uint32_t m_max_boxes = 0;
};
void NetFlow_api_initialize_python_module(py::module &m)
{
YOLOv5PostProcessingOpWrapper::add_to_python_module(m);
}
} /* namespace net_flow */
} /* namespace hailort */
#endif /* _HAILO_NET_FLOW_API_HPP_ */

View File

@@ -15,6 +15,7 @@ using namespace std;
#include "vdevice_api.hpp"
#include "device_api.hpp"
#include "quantization_api.hpp"
#include "net_flow_api.hpp"
#include "utils.hpp"
#include "utils.h"
@@ -157,8 +158,6 @@ private:
#endif
// End of temp hack for hlpcie
static void validate_versions_match()
{
hailo_version_t libhailort_version = {};
@@ -324,7 +323,7 @@ PYBIND11_MODULE(_pyhailort, m) {
py::class_<hailo_debug_notification_message_t>(m, "DebugNotificationMessage")
.def_readonly("connection_status", &hailo_debug_notification_message_t::connection_status)
.def_readonly("connection_type", &hailo_debug_notification_message_t::connection_type)
.def_readonly("pcie_is_active", &hailo_debug_notification_message_t::pcie_is_active)
.def_readonly("vdma_is_active", &hailo_debug_notification_message_t::vdma_is_active)
.def_readonly("host_port", &hailo_debug_notification_message_t::host_port)
.def_readonly("host_ip_addr", &hailo_debug_notification_message_t::host_ip_addr)
;
@@ -393,6 +392,7 @@ PYBIND11_MODULE(_pyhailort, m) {
.def_readonly("logger_version", &hailo_device_identity_t::logger_version)
.def_readonly("board_name_length", &hailo_device_identity_t::board_name_length)
.def_readonly("is_release", &hailo_device_identity_t::is_release)
.def_readonly("extended_context_switch_buffer", &hailo_device_identity_t::extended_context_switch_buffer)
.def_readonly("device_architecture", &hailo_device_identity_t::device_architecture)
.def_property_readonly("board_name", [](const hailo_device_identity_t& board_info) -> py::str {
return py::str(board_info.board_name, board_info.board_name_length);
@@ -413,6 +413,7 @@ PYBIND11_MODULE(_pyhailort, m) {
py::class_<hailo_core_information_t>(m, "CoreInformation")
.def_readonly("is_release", &hailo_core_information_t::is_release)
.def_readonly("extended_context_switch_buffer", &hailo_core_information_t::extended_context_switch_buffer)
.def_readonly("fw_version", &hailo_core_information_t::fw_version)
;
@@ -534,6 +535,10 @@ PYBIND11_MODULE(_pyhailort, m) {
.value("RGB888", HAILO_FORMAT_ORDER_RGB888)
.value("NCHW", HAILO_FORMAT_ORDER_NCHW)
.value("YUY2", HAILO_FORMAT_ORDER_YUY2)
.value("NV12", HAILO_FORMAT_ORDER_NV12)
.value("YYUV", HAILO_FORMAT_ORDER_HAILO_YYUV)
.value("NV21", HAILO_FORMAT_ORDER_NV21)
.value("YYVU", HAILO_FORMAT_ORDER_HAILO_YYVU)
;
py::enum_<hailo_format_flags_t>(m, "FormatFlags", py::arithmetic())
@@ -792,6 +797,7 @@ PYBIND11_MODULE(_pyhailort, m) {
)
.def_static("default", []() {
auto orig_params = HailoRTDefaults::get_vdevice_params();
orig_params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
VDeviceParamsWrapper params_wrapper{orig_params, ""};
return params_wrapper;
});
@@ -942,6 +948,10 @@ PYBIND11_MODULE(_pyhailort, m) {
.value("CPU1", HAILO_CPU_ID_1)
;
py::enum_<hailo_sleep_state_t>(m, "SleepState")
.value("SLEEP_STATE_SLEEPING", HAILO_SLEEP_STATE_SLEEPING)
.value("SLEEP_STATE_AWAKE", HAILO_SLEEP_STATE_AWAKE)
;
py::class_<uint32_t>(m, "HailoRTDefaults")
.def_static("HAILO_INFINITE", []() { return HAILO_INFINITE;} )
@@ -1066,6 +1076,7 @@ PYBIND11_MODULE(_pyhailort, m) {
VStream_api_initialize_python_module(m);
VDevice_api_initialize_python_module(m);
DeviceWrapper::add_to_python_module(m);
hailort::net_flow::NetFlow_api_initialize_python_module(m);
#if defined(__GNUC__)
TrafficControlUtilWrapper::add_to_python_module(m);

View File

@@ -49,7 +49,18 @@ public:
static VDeviceWrapper create_from_ids(const std::vector<std::string> &device_ids)
{
return VDeviceWrapper(device_ids);
auto device_ids_vector = HailoRTCommon::to_device_ids_vector(device_ids);
VALIDATE_EXPECTED(device_ids_vector);
hailo_vdevice_params_t params = {};
auto status = hailo_init_vdevice_params(&params);
VALIDATE_STATUS(status);
params.device_ids = device_ids_vector->data();
params.device_count = static_cast<uint32_t>(device_ids_vector->size());
params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
return VDeviceWrapper(params);
}
VDeviceWrapper(const hailo_vdevice_params_t &params)
@@ -60,14 +71,6 @@ public:
m_vdevice = vdevice_expected.release();
};
VDeviceWrapper(const std::vector<std::string> &device_ids)
{
auto vdevice_expected = VDevice::create(device_ids);
VALIDATE_EXPECTED(vdevice_expected);
m_vdevice = vdevice_expected.release();
}
py::list get_physical_devices_ids() const
{
const auto phys_devs_ids = m_vdevice->get_physical_devices_ids();

View File

@@ -3,38 +3,31 @@
- gcc
- g++
python_versions:
- version: '3.6'
installation: deb
package_name: python3.6-dev
- version: '3.7'
installation: deb
package_name: python3.7-dev
- version: '3.8'
installation: deb
package_name: python3.8-dev
- version: '3.9'
installation: deb
package_name: python3.9-dev
- version: '3.10'
installation: deb
package_name: python3.10-dev
- name: linux.aarch64
required_packages:
- gcc-aarch64-linux-gnu
- g++-aarch64-linux-gnu
python_versions:
- version: '3.6'
installation: manual
package_name: http://launchpadlibrarian.net/362976109/libpython3.6-dev_3.6.5-3_arm64.deb
package_dest: /usr/include/aarch64-linux-gnu
- version: '3.7'
installation: manual
package_name: http://launchpadlibrarian.net/450463692/libpython3.7-dev_3.7.5-2~18.04_arm64.deb
package_dest: /usr/include/aarch64-linux-gnu
- version: '3.8'
installation: manual
package_name: https://launchpad.net/ubuntu/+source/python3.8/3.8.2-1ubuntu1/+build/18834117/+files/libpython3.8-dev_3.8.2-1ubuntu1_arm64.deb
package_dest: /usr/include/aarch64-linux-gnu
- version: '3.9'
installation: manual
package_name: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa/+build/23779329/+files/libpython3.9-dev_3.9.13-1+bionic1_arm64.deb
package_name: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa/+build/24906233/+files/libpython3.9-dev_3.9.16-1+bionic1_arm64.deb
package_dest: /usr/include/aarch64-linux-gnu
- version: '3.10'
installation: manual
package_name: https://launchpadlibrarian.net/569418529/libpython3.10-dev_3.10.0-5_arm64.deb
package_dest: /usr/include/aarch64-linux-gnu
- name: linux.armv7l
required_packages:

View File

@@ -2,23 +2,9 @@ cmake_minimum_required(VERSION 3.0.0)
project(hailort-examples)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.10.0 EXACT REQUIRED)
add_library(example_base INTERFACE)
target_link_libraries(example_base INTERFACE HailoRT::libhailort Threads::Threads)
if(WIN32)
target_compile_options(example_base INTERFACE /W4 /WX /DWIN32_LEAN_AND_MEAN /DNOMINMAX /wd4201 /wd4251)
else()
target_compile_options(example_base INTERFACE -Werror -Wall -Wextra -Wconversion -O3 -DNDEBUG) # TODO support debug/release builds
endif()
add_subdirectory(cpp)
add_subdirectory(c)
set_target_properties(${EXAMPLES_CPP_TARGETS} PROPERTIES CXX_STANDARD 14)
add_custom_target(hailort_examples DEPENDS ${EXAMPLES_C_TARGETS} ${EXAMPLES_CPP_TARGETS})
# We add a costum target in order to compile all of the hailort examples
add_custom_target(hailort_examples)
add_dependencies(hailort_examples c_hailort_examples cpp_hailort_examples)

View File

@@ -15,9 +15,9 @@ The following examples are provided, demonstrating the HailoRT API:
- Get the networks information to create the vstreams for each network.
- The data is sent to the device via input vstreams and received via output vstreams.
- The data is transformed before sent and after receiving in a different thread using the virtual stream pipeline.
- `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT scheduler for automatic network group switching.
- `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT Model Scheduler for automatic network group switching.
- This example uses pcie devices.
- `switch_single_io_network_groups_manually_example` - Demonstrates how to work with multiple single input single output HEFs, switching the created network groups manually, using virtual streams.
- `switch_network_groups_manually_example` - Demonstrates how to work with multiple single input single output HEFs, switching the created network groups manually, using virtual streams.
- `data_quantization_example` - Demonstrates how to set input/output stream params so as to allow for custom quantization:
- Input streams may be marked as quantized, so that input data will not to be automatically quantized by the HailoRT library.
- Output streams may be marked as quantized, so that output data will remain quantized (as it is after exiting the device by default), and won't be 'de-quantized' by the HailoRT library.
@@ -31,13 +31,13 @@ The following examples are provided, demonstrating the HailoRT API:
- `vstreams_example` - Basic inference of a shortcut network, same as `vstreams_example` C example, uses HailoRT C++ api.
- `multi_device_example` - Basic inference of a shortcut network over multiple devices, same as `multi_device_example` C example, uses HailoRT C++ api.
- `multi_network_vstream_example` - Demonstrates how to work with multiple networks in a network group, same as `multi_network_vstream_example ` C example, uses HailoRT C++ api.
- `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT scheduler, same as `switch_network_groups_example ` C example, uses HailoRT C++ api.
- `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT Model Scheduler, same as `switch_network_groups_example ` C example, uses HailoRT C++ api.
- `switch_network_groups_manually_example` -Demonstrates how to work with multiple HEFs, switching the running network_groups manually, with performance optimizations for I/O threads re-usage instead of re-creation at each network group activation. Uses C++ api.
- `infer_streams_example` - Basic inference of a shortcut network, same as `raw_streams_example` C example, uses HailoRT C++ api.
- `infer_pipeline_example` - Basic inference of a shortcut network using inference pipeline (blocking) api.
- same as `infer_pipeline_example` C example, uses HailoRT C++ api.
- `raw_streams_example` - Basic inference of a shortcut network, same as `raw_streams_example` C example, uses HailoRT C++ api.
- `multi_process_example` - Demonstrates how to work with HailoRT as a service and using the HailoRT scheduler for network groups switching.
- `multi_process_example` - Demonstrates how to work with HailoRT as a service and using the HailoRT Model Scheduler for network groups switching.
Using the script `multi_process_example.sh` one can specify the number of processes to run each hef, see `multi_process_example.sh -h` for more information.
## Compiling with CMake
@@ -49,9 +49,21 @@ cmake --build build --config release
> **_NOTE:_** Write permissions are required to compile the examples from their current directory.
If this is not the case, copy the examples directory to another location with the required permissions.
In order to compile a specific example, add the example name as target with a c/cpp prefix:
```sh
cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
cmake --build build --config release --target cpp_vstreams_example
```
## Running the examples
One can run the example using the following commands, from the examples directory:
Before running an example, download the HEFs using the [download script](../../scripts/download_hefs.sh):
```sh
../../scripts/download_hefs.sh
```
To run an example, use (from this examples directory):
```sh
build/<c/cpp>/<example_name> [params..]
build/<c/cpp>/<example_name>/<example_name> [params..]
```

View File

@@ -1,43 +1,23 @@
cmake_minimum_required(VERSION 3.0.0)
file(GLOB_RECURSE C_EXAMPLE_SOURCES "*.c")
SET_SOURCE_FILES_PROPERTIES(${C_EXAMPLE_SOURCES} PROPERTIES LANGUAGE C)
add_subdirectory(data_quantization_example)
add_subdirectory(raw_streams_example)
add_subdirectory(vstreams_example)
add_subdirectory(infer_pipeline_example)
add_subdirectory(multi_network_vstream_example)
add_subdirectory(switch_network_groups_example)
add_subdirectory(switch_network_groups_manually_example)
add_subdirectory(multi_device_example)
add_subdirectory(power_measurement_example)
add_executable(c_data_quantization_example data_quantization_example.c)
target_link_libraries(c_data_quantization_example PRIVATE example_base)
add_executable(c_raw_streams_example raw_streams_example.c)
target_link_libraries(c_raw_streams_example PRIVATE example_base)
add_executable(c_vstreams_example vstreams_example.c)
target_link_libraries(c_vstreams_example PRIVATE example_base)
add_executable(c_infer_pipeline_example infer_pipeline_example.c)
target_link_libraries(c_infer_pipeline_example PRIVATE example_base)
add_executable(c_multi_network_vstream_example multi_network_vstream_example.c)
target_link_libraries(c_multi_network_vstream_example PRIVATE example_base)
add_executable(c_switch_network_groups_example switch_network_groups_example.c)
target_link_libraries(c_switch_network_groups_example PRIVATE example_base)
add_executable(c_switch_single_io_network_groups_manually_example switch_single_io_network_groups_manually_example.c)
target_link_libraries(c_switch_single_io_network_groups_manually_example PRIVATE example_base)
add_executable(c_multi_device_example multi_device_example.c)
target_link_libraries(c_multi_device_example PRIVATE example_base)
add_executable(c_power_measurement_example power_measurement_example.c)
target_link_libraries(c_power_measurement_example PRIVATE example_base)
set(EXAMPLES_C_TARGETS
add_custom_target(c_hailort_examples)
add_dependencies(c_hailort_examples
c_data_quantization_example
c_raw_streams_example
c_vstreams_example
c_infer_pipeline_example
c_multi_network_vstream_example
c_switch_network_groups_example
c_switch_single_io_network_groups_manually_example
c_switch_network_groups_manually_example
c_multi_device_example
c_power_measurement_example
PARENT_SCOPE)
c_power_measurement_example)

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.0.0)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.12.0 EXACT REQUIRED)
SET_SOURCE_FILES_PROPERTIES(data_quantization_example.c PROPERTIES LANGUAGE C)
add_executable(c_data_quantization_example data_quantization_example.c)
target_link_libraries(c_data_quantization_example PRIVATE HailoRT::libhailort Threads::Threads)
target_include_directories(c_data_quantization_example PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../common")
if(WIN32)
target_compile_options(c_data_quantization_example PRIVATE
/DWIN32_LEAN_AND_MEAN
/DNOMINMAX # NOMINMAX is required in order to play nice with std::min/std::max (otherwise Windows.h defines it's own)
/wd4201 /wd4251
)
endif()

View File

@@ -255,7 +255,6 @@ int main(int argc, char **argv)
hailo_output_vstream output_vstreams[MAX_EDGE_LAYERS] = {NULL};
size_t input_vstreams_size = MAX_EDGE_LAYERS;
size_t output_vstreams_size = MAX_EDGE_LAYERS;
hailo_activated_network_group activated_network_group = NULL;
quantization_args_t quant_args;
parse_arguments(argc, argv, &quant_args);
@@ -282,16 +281,12 @@ int main(int argc, char **argv)
&output_vstreams_size,quant_args);
REQUIRE_SUCCESS(status, l_release_hef, "Failed creating virtual streams");
status = hailo_activate_network_group(network_group, NULL, &activated_network_group);
REQUIRE_SUCCESS(status, l_release_vstreams, "Failed activate network group");
status = infer(input_vstreams, input_vstreams_size, output_vstreams, output_vstreams_size, quant_args);
REQUIRE_SUCCESS(status, l_deactivate_network_group, "Inference failure");
REQUIRE_SUCCESS(status, l_release_vstreams, "Inference failure");
printf("Inference ran successfully\n");
status = HAILO_SUCCESS;
l_deactivate_network_group:
(void)hailo_deactivate_network_group(activated_network_group);
l_release_vstreams:
(void)hailo_release_output_vstreams(output_vstreams, output_vstreams_size);
(void)hailo_release_input_vstreams(input_vstreams, input_vstreams_size);

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.0.0)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.12.0 EXACT REQUIRED)
SET_SOURCE_FILES_PROPERTIES(infer_pipeline_example.c PROPERTIES LANGUAGE C)
add_executable(c_infer_pipeline_example infer_pipeline_example.c)
target_link_libraries(c_infer_pipeline_example PRIVATE HailoRT::libhailort Threads::Threads)
target_include_directories(c_infer_pipeline_example PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../common")
if(WIN32)
target_compile_options(c_infer_pipeline_example PRIVATE
/DWIN32_LEAN_AND_MEAN
/DNOMINMAX # NOMINMAX is required in order to play nice with std::min/std::max (otherwise Windows.h defines it's own)
/wd4201 /wd4251
)
endif()

View File

@@ -11,7 +11,6 @@
#include "common.h"
#include "string.h"
#include "hailo_thread.h"
#include "hailo/hailort.h"
#define MAX_NUM_OF_DEVICES (5)
@@ -114,7 +113,7 @@ int main(int argc, char **argv)
REQUIRE_SUCCESS(status, l_exit, "Failed to create eth_device");
status = hailo_create_hef_file(&hef, HEF_FILE);
REQUIRE_SUCCESS(status, l_release_vdevice, "Failed reading hef file");
REQUIRE_SUCCESS(status, l_release_device, "Failed reading hef file");
status = hailo_init_configure_params(hef, HAILO_STREAM_INTERFACE_ETH, &config_params);
REQUIRE_SUCCESS(status, l_release_hef, "Failed initializing configure parameters");
@@ -154,7 +153,7 @@ l_deactivate_network_group:
(void)hailo_deactivate_network_group(activated_network_group);
l_release_hef:
(void) hailo_release_hef(hef);
l_release_vdevice:
l_release_device:
(void) hailo_release_device(device);
l_exit:
return status;

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.0.0)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.12.0 EXACT REQUIRED)
SET_SOURCE_FILES_PROPERTIES(multi_device_example.c PROPERTIES LANGUAGE C)
add_executable(c_multi_device_example multi_device_example.c)
target_link_libraries(c_multi_device_example PRIVATE HailoRT::libhailort Threads::Threads)
target_include_directories(c_multi_device_example PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../common")
if(WIN32)
target_compile_options(c_multi_device_example PRIVATE
/DWIN32_LEAN_AND_MEAN
/DNOMINMAX # NOMINMAX is required in order to play nice with std::min/std::max (otherwise Windows.h defines it's own)
/wd4201 /wd4251
)
endif()

View File

@@ -139,7 +139,6 @@ int main()
hailo_output_vstream_params_by_name_t output_vstream_params[MAX_EDGE_LAYERS] = {0};
size_t input_vstreams_size = MAX_EDGE_LAYERS;
size_t output_vstreams_size = MAX_EDGE_LAYERS;
hailo_activated_network_group activated_network_group = NULL;
hailo_input_vstream input_vstreams[MAX_EDGE_LAYERS] = {NULL};
hailo_output_vstream output_vstreams[MAX_EDGE_LAYERS] = {NULL};
@@ -183,16 +182,11 @@ int main()
status = hailo_create_output_vstreams(network_group, output_vstream_params, output_vstreams_size, output_vstreams);
REQUIRE_SUCCESS(status, l_release_input_vstream, "Failed creating output virtual streams\n");
status = hailo_activate_network_group(network_group, NULL, &activated_network_group);
REQUIRE_SUCCESS(status, l_release_output_vstream, "Failed activate network group");
status = infer(input_vstreams, input_vstreams_size, output_vstreams, output_vstreams_size);
REQUIRE_SUCCESS(status, l_deactivate_network_group, "Inference failure");
REQUIRE_SUCCESS(status, l_release_output_vstream, "Inference failure");
printf("Inference ran successfully\n");
status = HAILO_SUCCESS;
l_deactivate_network_group:
(void)hailo_deactivate_network_group(activated_network_group);
l_release_output_vstream:
(void)hailo_release_output_vstreams(output_vstreams, output_vstreams_size);
l_release_input_vstream:

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.0.0)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.12.0 EXACT REQUIRED)
SET_SOURCE_FILES_PROPERTIES(multi_network_vstream_example.c PROPERTIES LANGUAGE C)
add_executable(c_multi_network_vstream_example multi_network_vstream_example.c)
target_link_libraries(c_multi_network_vstream_example PRIVATE HailoRT::libhailort Threads::Threads)
target_include_directories(c_multi_network_vstream_example PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../common")
if(WIN32)
target_compile_options(c_multi_network_vstream_example PRIVATE
/DWIN32_LEAN_AND_MEAN
/DNOMINMAX # NOMINMAX is required in order to play nice with std::min/std::max (otherwise Windows.h defines it's own)
/wd4201 /wd4251
)
endif()

View File

@@ -171,6 +171,8 @@ int main()
status = hailo_init_vdevice_params(&params);
REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
/* Scheduler does not support different batches for different networks within the same network group */
params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
params.device_count = DEVICE_COUNT;
status = hailo_create_vdevice(&params, &vdevice);
REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
@@ -233,6 +235,7 @@ int main()
printf("Inference ran successfully\n");
status = HAILO_SUCCESS;
l_deactivate_network_group:
(void)hailo_deactivate_network_group(activated_network_group);
l_release_vstreams:

Some files were not shown because too many files have changed in this diff Show More