v4.10.0
This commit is contained in:
HailoRT-Automation
2022-09-28 22:49:02 +03:00
committed by GitHub
parent 8295c0685f
commit d61a3bc83f
238 changed files with 16091 additions and 5688 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -8,6 +8,11 @@ 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)
@@ -51,7 +56,8 @@ elseif(UNIX)
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra
# TODO: remove me warnings
-Wno-conversion
-Wno-deprecated-declarations
-Wno-deprecated-declarations # On c structures with deprecated attribute, clang generates implicit move ctor
# that causes a warning
-Wno-inconsistent-missing-override
)
else()

View File

@@ -23,6 +23,8 @@ 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 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).

View File

@@ -45,7 +45,8 @@
"temperature_orange_threshold": {"size": 1, "deserialize_as": "int"},
"temperature_orange_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
"temperature_throttling_enable": {"size": 1, "deserialize_as": "bool"},
"overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"}
"deprecated__overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"},
"overcurrent_throttling_enable": {"size": 1, "deserialize_as": "bool"}
}
},
"control":

View File

@@ -44,7 +44,7 @@
"temperature_red_hysteresis_threshold": {"$ref": "#/definitions/int8_t"},
"temperature_orange_threshold": {"$ref": "#/definitions/int8_t"},
"temperature_orange_hysteresis_threshold": {"$ref": "#/definitions/int8_t"},
"overcurrent_monitoring_orange_threshold_enable": {"type": "boolean"}
"deprecated__overcurrent_monitoring_orange_threshold_enable": {"type": "boolean"}
}
},
"control":

View File

@@ -40,6 +40,20 @@ extern "C" {
(((cluster_index) << CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_CLUSTER_INDEX_SHIFT) & CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_CLUSTER_INDEX_MASK)
#define CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__VDMA_CHANNEL_INDEX_MASK (0x1f)
#define CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__ENGINE_INDEX_MASK (0x60)
#define CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__ENGINE_INDEX_SHIFT (5)
#define CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__SET(dst, engine_index, vdma_channel_index) do { \
(dst) = (vdma_channel_index) | ((engine_index) << CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__ENGINE_INDEX_SHIFT);\
} while (0)
#define CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(src, engine_index, vdma_channel_index) do {\
(engine_index) = ((src) & CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__ENGINE_INDEX_MASK) >> \
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__ENGINE_INDEX_SHIFT; \
(vdma_channel_index) = ((src) & CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__VDMA_CHANNEL_INDEX_MASK); \
} while (0)
#pragma pack(push, 1)
typedef struct {
uint16_t core_bytes_per_buffer;
@@ -86,6 +100,7 @@ typedef enum __attribute__((packed)) {
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,
/* Must be last */
CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT
@@ -141,12 +156,12 @@ typedef struct {
typedef struct {
uint16_t descriptors_count;
uint8_t cfg_channel_number;
uint8_t packed_vdma_channel_id;
} CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t;
typedef struct {
uint16_t ccw_bursts;
uint8_t cfg_channel_number;
uint8_t config_stream_index;
} CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t;
typedef struct {
@@ -172,7 +187,7 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__disable_lcu_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
uint8_t edge_layer_direction;
bool is_inter_context;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
@@ -180,7 +195,7 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
uint8_t edge_layer_direction;
bool is_inter_context;
bool is_single_context_network_group;
@@ -189,7 +204,7 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t network_index;
uint32_t frame_periph_size;
@@ -199,14 +214,14 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__fetch_data_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
bool is_dummy_stream;
} CONTEXT_SWITCH_DEFS__change_vdma_to_stream_mapping_data_t;
typedef struct {
uint8_t h2d_vdma_channel_index;
uint8_t d2h_vdma_channel_index;
uint8_t h2d_packed_vdma_channel_id;
uint8_t d2h_packed_vdma_channel_id;
uint8_t network_index;
uint32_t descriptors_per_frame;
uint16_t programmed_descriptors_count;
@@ -218,7 +233,7 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
} CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t;
typedef struct {
@@ -235,7 +250,7 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__wait_nms_idle_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
bool is_inter_context;
} CONTEXT_SWITCH_DEFS__wait_dma_idle_data_t;
@@ -250,16 +265,17 @@ typedef struct {
/* edge layers structs */
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
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 {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
@@ -267,48 +283,55 @@ typedef struct {
} CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint64_t host_descriptors_base_address;
uint8_t desc_list_depth;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
uint8_t connected_d2h_packed_vdma_channel_id;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint32_t frame_credits_in_bytes;
uint16_t desc_page_size;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_boundary_output_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t;
typedef struct {
uint8_t packed_vdma_channel_id;
uint8_t stream_index;
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint32_t frame_credits_in_bytes;
uint64_t host_descriptors_base_address;
uint16_t desc_page_size;
uint8_t desc_list_depth;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
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 channel_index;
uint8_t packed_vdma_channel_id;
uint8_t config_stream_index;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_cfg_channel_t;
typedef struct {
uint8_t channel_index;
uint8_t packed_vdma_channel_id;
uint8_t config_stream_index;
} CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t;
#pragma pack(pop)

View File

@@ -35,13 +35,14 @@ extern "C" {
#define CONTROL_PROTOCOL__MAX_SERIAL_NUMBER_LENGTH (16)
#define CONTROL_PROTOCOL__MAX_PART_NUMBER_LENGTH (16)
#define CONTROL_PROTOCOL__MAX_PRODUCT_NAME_LENGTH (42)
#define CONTROL_PROTOCOL__MAX_CONTEXT_SWITCH_APPLICATIONS (8)
#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 (32)
#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)
#define CONTROL_PROTOCOL__MAX_VDMA_ENGINES_COUNT (3)
/* Tightly coupled with the sizeof PROCESS_MONITOR__detection_results_t
and HAILO_SOC_PM_VALUES_BYTES_LENGTH */
#define PM_RESULTS_LENGTH (24)
@@ -52,6 +53,8 @@ extern "C" {
/* Tightly coupled to HAILO_MAX_TEMPERATURE_THROTTLING_LEVELS_NUMBER */
#define MAX_TEMPERATURE_THROTTLING_LEVELS_NUMBER (4)
#define MAX_OVERCURRENT_THROTTLING_LEVELS_NUMBER (8)
#define CONTROL_PROTOCOL__MAX_NUMBER_OF_POWER_MEASUREMETS (4)
#define CONTROL_PROTOCOL__DEFAULT_INIT_SAMPLING_PERIOD_US (CONTROL_PROTOCOL__PERIOD_1100US)
#define CONTROL_PROTOCOL__DEFAULT_INIT_AVERAGING_FACTOR (CONTROL_PROTOCOL__AVERAGE_FACTOR_1)
@@ -143,7 +146,7 @@ extern "C" {
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CORE_IDENTIFY, true, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_D2H_EVENT_MANAGER_SET_HOST_INFO, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_D2H_EVENT_MANAGER_SEND_EVENT_HOST_INFO, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SWITCH_APPLICATION, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SWITCH_APPLICATION /* obsolete */, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_GET_CHIP_TEMPERATURE, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_READ_BOARD_CONFIG, true, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_WRITE_BOARD_CONFIG, true, CPU_ID_APP_CPU)\
@@ -169,6 +172,7 @@ extern "C" {
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CORE_PREVIOUS_SYSTEM_STATE, false, CPU_ID_CORE_CPU)\
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)\
typedef enum {
#define CONTROL_PROTOCOL__OPCODE_X(name, is_critical, cpu_id) name,
@@ -353,7 +357,8 @@ typedef struct {
typedef enum {
CONTROL_PROTOCOL__HAILO8_A0 = 0,
CONTROL_PROTOCOL__HAILO8_B0,
CONTROL_PROTOCOL__HAILO8,
CONTROL_PROTOCOL__HAILO8L,
CONTROL_PROTOCOL__MERCURY_CA,
CONTROL_PROTOCOL__MERCURY_VPU,
/* Must be last!! */
@@ -877,10 +882,10 @@ typedef struct {
typedef struct {
uint8_t dynamic_contexts_count;
uint32_t host_boundary_channels_bitmap;
uint8_t cfg_channel_numbers[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
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;
uint16_t batch_size[CONTROL_PROTOCOL__MAX_NETWORKS_PER_NETWORK_GROUP];
} CONTROL_PROTOCOL__application_header_t;
@@ -888,8 +893,6 @@ typedef struct {
typedef struct {
uint32_t context_switch_version_length;
uint32_t context_switch_version;
uint32_t validation_features_length;
CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t validation_features;
uint32_t application_count_length;
uint8_t application_count;
uint32_t application_header_length;
@@ -906,7 +909,6 @@ typedef enum {
typedef struct {
CONTROL_PROTOCOL__CONTEXT_SWITCH_VERSION_t context_switch_version;
CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t validation_features;
uint8_t application_count;
CONTROL_PROTOCOL__application_header_t application_header[CONTROL_PROTOCOL__MAX_CONTEXT_SWITCH_APPLICATIONS];
} CONTROL_PROTOCOL__context_switch_main_header_t;
@@ -969,6 +971,7 @@ typedef enum {
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,
@@ -1054,27 +1057,23 @@ 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 stream_index;
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 {
uint64_t host_descriptors_base_address;
uint8_t desc_list_depth;
} CONTROL_PROTOCOL__host_desc_address_info_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint32_t frame_credits_in_bytes;
uint16_t desc_page_size;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTROL_PROTOCOL__network_boundary_output_t;
typedef struct {
@@ -1084,9 +1083,7 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint32_t frame_credits_in_bytes;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
uint16_t desc_page_size;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t buffered_rows_count;
} CONTROL_PROTOCOL__ddr_buffer_output_t;
@@ -1097,7 +1094,7 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint16_t desc_page_size;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__network_boundary_input_t;
@@ -1109,8 +1106,10 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_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 {
@@ -1121,6 +1120,12 @@ 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
#pragma warning(push)
@@ -1133,8 +1138,8 @@ typedef struct {
uint8_t is_last_control_per_context;
uint32_t cfg_channels_count_length;
uint8_t cfg_channels_count;
uint32_t config_buffer_infos_length;
CONTROL_PROTOCOL__host_buffer_info_t config_buffer_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
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;
@@ -1209,14 +1214,14 @@ typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint16_t descriptors_count;
uint8_t cfg_channel_handle;
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 cfg_channel_handle;
uint8_t config_stream_index;
} CONTROL_PROTOCOL__FETCH_CCW_BURSTS_ACTION_t;
typedef struct {
@@ -1283,7 +1288,9 @@ typedef struct {
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;
@@ -1299,6 +1306,11 @@ typedef struct {
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;
@@ -1360,6 +1372,8 @@ typedef struct {
uint8_t application_index;
uint32_t dynamic_batch_size_length;
uint16_t dynamic_batch_size;
uint32_t keep_nn_config_during_reset_length;
uint8_t keep_nn_config_during_reset;
} CONTROL_PROTOCOL__change_context_switch_status_request_t;
typedef struct {
@@ -1371,13 +1385,6 @@ typedef struct {
uint8_t interrupt_sub_index;
} CONTROL_PROTOCOL__set_dataflow_interrupt_request_t;
typedef struct {
uint32_t application_index_length;
uint8_t application_index;
uint32_t dynamic_batch_size_length;
uint16_t dynamic_batch_size;
} CONTROL_PROTOCOL__switch_application_request_t;
typedef struct {
uint32_t connection_type_length;
uint8_t connection_type;
@@ -1429,6 +1436,8 @@ typedef struct {
CONTROL_PROTOCOL_fuse_info_t fuse_info;
uint32_t pd_info_length;
uint8_t pd_info[PM_RESULTS_LENGTH];
uint32_t partial_clusters_layout_bitmap_length;
uint32_t partial_clusters_layout_bitmap;
} CONTROL_PROTOCOL__get_extended_device_information_response_t;
/* Tightly coupled to hailo_throttling_level_t */
@@ -1446,8 +1455,8 @@ typedef struct {
uint8_t current_overcurrent_zone;
uint32_t red_overcurrent_threshold_length;
float32_t red_overcurrent_threshold;
uint32_t orange_overcurrent_threshold_length;
float32_t orange_overcurrent_threshold;
uint32_t overcurrent_throttling_active_length;
bool overcurrent_throttling_active;
uint32_t temperature_throttling_active_length;
bool temperature_throttling_active;
uint32_t current_temperature_zone_length;
@@ -1464,6 +1473,10 @@ typedef struct {
int32_t red_temperature_threshold;
uint32_t red_hysteresis_temperature_threshold_length;
int32_t red_hysteresis_temperature_threshold;
uint32_t requested_overcurrent_clock_freq_length;
uint32_t requested_overcurrent_clock_freq;
uint32_t requested_temperature_clock_freq_length;
uint32_t requested_temperature_clock_freq;
} CONTROL_PROTOCOL__get_health_information_response_t;
typedef enum {
@@ -1659,7 +1672,6 @@ typedef union {
CONTROL_PROTOCOL__d2h_event_manager_send_host_info_event_request_t d2h_event_manager_send_host_info_event_request;
CONTROL_PROTOCOL__read_board_config_request_t read_board_config_request;
CONTROL_PROTOCOL__write_board_config_request_t write_board_config_request;
CONTROL_PROTOCOL__switch_application_request_t switch_application_request;
CONTROL_PROTOCOL__config_context_switch_breakpoint_request_t config_context_switch_breakpoint_request;
CONTROL_PROTOCOL__get_context_switch_breakpoint_status_request_t get_context_switch_breakpoint_status_request;
CONTROL_PROTOCOL__enable_debugging_request_t enable_debugging_request;
@@ -1713,7 +1725,7 @@ typedef struct {
bool is_first_control_per_context;
bool is_last_control_per_context;
uint8_t cfg_channels_count;
CONTROL_PROTOCOL__host_buffer_info_t config_buffer_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
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;

View File

@@ -102,10 +102,10 @@ typedef struct {
typedef struct {
uint32_t overcurrent_zone;
float32_t exceeded_alert_threshold;
float32_t sampled_current_during_alert;
bool is_last_overcurrent_violation_reached;
} D2H_EVENT_health_monitor_overcurrent_alert_event_message_t;
#define D2H_EVENT_HEALTH_MONITOR_OVERCURRENT_ALERT_EVENT_PARAMETER_COUNT (2)
#define D2H_EVENT_HEALTH_MONITOR_OVERCURRENT_ALERT_EVENT_PARAMETER_COUNT (4)
/* D2H_EVENT_health_monitor_lcu_ecc_error_event_message_t should be the same as hailo_health_monitor_lcu_ecc_error_notification_message_t */
typedef struct {

View File

@@ -108,6 +108,9 @@ Updating rules:
FIRMWARE_STATUS__X(HAILO_STATUS_UPDATE_CLOCK_CORE_CPU_FAILED)\
FIRMWARE_STATUS__X(HAILO_STATUS_CONTROL_ETH_INIT_FAILED)\
FIRMWARE_STATUS__X(HAILO_STATUS_SEMAPHORE_INIT_FAILED)\
FIRMWARE_STATUS__X(HAILO_STATUS_DRAM_DMA_SERVICE_INIT_FAILED)\
FIRMWARE_STATUS__X(HAILO_STATUS_VDMA_SERVICE_INIT_FAILED)\
FIRMWARE_STATUS__X(HAILO_STATUS_ERROR_HANDLING_STACK_OVERFLOW)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__DATAFLOW)\
FIRMWARE_STATUS__X(HAILO_DATAFLOW_STATUS_INVALID_PARAMETER)\
@@ -399,6 +402,8 @@ Updating rules:
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CFG_CHANNELS_COUNT_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_DYNAMIC_BATCH_SIZE_LENGTH)\
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_MODULE__X(FIRMWARE_MODULE__POWER_MEASUREMENT)\
FIRMWARE_STATUS__X(HAILO_POWER_MEASUREMENT_STATUS_POWER_INIT_ERROR)\
@@ -735,6 +740,11 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CFG_CHANNELS_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_HOST_BUFFER_TYPE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_BURST_CREDITS_TASK_IS_NOT_IDLE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_KERNEL_COUNT_OVERFLOW)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CONFIG_STREAM_INDEX)\
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_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\
@@ -774,7 +784,7 @@ Updating rules:
FIRMWARE_STATUS__X(HEALTH_MONITOR_QUEUEING_OVERCURRENT_MESSAGE_FAILED)\
FIRMWARE_STATUS__X(HEALTH_MONITOR_QUEUEING_CORE_RESET_MESSAGE_FAILED)\
FIRMWARE_STATUS__X(HEALTH_MONITOR_QUEUEING_SOFT_RESET_MESSAGE_FAILED)\
FIRMWARE_STATUS__X(HEALTH_MONITOR_INVALID_OVERCURRENT_OVERCURRENT_ZONE)\
FIRMWARE_STATUS__X(HEALTH_MONITOR_INVALID_OVERCURRENT_OVERCURRENT_ZONE) /* DEPRECATED -*/\
FIRMWARE_STATUS__X(HEALTH_MONITOR_INVALID_MESSAGE_TYPE)\
FIRMWARE_STATUS__X(HEALTH_MONITOR_INVALID_TEMPERATURE_ALARM_TYPE) /* DEPRECATED - See TEMPERATURE_PROTECTION */\
FIRMWARE_STATUS__X(HEALTH_MONITOR_SETUP_SAFETY_INTERRUPTS_FAILED)\
@@ -843,7 +853,7 @@ Updating rules:
FIRMWARE_STATUS__X(GPIO_BAD_PINMUX_GROUP)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__OVERCURRENT_PROTECTION)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_INVALID_ALERT_THRESHOLD_VALUE)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_INVALID_ALERT_THRESHOLD_VALUE) /* DEPRECATED */\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_INVALID_SAMPLING_PERIOD_VALUE)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_INVALID_AVERAGING_FACTOR_VALUE)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_UNSUPPORTED_SENSOR_TYPE)\
@@ -851,7 +861,7 @@ Updating rules:
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_ALREADY_ACTIVE)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_IS_NOT_ACTIVE)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_INVALID_BOARD_CONFIG_VALUES)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_NULL_POINTER_PASSED)\
FIRMWARE_STATUS__X(OVERCURRENT_PROTECTION_NULL_POINTER_PASSED) /* DEPRECATED */\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__POWER)\
FIRMWARE_STATUS__X(POWER_INVALID_CONVERSION_TYPE)\
@@ -908,6 +918,7 @@ Updating rules:
FIRMWARE_STATUS__X(DDR_BUFFER_STATUS_TRYING_TO_CHANGE_STATE_TO_INFER_WHILE_ALREADY_DURING_INFER)\
FIRMWARE_STATUS__X(DDR_BUFFER_STATUS_NO_DDR_PAIRS_TO_RUN_INFER_ON)\
FIRMWARE_STATUS__X(DDR_BUFFER_STATUS_INFER_REACHED_TIMEOUT)\
FIRMWARE_STATUS__X(DDR_BUFFER_STATUS_OVERFLOW_IN_DESCRIPTORS_PER_BATCH)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__PL320)\
FIRMWARE_STATUS__X(PL320_MAILBOX_BUSY)\
@@ -984,6 +995,8 @@ Updating rules:
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INITIAL_DESC_BIGGER_THAN_TOTAL)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_INITIAL_CREDIT_SIZE)\
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_MODULE__X(FIRMWARE_MODULE__MEMORY_LOGGER)\
FIRMWARE_STATUS__X(MEMORY_LOGGER_STATUS_DEBUG_INSUFFICIENT_MEMORY)\
@@ -1007,6 +1020,13 @@ Updating rules:
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_TOTAL_DESCS_COUNT_MUST_BE_POWER_OF_2)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_INVALID_DESCS_COUNT)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_DESC_PER_INTERRUPT_NOT_IN_MASK)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_ENGINE_INDEX)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_QM_INDEX)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_CHANNEL_TYPE)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_PERIPH_BYTES_PER_BUFFER)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_BYTES_IN_PATTERN)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_STREAM_INDEX)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_CHANNEL_INDEX)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__NN_CORE_SERVICE)\
FIRMWARE_STATUS__X(NN_CORE_SERVICE_STATUS_INVALID_ARG_PASSED)\
@@ -1020,6 +1040,7 @@ Updating rules:
FIRMWARE_STATUS__X(DATA_STREAM_WRAPPER_STATUS_INVALID_STREAM_INDEX)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_STATUS_INVALID_CREDIT_TYPE)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_HOST_BUFFER_TYPE)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_STATUS_BATCH_CREDITS_OVERFLOW)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__BURST_CREDITS_TASK)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TRYING_TO_ADD_ACTION_WHILE_NOT_IN_IDLE_STATE)\

View File

@@ -30,7 +30,8 @@
/** Start of modifications for the open source file. **/
#include "stdint.h"
typedef uint8_t MD5_SUM_t[16];
#define MD5_DIGEST_LENGTH 16
typedef uint8_t MD5_SUM_t[MD5_DIGEST_LENGTH];
/* Any 32-bit or wider unsigned integer data type will do */
typedef size_t MD5_u32plus;
/** End of modifications. **/

View File

@@ -69,6 +69,19 @@ typedef enum {
SOC__NN_CLOCK_100MHz = 100 * 1000 * 1000
} SOC__NN_CLOCK_HZ_t;
typedef enum {
SOC__CPU_CLOCK_200MHz = SOC__NN_CLOCK_400MHz >> 1,
SOC__CPU_CLOCK_187MHz = SOC__NN_CLOCK_375MHz >> 1,
SOC__CPU_CLOCK_175MHz = SOC__NN_CLOCK_350MHz >> 1,
SOC__CPU_CLOCK_162MHz = SOC__NN_CLOCK_325MHz >> 1,
SOC__CPU_CLOCK_150MHz = SOC__NN_CLOCK_300MHz >> 1,
SOC__CPU_CLOCK_137MHz = SOC__NN_CLOCK_275MHz >> 1,
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_HZ_t;
typedef enum {
WD_SERVICE_MODE_HW_SW = 0,
WD_SERVICE_MODE_HW_ONLY,

View File

@@ -99,6 +99,18 @@
PP_HASCOMMA(PP_COMMA __VA_ARGS__ ()),\
PP_NARG_(__VA_ARGS__, PP_RSEQ_N()))
#define PP_ISEMPTY(...) \
_PP_ISEMPTY( \
PP_HASCOMMA(__VA_ARGS__), \
PP_HASCOMMA(PP_COMMA __VA_ARGS__), \
PP_HASCOMMA(__VA_ARGS__ (/*empty*/)), \
PP_HASCOMMA(PP_COMMA __VA_ARGS__ (/*empty*/)) \
)
#define PP_PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define _PP_ISEMPTY(_0, _1, _2, _3) PP_HASCOMMA(PP_PASTE5(_PP_IS_EMPTY_CASE_, _0, _1, _2, _3))
#define _PP_IS_EMPTY_CASE_0001 ,
#define UNUSED0(...)
#define UNUSED1(x) (void)(x)
#define UNUSED2(x,y) (void)(x),(void)(y)
@@ -111,4 +123,6 @@
#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs)
#define ALL_UNUSED(...) ALL_UNUSED_IMPL( PP_NARG(__VA_ARGS__))(__VA_ARGS__ )
#define MICROSECONDS_IN_MILLISECOND (1000)
#endif /* __UTILS_H__ */

View File

@@ -2,22 +2,29 @@ cmake_minimum_required(VERSION 3.0.0)
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
add_definitions( -DFIRMWARE_VERSION_MINOR=8 )
add_definitions( -DFIRMWARE_VERSION_REVISION=1 )
add_definitions( -DFIRMWARE_VERSION_MINOR=10 )
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}/libhailort/cmake/execute_cmake.cmake)
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=Release
-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 ${CMAKE_BUILD_TYPE} --target install ${CMAKE_EXTRA_BUILD_ARGS}
--config ${PRE_BUILD_BUILD_TYPE} --target install ${CMAKE_EXTRA_BUILD_ARGS}
PARALLEL_BUILD
)
@@ -53,13 +60,24 @@ endif()
add_subdirectory(external/protobuf/cmake EXCLUDE_FROM_ALL)
if(NOT MSVC)
set_target_properties(libprotobuf PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(libprotobuf-lite PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
if(HAILO_BUILD_SERVICE)
if(CMAKE_HOST_UNIX)
set(HAILO_GRPC_CPP_PLUGIN_EXECUTABLE "${HAILO_PRE_BUILD_BUILD_TOOLS}/build_grpc/grpc_cpp_plugin")
else()
set(HAILO_GRPC_CPP_PLUGIN_EXECUTABLE "${HAILO_PRE_BUILD_BUILD_TOOLS}/build_grpc/${PRE_BUILD_BUILD_TYPE}/grpc_cpp_plugin.exe")
endif()
endif()
set(HAILO_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
set(HAILORT_INC_DIR ${PROJECT_SOURCE_DIR}/hailort/libhailort/include)
set(HAILORT_SRC_DIR ${PROJECT_SOURCE_DIR}/hailort/libhailort/src)
set(HAILORT_COMMON_DIR ${PROJECT_SOURCE_DIR}/hailort/)
set(COMMON_INC_DIR ${PROJECT_SOURCE_DIR}/common/include)
set(DRIVER_INC_DIR ${PROJECT_SOURCE_DIR}/hailort/drivers/common)
set(RPC_DIR ${PROJECT_SOURCE_DIR}/hailort/rpc)
if(HAILO_BUILD_PYBIND)
if(NOT PYTHON_EXECUTABLE AND PYBIND11_PYTHON_VERSION)
@@ -87,6 +105,17 @@ if(CMAKE_SYSTEM_NAME STREQUAL QNX)
target_compile_definitions(pevents PRIVATE -DWFMO)
endif()
if(HAILO_BUILD_SERVICE)
set(BUILD_TESTING OFF) # disabe abseil tests
set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "Provider of zlib library")
# The following is an awful hack needed in order to force grpc to use our libprotobuf+liborotoc targets
# ('formal' options are to let grpc recompile it which causes a name conflict,
# or let it use find_package and take the risk it will use a different installed lib)
set(gRPC_PROTOBUF_PROVIDER "hack" CACHE STRING "Provider of protobuf library")
add_subdirectory(external/grpc EXCLUDE_FROM_ALL)
add_subdirectory(rpc)
endif()
# microprofile
if(HAILO_MICROPROFILE)
add_library(microprofile STATIC EXCLUDE_FROM_ALL external/microprofile/microprofile.cpp)
@@ -114,6 +143,10 @@ add_subdirectory(common)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
if(HAILO_BUILD_SERVICE)
add_subdirectory(hailort_service)
endif()
if(HAILO_WIN_DRIVER)
add_subdirectory(drivers/win)
add_subdirectory(packaging)

View File

@@ -1,15 +1,16 @@
| Package | Copyright (c) | License | Version | Notes | References |
|:---------------------------------|:----------------------------------|:-------------------|:---------------|:-------------------------------------------|:------------------------------------------------------------------------------|
| CLI11 | University of Cincinnati | 3-Clause BSD | 1.7 | Cloned entire package | https://github.com/CLIUtils/CLI11 |
| 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.11.4 | Cloned entire package | https://github.com/protocolbuffers/protobuf |
| 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 |
| 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 |
| readerwriterqueue | Cameron Desrochers | Simplified BSD | 1.0.3 | Cloned entire package | https://github.com/cameron314/readerwriterqueue |
| DotWriter | John Vilk | MIT License | master | Cloned entire package (forked) | https://github.com/jvilk/DotWriter |
| DotWriter | John Vilk | MIT License | master | Fork | https://github.com/hailo-ai/DotWriter |
| 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,7 @@ FUNCTION(disable_exceptions target)
if(WIN32)
# TODO: Find the right flag for windows (-fno-exceptions equivalent)
elseif(UNIX)
target_compile_options(libhailort PRIVATE -fno-exceptions)
target_compile_options(${target} PRIVATE -fno-exceptions)
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()

View File

@@ -12,7 +12,6 @@
#include <functional>
#include <thread>
#include <memory>
#include <atomic>
namespace hailort
{
@@ -27,7 +26,7 @@ public:
explicit AsyncThread(std::function<T(void)> func) :
m_result(),
m_thread([this, func]() {
m_result.store(func());
m_result = func();
})
{}
@@ -46,14 +45,15 @@ public:
if (m_thread.joinable()) {
m_thread.join();
}
return m_result.load();
return std::move(m_result);
}
private:
std::atomic<T> m_result;
T m_result;
std::thread m_thread;
};
template<typename T>
using AsyncThreadPtr = std::unique_ptr<AsyncThread<T>>;

View File

@@ -87,7 +87,7 @@ public:
CB_DEQUEUE(m_circ, 1);
}
T& front()
T &front()
{
return m_array[CB_TAIL(m_circ)];
}
@@ -102,6 +102,11 @@ public:
return 0 == CB_AVAIL(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ));
}
size_t size()
{
return CB_PROG(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ));
}
private:
circbuf_t m_circ;
std::vector<T> m_array;

View File

@@ -16,6 +16,7 @@
#include "hailo/expected.hpp"
#include <vector>
#include <string>
#include <chrono>
#if defined(__GNUC__)
#include <dirent.h>
@@ -29,7 +30,10 @@ public:
Filesystem() = delete;
static Expected<std::vector<std::string>> get_files_in_dir_flat(const std::string &dir_path);
static Expected<std::vector<std::string>> get_latest_files_in_dir_flat(const std::string &dir_path, std::chrono::milliseconds time_interval);
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 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());
@@ -92,6 +96,37 @@ private:
#endif
};
// TODO: HRT-7304 - Add support for windows
#if defined(__GNUC__)
class TempFile {
public:
static Expected<TempFile> create(const std::string &file_name, const std::string &file_directory = "");
~TempFile();
std::string name() const;
private:
TempFile(const char *path);
std::string m_path;
};
class LockedFile {
public:
// The mode param is the string containing the file access mode, compatible with `fopen` function.
static Expected<LockedFile> create(const std::string &file_path, const std::string &mode);
~LockedFile();
int get_fd() const;
private:
LockedFile(FILE *fp, int fd);
FILE *m_fp;
int m_fd;
};
#endif
} /* namespace hailort */
#endif /* _OS_FILESYSTEM_HPP_ */

View File

@@ -13,11 +13,13 @@
#include <errno.h>
#include <sys/stat.h>
#include <sys/file.h>
namespace hailort
{
const char *Filesystem::SEPARATOR = "/";
const std::string UNIQUE_TMP_FILE_SUFFIX = "XXXXXX\0";
Expected<Filesystem::DirWalker> Filesystem::DirWalker::create(const std::string &dir_path)
{
@@ -85,6 +87,61 @@ Expected<std::vector<std::string>> Filesystem::get_files_in_dir_flat(const std::
static_assert(false, "Unsupported Platform!");
#endif
Expected<time_t> Filesystem::get_file_modified_time(const std::string &file_path)
{
struct stat attr;
auto res = stat(file_path.c_str(), &attr);
CHECK_AS_EXPECTED((0 == res), HAILO_INTERNAL_FAILURE, "stat() failed on file {}, with errno {}", file_path, errno);
auto last_modification_time = attr.st_mtime;
return last_modification_time;
}
#if defined(__linux__)
Expected<std::vector<std::string>> Filesystem::get_latest_files_in_dir_flat(const std::string &dir_path,
std::chrono::milliseconds time_interval)
{
std::time_t curr_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
const std::string dir_path_with_sep = has_suffix(dir_path, SEPARATOR) ? dir_path : dir_path + SEPARATOR;
auto dir = DirWalker::create(dir_path_with_sep);
CHECK_EXPECTED(dir);
std::vector<std::string> files;
struct dirent *entry = nullptr;
while ((entry = dir->next_file()) != nullptr) {
if (entry->d_type != DT_REG) {
continue;
}
const std::string file_path = dir_path_with_sep + std::string(entry->d_name);
auto file_modified_time = get_file_modified_time(file_path);
CHECK_EXPECTED(file_modified_time);
auto time_diff_sec = std::difftime(curr_time, file_modified_time.value());
auto time_diff_millisec = time_diff_sec * 1000;
if (time_diff_millisec <= static_cast<double>(time_interval.count())) {
files.emplace_back(file_path);
}
}
return files;
}
#elif defined(__QNX__)
Expected<std::vector<std::string>> Filesystem::get_latest_files_in_dir_flat(const std::string &dir_path,
std::chrono::milliseconds time_interval)
{
// TODO: HRT-7643
(void)dir_path;
(void)time_interval;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
// Unsupported Platform
#else
static_assert(false, "Unsupported Platform!");
#endif // __linux__
Expected<bool> Filesystem::is_directory(const std::string &path)
{
struct stat path_stat{};
@@ -94,4 +151,75 @@ Expected<bool> Filesystem::is_directory(const std::string &path)
return S_ISDIR(path_stat.st_mode);
}
hailo_status Filesystem::create_directory(const std::string &dir_path)
{
auto ret_val = mkdir(dir_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO );
CHECK((ret_val == 0) || (errno == EEXIST), HAILO_FILE_OPERATION_FAILURE, "Failed to create directory {}", dir_path);
return HAILO_SUCCESS;
}
Expected<TempFile> TempFile::create(const std::string &file_name, const std::string &file_directory)
{
if (!file_directory.empty()) {
auto status = Filesystem::create_directory(file_directory);
CHECK_SUCCESS_AS_EXPECTED(status);
}
std::string file_path = file_directory + file_name + UNIQUE_TMP_FILE_SUFFIX;
char *fname = static_cast<char*>(std::malloc(sizeof(char) * (file_path.length() + 1)));
std::strncpy(fname, file_path.c_str(), file_path.length() + 1);
int fd = mkstemp(fname);
CHECK_AS_EXPECTED((-1 != fd), HAILO_FILE_OPERATION_FAILURE, "Failed to create tmp file {}, with errno {}", file_path, errno);
close(fd);
return TempFile(fname);
}
TempFile::TempFile(const char *path) : m_path(path)
{}
TempFile::~TempFile()
{
// TODO: Guarantee file deletion upon unexpected program termination.
std::remove(m_path.c_str());
}
std::string TempFile::name() const
{
return m_path;
}
Expected<LockedFile> LockedFile::create(const std::string &file_path, const std::string &mode)
{
auto fp = fopen(file_path.c_str(), mode.c_str());
CHECK_AS_EXPECTED((nullptr != fp), HAILO_OPEN_FILE_FAILURE, "Failed opening file: {}, with errno: {}", file_path, errno);
int fd = fileno(fp);
int done = flock(fd, LOCK_EX | LOCK_NB);
if (-1 == done) {
LOGGER__ERROR("Failed to flock file: {}, with errno: {}", file_path, errno);
fclose(fp);
return make_unexpected(HAILO_FILE_OPERATION_FAILURE);
}
return LockedFile(fp, fd);
}
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);
fclose(m_fp);
}
}
int LockedFile::get_fd() const
{
return m_fd;
}
} /* namespace hailort */

View File

@@ -129,7 +129,9 @@ hailo_status Socket::pton(int af, const char *src, void *dst)
CHECK_ARG_NOT_NULL(dst);
inet_rc = inet_pton(af, reinterpret_cast<const char*>(src), dst);
CHECK(1 == inet_rc, HAILO_ETH_FAILURE, "Could not convert string ip address to sockaddr struct");
if (1 != inet_rc) {
return HAILO_ETH_FAILURE;
}
return HAILO_SUCCESS;
}

View File

@@ -170,7 +170,7 @@ hailo_status EthernetUtils::get_interface_from_board_ip(const char *board_ip, ch
struct in_addr board_ip_struct{};
auto status = Socket::pton(AF_INET, board_ip, &board_ip_struct);
CHECK_SUCCESS(status);
CHECK_SUCCESS(status, "Invalid board ip address {}", board_ip);
for (const auto& network_interface : network_interfaces.value()) {
auto arp_table = ArpTable::create(network_interface.index());

View File

@@ -120,6 +120,22 @@ Expected<std::vector<std::string>> Filesystem::get_files_in_dir_flat(const std::
return files;
}
Expected<std::vector<std::string>> Filesystem::get_latest_files_in_dir_flat(const std::string &dir_path, std::chrono::milliseconds time_interval)
{
// TODO: HRT-7304
(void)dir_path;
(void)time_interval;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<time_t> Filesystem::get_file_modified_time(const std::string &file_path)
{
// TODO: HRT-7304
(void)file_path;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<bool> Filesystem::is_directory(const std::string &path)
{
if (path.length() > MAX_PATH) {

View File

@@ -138,7 +138,9 @@ hailo_status Socket::pton(int af, const char *src, void *dst)
CHECK_EXPECTED_AS_STATUS(module_wrapper);
inet_result = inet_pton(af, src, dst);
CHECK(1 == inet_result, HAILO_ETH_FAILURE, "Failed inet_pton. WSALE={}", WSAGetLastError());
if (1 != inet_result) {
return HAILO_ETH_FAILURE;
}
return HAILO_SUCCESS;
}

View File

@@ -10,6 +10,7 @@
#include "common/string_utils.hpp"
#include "common/utils.hpp"
#include <sstream>
#include <stdlib.h>
#include <errno.h>
@@ -71,4 +72,17 @@ Expected<uint8_t> StringUtils::to_uint8(const std::string &str, int base)
return static_cast<uint8_t>(number.value());
}
std::string StringUtils::to_hex_string(const uint8_t *array, size_t size, bool uppercase, const std::string &delimiter)
{
std::stringstream stream;
for (size_t i = 0; i < size; i++) {
const auto hex_byte = uppercase ? fmt::format("{:02X}", array[i]) : fmt::format("{:02x}", array[i]);
stream << hex_byte;
if (i != (size - 1)) {
stream << delimiter;
}
}
return stream.str();
}
} /* namespace hailort */

View File

@@ -21,6 +21,8 @@ public:
static Expected<int32_t> to_int32(const std::string &str, int base);
static Expected<uint8_t> to_uint8(const std::string &str, int base);
static Expected<uint32_t> to_uint32(const std::string &str, int base);
static std::string to_hex_string(const uint8_t *array, size_t size, bool uppercase, const std::string &delimiter="");
};
} /* namespace hailort */

View File

@@ -19,6 +19,7 @@
#include <map>
#include <set>
namespace hailort
{
@@ -221,6 +222,46 @@ _ISEMPTY( \
} while(0)
#define CHECK_SUCCESS_AS_EXPECTED(status, ...) _CHECK_SUCCESS_AS_EXPECTED(status, ISEMPTY(__VA_ARGS__), "" __VA_ARGS__)
#ifdef HAILO_SUPPORT_MULTI_PROCESS
#define _CHECK_SUCCESS_AS_RPC_STATUS(status, reply, is_default, fmt, ...) \
do { \
const auto &__check_success_status = (status); \
if (__check_success_status != HAILO_SUCCESS) { \
reply->set_status(static_cast<uint32_t>(__check_success_status)); \
LOGGER__ERROR( \
_CONSTRUCT_MSG(is_default, "CHECK_SUCCESS_AS_RPC_STATUS failed with status={}", fmt, __check_success_status, ##__VA_ARGS__) \
); \
return grpc::Status::OK; \
} \
} while(0)
#define CHECK_SUCCESS_AS_RPC_STATUS(status, reply, ...) _CHECK_SUCCESS_AS_RPC_STATUS(status, reply, ISEMPTY(__VA_ARGS__), "" __VA_ARGS__)
#define CHECK_EXPECTED_AS_RPC_STATUS(expected, reply, ...) CHECK_SUCCESS_AS_RPC_STATUS(expected.status(), reply, __VA_ARGS__)
#define _CHECK_AS_RPC_STATUS(cond, reply, ret_val, ...) \
do { \
if (!(cond)) { \
reply->set_status(ret_val); \
LOGGER__ERROR( \
_CONSTRUCT_MSG(is_default, "CHECK_AS_RPC_STATUS failed with status={}", fmt, ret_val, ##__VA_ARGS__) \
); \
return grpc::Status::OK; \
} \
} 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) \
do { \
if (!status.ok()) { \
LOGGER__ERROR("CHECK_GRPC_STATUS failed with error massage: {}.", status.error_message()); \
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))
#endif
#define _CHECK_EXPECTED(obj, is_default, fmt, ...) \
do { \
const auto &__check_expected_obj = (obj); \
@@ -244,6 +285,15 @@ _ISEMPTY( \
} while(0)
#define CHECK_EXPECTED_AS_STATUS(obj, ...) _CHECK_EXPECTED_AS_STATUS(obj, ISEMPTY(__VA_ARGS__), "" __VA_ARGS__)
#ifndef _MSC_VER
#define IGNORE_DEPRECATION_WARNINGS_BEGIN _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define IGNORE_DEPRECATION_WARNINGS_END _Pragma("GCC diagnostic pop")
#else
#define IGNORE_DEPRECATION_WARNINGS_BEGIN
#define IGNORE_DEPRECATION_WARNINGS_END
#endif
constexpr bool is_powerof2(size_t v) {
// bit trick
return (v & (v - 1)) == 0;
@@ -271,6 +321,18 @@ static uint32_t get_max_value_of_unordered_map(const std::unordered_map<K, V> &m
return max_count;
}
template<class K, class V>
static uint32_t get_min_value_of_unordered_map(const std::unordered_map<K, V> &map)
{
uint32_t min_count = UINT32_MAX;
for (auto &name_counter_pair : map) {
if (name_counter_pair.second < min_count) {
min_count = name_counter_pair.second;
}
}
return min_count;
}
} /* namespace hailort */
#endif /* HAILO_UTILS_H_ */

View File

@@ -8,9 +8,10 @@
// This value is not easily changeable.
// For example: the channel interrupts ioctls assume we have up to 32 channels
#define MAX_VDMA_CHANNELS (32)
#define SIZE_OF_VDMA_DESCRIPTOR (16)
#define VDMA_DEST_CHANNELS_START (16)
#define MAX_VDMA_CHANNELS_PER_ENGINE (32)
#define MAX_VDMA_ENGINES (3)
#define SIZE_OF_VDMA_DESCRIPTOR (16)
#define VDMA_DEST_CHANNELS_START (16)
#define CHANNEL_IRQ_TIMESTAMPS_SIZE (128 * 2) // Should be same as MAX_IRQ_TIMESTAMPS_SIZE (hailort_driver.hpp)
#define CHANNEL_IRQ_TIMESTAMPS_SIZE_MASK (CHANNEL_IRQ_TIMESTAMPS_SIZE - 1)
@@ -56,12 +57,13 @@ typedef uint8_t bool;
#define HAILO_GENERAL_IOCTL_MAGIC 'g'
#define HAILO_VDMA_IOCTL_MAGIC 'v'
#define HAILO_WINDOWS_IOCTL_MAGIC 'w'
#define HAILO_NON_LINUX_IOCTL_MAGIC 'w'
#elif defined(__QNX__) // #ifdef _MSC_VER
#include <devctl.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/mman.h>
// defines for devctl
#define _IOW_ __DIOF
#define _IOR_ __DIOT
@@ -69,6 +71,7 @@ typedef uint8_t bool;
#define _IO_ __DION
#define HAILO_GENERAL_IOCTL_MAGIC _DCMD_ALL
#define HAILO_VDMA_IOCTL_MAGIC _DCMD_MISC
#define HAILO_NON_LINUX_IOCTL_MAGIC _DCMD_PROC
#else // #ifdef _MSC_VER
#error "unsupported platform!"
@@ -103,13 +106,24 @@ enum hailo_allocation_mode {
/* structure used in ioctl HAILO_VDMA_BUFFER_MAP */
struct hailo_vdma_buffer_map_params {
#if defined(__linux__) || defined(_MSC_VER)
void* user_address; // in
#elif defined(__QNX__)
shm_handle_t shared_memory_handle; // in
#else
#error "unsupported platform!"
#endif // __linux__
size_t size; // in
enum hailo_dma_data_direction data_direction; // in
uintptr_t allocated_buffer_handle; // in
size_t mapped_handle; // out
};
/* structure used in ioctl HAILO_VDMA_BUFFER_UNMAP */
struct hailo_vdma_buffer_unmap_params {
size_t mapped_handle;
};
/* structure used in ioctl HAILO_DESC_LIST_CREATE */
struct hailo_desc_list_create_params {
size_t desc_count; // in
@@ -118,8 +132,8 @@ struct hailo_desc_list_create_params {
uint64_t dma_address; // out
};
/* structure used in ioctl HAILO_WINDOWS_DESC_LIST_MMAP */
struct hailo_windows_desc_list_mmap_params {
/* structure used in ioctl HAILO_NON_LINUX_DESC_LIST_MMAP */
struct hailo_non_linux_desc_list_mmap_params {
uintptr_t desc_handle; // in
size_t size; // in
void* user_address; // out
@@ -135,7 +149,8 @@ struct hailo_desc_list_bind_vdma_buffer_params {
/* structure used in ioctl HAILO_VDMA_CHANNEL_ENABLE */
struct hailo_vdma_channel_enable_params {
uint32_t channel_index; // in
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.
@@ -146,28 +161,39 @@ struct hailo_vdma_channel_enable_params {
/* structure used in ioctl HAILO_VDMA_CHANNEL_DISABLE */
struct hailo_vdma_channel_disable_params {
uint32_t channel_index; // in
uint8_t engine_index; // in
uint8_t channel_index; // in
uint64_t channel_handle; // in
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_WAIT_INT */
struct hailo_vdma_channel_wait_params {
uint32_t channel_index; // in
uint64_t channel_handle; // in
uint64_t timeout_ms; // in
struct hailo_channel_interrupt_timestamp *timestamps; // out
uint32_t timestamps_count; // inout
uint8_t engine_index; // in
uint8_t channel_index; // in
uint64_t channel_handle; // in
uint64_t timeout_ms; // in
uint32_t timestamps_count; // inout
// In linux send address to local buffer because there isnt room on stack for array
#if defined(__linux__)
struct hailo_channel_interrupt_timestamp *timestamps; // out
#elif defined(__QNX__) || defined(_MSC_VER)
struct hailo_channel_interrupt_timestamp timestamps[CHANNEL_IRQ_TIMESTAMPS_SIZE]; // out
#else
#error "unsupported platform!"
#endif // __linux__
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_ABORT */
struct hailo_vdma_channel_abort_params {
uint32_t channel_index; // in
uint8_t engine_index; // in
uint8_t channel_index; // in
uint64_t channel_handle; // in
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_CLEAR_ABORT */
struct hailo_vdma_channel_clear_abort_params {
uint32_t channel_index; // in
uint8_t engine_index; // in
uint8_t channel_index; // in
uint64_t channel_handle; // in
};
@@ -215,12 +241,24 @@ struct hailo_bar_transfer_params {
uint8_t buffer[MAX_BAR_TRANSFER_LENGTH]; // in/out
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_REGISTERS */
struct hailo_channel_registers_params {
enum hailo_transfer_direction transfer_direction; // in
off_t offset; // in
size_t size; // in
uint32_t data; // in/out
/* structure used in ioctl HAILO_VDMA_CHANNEL_READ_REGISTER */
struct hailo_vdma_channel_read_register_params {
uint8_t engine_index; // in
uint8_t channel_index; // in
enum hailo_dma_data_direction direction; // in
size_t offset; // in
size_t reg_size; // in, can be either 1, 2 or 4
uint32_t data; // out
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_WRITE_REGISTER */
struct hailo_vdma_channel_write_register_params {
uint8_t engine_index; // in
uint8_t channel_index; // in
enum hailo_dma_data_direction direction; // in
size_t offset; // in
size_t reg_size; // in, can be either 1, 2 or 4
uint32_t data; // in
};
/* structure used in ioctl HAILO_VDMA_BUFFER_SYNC */
@@ -267,6 +305,10 @@ struct hailo_device_properties {
enum hailo_board_type board_type;
enum hailo_allocation_mode allocation_mode;
enum hailo_dma_type dma_type;
size_t dma_engines_count;
#ifdef __QNX__
pid_t resource_manager_pid;
#endif // __QNX__
};
struct hailo_driver_info {
@@ -331,7 +373,8 @@ enum hailo_vdma_ioctl_code {
HAILO_VDMA_CHANNEL_WAIT_INT_CODE,
HAILO_VDMA_CHANNEL_ABORT_CODE,
HAILO_VDMA_CHANNEL_CLEAR_ABORT_CODE,
HAILO_VDMA_CHANNEL_REGISTERS_CODE,
HAILO_VDMA_CHANNEL_READ_REGISTER_CODE,
HAILO_VDMA_CHANNEL_WRITE_REGISTER_CODE,
HAILO_VDMA_BUFFER_MAP_CODE,
HAILO_VDMA_BUFFER_UNMAP_CODE,
HAILO_VDMA_BUFFER_SYNC_CODE,
@@ -348,19 +391,20 @@ enum hailo_vdma_ioctl_code {
HAILO_VDMA_IOCTL_MAX_NR,
};
#define HAILO_VDMA_CHANNEL_ENABLE _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_ENABLE_CODE, struct hailo_vdma_channel_enable_params)
#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_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_REGISTERS _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_REGISTERS_CODE, struct hailo_channel_registers_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)
#define HAILO_VDMA_CHANNEL_WRITE_REGISTER _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CHANNEL_WRITE_REGISTER_CODE, struct hailo_vdma_channel_write_register_params)
#define HAILO_VDMA_BUFFER_MAP _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_BUFFER_MAP_CODE, struct hailo_vdma_buffer_map_params)
#define HAILO_VDMA_BUFFER_UNMAP _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_BUFFER_UNMAP_CODE)
#define HAILO_VDMA_BUFFER_MAP _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_BUFFER_MAP_CODE, struct hailo_vdma_buffer_map_params)
#define HAILO_VDMA_BUFFER_UNMAP _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_BUFFER_UNMAP_CODE, struct hailo_vdma_buffer_unmap_params)
#define HAILO_VDMA_BUFFER_SYNC _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_BUFFER_SYNC_CODE, struct hailo_vdma_buffer_sync_params)
#define HAILO_DESC_LIST_CREATE _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_CREATE_CODE, struct hailo_desc_list_create_params)
#define HAILO_DESC_LIST_RELEASE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_RELEASE_CODE)
#define HAILO_DESC_LIST_RELEASE _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_RELEASE_CODE, uintptr_t)
#define HAILO_DESC_LIST_BIND_VDMA_BUFFER _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_BIND_VDMA_BUFFER_CODE, struct hailo_desc_list_bind_vdma_buffer_params)
#define HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC_CODE, struct hailo_allocate_low_memory_buffer_params)
@@ -372,14 +416,14 @@ enum hailo_vdma_ioctl_code {
#define HAILO_VDMA_CONTINUOUS_BUFFER_FREE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CONTINUOUS_BUFFER_FREE_CODE)
enum hailo_windows_ioctl_code {
HAILO_WINDOWS_DESC_LIST_MMAP_CODE,
enum hailo_non_linux_ioctl_code {
HAILO_NON_LINUX_DESC_LIST_MMAP_CODE,
// Must be last
HAILO_WINDOWS_IOCTL_MAX_NR,
HAILO_NON_LINUX_IOCTL_MAX_NR,
};
#define HAILO_WINDOWS_DESC_LIST_MMAP _IOWR_(HAILO_WINDOWS_IOCTL_MAGIC, HAILO_WINDOWS_DESC_LIST_MMAP_CODE, struct hailo_windows_desc_list_mmap_params)
#define HAILO_NON_LINUX_DESC_LIST_MMAP _IOWR_(HAILO_NON_LINUX_IOCTL_MAGIC, HAILO_NON_LINUX_DESC_LIST_MMAP_CODE, struct hailo_non_linux_desc_list_mmap_params)
#endif /* _HAILO_IOCTL_COMMON_H_ */

View File

@@ -75,7 +75,7 @@ struct tCompatibleHailoIoctlParam
#define HAILO_GENERAL_IOCTL_MAGIC 0
#define HAILO_VDMA_IOCTL_MAGIC 1
#define HAILO_WINDOWS_IOCTL_MAGIC 2
#define HAILO_NON_LINUX_IOCTL_MAGIC 2
@@ -111,13 +111,16 @@ struct tCompatibleHailoIoctlData
hailo_vdma_buffer_sync_params VdmaBufferSync;
hailo_fw_control FirmwareControl;
hailo_vdma_buffer_map_params VdmaBufferMap;
hailo_vdma_buffer_unmap_params VdmaBufferUnmap;
hailo_desc_list_create_params DescListCreate;
uintptr_t DescListReleaseParam;
hailo_desc_list_bind_vdma_buffer_params DescListBind;
hailo_d2h_notification D2HNotification;
hailo_device_properties DeviceProperties;
hailo_driver_info DriverInfo;
hailo_channel_registers_params ChannelRegisters;
hailo_windows_desc_list_mmap_params DescListMmap;
hailo_vdma_channel_read_register_params ChannelRegisterRead;
hailo_vdma_channel_write_register_params ChannelRegisterWrite;
hailo_non_linux_desc_list_mmap_params DescListMmap;
hailo_read_log_params ReadLog;
hailo_mark_as_in_use_params MarkAsInUse;
} Buffer;

View File

@@ -0,0 +1,47 @@
cmake_minimum_required(VERSION 3.0.0)
add_executable(hailort_service
hailort_rpc_service.cpp
hailort_service.cpp
service_resource_manager.hpp
)
target_compile_options(hailort_service PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailort_service PROPERTY CXX_STANDARD 14)
target_link_libraries(hailort_service
libhailort
spdlog::spdlog
grpc++_unsecure
hailort_rpc_grpc_proto)
target_include_directories(hailort_service
PRIVATE
${HAILORT_INC_DIR}
${COMMON_INC_DIR}
${RPC_DIR}
)
disable_exceptions(hailort_service)
# Install systemd unit file
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()
set(HAILORT_SERVICE_UNIT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/hailort.service)
install(
FILES "${HAILORT_SERVICE_UNIT_FILE}"
DESTINATION "${SYSTEMD_UNIT_DIR}"
CONFIGURATIONS Release
COMPONENT hailort_service
)
install(
TARGETS hailort_service
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
CONFIGURATIONS Release
)
# Create empty directory for hailort log file
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(HAILORT_LOG_DIR "/var/log/hailo")
install(DIRECTORY DESTINATION ${HAILORT_LOG_DIR})
endif()

View File

@@ -0,0 +1,13 @@
[Unit]
Description=HailoRT service
Documentation=https://github.com/hailo-ai/hailort
[Service]
Type=forking
ExecStart=/usr/local/bin/hailort_service
Restart=on-failure
RemainAfterExit=yes
Environment="HAILORT_LOGGER_PATH=/var/log/hailo"
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,744 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailort_rpc_service.cpp
* @brief Implementation of the hailort rpc service
**/
#include "hailort_rpc_service.hpp"
#include "rpc/rpc_definitions.hpp"
#include "service_resource_manager.hpp"
#include "common/utils.hpp"
#include "hailo/network_group.hpp"
#include "hailo/vdevice.hpp"
#include "hailo/vstream.hpp"
#include "hailo/hailort_common.hpp"
#include <syslog.h>
namespace hailort
{
grpc::Status HailoRtRpcService::client_keep_alive(grpc::ServerContext *ctx, const keepalive_Request *request,
empty*)
{
auto client_id = request->process_id();
while (!ctx->IsCancelled()) {
sleep(hailort::HAILO_KEEPALIVE_INTERVAL_SEC);
}
LOGGER__INFO("Client disconnected, pid: {}", client_id);
syslog(LOG_NOTICE, "Client disconnected, pid: %i", client_id);
ServiceResourceManager<OutputVStream>::get_instance().release_by_pid(client_id);
ServiceResourceManager<InputVStream>::get_instance().release_by_pid(client_id);
ServiceResourceManager<ConfiguredNetworkGroup>::get_instance().release_by_pid(client_id);
ServiceResourceManager<VDevice>::get_instance().release_by_pid(client_id);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::get_service_version(grpc::ServerContext*, const get_service_version_Request*,
get_service_version_Reply *reply)
{
hailo_version_t service_version = {};
auto status = hailo_get_library_version(&service_version);
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
auto hailo_version_proto = reply->mutable_hailo_version();
hailo_version_proto->set_major_version(service_version.major);
hailo_version_proto->set_minor_version(service_version.minor);
hailo_version_proto->set_revision_version(service_version.revision);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_create(grpc::ServerContext *, const VDevice_create_Request *request,
VDevice_create_Reply *reply)
{
// Deserialization
const auto params_proto = request->hailo_vdevice_params();
std::vector<hailo_device_id_t> device_ids;
device_ids.reserve(params_proto.device_ids().size());
for (auto device_id_str : params_proto.device_ids()) {
auto device_id_struct = HailoRTCommon::to_device_id(device_id_str);
CHECK_SUCCESS_AS_RPC_STATUS(device_id_struct.status(), reply);
device_ids.push_back(device_id_struct.release());
}
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(),
.multi_process_service = false
};
auto vdevice = VDevice::create(params);
CHECK_EXPECTED_AS_RPC_STATUS(vdevice, reply);
auto &manager = ServiceResourceManager<VDevice>::get_instance();
auto handle = manager.register_resource(request->pid(), std::move(vdevice.release()));
reply->set_handle(handle);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
{
auto &manager = ServiceResourceManager<VDevice>::get_instance();
auto status = manager.release_resource(request->handle());
reply->set_status(static_cast<uint32_t>(status));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_configure(grpc::ServerContext*, const VDevice_configure_Request *request,
VDevice_configure_Reply *reply)
{
auto hef_as_string = request->hef();
auto hef_memview = MemoryView::create_const(hef_as_string.c_str(), hef_as_string.length());
auto hef = Hef::create(hef_memview);
CHECK_SUCCESS_AS_RPC_STATUS(hef.status(), reply);
NetworkGroupsParamsMap configure_params_map;
for (auto &name_configure_params_pair : request->configure_params_map()) {
ConfigureNetworkParams network_configure_params;
auto proto_configure_params = name_configure_params_pair.params();
network_configure_params.batch_size = static_cast<uint16_t>(proto_configure_params.batch_size());
network_configure_params.power_mode = static_cast<hailo_power_mode_t>(proto_configure_params.power_mode());
network_configure_params.latency = static_cast<hailo_latency_measurement_flags_t>(proto_configure_params.latency());
// Init streams params
for (auto &proto_name_streams_params_pair : proto_configure_params.stream_params_map()) {
auto proto_streams_params = proto_name_streams_params_pair.params();
auto stream_direction = static_cast<hailo_stream_direction_t>(proto_streams_params.direction());
hailo_stream_parameters_t stream_params;
if (stream_direction == HAILO_H2D_STREAM) {
stream_params = {
.stream_interface = static_cast<hailo_stream_interface_t>(proto_streams_params.stream_interface()),
.direction = stream_direction,
{.pcie_input_params = {
.reserved = 0
}}
};
} else {
stream_params = {
.stream_interface = static_cast<hailo_stream_interface_t>(proto_streams_params.stream_interface()),
.direction = stream_direction,
{.pcie_output_params = {
.reserved = 0
}}
};
}
network_configure_params.stream_params_by_name.insert({proto_name_streams_params_pair.name(), stream_params});
}
// Init networks params
for (auto &proto_name_network_params_pair : proto_configure_params.network_params_map()) {
auto proto_network_params = proto_name_network_params_pair.params();
hailo_network_parameters_t net_params {
.batch_size = static_cast<uint16_t>(proto_network_params.batch_size())
};
network_configure_params.network_params_by_name.insert({proto_name_network_params_pair.name(), net_params});
}
configure_params_map.insert({name_configure_params_pair.name(), network_configure_params});
}
auto lambda = [](std::shared_ptr<VDevice> vdevice, Hef &hef, NetworkGroupsParamsMap &configure_params_map) {
return vdevice->configure(hef, configure_params_map);
};
auto &vdevice_manager = ServiceResourceManager<VDevice>::get_instance();
auto networks = vdevice_manager.execute<Expected<ConfiguredNetworkGroupVector>>(request->handle(), lambda, hef.release(), configure_params_map);
CHECK_SUCCESS_AS_RPC_STATUS(networks.status(), reply);
auto &networks_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
for (auto network : networks.value()) {
auto handle = networks_manager.register_resource(request->pid(), network);
reply->add_networks_handles(handle);
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_get_physical_devices_ids(grpc::ServerContext*,
const VDevice_get_physical_devices_ids_Request* request, VDevice_get_physical_devices_ids_Reply* reply)
{
auto lambda = [](std::shared_ptr<VDevice> vdevice) {
return vdevice->get_physical_devices_ids();
};
auto &vdevice_manager = ServiceResourceManager<VDevice>::get_instance();
auto expected_devices_ids = vdevice_manager.execute<Expected<std::vector<std::string>>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(expected_devices_ids, reply);
auto devices_ids = expected_devices_ids.value();
auto devices_ids_proto = reply->mutable_devices_ids();
for (auto &device_id : devices_ids) {
devices_ids_proto->Add(std::move(device_id));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
{
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = manager.release_resource(request->handle());
reply->set_status(static_cast<uint32_t>(status));
return grpc::Status::OK;
}
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)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, bool quantized,
hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size, std::string network_name) {
return cng->make_input_vstream_params(quantized, format_type, timeout_ms, queue_size, network_name);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_params = manager.execute<Expected<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(), request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto params_map = reply->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));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_make_output_vstream_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_output_vstream_params_Request *request,
ConfiguredNetworkGroup_make_output_vstream_params_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, std::string network_name) {
return cng->make_output_vstream_params(quantized, format_type, timeout_ms, queue_size, network_name);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_params = manager.execute<Expected<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(), request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_params, reply);
auto params_map = reply->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));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_default_stream_interface(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_default_stream_interface_Request *request,
ConfiguredNetworkGroup_get_default_stream_interface_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->get_default_streams_interface();
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_stream_interface = net_group_manager.execute<Expected<hailo_stream_interface_t>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(expected_stream_interface, reply);
reply->set_stream_interface(static_cast<uint32_t>(expected_stream_interface.value()));
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_output_vstream_groups(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_output_vstream_groups_Request *request,
ConfiguredNetworkGroup_get_output_vstream_groups_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->get_output_vstream_groups();
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_output_vstream_groups = net_group_manager.execute<Expected<std::vector<std::vector<std::string>>>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(expected_output_vstream_groups, reply);
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;
for (auto& name : group) {
auto vstream_group_proto = group_proto.mutable_vstream_group();
vstream_group_proto->Add(std::move(name));
}
groups_proto->Add(std::move(group_proto));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
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);
vstream_infos_proto->Add(std::move(info_proto));
}
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_input_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, std::string network_name) {
return cng->get_input_vstream_infos(network_name);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_vstream_infos = net_group_manager.execute<Expected<std::vector<hailo_vstream_info_t>>>(request->handle(), lambda, request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_vstream_infos, reply);
serialize_vstream_infos(reply, expected_vstream_infos.value());
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_output_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, std::string network_name) {
return cng->get_output_vstream_infos(network_name);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_vstream_infos = net_group_manager.execute<Expected<std::vector<hailo_vstream_info_t>>>(request->handle(), lambda, request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_vstream_infos, reply);
serialize_vstream_infos(reply, expected_vstream_infos.value());
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_all_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, std::string network_name) {
return cng->get_all_vstream_infos(network_name);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_vstream_infos = net_group_manager.execute<Expected<std::vector<hailo_vstream_info_t>>>(request->handle(), lambda, request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_vstream_infos, reply);
serialize_vstream_infos(reply, expected_vstream_infos.value());
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_scheduler_timeout(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_scheduler_timeout_Request *request,
ConfiguredNetworkGroup_set_scheduler_timeout_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, std::chrono::milliseconds timeout_ms) {
return cng->set_scheduler_timeout(timeout_ms);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = net_group_manager.execute<hailo_status>(request->handle(), lambda, static_cast<std::chrono::milliseconds>(request->timeout_ms()));
reply->set_status(status);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_scheduler_threshold(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_scheduler_threshold_Request *request,
ConfiguredNetworkGroup_set_scheduler_threshold_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, uint32_t threshold, std::string network_name) {
return cng->set_scheduler_threshold(threshold, network_name);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = net_group_manager.execute<hailo_status>(request->handle(), lambda, request->threshold(),
request->network_name());
reply->set_status(status);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply)
{
std::map<std::string, hailo_vstream_params_t> inputs_params;
for (auto& param_proto : request->vstreams_params()) {
auto vstream_params_proto = param_proto.params();
auto user_buffer_format_proto = vstream_params_proto.user_buffer_format();
hailo_format_t format;
format.flags = hailo_format_flags_t(user_buffer_format_proto.flags());
format.order = hailo_format_order_t(user_buffer_format_proto.order());
format.type = hailo_format_type_t(user_buffer_format_proto.type());
hailo_vstream_params_t params = {
.user_buffer_format = format,
.timeout_ms = vstream_params_proto.timeout_ms(),
.queue_size = vstream_params_proto.queue_size(),
.vstream_stats_flags = hailo_vstream_stats_flags_t(vstream_params_proto.vstream_stats_flags()),
.pipeline_elements_stats_flags = hailo_pipeline_elem_stats_flags_t(vstream_params_proto.pipeline_elements_stats_flags())
};
inputs_params.emplace(param_proto.name(), std::move(params));
}
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, const std::map<std::string, hailo_vstream_params_t> &inputs_params) {
return cng->create_input_vstreams(inputs_params);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto vstreams_expected = net_group_manager.execute<Expected<std::vector<InputVStream>>>(request->net_group(), lambda, inputs_params);
CHECK_EXPECTED_AS_RPC_STATUS(vstreams_expected, reply);
auto vstreams = vstreams_expected.release();
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto client_pid = request->pid();
for (size_t i = 0; i < vstreams.size(); i++) {
auto handle = manager.register_resource(client_pid, make_shared_nothrow<InputVStream>(std::move(vstreams[i])));
reply->add_handles(handle);
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_release(grpc::ServerContext *, const Release_Request *request,
Release_Reply *reply)
{
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto status = manager.release_resource(request->handle());
reply->set_status(static_cast<uint32_t>(status));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply)
{
std::map<std::string, hailo_vstream_params_t> output_params;
for (auto& param_proto : request->vstreams_params()) {
auto vstream_params_proto = param_proto.params();
auto user_buffer_format_proto = vstream_params_proto.user_buffer_format();
hailo_format_t format;
format.flags = hailo_format_flags_t(user_buffer_format_proto.flags());
format.order = hailo_format_order_t(user_buffer_format_proto.order());
format.type = hailo_format_type_t(user_buffer_format_proto.type());
hailo_vstream_params_t params = {
.user_buffer_format = format,
.timeout_ms = vstream_params_proto.timeout_ms(),
.queue_size = vstream_params_proto.queue_size(),
.vstream_stats_flags = hailo_vstream_stats_flags_t(vstream_params_proto.vstream_stats_flags()),
.pipeline_elements_stats_flags = hailo_pipeline_elem_stats_flags_t(vstream_params_proto.pipeline_elements_stats_flags())
};
output_params.emplace(param_proto.name(), std::move(params));
}
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, const std::map<std::string, hailo_vstream_params_t> &output_params) {
return cng->create_output_vstreams(output_params);
};
auto &net_group_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto vstreams_expected = net_group_manager.execute<Expected<std::vector<OutputVStream>>>(request->net_group(), lambda, output_params);
CHECK_EXPECTED_AS_RPC_STATUS(vstreams_expected, reply);
auto vstreams = vstreams_expected.release();
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto client_pid = request->pid();
for (size_t i = 0; i < vstreams.size(); i++) {
auto handle = manager.register_resource(client_pid, make_shared_nothrow<OutputVStream>(std::move(vstreams[i])));
reply->add_handles(handle);
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_release(grpc::ServerContext *, const Release_Request *request,
Release_Reply *reply)
{
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto status = manager.release_resource(request->handle());
reply->set_status(static_cast<uint32_t>(status));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_name(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_name_Request *request,
ConfiguredNetworkGroup_get_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->name();
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto network_group_name = manager.execute<std::string>(request->handle(), lambda);
reply->set_network_group_name(network_group_name);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_write(grpc::ServerContext*, const InputVStream_write_Request *request,
InputVStream_write_Reply *reply)
{
auto buffer_expected = Buffer::create_shared(request->data().length());
CHECK_EXPECTED_AS_RPC_STATUS(buffer_expected, reply);
std::vector<uint8_t> data(request->data().begin(), request->data().end());
auto lambda = [](std::shared_ptr<InputVStream> input_vstream, const MemoryView &buffer) {
return input_vstream->write(std::move(buffer));
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto status = manager.execute<hailo_status>(request->handle(), lambda, MemoryView::create_const(data.data(), data.size()));
CHECK_SUCCESS_AS_RPC_STATUS(status, reply, "VStream write failed");
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_network_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_network_infos_Request *request,
ConfiguredNetworkGroup_get_network_infos_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->get_network_infos();
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_network_infos = manager.execute<Expected<std::vector<hailo_network_info_t>>>(request->handle(), lambda);
CHECK_EXPECTED_AS_RPC_STATUS(expected_network_infos, reply);
auto infos_proto = reply->mutable_network_infos();
for (auto& info : expected_network_infos.value()) {
infos_proto->Add(std::string(info.name));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_read(grpc::ServerContext*, const OutputVStream_read_Request *request,
OutputVStream_read_Reply *reply)
{
std::vector<uint8_t> data(request->size());
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream, MemoryView &buffer) {
return output_vstream->read(std::move(buffer));
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto status = manager.execute<hailo_status>(request->handle(), lambda, MemoryView(data.data(), data.size()));
CHECK_SUCCESS_AS_RPC_STATUS(status, reply, "VStream read failed");
reply->set_data(data.data(), data.size());
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_all_stream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_all_stream_infos_Request *request,
ConfiguredNetworkGroup_get_all_stream_infos_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->get_all_stream_infos();
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_stream_infos = manager.execute<Expected<std::vector<hailo_stream_info_t>>>(request->handle(), lambda);
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;
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);
proto_nms_info->set_max_bboxes_per_class(stream_info.nms_info.max_bboxes_per_class);
proto_nms_info->set_bbox_size(stream_info.nms_info.bbox_size);
proto_nms_info->set_chunks_per_frame(stream_info.nms_info.chunks_per_frame);
proto_nms_info->set_is_defused(stream_info.nms_info.is_defused);
auto proto_nms_info_defuse_info = proto_nms_info->mutable_defuse_info();
proto_nms_info_defuse_info->set_class_group_index(stream_info.nms_info.defuse_info.class_group_index);
proto_nms_info_defuse_info->set_original_name(std::string(stream_info.nms_info.defuse_info.original_name));
} else {
auto proto_stream_shape = proto_stream_info.mutable_stream_shape();
auto proto_stream_shape_shape = proto_stream_shape->mutable_shape();
proto_stream_shape_shape->set_height(stream_info.shape.height);
proto_stream_shape_shape->set_width(stream_info.shape.width);
proto_stream_shape_shape->set_features(stream_info.shape.features);
auto proto_stream_shape_hw_shape = proto_stream_shape->mutable_hw_shape();
proto_stream_shape_hw_shape->set_height(stream_info.hw_shape.height);
proto_stream_shape_hw_shape->set_width(stream_info.hw_shape.width);
proto_stream_shape_hw_shape->set_features(stream_info.hw_shape.features);
}
proto_stream_info.set_hw_data_bytes(stream_info.hw_data_bytes);
proto_stream_info.set_hw_frame_size(stream_info.hw_frame_size);
auto proto_stream_info_format = proto_stream_info.mutable_format();
proto_stream_info_format->set_type(stream_info.format.type);
proto_stream_info_format->set_order(stream_info.format.order);
proto_stream_info_format->set_flags(stream_info.format.flags);
proto_stream_info.set_direction(static_cast<uint32_t>(stream_info.direction));
proto_stream_info.set_index(stream_info.index);
proto_stream_info.set_name(stream_info.name);
auto proto_quant_info = proto_stream_info.mutable_quant_info();
proto_quant_info->set_qp_zp(stream_info.quant_info.qp_zp);
proto_quant_info->set_qp_scale(stream_info.quant_info.qp_scale);
proto_quant_info->set_limvals_min(stream_info.quant_info.limvals_min);
proto_quant_info->set_limvals_max(stream_info.quant_info.limvals_max);
proto_stream_info.set_is_mux(stream_info.is_mux);
proto_stream_infos->Add(std::move(proto_stream_info));
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_latency_measurement(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_latency_measurement_Request *request,
ConfiguredNetworkGroup_get_latency_measurement_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, const std::string &network_name) {
return cng->get_latency_measurement(network_name);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto expected_latency_result = manager.execute<Expected<LatencyMeasurementResult>>(request->handle(), lambda, request->network_name());
CHECK_EXPECTED_AS_RPC_STATUS(expected_latency_result, reply);
reply->set_avg_hw_latency(static_cast<uint32_t>(expected_latency_result.value().avg_hw_latency.count()));
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)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->get_frame_size();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto frame_size = manager.execute<size_t>(request->handle(), lambda);
reply->set_frame_size(static_cast<uint32_t>(frame_size));
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_get_frame_size(grpc::ServerContext*, const VStream_get_frame_size_Request *request,
VStream_get_frame_size_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->get_frame_size();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto frame_size = manager.execute<size_t>(request->handle(), lambda);
reply->set_frame_size(static_cast<uint32_t>(frame_size));
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_flush(grpc::ServerContext*, const InputVStream_flush_Request *request,
InputVStream_flush_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->flush();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto flush_status = manager.execute<hailo_status>(request->handle(), lambda);
reply->set_status(static_cast<uint32_t>(flush_status));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_name(grpc::ServerContext*, const VStream_name_Request *request,
VStream_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->name();
};
auto &manager = ServiceResourceManager<InputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_name(name);
reply->set_status(HAILO_SUCCESS);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_name(grpc::ServerContext*, const VStream_name_Request *request,
VStream_name_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->name();
};
auto &manager = ServiceResourceManager<OutputVStream>::get_instance();
auto name = manager.execute<std::string>(request->handle(), lambda);
reply->set_name(name);
reply->set_status(HAILO_SUCCESS);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::InputVStream_abort(grpc::ServerContext*, const VStream_abort_Request *request,
VStream_abort_Reply *reply)
{
auto lambda = [](std::shared_ptr<InputVStream> input_vstream) {
return input_vstream->abort();
};
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_abort(grpc::ServerContext*, const VStream_abort_Request *request,
VStream_abort_Reply *reply)
{
auto lambda = [](std::shared_ptr<OutputVStream> output_vstream) {
return output_vstream->abort();
};
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_resume(grpc::ServerContext*, const VStream_resume_Request *,
VStream_resume_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);
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::OutputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *,
VStream_resume_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);
return grpc::Status::OK;
}
}

View File

@@ -0,0 +1,125 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailort_rpc_service.hpp
* @brief TODO
**/
#ifndef HAILO_HAILORT_RPC_SERVICE_HPP_
#define HAILO_HAILORT_RPC_SERVICE_HPP_
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4244 4267 4127)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <grpcpp/grpcpp.h>
#include "hailort_rpc.grpc.pb.h"
#if defined(_MSC_VER)
#pragma warning( pop )
#else
#pragma GCC diagnostic pop
#endif
namespace hailort
{
class HailoRtRpcService final : public HailoRtRpc::Service {
public:
virtual grpc::Status client_keep_alive(grpc::ServerContext *ctx, const keepalive_Request *request,
empty*) override;
virtual grpc::Status get_service_version(grpc::ServerContext *, const get_service_version_Request *request,
get_service_version_Reply *reply) override;
virtual grpc::Status VDevice_create(grpc::ServerContext *, const VDevice_create_Request *request,
VDevice_create_Reply *reply) override;
virtual grpc::Status VDevice_release(grpc::ServerContext *, const Release_Request *request,
Release_Reply* reply) override;
virtual grpc::Status VDevice_configure(grpc::ServerContext*, const VDevice_configure_Request* request,
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 InputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply) override;
virtual grpc::Status InputVStream_release(grpc::ServerContext * , const Release_Request *request,
Release_Reply *reply) override;
virtual grpc::Status OutputVStreams_create(grpc::ServerContext *, const VStream_create_Request *request,
VStreams_create_Reply *reply) override;
virtual grpc::Status OutputVStream_release(grpc::ServerContext *, const Release_Request *request,
Release_Reply *reply) override;
virtual grpc::Status InputVStream_write(grpc::ServerContext*, const InputVStream_write_Request *request,
InputVStream_write_Reply *reply) override;
virtual grpc::Status OutputVStream_read(grpc::ServerContext*, const OutputVStream_read_Request *request,
OutputVStream_read_Reply *reply) override;
virtual grpc::Status InputVStream_get_frame_size(grpc::ServerContext*, const VStream_get_frame_size_Request *request,
VStream_get_frame_size_Reply *reply) override;
virtual grpc::Status OutputVStream_get_frame_size(grpc::ServerContext*, const VStream_get_frame_size_Request *request,
VStream_get_frame_size_Reply *reply) override;
virtual grpc::Status InputVStream_flush(grpc::ServerContext*, const InputVStream_flush_Request *request,
InputVStream_flush_Reply *reply) override;
virtual grpc::Status InputVStream_name(grpc::ServerContext*, const VStream_name_Request *request,
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_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,
VStream_abort_Reply *reply) override;
virtual grpc::Status InputVStream_resume(grpc::ServerContext*, const VStream_resume_Request *request,
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 ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request* request,
Release_Reply* reply) override;
virtual grpc::Status ConfiguredNetworkGroup_make_input_vstream_params(grpc::ServerContext*,
const ConfiguredNetworkGroup_make_input_vstream_params_Request *request,
ConfiguredNetworkGroup_make_input_vstream_params_Reply *reply) override;
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_get_network_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_network_infos_Request *request,
ConfiguredNetworkGroup_get_network_infos_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_all_stream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_all_stream_infos_Request *request,
ConfiguredNetworkGroup_get_all_stream_infos_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_default_stream_interface(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_default_stream_interface_Request *request,
ConfiguredNetworkGroup_get_default_stream_interface_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_output_vstream_groups(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_output_vstream_groups_Request *request,
ConfiguredNetworkGroup_get_output_vstream_groups_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_input_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_all_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_set_scheduler_timeout(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_scheduler_timeout_Request *request,
ConfiguredNetworkGroup_set_scheduler_timeout_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_set_scheduler_threshold(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_scheduler_threshold_Request *request,
ConfiguredNetworkGroup_set_scheduler_threshold_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_output_vstream_infos(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_vstream_infos_Request *request,
ConfiguredNetworkGroup_get_vstream_infos_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_get_latency_measurement(grpc::ServerContext*,
const ConfiguredNetworkGroup_get_latency_measurement_Request *request,
ConfiguredNetworkGroup_get_latency_measurement_Reply *reply) override;
};
}
#endif // HAILO_HAILORT_RPC_SERVICE_HPP_

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
*
* @file hailort_service.cpp
* @brief main for hailort service
* TODO: move to user guide (HRT-7559)
* * 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:
* 1) Install the HailoRT:
* cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release -DHAILO_BUILD_SERVICE=1 && sudo cmake --build build --target install
*
* 2) Reload systemd manager configuration:
* sudo systemctl daemon-reload
*
* 3) Enable and start the service
* sudo systemctl enable --now hailort.service
*
* 4) Stop service
* sudo systemctl stop hailort.service
*/
#include "hailort_rpc_service.hpp"
#include "rpc/rpc_definitions.hpp"
#include "common/utils.hpp"
#include "hailo/hailort_common.hpp"
#include <syslog.h>
#include <sys/stat.h>
void RunService() {
std::string server_address(hailort::HAILO_DEFAULT_UDS_ADDR);
hailort::HailoRtRpcService service;
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.SetMaxReceiveMessageSize(-1);
builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
chmod(hailort::HAILO_DEFAULT_SERVICE_ADDR.c_str(), S_IROTH | S_IWOTH | S_IRUSR | S_IWUSR);
server->Wait();
}
int main(int argc, char *argv[])
{
bool is_standalone = ((1 < argc) && (strcmp("standalone", argv[1]) == 0));
if (!is_standalone) {
int ret = daemon(0,0);
if (ret < 0) {
syslog(LOG_ERR, "Failed to create daemon with errno %i", errno);
exit(EXIT_FAILURE);
}
}
RunService();
return 0;
}

View File

@@ -0,0 +1,113 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file service_resource_manager.hpp
* @brief manages handles for resource objects.
*
**/
#ifndef HAILO_SERVICE_RESOURCE_MANAGER_HPP_
#define HAILO_SERVICE_RESOURCE_MANAGER_HPP_
#include "hailo/expected.hpp"
#include "common/utils.hpp"
#include <mutex>
#include <shared_mutex>
namespace hailort
{
template<class T>
struct Resource {
Resource(uint32_t pid, std::shared_ptr<T> resource)
: pid(pid), resource(std::move(resource))
{}
std::shared_timed_mutex resource_mutex;
uint32_t pid;
std::shared_ptr<T> resource;
};
template<class T>
class ServiceResourceManager
{
public:
static ServiceResourceManager& get_instance()
{
static ServiceResourceManager instance;
return instance;
}
template<class K, class Func, typename... Args>
K execute(uint32_t key, Func &lambda, Args... args)
{
std::unique_lock<std::mutex> lock(m_mutex);
auto resource_expected = resource_lookup(key);
assert(resource_expected);
auto resource = resource_expected.release();
std::shared_lock<std::shared_timed_mutex> resource_lock(resource->resource_mutex);
lock.unlock();
K ret = lambda(resource->resource, args...);
return ret;
}
uint32_t register_resource(uint32_t pid, std::shared_ptr<T> const &resource)
{
std::unique_lock<std::mutex> lock(m_mutex);
// Create a new resource and register
auto index = m_current_handle_index;
m_resources.emplace(m_current_handle_index++, std::make_shared<Resource<T>>(pid, std::move(resource)));
return index;
}
hailo_status release_resource(uint32_t key)
{
std::unique_lock<std::mutex> lock(m_mutex);
auto found = m_resources.find(key);
CHECK(found != m_resources.end(), HAILO_NOT_FOUND, "Failed to release resource with key {}, resource does not exist", key);
std::unique_lock<std::shared_timed_mutex> resource_lock(found->second->resource_mutex);
m_resources.erase(key);
return HAILO_SUCCESS;
}
void release_by_pid(uint32_t pid)
{
std::unique_lock<std::mutex> lock(m_mutex);
for (auto iter = m_resources.begin(); iter != m_resources.end(); ) {
if (iter->second->pid == pid) {
std::unique_lock<std::shared_timed_mutex> resource_lock(iter->second->resource_mutex);
iter = m_resources.erase(iter);
} else {
++iter;
}
}
}
private:
ServiceResourceManager()
: m_current_handle_index(0)
{}
Expected<std::shared_ptr<Resource<T>>> resource_lookup(uint32_t key)
{
auto found = m_resources.find(key);
CHECK_AS_EXPECTED(found != m_resources.end(), HAILO_NOT_FOUND, "Failed to find resource with key {}", key);
auto resource = found->second;
return resource;
}
std::mutex m_mutex;
uint32_t m_current_handle_index;
std::unordered_map<uint32_t, std::shared_ptr<Resource<T>>> m_resources;
};
}
#endif /* HAILO_SERVICE_RESOURCE_MANAGER_HPP_ */

View File

@@ -23,6 +23,7 @@ set(HAILORTCLI_CPP_FILES
temp_measurement.cpp
parse_hef_command.cpp
graph_printer.cpp
mon_command.cpp
)
if(UNIX)
@@ -52,8 +53,14 @@ add_executable(hailortcli
target_compile_options(hailortcli PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailortcli PROPERTY CXX_STANDARD 14)
set_property(TARGET hailortcli PROPERTY INSTALL_RPATH "$ORIGIN" "../lib/") # Link with a relative libhailort
target_link_libraries(hailortcli libhailort CLI11::CLI11 nlohmann_json spdlog::spdlog readerwriterqueue)
target_link_libraries(hailortcli DotWriter)
target_link_libraries(hailortcli
libhailort
CLI11::CLI11
nlohmann_json
spdlog::spdlog
readerwriterqueue
DotWriter
scheduler_mon_proto)
# TODO: Remove microprofile after removing pipeline.cpp from hailortcli sources
target_link_libraries(hailortcli microprofile)
@@ -72,4 +79,6 @@ target_include_directories(hailortcli
install(TARGETS hailortcli
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
CONFIGURATIONS Release)
CONFIGURATIONS Release
)
cli11_install_completion_file(hailortcli)

View File

@@ -18,8 +18,7 @@ BenchmarkCommand::BenchmarkCommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("benchmark", "Measure basic performance on compiled network")),
m_params({})
{
add_device_options(m_app, m_params.device_params);
add_vdevice_options(m_app, m_params.device_params);
add_vdevice_options(m_app, m_params.vdevice_params);
m_params.measure_overall_latency = false;
m_params.power_measurement.measure_current = false;
m_params.show_progress = true;
@@ -56,7 +55,7 @@ BenchmarkCommand::BenchmarkCommand(CLI::App &parent_app) :
// TODO HRT-5363 support multiple devices
m_app->parse_complete_callback([this]() {
PARSE_CHECK((this->m_params.device_params.vdevice_params.device_count == 1) || this->m_csv_file_path.empty() || this->m_not_measure_power,
PARSE_CHECK((m_params.vdevice_params.device_count == 1) || m_csv_file_path.empty() || m_not_measure_power,
"Writing power measurements in csv format is not supported for multiple devices");
});
}
@@ -73,22 +72,37 @@ hailo_status BenchmarkCommand::execute()
auto streaming_mode_info = fps_streaming_mode();
CHECK_EXPECTED_AS_STATUS(streaming_mode_info, "FPS in streaming mode failed");
// TODO - HRT-6931 - measure latnecy only in the case of single device.
// TODO - HRT-6931 - measure latency only in the case of single device.
std::cout << "Measuring HW Latency" << std::endl;
auto latency_info = latency();
CHECK_EXPECTED_AS_STATUS(latency_info, "Latency measuring failed");
assert(hw_only_mode_info->network_group_results().size() == streaming_mode_info->network_group_results().size());
assert(latency_info->network_group_results().size() == streaming_mode_info->network_group_results().size());
std::cout << std::endl;
std::cout << "=======" << std::endl;
std::cout << "Summary" << std::endl;
std::cout << "=======" << std::endl;
std::cout << "FPS (hw_only) = " << hw_only_mode_info->fps().value() <<std::endl;
std::cout << " (streaming) = " << streaming_mode_info->fps().value() <<std::endl;
if (auto hw_latency = latency_info->hw_latency()) {
std::cout << "Latency (hw) = " << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value()) << " ms" << std::endl;
}
if (auto overall_latency = latency_info->overall_latency()) {
std::cout << " (overall) = " << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value()) << " ms" << std::endl;
for (auto &hw_only_res : hw_only_mode_info->network_group_results()) {
auto network_group_name = hw_only_res.network_group_name();
auto streaming_res = std::find_if(streaming_mode_info->network_group_results().begin(), streaming_mode_info->network_group_results().end(),
[network_group_name] (NetworkGroupInferResult &infer_results) { return (infer_results.network_group_name() == network_group_name); });
CHECK(streaming_mode_info->network_group_results().end() != streaming_res, HAILO_INTERNAL_FAILURE, "Failed to fun streaming results for network group {}", network_group_name);
auto latency_res = std::find_if(latency_info->network_group_results().begin(), latency_info->network_group_results().end(),
[network_group_name] (NetworkGroupInferResult &infer_results) { return (infer_results.network_group_name() == network_group_name); });
CHECK(latency_info->network_group_results().end() != latency_res, HAILO_INTERNAL_FAILURE, "Failed to fun latency results for network group {}", network_group_name);
std::cout << "FPS (hw_only) = " << hw_only_res.fps().value() <<std::endl;
std::cout << " (streaming) = " << streaming_res->fps().value() <<std::endl;
if (auto hw_latency = latency_res->hw_latency()) {
std::cout << "Latency (hw) = " << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value()) << " ms" << std::endl;
}
if (auto overall_latency = latency_res->overall_latency()) {
std::cout << " (overall) = " << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value()) << " ms" << std::endl;
}
}
if (!m_not_measure_power) {
for (const auto &pair : streaming_mode_info->m_power_measurements) {
@@ -98,7 +112,6 @@ hailo_status BenchmarkCommand::execute()
std::cout << " Power in streaming mode (average) = " << data.average_value << " " << power_units << std::endl;
std::cout << " (max) = " << data.max_value << " " << power_units << std::endl;
}
}
if (!m_csv_file_path.empty()){
@@ -106,13 +119,13 @@ hailo_status BenchmarkCommand::execute()
auto printer = InferStatsPrinter::create(m_params, false);
CHECK_EXPECTED_AS_STATUS(printer, "Failed to initialize infer stats printer");
printer->print_benchmark_csv_header();
printer->print_benchmark_csv(m_params.hef_path, hw_only_mode_info.release(),
streaming_mode_info.release(), latency_info.release());
printer->print_benchmark_csv(hw_only_mode_info.value(),
streaming_mode_info.value(), latency_info.value());
}
return HAILO_SUCCESS;
}
Expected<NetworkGroupInferResult> BenchmarkCommand::hw_only_mode()
Expected<InferResult> BenchmarkCommand::hw_only_mode()
{
m_params.transform.transform = (m_params.inputs_name_and_file_path.size() > 0);
m_params.power_measurement.measure_power = false;
@@ -121,7 +134,7 @@ Expected<NetworkGroupInferResult> BenchmarkCommand::hw_only_mode()
return run_command_hef(m_params);
}
Expected<NetworkGroupInferResult> BenchmarkCommand::fps_streaming_mode()
Expected<InferResult> BenchmarkCommand::fps_streaming_mode()
{
m_params.power_measurement.measure_power = !m_not_measure_power;
m_params.mode = InferMode::STREAMING;
@@ -131,7 +144,7 @@ Expected<NetworkGroupInferResult> BenchmarkCommand::fps_streaming_mode()
return run_command_hef(m_params);
}
Expected<NetworkGroupInferResult> BenchmarkCommand::latency()
Expected<InferResult> BenchmarkCommand::latency()
{
m_params.power_measurement.measure_power = false;
m_params.measure_latency = true;

View File

@@ -21,9 +21,9 @@ public:
hailo_status execute() override;
private:
Expected<NetworkGroupInferResult> hw_only_mode();
Expected<NetworkGroupInferResult> fps_streaming_mode();
Expected<NetworkGroupInferResult> latency();
Expected<InferResult> hw_only_mode();
Expected<InferResult> fps_streaming_mode();
Expected<InferResult> latency();
inference_runner_params m_params;
bool m_not_measure_power;

View File

@@ -41,34 +41,21 @@ DeviceCommand::DeviceCommand(CLI::App *app) :
hailo_status DeviceCommand::execute()
{
if ((DeviceType::PCIE == m_device_params.device_type ) &&
("*" == m_device_params.pcie_params.pcie_bdf)) {
return execute_on_all_pcie_devices();
auto devices = create_devices(m_device_params);
if (!devices) {
return devices.status();
}
auto device = create_device(m_device_params);
if (!device) {
return device.status();
}
return execute_on_device(*device.value());
return execute_on_devices(devices.value());
}
hailo_status DeviceCommand::execute_on_all_pcie_devices()
hailo_status DeviceCommand::execute_on_devices(std::vector<std::unique_ptr<Device>> &devices)
{
auto status = HAILO_SUCCESS; // Best effort
auto all_devices_infos = Device::scan_pcie();
if (!all_devices_infos) {
return all_devices_infos.status();
}
for (auto &dev_info : all_devices_infos.value()) {
auto device = Device::create_pcie(dev_info);
if (!device) {
return device.status();
}
auto execute_status = execute_on_device(*device.value());
for (auto &device : devices) {
std::cout << "Executing on device: " << device->get_dev_id() << std::endl;
auto execute_status = execute_on_device(*device);
if (HAILO_SUCCESS != execute_status) {
std::cerr << "Failed to execute on device: " << device.value()->get_dev_id() << ". status= " << execute_status << std::endl;
std::cerr << "Failed to execute on device: " << device->get_dev_id() << ". status= " << execute_status << std::endl;
status = execute_status;
}
}

View File

@@ -65,7 +65,7 @@ public:
protected:
virtual hailo_status execute_on_device(Device &device) = 0;
hailo_status execute_on_all_pcie_devices();
hailo_status execute_on_devices(std::vector<std::unique_ptr<Device>> &devices);
private:
hailo_device_params m_device_params;

View File

@@ -50,4 +50,30 @@ struct FileSuffixValidator : public CLI::Validator {
}
};
#endif /* _HAILO_HAILORTCLI_COMMON_HPP_ */
// Based on NLOHMANN_JSON_SERIALIZE_ENUM (json/include/nlohmann/json.hpp)
// Accepts a static array instead of building one in the function
#define NLOHMANN_JSON_SERIALIZE_ENUM2(ENUM_TYPE, _pair_arr)\
template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
auto it = std::find_if(std::begin(_pair_arr), std::end(_pair_arr), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
j = ((it != std::end(_pair_arr)) ? it : std::begin(_pair_arr))->second; \
} \
template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
auto it = std::find_if(std::begin(_pair_arr), std::end(_pair_arr), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
e = ((it != std::end(_pair_arr)) ? it : std::begin(_pair_arr))->first; \
}
#endif /* _HAILO_HAILORTCLI_COMMON_HPP_ */

View File

@@ -10,12 +10,16 @@
#include "download_action_list_command.hpp"
#include "common.hpp"
#include "common/file_utils.hpp"
#include "md5.h"
#include "common/string_utils.hpp"
#include <iostream>
#include <iomanip>
#define MHz (1000 * 1000)
// div factor is valid only for Hailo8-B0 platform.
// 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)
constexpr int DownloadActionListCommand::INVALID_NUMERIC_VALUE;
@@ -38,7 +42,7 @@ hailo_status DownloadActionListCommand::execute(Device &device, const std::strin
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 / MHz;
const auto 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()},
@@ -90,6 +94,7 @@ Expected<ordered_json> DownloadActionListCommand::parse_hef_metadata(const std::
return hef_info_json;
}
bool DownloadActionListCommand::is_valid_hef(const std::string &hef_file_path)
{
// Open hef, to check that it's valid
@@ -108,14 +113,8 @@ Expected<std::string> DownloadActionListCommand::calc_md5_hexdigest(const std::s
MD5_Update(&md5_ctx, hef_bin->data(), hef_bin->size());
MD5_Final(md5_sum, &md5_ctx);
std::stringstream hexdigest;
for (uint32_t i = 0; i < ARRAY_ENTRIES(md5_sum); i++) {
// cast to int needed for proper formatting
static const int NUM_HEX_DIGITS_IN_UNIT8 = 2;
hexdigest << std::hex << std::setfill('0') << std::setw(NUM_HEX_DIGITS_IN_UNIT8) << static_cast<int>(md5_sum[i]);
}
return hexdigest.str();
const bool LOWERCASE = false;
return StringUtils::to_hex_string(md5_sum, ARRAY_ENTRIES(md5_sum), LOWERCASE);
}
hailo_status DownloadActionListCommand::write_json(const ordered_json &json_obj, const std::string &output_file_path,
@@ -131,6 +130,11 @@ hailo_status DownloadActionListCommand::write_json(const ordered_json &json_obj,
return HAILO_SUCCESS;
}
// We want to make sure that the switch-case bellow handles all of the action types in order to prevent parsing errors
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t base_address, uint8_t *action,
uint32_t current_buffer_offset, uint32_t *action_length, CONTEXT_SWITCH_DEFS__ACTION_TYPE_t action_type,
uint32_t timestamp, uint8_t sub_action_index, bool sub_action_index_set, bool *is_repeated, uint8_t *num_repeated,
@@ -275,14 +279,24 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_RESET:
data_json = json({});
action_length_local = 0;
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
default:
std::cerr << "PARSING ERROR ! unknown action main type" << std::endl;
std::cerr << "PARSING ERROR ! unknown action main type " << action_type << std::endl;
return make_unexpected(HAILO_INTERNAL_FAILURE);
}
action_json["data"] = data_json;
*action_length = static_cast<uint32_t>(action_length_local);
return action_json;
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
Expected<ordered_json> DownloadActionListCommand::parse_single_repeated_action(uint32_t base_address,
uint8_t *action, uint32_t current_buffer_offset, uint32_t *action_length,
@@ -410,12 +424,68 @@ Expected<ordered_json> DownloadActionListCommand::parse_network_groups(Device &d
return network_group_list_json;
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data) {
j = json{{"descriptors_count", data.descriptors_count}, {"channel_index", data.cfg_channel_number}};
template<typename ActionData>
static json unpack_vdma_channel_id(const ActionData &data)
{
uint8_t engine_index = 0;
uint8_t vdma_channel_index = 0;
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.packed_vdma_channel_id, engine_index, vdma_channel_index);
return json{{"vdma_channel_index", vdma_channel_index}, {"engine_index", engine_index}};
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t& data) {
j = json{{"channel_index", data.cfg_channel_number}};
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t &data)
{
j = unpack_vdma_channel_id(data);
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t &data)
{
j = unpack_vdma_channel_id(data);
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_boundary_output_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
// Needs to be backwards compatible, so we use "channel_index" instead of "vdma_channel_index".
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data) {
uint8_t engine_index = 0;
uint8_t vdma_channel_index = 0;
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.packed_vdma_channel_id, engine_index, vdma_channel_index);
j = json{{"descriptors_count", data.descriptors_count}, {"channel_index", vdma_channel_index},
{"engine_index", engine_index}};
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t& data) {
@@ -437,8 +507,26 @@ void to_json(json& j, const CONTEXT_SWITCH_DEFS__disable_lcu_action_data_t& data
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__change_vdma_to_stream_mapping_data_t& data) {
j = json{{"vdma_channel_index", data.vdma_channel_index}, {"stream_index", data.stream_index},
{"type", data.is_dummy_stream ? "dummy" : "active"}};
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
j["type"] = data.is_dummy_stream ? "dummy" : "active";
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__fetch_data_action_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__wait_dma_idle_data_t &data)
{
j = unpack_vdma_channel_id(data);
j["stream_index"] = data.stream_index;
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t &data)
{
j = unpack_vdma_channel_id(data);
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t& data) {
@@ -446,3 +534,36 @@ void to_json(json& j, const CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t& data) {
const auto lcu_index = CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_LCU_INDEX_READ(data.packed_lcu_id);
j = json{{"cluster_index", cluster_index}, {"lcu_index", lcu_index}};
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_cfg_channel_t &data)
{
uint8_t engine_index = 0;
uint8_t vdma_channel_index = 0;
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.packed_vdma_channel_id, engine_index, vdma_channel_index);
j = json{{"config_stream_index", data.config_stream_index}, {"channel_index", vdma_channel_index},
{"engine_index", engine_index}};
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t &data)
{
uint8_t engine_index = 0;
uint8_t vdma_channel_index = 0;
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.packed_vdma_channel_id, engine_index, vdma_channel_index);
j = json{{"config_stream_index", data.config_stream_index}, {"channel_index", vdma_channel_index},
{"engine_index", engine_index}};
}
void to_json(json &j, const CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t &data)
{
uint8_t h2d_engine_index = 0;
uint8_t h2d_vdma_channel_index = 0;
uint8_t d2h_engine_index = 0;
uint8_t d2h_vdma_channel_index = 0;
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.h2d_packed_vdma_channel_id, h2d_engine_index,
h2d_vdma_channel_index);
CONTEXT_SWITCH_DEFS__PACKED_VDMA_CHANNEL_ID__READ(data.d2h_packed_vdma_channel_id, d2h_engine_index,
d2h_vdma_channel_index);
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}};
}

View File

@@ -11,9 +11,11 @@
#define _HAILO_DOWNLOAD_ACTION_LIST_COMMAND_HPP_
#include "hailortcli.hpp"
#include "common.hpp"
#include "command.hpp"
#include "context_switch_defs.h"
#include "common/utils.hpp"
#include <nlohmann/json.hpp>
@@ -62,7 +64,7 @@ private:
// JSON serialization
NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
static std::pair<CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, std::string> mapping[] = {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS, "fetch_cfg_channel_descriptors"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_TRIGGER_SEQUENCER, "trigger_sequencer"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_DATA_FROM_VDMA_CHANNEL, "fetch_data_from_vdma_channel"},
@@ -93,38 +95,42 @@ NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
{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_FETCH_CCW_BURSTS, "fetch_ccw_bursts"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT, nullptr},
});
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_RESET, "ddr_buffering_reset"}
};
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");
NLOHMANN_JSON_SERIALIZE_ENUM2(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, mapping);
// Default implementions
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__deactivate_vdma_channel_action_data_t, vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t, vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__fetch_data_action_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t, h2d_vdma_channel_index, d2h_vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t, vdma_channel_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_dma_idle_data_t, vdma_channel_index, stream_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__activate_boundary_input_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_boundary_output_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__activate_cfg_channel_t, channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t, channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t, config_stream_index);
// Non-default implementations
void to_json(json& j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__disable_lcu_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__change_vdma_to_stream_mapping_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_boundary_output_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__disable_lcu_action_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__change_vdma_to_stream_mapping_data_t& data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__fetch_data_action_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__wait_dma_idle_data_t &data);
void to_json(json &j, const CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t &data);
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);
#endif /* _HAILO_DOWNLOAD_ACTION_LIST_COMMAND_HPP_ */

View File

@@ -12,6 +12,7 @@
#include "hailo/hailort.h"
#include "user_config_common.h"
#include "common/file_utils.hpp"
#include "common/string_utils.hpp"
#include <fstream>
#include <sstream>
@@ -266,16 +267,8 @@ Expected<json> FwConfigJsonSerializer::deserialize_mac_address(uint8_t *entry_va
CHECK_AS_EXPECTED((MAC_ADDRESS_LENGTH == size), HAILO_INTERNAL_FAILURE,
"Mac address length is invalid. Length recieved is: {}, length expected: {}", size, MAC_ADDRESS_LENGTH);
std::stringstream ss;
for (size_t i = 0; i < MAC_ADDRESS_LENGTH; i++) {
if (i != 0) {
ss << ':';
}
ss.width(2);
ss.fill('0');
ss << std::uppercase << std::hex << (int)(entry_value[i]);
}
return json(ss.str());
const bool UPPERCASE = true;
return json(StringUtils::to_hex_string(entry_value, size, UPPERCASE, ":"));
}
Expected<json> FwConfigJsonSerializer::deserialize_supported_aspm_states(uint8_t *entry_value, uint32_t size)

View File

@@ -9,9 +9,10 @@
#include "fw_control_command.hpp"
#include "firmware_header_utils.h"
#include "common/string_utils.hpp"
static const char *NOT_CONFIGURED_ATTR = "<Not Configured>";
static const char *NOT_CONFIGURED_ATTR = "<N/A>";
#define MHz (1000 * 1000)
@@ -55,14 +56,8 @@ static std::string extended_device_information_supported_features(hailo_device_s
static void extended_device_information_print_array(uint8_t *array_for_print, size_t array_length, std::string splitter)
{
uint32_t i = 0;
for(i = 0; i < array_length; i++) {
std::cout << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << static_cast<int>(array_for_print[i]);
if(array_length != (i+1)) {
std::cout << splitter;
}
}
std::cout << std::endl;
const bool UPPERCASE = true;
std::cout << StringUtils::to_hex_string(array_for_print, array_length, UPPERCASE, splitter) << std::endl;
}
static bool extended_device_information_is_array_not_empty(uint8_t *array_for_print, size_t array_length)
@@ -135,8 +130,10 @@ static std::string fw_version_string(const hailo_device_identity_t &identity)
static std::string identity_arch_string(const hailo_device_identity_t &identity)
{
switch (identity.device_architecture) {
case HAILO_ARCH_HAILO8_B0:
return "HAILO8_B0";
case HAILO_ARCH_HAILO8:
return "HAILO8";
case HAILO_ARCH_HAILO8L:
return "HAILO8L";
case HAILO_ARCH_MERCURY_CA:
return "MERCURY_CA";
case HAILO_ARCH_MERCURY_VPU:

View File

@@ -206,55 +206,60 @@ void PipelineGraphNode::set_visited()
m_visited = true;
}
hailo_status GraphPrinter::write_dot_file(const std::map<std::string, std::vector<InputVStream>> &input_vstreams_per_network,
const std::map<std::string, std::vector<OutputVStream>> &output_vstreams_per_network, const std::string &graph_title,
hailo_status GraphPrinter::write_dot_file(const std::vector<std::map<std::string, std::vector<std::reference_wrapper<InputVStream>>>> &input_vstreams_per_network_group,
const std::vector<std::map<std::string, std::vector<std::reference_wrapper<OutputVStream>>>> &output_vstreams_per_network_group, const std::string &graph_title,
const std::string &output_path, bool write_pipeline_stats)
{
PipelineGraph graph(input_vstreams_per_network, output_vstreams_per_network, graph_title, write_pipeline_stats);
PipelineGraph graph(input_vstreams_per_network_group, output_vstreams_per_network_group, graph_title, write_pipeline_stats);
return graph.write_dot_file(output_path);
}
GraphPrinter::PipelineGraph::PipelineGraph(const std::map<std::string, std::vector<InputVStream>> &input_vstreams_per_network,
const std::map<std::string, std::vector<OutputVStream>> &output_vstreams_per_network,
GraphPrinter::PipelineGraph::PipelineGraph(const std::vector<std::map<std::string, std::vector<std::reference_wrapper<InputVStream>>>> &input_vstreams_per_network_group,
const std::vector<std::map<std::string, std::vector<std::reference_wrapper<OutputVStream>>>> &output_vstreams_per_network_group,
const std::string &graph_title, bool write_pipeline_stats) :
m_graph(true, create_graph_title_label(graph_title, DefaultNodeAttrs::MAIN_LABEL_FONT_SIZE)),
m_elems_in_graph()
{
size_t total_inputs_count = 0;
for (auto &input_vstreams_pair : input_vstreams_per_network) {
total_inputs_count += input_vstreams_pair.second.size();
}
size_t total_outputs_count = 0;
for (auto &output_vstreams_pair : output_vstreams_per_network) {
total_outputs_count += output_vstreams_pair.second.size();
}
// Set the graph "graph title" label to be on top
m_graph.GetAttributes().SetLabelLoc(DotWriter::LabelLoc::T);
// Set the graph direction from left to right
m_graph.GetAttributes().SetRankDir(DotWriter::RankDir::LR);
m_graph.GetAttributes().SetPackMode(format_pack_mode(total_outputs_count + total_inputs_count));
// Note: This order is important (input pipelines will be printed above output pipelines)
for (const auto &output_vstreams_pair : output_vstreams_per_network) {
for (const auto &vstream : output_vstreams_pair.second) {
update_graph_nodes(vstream.get_pipeline(), write_pipeline_stats);
assert(input_vstreams_per_network_group.size() == output_vstreams_per_network_group.size());
for (size_t network_group_index = 0; network_group_index < input_vstreams_per_network_group.size(); network_group_index++) {
size_t total_inputs_count = 0;
for (auto &input_vstreams_pair : input_vstreams_per_network_group[network_group_index]) {
total_inputs_count += input_vstreams_pair.second.size();
}
}
for (const auto &input_vstreams_pair : input_vstreams_per_network) {
for (const auto &vstream : input_vstreams_pair.second) {
update_graph_nodes(vstream.get_pipeline(), write_pipeline_stats);
size_t total_outputs_count = 0;
for (auto &output_vstreams_pair : output_vstreams_per_network_group[network_group_index]) {
total_outputs_count += output_vstreams_pair.second.size();
}
}
for (const auto &output_vstreams_pair : output_vstreams_per_network) {
for (const auto &vstream : output_vstreams_pair.second) {
update_edges_in_graph(vstream.get_pipeline(), "HW", "user_output");
m_graph.GetAttributes().SetPackMode(format_pack_mode(total_outputs_count + total_inputs_count));
// Note: This order is important (input pipelines will be printed above output pipelines)
for (const auto &output_vstreams_pair : output_vstreams_per_network_group[network_group_index]) {
for (const auto &vstream : output_vstreams_pair.second) {
update_graph_nodes(vstream.get().get_pipeline(), write_pipeline_stats);
}
}
}
for (const auto &input_vstreams_pair : input_vstreams_per_network) {
for (const auto &vstream : input_vstreams_pair.second) {
update_edges_in_graph(vstream.get_pipeline(), "user_input", "HW");
for (const auto &input_vstreams_pair : input_vstreams_per_network_group[network_group_index]) {
for (const auto &vstream : input_vstreams_pair.second) {
update_graph_nodes(vstream.get().get_pipeline(), write_pipeline_stats);
}
}
for (const auto &output_vstreams_pair : output_vstreams_per_network_group[network_group_index]) {
for (const auto &vstream : output_vstreams_pair.second) {
update_edges_in_graph(vstream.get().get_pipeline(), "HW", "user_output");
}
}
for (const auto &input_vstreams_pair : input_vstreams_per_network_group[network_group_index]) {
for (const auto &vstream : input_vstreams_pair.second) {
update_edges_in_graph(vstream.get().get_pipeline(), "user_input", "HW");
}
}
}
}

View File

@@ -121,16 +121,16 @@ class GraphPrinter
{
public:
GraphPrinter() = delete;
static hailo_status write_dot_file(const std::map<std::string, std::vector<InputVStream>> &input_vstreams_per_network,
const std::map<std::string, std::vector<OutputVStream>> &output_vstreams_per_network,
static hailo_status write_dot_file(const std::vector<std::map<std::string, std::vector<std::reference_wrapper<InputVStream>>>> &input_vstreams_per_network_group,
const std::vector<std::map<std::string, std::vector<std::reference_wrapper<OutputVStream>>>> &output_vstreams_per_network_group,
const std::string &graph_title, const std::string &output_path, bool write_pipeline_stats);
private:
class PipelineGraph final
{
public:
PipelineGraph(const std::map<std::string, std::vector<InputVStream>> &input_vstreams_per_network,
const std::map<std::string, std::vector<OutputVStream>> &output_vstreams_per_network,
PipelineGraph(const std::vector<std::map<std::string, std::vector<std::reference_wrapper<InputVStream>>>> &input_vstreams_per_network_group,
const std::vector<std::map<std::string, std::vector<std::reference_wrapper<OutputVStream>>>> &output_vstreams_per_network_group,
const std::string &graph_title, bool write_pipeline_stats);
hailo_status write_dot_file(const std::string &output_path);

View File

@@ -19,6 +19,7 @@
#include "fw_config_command.hpp"
#include "fw_logger_command.hpp"
#include "benchmark_command.hpp"
#include "mon_command.hpp"
#if defined(__GNUC__)
#include "udp_rate_limiter_command.hpp"
#endif
@@ -42,148 +43,123 @@
#include <thread>
#include <map>
static Expected<hailo_pcie_device_info_t> get_pcie_device_info(const hailo_pcie_params &pcie_params)
{
if (pcie_params.pcie_bdf.empty()) {
auto scan_result = Device::scan_pcie();
if (!scan_result) {
std::cerr << "Hailo PCIe scan failed (maybe pcie device not exists). status=" << scan_result.status() << std::endl;
return make_unexpected(scan_result.status());
}
if (scan_result->size() == 0) {
std::cerr << "Hailo PCIe not found.." << std::endl;
return make_unexpected(HAILO_INTERNAL_FAILURE);
}
return std::move(scan_result->at(0));
} else {
auto device_info_expected = Device::parse_pcie_device_info(pcie_params.pcie_bdf);
if (!device_info_expected) {
std::cerr << "Invalid pcie bdf format" << std::endl;
return make_unexpected(device_info_expected.status());
}
return device_info_expected.release();
Expected<std::vector<std::string>> get_device_ids(const hailo_device_params &device_params)
{
if (device_params.device_ids.empty() || contains(device_params.device_ids, std::string("*"))) {
// No device id given, using all devices in the system.
return Device::scan();
}
else {
return std::vector<std::string>(device_params.device_ids);
}
}
Expected<std::unique_ptr<Device>> create_pcie_device(const hailo_pcie_params &pcie_params)
Expected<std::vector<std::unique_ptr<Device>>> create_devices(const hailo_device_params &device_params)
{
auto device_info = get_pcie_device_info(pcie_params);
if (!device_info) {
return make_unexpected(device_info.status());
std::vector<std::unique_ptr<Device>> res;
auto device_ids = get_device_ids(device_params);
CHECK_EXPECTED(device_ids);
for (auto device_id : device_ids.value()) {
auto device = Device::create(device_id);
CHECK_EXPECTED(device);
res.emplace_back(device.release());
}
auto device = Device::create_pcie(device_info.value());
if (!device) {
std::cerr << "Failed create pcie device. status=" << device.status() << std::endl;
return make_unexpected(device.status());
}
return Expected<std::unique_ptr<Device>>(device.release());
return res;
}
static Expected<std::unique_ptr<Device>> create_eth_device(const hailo_eth_params &eth_params)
{
auto device = Device::create_eth(eth_params.ip_addr);
if (!device) {
std::cerr << "Failed create ethernet device. status=" << device.status() << std::endl;
return make_unexpected(device.status());
}
class BDFValidator : public CLI::Validator {
public:
BDFValidator(bool support_asterisk) : Validator("BDF") {
func_ = [support_asterisk](std::string &bdf) {
if (support_asterisk && (bdf == "*")) {
return std::string();
}
return Expected<std::unique_ptr<Device>>(device.release());
}
Expected<std::unique_ptr<Device>> create_device(const hailo_device_params &device_params)
{
switch (device_params.device_type) {
case DeviceType::PCIE:
return create_pcie_device(device_params.pcie_params);
case DeviceType::ETH:
return create_eth_device(device_params.eth_params);
case DeviceType::DEFAULT:
// If core driver is loaded (we are running on Mercury) then the default is core device; else, pcie device
if (Device::is_core_driver_loaded()) {
return Device::create_core_device();
} else {
return create_pcie_device(device_params.pcie_params);
}
default:
std::cerr << "Invalid device type" << std::endl;
return make_unexpected(HAILO_INVALID_ARGUMENT);
}
}
void add_device_options(CLI::App *app, hailo_device_params &device_params)
{
// Initialize the device type to default
device_params.device_type = DeviceType::DEFAULT;
auto group = app->add_option_group("Device Options");
const HailoCheckedTransformer<DeviceType> device_type_transformer({
{ "pcie", DeviceType::PCIE },
{ "eth", DeviceType::ETH },
});
auto *device_type_option = group->add_option("-d,--device-type,--target", device_params.device_type,
"Device type to use\n"
"Default is pcie.")
->transform(device_type_transformer);
// PCIe options
auto *pcie_bdf_option = group->add_option("-s,--bdf", device_params.pcie_params.pcie_bdf,
"Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command).\n" \
"In order to run on all PCIe devices connected to the machine one-by-one, use '*' (instead of device id).")
->default_val("");
// Ethernet options
auto *ip_option = group->add_option("--ip", device_params.eth_params.ip_addr, "IP address of the target")
->default_val("")
->check(CLI::ValidIPV4);
group->parse_complete_callback([&device_params, device_type_option, pcie_bdf_option, ip_option](){
// The user didn't put target, we can figure it ourself
if (device_type_option->empty()) {
if (!ip_option->empty()) {
// User gave IP, target is eth
device_params.device_type = DeviceType::ETH;
} else if (!pcie_bdf_option->empty()) {
// User gave bdf, target is pcie
device_params.device_type = DeviceType::PCIE;
auto pcie_device_info = Device::parse_pcie_device_info(bdf);
if (pcie_device_info.has_value()) {
return std::string();
}
else {
device_params.device_type = DeviceType::DEFAULT;
return std::string("Invalid PCIe BDF " + bdf);
}
}
};
}
};
if (ip_option->empty() && device_params.device_type == DeviceType::ETH) {
throw CLI::ParseError("IP address is not set", CLI::ExitCodes::InvalidError);
}
void add_vdevice_options(CLI::App *app, hailo_vdevice_params &vdevice_params)
{
add_device_options(app, vdevice_params.device_params, false);
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,
"VDevice multi process service");
group->add_option("--group-id", vdevice_params.group_id, "VDevice group id")->needs(multi_process_option);
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
PARSE_CHECK(device_count_option->empty(),
"Passing " + device_count_option->get_name() + " in combination with device-ids is not allowed");
if (!ip_option->empty() && device_params.device_type != DeviceType::ETH) {
throw CLI::ParseError("IP address is set on non eth device", CLI::ExitCodes::InvalidError);
}
if (!pcie_bdf_option->empty() && device_params.device_type != DeviceType::PCIE) {
throw CLI::ParseError("bdf (-s) is set on non pcie device", CLI::ExitCodes::InvalidError);
// Fill device_count with real value
vdevice_params.device_count = static_cast<uint32_t>(vdevice_params.device_params.device_ids.size());
}
});
}
void add_vdevice_options(CLI::App *app, hailo_device_params &device_params) {
auto group = app->add_option_group("VDevice Options");
void add_device_options(CLI::App *app, hailo_device_params &device_params, bool support_asterisk)
{
auto group = app->add_option_group("Device Options");
// VDevice options
auto *device_count_option = group->add_option("--device-count", device_params.vdevice_params.device_count, "VDevice device count")
->default_val(HAILO_DEFAULT_DEVICE_COUNT)
->check(CLI::PositiveNumber);
// General device id
auto *device_id_option = group->add_option("-s,--device-id", device_params.device_ids,
std::string("Device id, same as returned from `hailortcli scan` command. ") +
std::string("For multiple devices, use space as separator.\n") +
(support_asterisk ?
std::string("In order to run on all devices connected to the machine one-by-one, use '*' (instead of device id).") :
std::string("")));
group->parse_complete_callback([&device_params, device_count_option](){
// The user gave device_count
if (!device_count_option->empty()) {
if ((device_params.vdevice_params.device_count > 1) &&
((DeviceType::ETH == device_params.device_type) || (DeviceType::PCIE == device_params.device_type && !device_params.pcie_params.pcie_bdf.empty()))) {
throw CLI::ParseError("Device type must not be specified when using multiple devices", CLI::ExitCodes::InvalidError);
}
// PCIe options
auto *pcie_bdf_option = group->add_option("--bdf", device_params.device_ids,
std::string("Device bdf ([<domain>]:<bus>:<device>.<func>, same as in lspci command).\n") +
std::string("For multiple BDFs, use space as separator.\n") +
(support_asterisk ?
std::string("In order to run on all devices connected to the machine one-by-one, use '*' (instead of device id).") :
std::string("")))
->check(BDFValidator(support_asterisk));
// Ethernet options
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
const std::string device_id_options_names = device_id_option->get_name(true, true) + ", " +
pcie_bdf_option->get_name(true, true) + ", " +
ip_option->get_name(true, true);
const auto dev_id_options_parsed =
static_cast<size_t>(!device_id_option->empty()) +
static_cast<size_t>(!pcie_bdf_option->empty()) +
static_cast<size_t>(!ip_option->empty());
PARSE_CHECK(dev_id_options_parsed <= 1,
"Only one of " + device_id_options_names + " Can bet set");
if (contains(device_params.device_ids, std::string("*"))) {
PARSE_CHECK(support_asterisk, "Passing * is not allowed in this command");
PARSE_CHECK(device_params.device_ids.size() == 1, "passing '*' in combination with other device ids is not allowed");
}
});
}
@@ -235,6 +211,7 @@ public:
add_subcommand<FwLoggerCommand>();
add_subcommand<FwUpdateCommand>();
add_subcommand<SSBUpdateCommand>();
add_subcommand<MonCommand>();
#if defined(__GNUC__)
add_subcommand<UdpRateLimiterCommand>();
#endif

View File

@@ -27,35 +27,21 @@ using namespace hailort;
} \
} while (0)
struct hailo_pcie_params {
std::string pcie_bdf; // if empty use the first scanned. if '*', run on all devices on the machine one-by-one
};
struct hailo_eth_params {
std::string ip_addr;
struct hailo_device_params {
std::vector<std::string> device_ids;
};
struct hailo_vdevice_params {
uint32_t device_count;
hailo_device_params device_params;
uint32_t device_count = HAILO_DEFAULT_DEVICE_COUNT;
std::string group_id;
bool multi_process_service = false;
};
enum class DeviceType {
PCIE = 0,
ETH,
DEFAULT
};
struct hailo_device_params {
DeviceType device_type;
hailo_pcie_params pcie_params;
hailo_eth_params eth_params;
hailo_vdevice_params vdevice_params;
};
void add_device_options(CLI::App *app, hailo_device_params &device_params);
void add_vdevice_options(CLI::App *app, hailo_device_params &device_params);
Expected<std::unique_ptr<Device>> create_device(const hailo_device_params &device_params);
Expected<std::unique_ptr<Device>> create_pcie_device(const hailo_pcie_params &pcie_params);
void add_vdevice_options(CLI::App *app, hailo_vdevice_params &vdevice_params);
void add_device_options(CLI::App *app, hailo_device_params &device_params, bool support_asterisk=true);
Expected<std::vector<std::unique_ptr<Device>>> create_devices(const hailo_device_params &device_params);
Expected<std::vector<std::string>> get_device_ids(const hailo_device_params &device_params);
/**
* CLI11 transformer object, converting enum argument from string.
@@ -101,7 +87,7 @@ using DeprecationActionPtr = std::shared_ptr<DeprecationAction>;
class OptionDeprecation : public DeprecationAction
{
public:
OptionDeprecation(CLI::Option *opt, const std::string &replacement) :
OptionDeprecation(CLI::Option *opt, const std::string &replacement = std::string()) :
DeprecationAction(),
m_opt(opt),
m_replacement(replacement)
@@ -115,7 +101,12 @@ public:
virtual std::string deprecate(bool message_inline) override
{
std::stringstream message;
message << "'" << m_opt->get_name() << "' is deprecated, please use '" << m_replacement << "' instead." << std::endl;
message << "'" << m_opt->get_name() << "' is deprecated";
if (!m_replacement.empty()) {
std::cout << ", please use " << m_replacement << "' instead.";
}
message << std::endl;
CLI::Validator deprecate_warning(
[message = message.str()](std::string &) {
std::cout << message;

View File

@@ -10,6 +10,7 @@
#include "infer_stats_printer.hpp"
#include "run_command.hpp"
#include "common.hpp"
#include "pipeline.hpp"
#include <fstream>
#include <iostream>
@@ -103,20 +104,22 @@ InferStatsPrinter::InferStatsPrinter(const inference_runner_params &params, hail
output_status = HAILO_SUCCESS;
}
void InferStatsPrinter::print(const std::string &network_group_name, Expected<NetworkGroupInferResult>& inference_result)
void InferStatsPrinter::print(const std::vector<std::string> &network_groups_names, Expected<InferResult> &inference_result)
{
if (m_results_csv_file.is_open()) {
std::cout << "> Writing inference results to '" << m_results_csv_path << "'... ";
print_csv(network_group_name, inference_result);
print_csv(network_groups_names, inference_result);
std::cout << "done." << std::endl;
}
if (m_pipeline_stats_csv_file.is_open()) {
if (m_pipeline_stats_csv_file.is_open() && (inference_result)) {
std::cout << "> Writing pipeline statistics to '" << m_pipeline_stats_csv_path << "'... ";
m_pipeline_stats_csv_file << "net_name,vstream_name,param_type,element,mean,min,max,var,sd,mean_sd,index" << std::endl;
print_pipeline_elem_stats_csv(network_group_name, inference_result->m_fps_accumulators);
print_pipeline_elem_stats_csv(network_group_name, inference_result->m_latency_accumulators);
print_pipeline_elem_stats_csv(network_group_name, inference_result->m_queue_size_accumulators);
print_entire_pipeline_stats_csv(network_group_name, inference_result->m_pipeline_latency_accumulators);
for (auto &network_group_results : inference_result->network_group_results()) {
print_pipeline_elem_stats_csv(network_group_results.network_group_name(), network_group_results.m_fps_accumulators);
print_pipeline_elem_stats_csv(network_group_results.network_group_name(), network_group_results.m_latency_accumulators);
print_pipeline_elem_stats_csv(network_group_results.network_group_name(), network_group_results.m_queue_size_accumulators);
print_entire_pipeline_stats_csv(network_group_results.network_group_name(), network_group_results.m_pipeline_latency_accumulators);
}
std::cout << "done." << std::endl;
}
print_stdout(inference_result);
@@ -132,100 +135,106 @@ void InferStatsPrinter::print_benchmark_csv_header()
m_results_csv_file << "net_name,fps,hw_only_fps,num_of_frames,num_of_frames_hw_only,hw_latency,overall_latency,min_power,average_power,max_power" << std::endl;
}
void InferStatsPrinter::print_csv(const std::string &network_group_name, Expected<NetworkGroupInferResult>& inference_result)
void InferStatsPrinter::print_csv(const std::vector<std::string> &network_groups_names, Expected<InferResult> &inference_result)
{
auto status_description = hailo_get_status_message(inference_result.status());
m_results_csv_file << network_group_name << "," << static_cast<uint32_t>(inference_result.status()) << "," << status_description;
if (!inference_result) {
m_results_csv_file << ",,,,,,,,,,,";
}
else {
m_results_csv_file << ",";
if (auto fps = inference_result->fps()) {
m_results_csv_file << fps.value();
}
m_results_csv_file << ",";
if (auto frames_count = inference_result->frames_count()) {
m_results_csv_file << frames_count.value();
}
m_results_csv_file << ",";
if (auto send_data_rate = inference_result->send_data_rate_mbit_sec()) {
m_results_csv_file << send_data_rate.value();
}
m_results_csv_file << ",";
if (auto recv_data_rate = inference_result->recv_data_rate_mbit_sec()) {
m_results_csv_file << recv_data_rate.value();
}
m_results_csv_file << ",";
if (auto hw_latency = inference_result->hw_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value());
}
m_results_csv_file << ",";
if (auto overall_latency = inference_result->overall_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value());
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_power_measurements.size()) {
for (const auto &pair : inference_result->m_power_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
if (HAILO_SUCCESS != inference_result.status()) {
for (auto &network_group_name : network_groups_names) {
m_results_csv_file << network_group_name << "," << static_cast<uint32_t>(inference_result.status()) << "," << status_description;
if (!inference_result) {
m_results_csv_file << ",,,,,,,,,,,";
}
} else {
m_results_csv_file << ",,,";
}
} else {
for (auto &results : inference_result->network_group_results()) {
m_results_csv_file << results.network_group_name() << "," << static_cast<uint32_t>(inference_result.status()) << "," << status_description;
m_results_csv_file << ",";
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_current_measurements.size()) {
for (const auto &pair : inference_result->m_current_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
if (auto fps = results.fps()) {
m_results_csv_file << fps.value();
}
} else {
m_results_csv_file << ",,,";
}
m_results_csv_file << ",";
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_temp_measurements.size()) {
for (const auto &pair : inference_result->m_temp_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->max_value;
} else {
m_results_csv_file << ",,,";
}
if (auto frames_count = results.frames_count()) {
m_results_csv_file << frames_count.value();
}
} else {
m_results_csv_file << ",,,";
m_results_csv_file << ",";
if (auto send_data_rate = results.send_data_rate_mbit_sec()) {
m_results_csv_file << send_data_rate.value();
}
m_results_csv_file << ",";
if (auto recv_data_rate = results.recv_data_rate_mbit_sec()) {
m_results_csv_file << recv_data_rate.value();
}
m_results_csv_file << ",";
if (auto hw_latency = results.hw_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value());
}
m_results_csv_file << ",";
if (auto overall_latency = results.overall_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value());
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_power_measurements.size()) {
for (const auto &pair : inference_result->m_power_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
}
} else {
m_results_csv_file << ",,,";
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_current_measurements.size()) {
for (const auto &pair : inference_result->m_current_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
}
} else {
m_results_csv_file << ",,,";
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == inference_result->m_temp_measurements.size()) {
for (const auto &pair : inference_result->m_temp_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->max_value;
} else {
m_results_csv_file << ",,,";
}
}
} else {
m_results_csv_file << ",,,";
}
m_results_csv_file << std::endl;
}
}
m_results_csv_file << std::endl;
}
void InferStatsPrinter::print_pipeline_elem_stats_csv(const std::string &network_group_name,
@@ -273,59 +282,72 @@ void InferStatsPrinter::print_entire_pipeline_stats_csv(const std::string &netwo
}
}
void InferStatsPrinter::print_benchmark_csv(const std::string &network_group_name, const NetworkGroupInferResult &hw_inference_result,
const NetworkGroupInferResult &streaming_inference_result, const NetworkGroupInferResult &hw_latency_result)
void InferStatsPrinter::print_benchmark_csv(InferResult &hw_inference_result,
InferResult &streaming_inference_result, InferResult &hw_latency_result)
{
m_results_csv_file << network_group_name << ",";
assert(hw_inference_result.network_group_results().size() == streaming_inference_result.network_group_results().size());
assert(hw_latency_result.network_group_results().size() == streaming_inference_result.network_group_results().size());
for (auto &hw_res : hw_inference_result.network_group_results()) {
auto network_group_name = hw_res.network_group_name();
if (auto fps = streaming_inference_result.fps()) {
m_results_csv_file << fps.value();
}
m_results_csv_file << ",";
auto streaming_res = std::find_if(streaming_inference_result.network_group_results().begin(), streaming_inference_result.network_group_results().end(),
[network_group_name] (NetworkGroupInferResult &infer_results) { return (infer_results.network_group_name() == network_group_name); });
if (auto hw_only_fps = hw_inference_result.fps()) {
m_results_csv_file << hw_only_fps.value();
}
m_results_csv_file << ",";
auto latency_res = std::find_if(hw_latency_result.network_group_results().begin(), hw_latency_result.network_group_results().end(),
[network_group_name] (NetworkGroupInferResult &infer_results) { return (infer_results.network_group_name() == network_group_name); });
if (auto frames_count = streaming_inference_result.frames_count()) {
m_results_csv_file << frames_count.value();
}
m_results_csv_file << ",";
m_results_csv_file << network_group_name << ",";
if (auto frames_count = hw_inference_result.frames_count()) {
m_results_csv_file << frames_count.value();
}
m_results_csv_file << ",";
if (auto hw_latency = hw_latency_result.hw_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value());
}
m_results_csv_file << ",";
if (auto overall_latency = hw_latency_result.overall_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value());
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == streaming_inference_result.m_power_measurements.size()) {
for (const auto &pair : streaming_inference_result.m_power_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
if (auto fps = streaming_res->fps()) {
m_results_csv_file << fps.value();
}
} else {
m_results_csv_file << ",,,";
}
m_results_csv_file << ",";
m_results_csv_file << std::endl;
if (auto hw_only_fps = hw_res.fps()) {
m_results_csv_file << hw_only_fps.value();
}
m_results_csv_file << ",";
if (auto frames_count = streaming_res->frames_count()) {
m_results_csv_file << frames_count.value();
}
m_results_csv_file << ",";
if (auto frames_count = hw_res.frames_count()) {
m_results_csv_file << frames_count.value();
}
m_results_csv_file << ",";
if (auto hw_latency = latency_res->hw_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value());
}
m_results_csv_file << ",";
if (auto overall_latency = latency_res->overall_latency()) {
m_results_csv_file << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value());
}
// TODO HRT-5363 support multiple devices (Currently assumes 1 device in the map)
if (1 == streaming_inference_result.m_power_measurements.size()) {
for (const auto &pair : streaming_inference_result.m_power_measurements) {
if (nullptr != pair.second) {
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().min_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().average_value;
m_results_csv_file << ",";
m_results_csv_file << pair.second->data().max_value;
} else {
m_results_csv_file << ",,,";
}
}
} else {
m_results_csv_file << ",,,";
}
m_results_csv_file << std::endl;
}
}
template< typename T>
void InferStatsPrinter::print_stdout_single_element(const T &results, size_t frames_count)
@@ -351,13 +373,14 @@ void InferStatsPrinter::print_stdout_single_element(const T &results, size_t fra
if (auto hw_latency = results.hw_latency()) {
std::cout << " HW Latency: " << InferResultsFormatUtils::latency_result_to_ms(hw_latency.value()) << " ms" << std::endl;
}
if (auto overall_latency = results.overall_latency()) {
std::cout << " Overall Latency: " << InferResultsFormatUtils::latency_result_to_ms(overall_latency.value()) << " ms" << std::endl;
}
}
void InferStatsPrinter::print_stdout(Expected<NetworkGroupInferResult>& inference_result)
void InferStatsPrinter::print_stdout(Expected<InferResult> &inference_result)
{
if (!inference_result) {
return;
@@ -369,31 +392,36 @@ void InferStatsPrinter::print_stdout(Expected<NetworkGroupInferResult>& inferenc
std::cout << std::setprecision(2) << std::fixed;
std::cout << FORMAT_CLEAR_LINE << "> Inference result:" << std::endl;
if (1 < inference_result->m_result_per_network.size()) {
// If there is more than 1 network, we print results per network, and than sum of bandwith
for (auto &network_result_pair : inference_result->m_result_per_network) {
std::cout << " Network: " << network_result_pair.first << std::endl;
auto frames_count = (m_print_frame_count) ? network_result_pair.second.m_frames_count : 0;
print_stdout_single_element<NetworkInferResult>(network_result_pair.second, frames_count);
}
std::stringstream bandwidth_stream;
bandwidth_stream << std::setprecision(2) << std::fixed;
if (auto send_data_rate = inference_result->send_data_rate_mbit_sec()) {
bandwidth_stream << " Send Rate: " << send_data_rate.value() << " Mbit/s" << std::endl;
}
for (auto &network_group_results : inference_result.value().network_group_results()) {
std::cout << " Network group: " << network_group_results.network_group_name() << std::endl;
if (1 < network_group_results.m_result_per_network.size()) {
// If there is more than 1 network, we print results per network, and than sum of bandwith
for (auto &network_result_pair : network_group_results.m_result_per_network) {
std::cout << " Network: " << network_result_pair.first << std::endl;
auto frames_count = (m_print_frame_count) ? network_result_pair.second.m_frames_count : 0;
print_stdout_single_element<NetworkInferResult>(network_result_pair.second, frames_count);
}
std::stringstream bandwidth_stream;
bandwidth_stream << std::setprecision(2) << std::fixed;
if (auto send_data_rate = network_group_results.send_data_rate_mbit_sec()) {
bandwidth_stream << " Send Rate: " << send_data_rate.value() << " Mbit/s" << std::endl;
}
if (auto recv_data_rate = inference_result->recv_data_rate_mbit_sec()) {
bandwidth_stream << " Recv Rate: " << recv_data_rate.value() << " Mbit/s" << std::endl;
}
if (auto recv_data_rate = network_group_results.recv_data_rate_mbit_sec()) {
bandwidth_stream << " Recv Rate: " << recv_data_rate.value() << " Mbit/s" << std::endl;
}
if (0 != bandwidth_stream.rdbuf()->in_avail()) {
std::cout << " Total bandwidth: " << std::endl;
std::cout << bandwidth_stream.rdbuf();
if (0 != bandwidth_stream.rdbuf()->in_avail()) {
std::cout << " Total bandwidth: " << std::endl;
std::cout << bandwidth_stream.rdbuf();
}
std::cout << std::endl;
} else {
auto frames_count_exp = network_group_results.frames_count();
auto frames_count = ((frames_count_exp) && (m_print_frame_count)) ? frames_count_exp.value() : 0;
print_stdout_single_element<NetworkGroupInferResult>(network_group_results, frames_count);
std::cout << std::endl;
}
} else {
auto frames_count_exp = inference_result->frames_count();
auto frames_count = ((frames_count_exp) && (m_print_frame_count)) ? frames_count_exp.value() : 0;
print_stdout_single_element<NetworkGroupInferResult>(inference_result.value(), frames_count);
}
if ((inference_result->m_power_measurements.size() != inference_result->m_current_measurements.size()) ||
@@ -419,9 +447,9 @@ void InferStatsPrinter::print_stdout(Expected<NetworkGroupInferResult>& inferenc
}
auto temp_measure_iter = inference_result->m_temp_measurements.find(pair.first);
if ((temp_measure_iter != inference_result->m_temp_measurements.end()) && (nullptr != temp_measure_iter->second)) {
measurement_stream << " Minimum chip temperature: " << temp_measure_iter->second->min_value << "°C" << std::endl;
measurement_stream << " Average chip temperature: " << temp_measure_iter->second->average_value << "°C" << std::endl;
measurement_stream << " Maximum chip temperature: " << temp_measure_iter->second->max_value << "°C" << std::endl;
measurement_stream << " Minimum chip temperature: " << temp_measure_iter->second->min_value << "C" << std::endl;
measurement_stream << " Average chip temperature: " << temp_measure_iter->second->average_value << "C" << std::endl;
measurement_stream << " Maximum chip temperature: " << temp_measure_iter->second->max_value << "C" << std::endl;
}
if (0 != measurement_stream.rdbuf()->in_avail()) {
std::cout << " Device: " << pair.first << std::endl;
@@ -439,6 +467,8 @@ void InferStatsPrinter::write_accumulator_results(std::ofstream &output_stream,
{
const auto &accumulator_result = accumulator->get();
if ((!accumulator_result.count()) || (accumulator_result.count().value() == 0)) {
LOGGER__WARNING("No {} data has been collected for element '{}' (vstream '{}'). Collection begins after the element has processed {} frames...",
accumulator->get_data_type(), elem_name, vstream_name, DEFAULT_NUM_FRAMES_BEFORE_COLLECTION_START);
return;
}

View File

@@ -29,9 +29,9 @@ public:
class InferStatsPrinter final {
public:
static Expected<InferStatsPrinter> create(const inference_runner_params &params, bool print_running_info = true);
void print(const std::string &network_name, Expected<NetworkGroupInferResult>& inference_result);
void print_benchmark_csv(const std::string &network_name, const NetworkGroupInferResult &hw_inference_result,
const NetworkGroupInferResult &streaming_inference_result, const NetworkGroupInferResult &hw_latency_result);
void print(const std::vector<std::string> &network_groups_names, Expected<InferResult> &inference_result);
void print_benchmark_csv(InferResult &hw_inference_result,
InferResult &streaming_inference_result, InferResult &hw_latency_result);
void print_csv_header();
void print_benchmark_csv_header();
@@ -39,14 +39,14 @@ private:
static constexpr uint32_t NO_INDEX = std::numeric_limits<uint32_t>::max();
InferStatsPrinter(const inference_runner_params &params, hailo_status &output_status, bool print_running_info = true);
void print_csv(const std::string &network_name, Expected<NetworkGroupInferResult>& inference_result);
void print_csv(const std::vector<std::string> &network_groups_names, Expected<InferResult> &inference_result);
void print_pipeline_elem_stats_csv(const std::string &network_name,
const std::map<std::string, std::map<std::string, AccumulatorPtr>> &inference_result);
void print_pipeline_elem_stats_csv(const std::string &network_name,
const std::map<std::string, std::map<std::string, std::vector<AccumulatorPtr>>> &inference_result);
void print_entire_pipeline_stats_csv(const std::string &network_name,
const std::map<std::string, AccumulatorPtr> &inference_result);
void print_stdout(Expected<NetworkGroupInferResult>& inference_result);
void print_stdout(Expected<InferResult> &inference_result);
template <typename T>
void print_stdout_single_element(const T &results, size_t frames_count);

View File

@@ -13,33 +13,59 @@
#include <iostream>
#include <iomanip>
InferProgress::InferProgress(ConfiguredNetworkGroup &configured_network_group, const inference_runner_params &params,
std::chrono::duration<double> print_interval) :
m_configured_network_group(configured_network_group), m_params(params),
m_print_interval(print_interval), m_networks_progress(), m_stop(true) {}
Expected<std::shared_ptr<InferProgress>> InferProgress::create(const inference_runner_params &params,
std::chrono::milliseconds print_interval)
{
auto status = HAILO_UNINITIALIZED;
auto progress_bar_ptr = std::shared_ptr<InferProgress>(new (std::nothrow) InferProgress(params, print_interval, status));
CHECK_AS_EXPECTED((nullptr != progress_bar_ptr), HAILO_OUT_OF_HOST_MEMORY);
return progress_bar_ptr;
}
InferProgress::InferProgress(const inference_runner_params &params,
std::chrono::milliseconds print_interval, hailo_status &status) :
m_params(params), m_print_interval(print_interval), m_networks_progress(),
m_stop_event(Event::create_shared(Event::State::not_signalled)), m_finished(false)
{
if (nullptr == m_stop_event) {
LOGGER__ERROR("Failed to create event for progress bar");
status = HAILO_OUT_OF_HOST_MEMORY;
return;
}
status = HAILO_SUCCESS;
}
void InferProgress::start()
{
m_stop = false;
m_print_thread = std::thread([this] () {
while (!m_stop.load()) {
while (true) {
print_progress(true);
std::this_thread::sleep_for(m_print_interval);
auto status = m_stop_event->wait(m_print_interval);
if (HAILO_TIMEOUT != status) {
break;
}
}
});
}
void InferProgress::finish(bool should_print_progress)
{
m_stop = true;
m_print_thread.join();
(void)m_stop_event->signal();
if (m_print_thread.joinable()) {
m_print_thread.join();
}
if (should_print_progress) {
print_progress(false);
}
m_finished = true;
}
void InferProgress::print_progress(bool should_reset_cursor)
{
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &network_progress_bar : m_networks_progress) {
std::cout << network_progress_bar->get_progress_text() << std::endl;
}
@@ -50,15 +76,15 @@ void InferProgress::print_progress(bool should_reset_cursor)
InferProgress::~InferProgress()
{
if (!m_stop.load()) {
if (!m_finished) {
finish(false);
}
}
Expected<std::shared_ptr<NetworkProgressBar>> InferProgress::create_network_progress_bar(const std::string &network_name)
Expected<std::shared_ptr<NetworkProgressBar>> InferProgress::create_network_progress_bar(std::shared_ptr<ConfiguredNetworkGroup> network_group, const std::string &network_name)
{
std::shared_ptr<NetworkProgressBar> network_progress_ber =
make_shared_nothrow<NetworkProgressBar>(m_configured_network_group, m_params, network_name);
make_shared_nothrow<NetworkProgressBar>(network_group, m_params, network_name);
CHECK_NOT_NULL_AS_EXPECTED(network_progress_ber, HAILO_OUT_OF_HOST_MEMORY);
{
@@ -71,7 +97,7 @@ Expected<std::shared_ptr<NetworkProgressBar>> InferProgress::create_network_prog
return prog_bar_cpy;
}
NetworkProgressBar::NetworkProgressBar(ConfiguredNetworkGroup &configured_network_group,
NetworkProgressBar::NetworkProgressBar(std::shared_ptr<ConfiguredNetworkGroup> configured_network_group,
const inference_runner_params &params, const std::string &network_name) :
m_network_name(network_name), m_configured_network_group(configured_network_group), m_params(params),
m_progress_count(0), m_start(std::chrono::steady_clock::now()) // NetworkProgressBar sets start time to its creation time
@@ -110,7 +136,7 @@ std::string NetworkProgressBar::get_progress_text()
res << " | FPS: " << fps;
} else {
double avg_hw_latency = 0;
auto latency_expected = m_configured_network_group.get_latency_measurement(m_network_name);
auto latency_expected = m_configured_network_group->get_latency_measurement(m_network_name);
if (latency_expected) {
avg_hw_latency = InferResultsFormatUtils::latency_result_to_ms(latency_expected.release().avg_hw_latency);
}

View File

@@ -19,14 +19,14 @@
class NetworkProgressBar final {
public:
NetworkProgressBar(ConfiguredNetworkGroup &configured_network_group,
NetworkProgressBar(std::shared_ptr<ConfiguredNetworkGroup> configured_network_group,
const inference_runner_params &params, const std::string &network_name);
void make_progress();
std::string get_progress_text();
private:
const std::string m_network_name;
ConfiguredNetworkGroup &m_configured_network_group;
std::shared_ptr<ConfiguredNetworkGroup> m_configured_network_group;
const inference_runner_params m_params;
std::atomic<uint32_t> m_progress_count;
std::chrono::time_point<std::chrono::steady_clock> m_start;
@@ -34,25 +34,29 @@ private:
class InferProgress final {
public:
InferProgress(ConfiguredNetworkGroup &configured_network_group,
const inference_runner_params &params, std::chrono::duration<double> print_interval);
static Expected<std::shared_ptr<InferProgress>> create(const inference_runner_params &params,
std::chrono::milliseconds print_interval);
~InferProgress();
Expected<std::shared_ptr<NetworkProgressBar>> create_network_progress_bar(const std::string &network_name);
Expected<std::shared_ptr<NetworkProgressBar>> create_network_progress_bar(std::shared_ptr<ConfiguredNetworkGroup> network_group,
const std::string &network_name);
void start();
void finish(bool should_print_progress = true);
InferProgress(const inference_runner_params &params, std::chrono::milliseconds print_interval, hailo_status &status);
private:
void print_progress(bool should_reset_cursor);
ConfiguredNetworkGroup &m_configured_network_group;
std::vector<std::shared_ptr<ConfiguredNetworkGroup>> m_configured_network_groups;
const inference_runner_params m_params;
std::chrono::duration<double> m_print_interval;
std::chrono::milliseconds m_print_interval;
std::vector<std::shared_ptr<NetworkProgressBar>> m_networks_progress;
std::atomic_bool m_stop;
EventPtr m_stop_event;
std::thread m_print_thread;
std::mutex m_mutex;
std::atomic_bool m_finished;
};
#endif /* _HAILO_INFERENCE_PROGRESS_HPP_ */

View File

@@ -47,7 +47,7 @@ public:
Expected<double> send_data_rate_mbit_sec() const
{
if (!m_infer_duration) {
if (!m_infer_duration || !m_total_send_frame_size) {
return make_unexpected(HAILO_NOT_AVAILABLE);
}
return (static_cast<double>(m_frames_count * m_total_send_frame_size) / *m_infer_duration) * MBIT_PER_BYTE;
@@ -55,7 +55,7 @@ public:
Expected<double> recv_data_rate_mbit_sec() const
{
if (!m_infer_duration) {
if (!m_infer_duration || !m_total_recv_frame_size) {
return make_unexpected(HAILO_NOT_AVAILABLE);
}
return (static_cast<double>(m_frames_count * m_total_recv_frame_size) / *m_infer_duration) * MBIT_PER_BYTE;
@@ -84,25 +84,28 @@ public:
size_t m_total_recv_frame_size;
// TODO: change to optional
std::unique_ptr<double> m_infer_duration;
std::unique_ptr<std::chrono::nanoseconds> m_hw_latency;
std::unique_ptr<std::chrono::nanoseconds> m_overall_latency;
std::shared_ptr<double> m_infer_duration;
std::shared_ptr<std::chrono::nanoseconds> m_hw_latency;
std::shared_ptr<std::chrono::nanoseconds> m_overall_latency;
};
struct NetworkGroupInferResult
{
public:
NetworkGroupInferResult(std::map<std::string, NetworkInferResult> &&result_per_network = {}) :
NetworkGroupInferResult(const std::string &network_group_name, std::map<std::string, NetworkInferResult> &&result_per_network = {}) :
m_network_group_name(network_group_name),
m_result_per_network(std::move(result_per_network)),
m_power_measurements(),
m_current_measurements(),
m_temp_measurements(),
m_fps_accumulators(),
m_latency_accumulators(),
m_queue_size_accumulators(),
m_pipeline_latency_accumulators()
{}
std::string network_group_name()
{
return m_network_group_name;
}
Expected<double> infer_duration(const std::string &network_name = "") const
{
if (network_name.empty()) {
@@ -228,15 +231,15 @@ public:
return frames_count_cpy;
}
const std::map<std::string, NetworkInferResult> &results_per_network() const
{
return m_result_per_network;
}
std::string m_network_group_name;
// <network_name, network_inference_results>
std::map<std::string, NetworkInferResult> m_result_per_network;
// <device_id, measurement>
// TODO: create a struct contianing all device measurements, and keep only one map
std::map<std::string, std::unique_ptr<LongPowerMeasurement>> m_power_measurements;
std::map<std::string, std::unique_ptr<LongPowerMeasurement>> m_current_measurements;
std::map<std::string, std::unique_ptr<TempMeasurementData>> m_temp_measurements;
// <vstream_name, accumulator>
std::map<std::string, std::map<std::string, AccumulatorPtr>> m_fps_accumulators;
std::map<std::string, std::map<std::string, AccumulatorPtr>> m_latency_accumulators;
@@ -274,40 +277,7 @@ public:
void update_pipeline_stats(const std::map<std::string, std::vector<std::reference_wrapper<InputStream>>> &/*inputs_per_network*/,
const std::map<std::string, std::vector<std::reference_wrapper<OutputStream>>> &/*outputs_per_network*/)
{
// Overloading fow hw_object inference - not using any pipelines so nothing to update
}
void initialize_measurements(const std::vector<std::reference_wrapper<Device>> &devices)
{
for (const auto &device : devices) {
m_power_measurements.emplace(device.get().get_dev_id(), std::unique_ptr<LongPowerMeasurement>{});
m_current_measurements.emplace(device.get().get_dev_id(), std::unique_ptr<LongPowerMeasurement>{});
m_temp_measurements.emplace(device.get().get_dev_id(), std::unique_ptr<TempMeasurementData>{});
}
}
hailo_status set_power_measurement(const std::string &device_id, std::unique_ptr<LongPowerMeasurement> &&power_measure)
{
auto iter = m_power_measurements.find(device_id);
CHECK(m_power_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(power_measure);
return HAILO_SUCCESS;
}
hailo_status set_current_measurement(const std::string &device_id, std::unique_ptr<LongPowerMeasurement> &&current_measure)
{
auto iter = m_current_measurements.find(device_id);
CHECK(m_current_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(current_measure);
return HAILO_SUCCESS;
}
hailo_status set_temp_measurement(const std::string &device_id, std::unique_ptr<TempMeasurementData> &&temp_measure)
{
auto iter = m_temp_measurements.find(device_id);
CHECK(m_temp_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(temp_measure);
return HAILO_SUCCESS;
// Overloading fow hw_only inference - not using any pipelines so nothing to update
}
private:
@@ -323,4 +293,58 @@ private:
}
};
struct InferResult
{
public:
InferResult(std::vector<NetworkGroupInferResult> &&network_groups_results) : m_network_group_results(std::move(network_groups_results))
{}
std::vector<NetworkGroupInferResult> &network_group_results()
{
return m_network_group_results;
}
void initialize_measurements(const std::vector<std::reference_wrapper<Device>> &devices)
{
for (const auto &device : devices) {
m_power_measurements.emplace(device.get().get_dev_id(), std::shared_ptr<LongPowerMeasurement>{});
m_current_measurements.emplace(device.get().get_dev_id(), std::shared_ptr<LongPowerMeasurement>{});
m_temp_measurements.emplace(device.get().get_dev_id(), std::shared_ptr<TempMeasurementData>{});
}
}
hailo_status set_power_measurement(const std::string &device_id, std::shared_ptr<LongPowerMeasurement> &&power_measure)
{
auto iter = m_power_measurements.find(device_id);
CHECK(m_power_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(power_measure);
return HAILO_SUCCESS;
}
hailo_status set_current_measurement(const std::string &device_id, std::shared_ptr<LongPowerMeasurement> &&current_measure)
{
auto iter = m_current_measurements.find(device_id);
CHECK(m_current_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(current_measure);
return HAILO_SUCCESS;
}
hailo_status set_temp_measurement(const std::string &device_id, std::shared_ptr<TempMeasurementData> &&temp_measure)
{
auto iter = m_temp_measurements.find(device_id);
CHECK(m_temp_measurements.end() != iter, HAILO_INVALID_ARGUMENT);
iter->second = std::move(temp_measure);
return HAILO_SUCCESS;
}
// <device_id, measurement>
// TODO: create a struct containing all device measurements, and keep only one map
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> m_power_measurements;
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> m_current_measurements;
std::map<std::string, std::shared_ptr<TempMeasurementData>> m_temp_measurements;
private:
std::vector<NetworkGroupInferResult> m_network_group_results;
};
#endif /* _HAILO_INFER_RESULT_ */

View File

@@ -0,0 +1,165 @@
/**
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file mon_command.cpp
* @brief Monitor of networks - Presents information about the running networks
**/
#include "mon_command.hpp"
#include "common.hpp"
#include "hailo/hailort.h"
#include "common/filesystem.hpp"
#include <iostream>
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 NUMBER_WIDTH = 15;
constexpr size_t LINE_LENGTH = 125;
MonCommand::MonCommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("monitor", "Monitor of networks - Presents information about the running networks. " \
"To enable monitor, set in the application process the environment variable '" + std::string(SCHEDULER_MON_ENV_VAR) + "' to 1."))
{}
hailo_status MonCommand::execute()
{
#ifdef _WIN32
LOGGER__ERROR("hailortcli `monitor` command is not supported on Windows");
return HAILO_NOT_IMPLEMENTED;
#else
return print_table();
#endif
}
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(NUMBER_WIDTH) << std::left << "PID" <<
"\n" << std::left << std::string(LINE_LENGTH, '-') << "\n";
static const uint32_t header_lines_count = 2;
return header_lines_count;
}
size_t MonCommand::print_networks_info_table(const ProtoMon &mon_message)
{
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();
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";
}
return mon_message.networks_infos().size();
}
size_t MonCommand::print_frames_header()
{
std::cout <<
std::setw(NETWORK_NAME_WIDTH) << std::left << "Network" <<
std::setw(STREAM_NAME_WIDTH) << std::left << "Stream" <<
std::setw(NUMBER_WIDTH) << std::left << "Direction" <<
std::setw(NUMBER_WIDTH) << std::left << "Frames" <<
"\n" << std::left << std::string(LINE_LENGTH, '-') << "\n";
static const size_t header_lines_count = 2;
return header_lines_count;
}
size_t MonCommand::print_frames_table(const ProtoMon &mon_message)
{
size_t table_lines_count = 0;
for (auto &net_info : mon_message.net_frames_infos()) {
auto &net_name = net_info.network_name();
table_lines_count += net_info.streams_frames_infos().size();
for (auto &streams_frames : net_info.streams_frames_infos()) {
auto &stream_name = streams_frames.stream_name();
auto stream_direction = (streams_frames.stream_direction() == PROTO__STREAM_DIRECTION__HOST_TO_DEVICE) ? "H2D" : "D2H";
std::string frames;
if (SCHEDULER_MON_NAN_VAL == streams_frames.buffer_frames_size() || SCHEDULER_MON_NAN_VAL == streams_frames.pending_frames_count()) {
frames = "NaN";
} else {
frames = std::to_string(streams_frames.pending_frames_count()) + "/" + std::to_string(streams_frames.buffer_frames_size());
}
std::cout <<
std::setw(NETWORK_NAME_WIDTH) << std::left << net_name <<
std::setw(STREAM_NAME_WIDTH) << std::left << stream_name <<
std::setw(NUMBER_WIDTH) << std::left << stream_direction <<
std::setw(NUMBER_WIDTH) << std::left << frames << "\n";
}
}
return table_lines_count;
}
#if defined(__GNUC__)
hailo_status MonCommand::print_table()
{
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;
}
std::vector<ProtoMon> mon_messages;
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());
continue;
}
ProtoMon mon_message;
if (!mon_message.ParseFromFileDescriptor(file->get_fd())) {
LOGGER__WARNING("Failed to ParseFromFileDescriptor monitor file {} with errno {}", mon_file, errno);
continue;
}
mon_messages.emplace_back(std::move(mon_message));
}
size_t 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";
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);
std::this_thread::sleep_for(DEFAULT_SCHEDULER_MON_INTERVAL);
}
return HAILO_SUCCESS;
}
#endif
} /* namespace hailort */

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file mon_command.hpp
* @brief Monitor of networks - Presents information about the running networks
**/
#ifndef _HAILO_MON_COMMAND_HPP_
#define _HAILO_MON_COMMAND_HPP_
#include "hailo/hailort.h"
#include "hailortcli.hpp"
#include "command.hpp"
#include "scheduler_mon.hpp"
#include "CLI/CLI.hpp"
namespace hailort
{
class MonCommand : public Command
{
public:
explicit MonCommand(CLI::App &parent_app);
virtual hailo_status execute() override;
private:
hailo_status print_table();
size_t print_networks_info_header();
size_t print_frames_header();
size_t print_networks_info_table(const ProtoMon &mon_message);
size_t print_frames_table(const ProtoMon &mon_message);
};
} /* namespace hailort */
#endif /* _HAILO_MON_COMMAND_HPP_ */

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,9 @@ 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;
@@ -51,7 +54,7 @@ struct runtime_data_params {
};
struct inference_runner_params {
hailo_device_params device_params;
hailo_vdevice_params vdevice_params;
std::string hef_path;
uint32_t frames_count;
uint32_t time_to_run;
@@ -75,7 +78,7 @@ struct inference_runner_params {
bool should_measure_pipeline_stats(const inference_runner_params& params);
CLI::App* create_run_command(CLI::App& parent, inference_runner_params& params);
hailo_status run_command(const inference_runner_params &params);
Expected<NetworkGroupInferResult> run_command_hef(const inference_runner_params &params);
Expected<InferResult> run_command_hef(const inference_runner_params &params);
std::string format_type_to_string(hailo_format_type_t format_type);

View File

@@ -14,17 +14,13 @@
ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("scan", "Shows all available devices")),
m_device_type(Device::Type::PCIE)
Command(parent_app.add_subcommand("scan", "Shows all available devices"))
{
const HailoCheckedTransformer<Device::Type> device_type_transformer({
{ "pcie", Device::Type::PCIE },
{ "eth", Device::Type::ETH },
});
auto *device_type_option = m_app->add_option("-d,--device-type,--target", m_device_type,
"Device type to use.")
->transform(device_type_transformer)
->default_val("pcie");
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");
@@ -33,63 +29,37 @@ ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
->default_val("")
->check(CLI::ValidIPV4);
auto *interface_name_option = eth_options_group->add_option("--interface", m_interface_name, "Interface name to scan")
eth_options_group->add_option("--interface", m_interface_name, "Interface name to scan")
->default_val("")
->excludes(interface_ip_option);
m_app->parse_complete_callback([this, device_type_option, interface_ip_option, interface_name_option]() {
bool eth_options_given = !interface_ip_option->empty() || !interface_name_option->empty();
// The user didn't put target, we can figure it ourself
if (device_type_option->empty()) {
if (eth_options_given) {
// User gave IP, target is eth
m_device_type = Device::Type::ETH;
}
else {
// Default is pcie
m_device_type = Device::Type::PCIE;
}
}
if (!eth_options_given && (m_device_type == Device::Type::ETH)) {
throw CLI::ParseError("Ethernet options not set", CLI::ExitCodes::InvalidError);
}
if (eth_options_given && (m_device_type != Device::Type::ETH)) {
throw CLI::ParseError("Ethernet options set on non eth device", CLI::ExitCodes::InvalidError);
}
});
}
hailo_status ScanSubcommand::execute()
{
switch (m_device_type)
{
case Device::Type::PCIE:
return scan_pcie();
case Device::Type::ETH:
return scan_ethernet(m_interface_ip_addr, m_interface_name).status();
default:
std::cerr << "Unkown target" << std::endl;
return HAILO_INVALID_ARGUMENT;
const bool request_for_eth_scan = !m_interface_name.empty() || !m_interface_ip_addr.empty();
if (!request_for_eth_scan) {
return scan();
}
else {
auto res = scan_ethernet(m_interface_ip_addr, m_interface_name);
CHECK_EXPECTED_AS_STATUS(res);
return HAILO_SUCCESS;
}
}
hailo_status ScanSubcommand::scan_pcie()
hailo_status ScanSubcommand::scan()
{
auto scan_result = Device::scan_pcie();
CHECK_SUCCESS(scan_result.status(), "Error scan failed status = {}", scan_result.status());
auto device_ids = Device::scan();
CHECK_EXPECTED_AS_STATUS(device_ids);
if (scan_result->size() == 0) {
std::cout << "Hailo PCIe devices not found" << std::endl;
if (device_ids->size() == 0) {
std::cout << "Hailo devices not found" << std::endl;
}
else {
std::cout << "Hailo PCIe Devices:" << std::endl;
for (const auto& device_info : scan_result.value()) {
auto device_info_str = Device::pcie_device_info_to_string(device_info);
CHECK_EXPECTED_AS_STATUS(device_info_str);
std::cout << "[-] Device BDF: " << device_info_str.value() << std::endl;
std::cout << "Hailo Devices:" << std::endl;
for (const auto& device_id : device_ids.value()) {
std::cout << "[-] Device: " << device_id << std::endl;
}
}

View File

@@ -26,9 +26,8 @@ public:
const std::string &interface_name);
private:
hailo_status scan_pcie();
Device::Type m_device_type;
// Scans any system device
hailo_status scan();
// Ethernet scan options
std::string m_interface_ip_addr;

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
set(HAILORT_MINOR_VERSION 8)
set(HAILORT_REVISION_VERSION 1)
set(HAILORT_MINOR_VERSION 10)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
@@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
protobuf_generate_cpp(PROTO_HEF_SRC PROTO_HEF_HEADR hef.proto)
add_library(hef_proto ${PROTO_HEF_SRC} ${PROTO_HEF_HEADR})
target_link_libraries(hef_proto libprotobuf)
target_link_libraries(hef_proto libprotobuf-lite)
set_target_properties(hef_proto PROPERTIES CXX_STANDARD 14 GENERATED TRUE POSITION_INDEPENDENT_CODE ON)
if(CMAKE_HOST_WIN32)
# https://github.com/protocolbuffers/protobuf/tree/master/cmake#notes-on-compiler-warnings
@@ -25,11 +25,26 @@ target_include_directories(hef_proto
$<BUILD_INTERFACE: ${Protobuf_INCLUDE_DIRS}>
)
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)
set_target_properties(scheduler_mon_proto PROPERTIES CXX_STANDARD 14 GENERATED TRUE POSITION_INDEPENDENT_CODE ON)
if(CMAKE_HOST_WIN32)
target_compile_options(scheduler_mon_proto PRIVATE /wd4244)
endif()
get_filename_component(PROTO_SCHEDULER_MON_HEADER_DIRECTORY ${PROTO_SCHEDULER_MON_HEADR} DIRECTORY)
target_include_directories(scheduler_mon_proto
PUBLIC
$<BUILD_INTERFACE: ${PROTO_SCHEDULER_MON_HEADER_DIRECTORY}>
$<BUILD_INTERFACE: ${Protobuf_INCLUDE_DIRS}>
)
# Add readerwriterqueue as a header-only library
add_library(readerwriterqueue INTERFACE)
target_include_directories(readerwriterqueue INTERFACE ${HAILO_EXTERNAL_DIR}/readerwriterqueue)
add_subdirectory(src)
if(HAILO_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

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.8.1 EXACT REQUIRED)
find_package(HailoRT 4.10.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")

View File

@@ -48,7 +48,7 @@ using namespace hailort;
#define DEFAULT_VDEVICE_KEY (0)
#define MIN_VALID_VDEVICE_KEY (1)
#define HAILO_SUPPORTED_FORMATS "{ RGB, YUY2 }"
#define HAILO_SUPPORTED_FORMATS "{ RGB, RGBA, YUY2 }"
#define HAILO_VIDEO_CAPS GST_VIDEO_CAPS_MAKE(HAILO_SUPPORTED_FORMATS)
#define HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS (0)
@@ -70,6 +70,14 @@ using namespace hailort;
} \
} while(0)
#define GST_CHECK_SUCCESS_AS_EXPECTED(status, element, domain, ...) \
do { \
if (HAILO_SUCCESS != (status)) { \
GST_ELEMENT_ERROR((element), domain, FAILED, (__VA_ARGS__), (NULL)); \
return make_unexpected(status); \
} \
} while(0)
#define GST_CHECK_EXPECTED(obj, element, domain, ...) \
do { \
if (!(obj)) { \

View File

@@ -570,7 +570,7 @@ hailo_status HailoNetImpl::configure_network_group()
GST_CHECK_EXPECTED_AS_STATUS(network_group_name, m_element, RESOURCE, "Could not get network group name from name %s, status = %d",
m_props.m_network_name.get(), network_group_name.status());
hailo_status status = m_net_group_handle->configure_network_group(network_group_name->c_str(), m_props.m_batch_size.get());
hailo_status status = m_net_group_handle->configure_network_group(network_group_name->c_str(), m_props.m_scheduling_algorithm.get(), m_props.m_batch_size.get());
if (HAILO_SUCCESS != status) {
return status;
}
@@ -585,7 +585,7 @@ hailo_status HailoNetImpl::configure_network_group()
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting scheduler threshold failed, status = %d", status);
}
auto vstreams = m_net_group_handle->create_vstreams(m_props.m_network_name.get(), m_output_formats);
auto vstreams = m_net_group_handle->create_vstreams(m_props.m_network_name.get(), m_props.m_scheduling_algorithm.get(), m_output_formats);
GST_CHECK_EXPECTED_AS_STATUS(vstreams, m_element, RESOURCE, "Creating vstreams failed, status = %d", status);
GST_HAILOSEND(m_hailosend)->impl->set_input_vstreams(std::move(vstreams->first));

View File

@@ -29,7 +29,10 @@
GST_DEBUG_CATEGORY_STATIC(gst_hailosend_debug_category);
#define GST_CAT_DEFAULT gst_hailosend_debug_category
#define RGB_FEATURES_SIZE (3)
#define RGBA_FEATURES_SIZE (4)
#define YUY2_FEATURES_SIZE (2)
#define NV12_FEATURES_SIZE (3)
#define NV21_FEATURES_SIZE (3)
static void gst_hailosend_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void gst_hailosend_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -61,7 +64,7 @@ static void gst_hailosend_class_init(GstHailoSendClass *klass)
gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, gst_caps_from_string(HAILO_VIDEO_CAPS)));
gst_element_class_set_static_metadata(GST_ELEMENT_CLASS(klass),
"hailosend element", "Hailo/Filter/Video", "Send RGB/YUY2 video to HailoRT", PLUGIN_AUTHOR);
"hailosend element", "Hailo/Filter/Video", "Send RGB/RGBA/YUY2 video to HailoRT", PLUGIN_AUTHOR);
element_class->change_state = GST_DEBUG_FUNCPTR(gst_hailosend_change_state);
@@ -173,7 +176,7 @@ hailo_status HailoSendImpl::write_to_vstreams(void *buf, size_t size)
return HAILO_SUCCESS;
}
GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*direction*/, GstCaps */*caps*/, GstCaps */*filter*/)
GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*direction*/, GstCaps *caps, GstCaps */*filter*/)
{
GST_DEBUG_OBJECT(m_element, "transform_caps");
@@ -190,6 +193,11 @@ GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*
const gchar *format = nullptr;
switch (m_input_vstream_infos[0].format.order) {
case HAILO_FORMAT_ORDER_NHWC:
if (m_input_vstream_infos[0].shape.features == RGBA_FEATURES_SIZE) {
format = "RGBA";
break;
}
/* Fallthrough */
case HAILO_FORMAT_ORDER_NHCW:
case HAILO_FORMAT_ORDER_FCR:
case HAILO_FORMAT_ORDER_F8CR:
@@ -204,6 +212,18 @@ GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*
"Features of input vstream %s is not %d for YUY2 format! (features=%d)", m_input_vstream_infos[0].name, YUY2_FEATURES_SIZE,
m_input_vstream_infos[0].shape.features);
break;
case HAILO_FORMAT_ORDER_NV12:
format = "NV12";
GST_CHECK(NV12_FEATURES_SIZE == m_input_vstream_infos[0].shape.features, NULL, m_element, STREAM,
"Features of input vstream %s is not %d for NV12 format! (features=%d)", m_input_vstream_infos[0].name, NV12_FEATURES_SIZE,
m_input_vstream_infos[0].shape.features);
break;
case HAILO_FORMAT_ORDER_NV21:
format = "NV21";
GST_CHECK(NV21_FEATURES_SIZE == m_input_vstream_infos[0].shape.features, NULL, m_element, STREAM,
"Features of input vstream %s is not %d for NV21 format! (features=%d)", m_input_vstream_infos[0].name, NV21_FEATURES_SIZE,
m_input_vstream_infos[0].shape.features);
break;
default:
GST_ELEMENT_ERROR(m_element, RESOURCE, FAILED,
("Input VStream %s has an unsupported format order! order = %d", m_input_vstream_infos[0].name, m_input_vstream_infos[0].format.order), (NULL));
@@ -211,11 +231,12 @@ GstCaps *HailoSendImpl::get_caps(GstBaseTransform */*trans*/, GstPadDirection /*
}
/* filter against set allowed caps on the pad */
return gst_caps_new_simple("video/x-raw",
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,
NULL);
return gst_caps_intersect(caps, new_caps);
}
void HailoSendImpl::set_input_vstream_infos(std::vector<hailo_vstream_info_t> &&input_vstream_infos)

View File

@@ -22,14 +22,96 @@
#include <sstream>
#include <chrono>
VDeviceManager NetworkGroupHandle::m_vdevice_manager;
std::unordered_set<std::shared_ptr<VDevice>> NetworkGroupHandle::m_vdevices;
NetworkGroupConfigManager NetworkGroupHandle::m_net_group_config_manager;
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)
{
// If passing device_id, than device_count must be 1
const auto device_count = 1;
auto device_id_expected = HailoRTCommon::to_device_id(device_id);
GST_CHECK_EXPECTED(device_id_expected, element, RESOURCE, "Failed parsing device id, status = %d", device_id_expected.status());
hailo_vdevice_params_t params = {};
auto status = hailo_init_vdevice_params(&params);
GST_CHECK_SUCCESS_AS_EXPECTED(status, element, RESOURCE, "Failed hailo_init_vdevice_params, status = %d", status);
params.device_count = device_count;
params.device_ids = &(device_id_expected.value());
params.scheduling_algorithm = scheduling_algorithm;
if (vdevice_key == DEFAULT_VDEVICE_KEY) {
params.group_id = HAILO_UNIQUE_VDEVICE_GROUP_ID;
} else {
auto key = std::to_string(vdevice_key);
params.group_id = key.c_str();
}
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());
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)
{
auto device_id = std::to_string(vdevice_key);
hailo_vdevice_params_t params = {};
auto status = hailo_init_vdevice_params(&params);
GST_CHECK_SUCCESS_AS_EXPECTED(status, element, RESOURCE, "Failed hailo_init_vdevice_params, status = %d", status);
params.device_count = device_count;
params.scheduling_algorithm = scheduling_algorithm;
params.group_id = device_id.c_str();
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());
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_vdevice_params_t params = {};
auto status = hailo_init_vdevice_params(&params);
GST_CHECK_SUCCESS_AS_EXPECTED(status, element, RESOURCE, "Failed hailo_init_vdevice_params, status = %d", status);
params.device_count = device_count;
params.scheduling_algorithm = scheduling_algorithm;
params.group_id = HAILO_UNIQUE_VDEVICE_GROUP_ID;
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());
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)
{
if (!device_id.empty()) {
auto result = create_shared_vdevice(element, device_id, vdevice_key, scheduling_algorithm);
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);
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);
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)
{
auto expected_device = m_vdevice_manager.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);
GST_CHECK_EXPECTED(expected_device, m_element, RESOURCE, "Failed creating vdevice, status = %d", expected_device.status());
return expected_device;
}
@@ -65,12 +147,13 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
return HAILO_SUCCESS;
}
hailo_status NetworkGroupHandle::configure_network_group(const char *net_group_name, uint16_t batch_size)
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);
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, net_group_name, batch_size, m_vdevice, m_hef, net_groups_params_map.value());
auto expected_cng = m_net_group_config_manager.configure_network_group(m_element, m_shared_device_id, scheduling_algorithm,
net_group_name, batch_size, m_vdevice, m_hef, net_groups_params_map.value());
GST_CHECK_EXPECTED_AS_STATUS(expected_cng, m_element, RESOURCE, "Failed configuring network, status = %d", expected_cng.status());
m_cng = expected_cng.release();
@@ -91,14 +174,16 @@ hailo_status NetworkGroupHandle::set_scheduler_threshold(const char *network_nam
}
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> NetworkGroupHandle::create_vstreams(const char *network_name,
const std::vector<hailo_format_with_name_t> &output_formats)
hailo_scheduling_algorithm_t scheduling_algorithm, const std::vector<hailo_format_with_name_t> &output_formats)
{
GST_CHECK(nullptr != network_name, make_unexpected(HAILO_INVALID_ARGUMENT), m_element, RESOURCE, "Got nullptr in network name!");
m_network_name = network_name;
hailo_status status = m_net_group_config_manager.add_network_to_shared_network_group(m_shared_device_id, m_network_name, m_element);
GST_CHECK(HAILO_SUCCESS == status, make_unexpected(status), m_element, RESOURCE,
"Inserting network name to configured networks has failed, status = %d", status);
if (scheduling_algorithm == HAILO_SCHEDULING_ALGORITHM_NONE) {
hailo_status status = m_net_group_config_manager.add_network_to_shared_network_group(m_shared_device_id, m_network_name, m_element);
GST_CHECK(HAILO_SUCCESS == status, make_unexpected(status), m_element, RESOURCE,
"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,
HAILO_DEFAULT_VSTREAM_QUEUE_SIZE, m_network_name);
@@ -151,7 +236,8 @@ Expected<NetworkGroupsParamsMap> NetworkGroupHandle::get_configure_params(Hef &h
hailo_status NetworkGroupHandle::activate_network_group()
{
auto expected_ang = m_net_group_activation_manager.activate_network_group(m_element, m_shared_device_id, m_net_group_name.c_str(), m_batch_size, m_cng);
auto expected_ang = m_net_group_activation_manager.activate_network_group(m_element, m_shared_device_id, m_hef->hash(),
m_net_group_name.c_str(), m_batch_size, m_cng);
GST_CHECK_EXPECTED_AS_STATUS(expected_ang, m_element, RESOURCE, "Failed activating network, status = %d", expected_ang.status());
m_ang = expected_ang.release();
return HAILO_SUCCESS;
@@ -197,7 +283,8 @@ Expected<bool> NetworkGroupHandle::remove_network_group()
// If use count is 2, it means the only references to the activated network group is in the manager and the one here, meaning that we can clear it
// from the manager
if (m_ang.use_count() == 2) {
hailo_status status = m_net_group_activation_manager.remove_activated_network(m_shared_device_id, m_net_group_name.c_str(), m_batch_size);
hailo_status status = m_net_group_activation_manager.remove_activated_network(m_shared_device_id, m_hef->hash(),
m_net_group_name.c_str(), m_batch_size);
GST_CHECK(HAILO_SUCCESS == status, make_unexpected(status), m_element, RESOURCE, "Cound not find activated network group! status = %d", status);
was_network_deactivated = true;
@@ -209,129 +296,45 @@ Expected<bool> NetworkGroupHandle::remove_network_group()
return was_network_deactivated;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_vdevice(const void *element, const std::string &device_id, uint16_t device_count,
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (!device_id.empty()) {
return create_shared_vdevice(element, device_id, scheduling_algorithm);
}
if (DEFAULT_VDEVICE_KEY != vdevice_key) {
return create_shared_vdevice(element, device_count, vdevice_key, scheduling_algorithm);
}
return create_unique_vdevice(element, device_count, scheduling_algorithm);
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
// If passing device_id, than device_count must be 1
const auto device_count = 1;
// If vdevice already exist, use it
auto found_vdevice = get_vdevice(device_id, scheduling_algorithm);
if (found_vdevice.status() != HAILO_NOT_FOUND) {
GST_CHECK_EXPECTED(found_vdevice, element, RESOURCE, "Failed using shared vdevice, status = %d", found_vdevice.status());
return found_vdevice.release();
}
auto device_info_expected = Device::parse_pcie_device_info(device_id);
GST_CHECK_EXPECTED(device_info_expected, element, RESOURCE, "Failed parsing pcie device info, status = %d", device_info_expected.status());
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = &(device_info_expected.value());
params.scheduling_algorithm = scheduling_algorithm;
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());
m_shared_vdevices[device_id] = vdevice_ptr;
m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
auto device_id = std::to_string(device_count) + "-" + std::to_string(vdevice_key);
// If vdevice already exist, use it
auto found_vdevice = get_vdevice(device_id, scheduling_algorithm);
if (found_vdevice.status() != HAILO_NOT_FOUND) {
GST_CHECK_EXPECTED(found_vdevice, element, RESOURCE, "Failed using shared vdevice, status = %d", found_vdevice.status());
return found_vdevice.release();
}
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = nullptr;
params.scheduling_algorithm = scheduling_algorithm;
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());
m_shared_vdevices[device_id] = vdevice_ptr;
m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = nullptr;
params.scheduling_algorithm = scheduling_algorithm;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
// Unique vdevices are not saved in VDeviceManager, only in their hailonet
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
m_unique_vdevices.push_back(vdevice_ptr);
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::get_vdevice(const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
auto found = m_shared_vdevices.find(device_id);
if (found == m_shared_vdevices.end()) {
return make_unexpected(HAILO_NOT_FOUND);
}
// shared_vdevice is found, verify the requested scheduling_algorithm
assert(m_shared_vdevices_scheduling_algorithm.end() != m_shared_vdevices_scheduling_algorithm.find(device_id));
if (scheduling_algorithm != m_shared_vdevices_scheduling_algorithm[device_id]) {
auto status = HAILO_INVALID_OPERATION;
g_warning("Shared vdevice with the same credentials is already exists (%s) but with a different scheduling-algorithm (requested: %d, exists: %d), status = %d",
device_id.c_str(), scheduling_algorithm, m_shared_vdevices_scheduling_algorithm[device_id], status);
return make_unexpected(HAILO_INVALID_OPERATION);
}
auto vdevice_cpy = found->second;
return vdevice_cpy;
}
Expected<std::shared_ptr<ConfiguredNetworkGroup>> NetworkGroupConfigManager::configure_network_group(const void *element, const std::string &device_id,
const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
hailo_scheduling_algorithm_t scheduling_algorithm, const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
NetworkGroupsParamsMap &net_groups_params_map)
{
std::unique_lock<std::mutex> lock(m_mutex);
std::shared_ptr<ConfiguredNetworkGroup> found_cng = get_configured_network_group(device_id, network_group_name, batch_size);
std::shared_ptr<ConfiguredNetworkGroup> found_cng = get_configured_network_group(device_id, hef->hash(), network_group_name, batch_size);
if (nullptr != found_cng) {
return found_cng;
// If cng was already configured
auto infos = found_cng->get_network_infos();
GST_CHECK_EXPECTED(infos, element, RESOURCE, "Failed getting network infos");
if ((infos.release().size() > 1) || (scheduling_algorithm == HAILO_SCHEDULING_ALGORITHM_NONE)) {
// But hailonet is not running all networks in the cng (or if not using scheduler) -
// Do not use multiplexer!
return found_cng;
}
}
auto network_group_list = vdevice->configure(*hef, net_groups_params_map);
GST_CHECK_EXPECTED(network_group_list, element, RESOURCE, "Failed configure device from hef, status = %d",
network_group_list.status());
m_configured_net_groups[get_configure_string(device_id, network_group_name, batch_size)] = network_group_list->at(0);
std::shared_ptr<ConfiguredNetworkGroup> result = nullptr;
for (auto &network_group : network_group_list.value()) {
m_configured_net_groups[get_configure_string(device_id, hef->hash(), network_group->name().c_str(), batch_size)] = network_group;
if (std::string(network_group_name) == network_group->name()) {
result = network_group;
break;
}
}
return std::move(network_group_list->at(0));
if (result) {
return result;
} else if (1 != network_group_list->size()) {
g_error("Configuring HEF with multiple network_groups without providing valid network_group name. passed name = %s, status = %d", network_group_name, HAILO_NOT_FOUND);
return make_unexpected(HAILO_NOT_FOUND);
} else {
return std::move(network_group_list->at(0));
}
}
hailo_status NetworkGroupConfigManager::add_network_to_shared_network_group(const std::string &shared_device_id, const std::string &network_name,
@@ -356,9 +359,9 @@ hailo_status NetworkGroupConfigManager::add_network_to_shared_network_group(cons
}
std::shared_ptr<ConfiguredNetworkGroup> NetworkGroupConfigManager::get_configured_network_group(const std::string &device_id,
const char *network_group_name, uint16_t batch_size)
const std::string &hef_hash, const char *network_group_name, uint16_t batch_size)
{
auto found = m_configured_net_groups.find(get_configure_string(device_id, network_group_name, batch_size));
auto found = m_configured_net_groups.find(get_configure_string(device_id, hef_hash, network_group_name, batch_size));
if (found == m_configured_net_groups.end()) {
return nullptr;
}
@@ -366,7 +369,8 @@ std::shared_ptr<ConfiguredNetworkGroup> NetworkGroupConfigManager::get_configure
return found->second;
}
std::string NetworkGroupConfigManager::get_configure_string(const std::string &device_id, const char *network_group_name, uint16_t batch_size)
std::string NetworkGroupConfigManager::get_configure_string(const std::string &device_id, const std::string &hef_hash,
const char *network_group_name, uint16_t batch_size)
{
const char *EMPTY_FIELD = "NULL,";
std::ostringstream oss;
@@ -377,6 +381,8 @@ std::string NetworkGroupConfigManager::get_configure_string(const std::string &d
oss << device_id << ",";
}
oss << hef_hash << ",";
if (nullptr == network_group_name) {
oss << EMPTY_FIELD;
} else {
@@ -388,11 +394,11 @@ std::string NetworkGroupConfigManager::get_configure_string(const std::string &d
}
Expected<std::shared_ptr<ActivatedNetworkGroup>> NetworkGroupActivationManager::activate_network_group(const void *element, const std::string &device_id,
const char *net_group_name, uint16_t batch_size, std::shared_ptr<ConfiguredNetworkGroup> cng)
const std::string &hef_hash, const char *net_group_name, uint16_t batch_size, std::shared_ptr<ConfiguredNetworkGroup> cng)
{
std::unique_lock<std::mutex> lock(m_mutex);
std::shared_ptr<ActivatedNetworkGroup> found_ang = get_activated_network_group(device_id, net_group_name, batch_size);
std::shared_ptr<ActivatedNetworkGroup> found_ang = get_activated_network_group(device_id, hef_hash, net_group_name, batch_size);
if (nullptr != found_ang) {
return found_ang;
}
@@ -402,15 +408,15 @@ Expected<std::shared_ptr<ActivatedNetworkGroup>> NetworkGroupActivationManager::
activated_network_group.status());
std::shared_ptr<ActivatedNetworkGroup> ang = std::move(activated_network_group.release());
m_activated_net_groups[NetworkGroupConfigManager::get_configure_string(device_id, net_group_name, batch_size)] = ang;
m_activated_net_groups[NetworkGroupConfigManager::get_configure_string(device_id, hef_hash, net_group_name, batch_size)] = ang;
return ang;
}
std::shared_ptr<ActivatedNetworkGroup> NetworkGroupActivationManager::get_activated_network_group(const std::string &device_id,
const char *net_group_name, uint16_t batch_size)
const std::string &hef_hef, const char *net_group_name, uint16_t batch_size)
{
auto found = m_activated_net_groups.find(NetworkGroupConfigManager::get_configure_string(device_id, net_group_name, batch_size));
auto found = m_activated_net_groups.find(NetworkGroupConfigManager::get_configure_string(device_id, hef_hef, net_group_name, batch_size));
if (found == m_activated_net_groups.end()) {
return nullptr;
}
@@ -418,12 +424,12 @@ std::shared_ptr<ActivatedNetworkGroup> NetworkGroupActivationManager::get_activa
return found->second;
}
hailo_status NetworkGroupActivationManager::remove_activated_network(const std::string &device_id, const char *net_group_name,
uint16_t batch_size)
hailo_status NetworkGroupActivationManager::remove_activated_network(const std::string &device_id, const std::string &hef_hash,
const char *net_group_name, uint16_t batch_size)
{
std::unique_lock<std::mutex> lock(m_mutex);
auto found = m_activated_net_groups.find(NetworkGroupConfigManager::get_configure_string(device_id, net_group_name, batch_size));
auto found = m_activated_net_groups.find(NetworkGroupConfigManager::get_configure_string(device_id, hef_hash, net_group_name, batch_size));
if (found == m_activated_net_groups.end()) {
return HAILO_NOT_FOUND;
}

View File

@@ -26,32 +26,7 @@
#include <unordered_map>
#include <mutex>
class VDeviceManager final
{
public:
VDeviceManager() : m_shared_vdevices(), m_shared_vdevices_scheduling_algorithm(), m_unique_vdevices() {}
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);
private:
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm);
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);
Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count,
hailo_scheduling_algorithm_t scheduling_algorithm);
Expected<std::shared_ptr<VDevice>> get_vdevice(const std::string &device_id, hailo_scheduling_algorithm_t scheduling_algorithm);
/* Contains only the shared vdevices (either created by bdf, or with device-count && vdevice-key)
Keys are either "<BDF>" or "<device_count>-<vdevice_key>" */
std::unordered_map<std::string, std::shared_ptr<VDevice>> m_shared_vdevices;
std::unordered_map<std::string, hailo_scheduling_algorithm_t> m_shared_vdevices_scheduling_algorithm; // Used to check that 2 shared vdevices gets the same scheduling-algorithm
std::vector<std::shared_ptr<VDevice>> m_unique_vdevices;
std::mutex m_mutex;
};
#include <unordered_set>
using device_id_t = std::string;
using network_name_t = std::string;
@@ -62,17 +37,18 @@ class NetworkGroupConfigManager final
public:
NetworkGroupConfigManager() : m_configured_net_groups() {}
Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(const void *element, const std::string &device_id,
const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
hailo_scheduling_algorithm_t scheduling_algorithm, const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
NetworkGroupsParamsMap &net_groups_params_map);
hailo_status add_network_to_shared_network_group(const std::string &shared_device_id, const std::string &network_name,
const GstElement *owner_element);
private:
static std::string get_configure_string(const std::string &device_id, const char *network_group_name, uint16_t batch_size);
static std::string get_configure_string(const std::string &device_id, const std::string &hef_hash,
const char *network_group_name, uint16_t batch_size);
friend class NetworkGroupActivationManager;
std::shared_ptr<ConfiguredNetworkGroup> get_configured_network_group(const std::string &device_id, const char *net_group_name,
uint16_t batch_size);
std::shared_ptr<ConfiguredNetworkGroup> get_configured_network_group(const std::string &device_id, const std::string &hef_hash,
const char *net_group_name, uint16_t batch_size);
// TODO: change this map to store only the shared network_groups (used by multiple hailonets with the same vdevices)
std::unordered_map<std::string, std::shared_ptr<ConfiguredNetworkGroup>> m_configured_net_groups;
@@ -85,12 +61,12 @@ class NetworkGroupActivationManager final
public:
NetworkGroupActivationManager() : m_activated_net_groups() {}
Expected<std::shared_ptr<ActivatedNetworkGroup>> activate_network_group(const void *element, const std::string &device_id,
const char *net_group_name, uint16_t batch_size, std::shared_ptr<ConfiguredNetworkGroup> cng);
hailo_status remove_activated_network(const std::string &device_id, const char *net_group_name, uint16_t batch_size);
const std::string &hef_hash, const char *net_group_name, uint16_t batch_size, std::shared_ptr<ConfiguredNetworkGroup> cng);
hailo_status remove_activated_network(const std::string &device_id, const std::string &hef_hash, const char *net_group_name, uint16_t batch_size);
private:
std::shared_ptr<ActivatedNetworkGroup> get_activated_network_group(const std::string &device_id, const char *net_group_name,
uint16_t batch_size);
std::shared_ptr<ActivatedNetworkGroup> get_activated_network_group(const std::string &device_id, const std::string &hef_hash,
const char *net_group_name, uint16_t batch_size);
// TODO: change this map to store only the shared network_groups (used by multiple hailonets with the same vdevices)
std::unordered_map<std::string, std::shared_ptr<ActivatedNetworkGroup>> m_activated_net_groups;
@@ -105,9 +81,9 @@ public:
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);
hailo_status configure_network_group(const char *net_group_name, uint16_t batch_size);
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,
const std::vector<hailo_format_with_name_t> &output_formats);
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();
@@ -123,10 +99,12 @@ public:
private:
Expected<NetworkGroupsParamsMap> get_configure_params(Hef &hef, 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);
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);
static VDeviceManager m_vdevice_manager;
static std::unordered_set<std::shared_ptr<VDevice>> m_vdevices;
static NetworkGroupConfigManager m_net_group_config_manager;
static NetworkGroupActivationManager m_net_group_activation_manager;
const GstElement *m_element;

View File

@@ -19,14 +19,16 @@ def main():
network_group = network_groups[0]
network_group_params = network_group.create_params()
input_vstreams_params = InputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)
output_vstreams_params = OutputVStreamParams.make(network_group, quantized=True, format_type=FormatType.UINT8)
output_vstreams_params = OutputVStreamParams.make(network_group, quantized=True, format_type=FormatType.AUTO)
with InferVStreams(network_group, input_vstreams_params, output_vstreams_params) as infer_pipeline:
input_names_to_shape = {vstream_info.name: vstream_info.shape for vstream_info in hef.get_input_vstream_infos()}
input_data = {name : 1 + np.ndarray([args.num_frames] + list(shape), dtype=np.float32) for name, shape in input_names_to_shape.items()}
with network_group.activate(network_group_params):
_ = infer_pipeline.infer(input_data)
fps = args.num_frames / infer_pipeline.get_hw_time()
print('Inference ran successfully')
print(f'FPS: {fps}')
if __name__ == '__main__':
main()

View File

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

View File

@@ -1,19 +1,11 @@
#!/usr/bin/env python
"""Control operations for the Hailo hardware device."""
import struct
import sys
import signal
from builtins import object
from abc import ABCMeta, abstractmethod
from future.utils import with_metaclass
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.pyhailort.hailo_control_protocol import BoardInformation, CoreInformation, DeviceArchitectureTypes, ExtendedDeviceInformation, HealthInformation
from hailo_platform.pyhailort.power_measurement import SamplingPeriod, AveragingFactor, DvmTypes, PowerMeasurementTypes, MeasurementBufferIndex, _get_buffer_index_enum_member
from hailo_platform.pyhailort.pyhailort import InternalPcieDevice, ExceptionWrapper
from hailo_platform.pyhailort.pyhailort import (Control, InternalPcieDevice, ExceptionWrapper, BoardInformation, # noqa F401
CoreInformation, DeviceArchitectureTypes, ExtendedDeviceInformation, # noqa F401
HealthInformation, SamplingPeriod, AveragingFactor, DvmTypes, # noqa F401
PowerMeasurementTypes, MeasurementBufferIndex) # noqa F401
import hailo_platform.pyhailort._pyhailort as _pyhailort
@@ -27,655 +19,12 @@ class FirmwareUpdateException(Exception):
pass
class HailoControl(with_metaclass(ABCMeta, object)):
class HailoControl(Control):
"""Control object that sends control operations to a Hailo hardware device."""
def __init__(self):
"""Initializes a new HailoControl object."""
self._logger = default_logger()
self._device = None
if sys.platform != "win32":
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGWINCH])
@abstractmethod
def open(self):
"""Initializes the resources needed for using a control device."""
pass
@abstractmethod
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def configure(self, hef, configure_params_by_name={}):
"""
Configures 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. In case of a mismatch with net_groups_names, default params will
be used.
"""
with ExceptionWrapper():
return self._device.configure(hef._hef, configure_params_by_name)
@abstractmethod
def chip_reset(self):
"""Resets the device (chip reset)."""
pass
@abstractmethod
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte.
"""
pass
@abstractmethod
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
pass
class HcpControl(HailoControl):
"""Control object that uses the HCP protocol for controlling the device."""
WORD_SIZE = 4
def __init__(self):
super(HcpControl, self).__init__()
@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.
"""
return self._device_id
def open(self):
"""Initializes the resources needed for using a control device."""
pass
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def chip_reset(self):
"""Resets the device (chip reset)."""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.CHIP)
def nn_core_reset(self):
"""Resets the nn_core."""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.NN_CORE)
def soft_reset(self):
"""reloads the device firmware (soft reset)"""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.SOFT)
def forced_soft_reset(self):
"""reloads the device firmware (forced soft reset)"""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.FORCED_SOFT)
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip. Byte order isn't changed. The core uses little-endian
byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte
"""
with ExceptionWrapper():
return self._device.read_memory(address, data_length)
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip. Byte order isn't changed. The core uses little-endian byte
order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
with ExceptionWrapper():
return self._device.write_memory(address, data_buffer, len(data_buffer))
def power_measurement(self, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Perform a single power measurement on an Hailo chip. It works with the default settings
where the sensor returns a new value every 2.2 ms without averaging the values.
Args:
dvm (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Returns:
float: The measured power. \n
For :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power. For all supported
measurement types, please look at
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
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):
"""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`):
Related conversion time, sensor configuration value. The sensor samples the power
every ``sampling_period`` [ms] and averages every ``averaging_factor`` samples. The
sensor provides a new value every: 2 * sampling_period * averaging_factor [ms]. The
firmware wakes up every ``delay`` [ms] and checks the sensor. If there is a new`
value to read from the sensor, the firmware reads it. Note that the average
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)
def stop_power_measurement(self):
"""Stop performing a long power measurement. Deletes all saved results from the firmware.
Calling the function eliminates the start function settings for the averaging the samples,
and returns to the default values, so the sensor will return a new value every 2.2 ms
without averaging values.
"""
with ExceptionWrapper():
return self._device.stop_power_measurement()
def set_power_measurement(self, buffer_index=MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Set parameters for long power measurement on an Hailo chip.
Args:
buffer_index (:class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex`): Index of the buffer on the firmware the data would be saved at.
Default is :class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0`
dvm (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Note:
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)
def get_power_measurement(self, buffer_index=MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0, should_clear=True):
"""Read measured power from a long power measurement
Args:
buffer_index (:class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex`): Index of the buffer on the firmware the data would be saved at.
Default is :class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0`
should_clear (bool): Flag indicating if the results saved at the firmware will be deleted after reading.
Returns:
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementData`:
Object containing measurement data \n
For :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power.
For all supported measurement types view
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.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)
def _examine_user_config(self):
with ExceptionWrapper():
return self._device.examine_user_config()
def read_user_config(self):
"""Read the user configuration section as binary data.
Returns:
str: User config as a binary buffer.
"""
with ExceptionWrapper():
return self._device.read_user_config()
def write_user_config(self, configuration):
"""Write the user configuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
with ExceptionWrapper():
return self._device.write_user_config(configuration)
def _erase_user_config(self):
with ExceptionWrapper():
return self._device.erase_user_config()
def read_board_config(self):
"""Read the board configuration section as binary data.
Returns:
str: Board config as a binary buffer.
"""
with ExceptionWrapper():
return self._device.read_board_config()
def write_board_config(self, configuration):
"""Write the static confuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
with ExceptionWrapper():
return self._device.write_board_config(configuration)
def identify(self):
"""Gets the Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
with ExceptionWrapper():
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)
return board_information
def core_identify(self):
"""Gets the Core Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
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)
return core_information
def set_fw_logger(self, level, interface_mask):
"""Configure logger level and interface of sending.
Args:
level (FwLoggerLevel): The minimum logger level.
interface_mask (int): Output interfaces (mix of FwLoggerInterface).
"""
with ExceptionWrapper():
return self._device.set_fw_logger(level, interface_mask)
def set_throttling_state(self, should_activate):
"""Change throttling state of temperature protection component.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
with ExceptionWrapper():
return self._device.set_throttling_state(should_activate)
def get_throttling_state(self):
"""Get the current throttling state of temperature protection component.
Returns:
bool: true if temperature throttling is enabled, false otherwise.
"""
with ExceptionWrapper():
return self._device.get_throttling_state()
def _set_overcurrent_state(self, should_activate):
"""Control whether the overcurrent protection is enabled or disabled.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
with ExceptionWrapper():
return self._device._set_overcurrent_state(should_activate)
def _get_overcurrent_state(self):
"""Get the overcurrent protection state.
Returns:
bool: true if overcurrent protection is enabled, false otherwise.
"""
with ExceptionWrapper():
return self._device._get_overcurrent_state()
@staticmethod
def _create_c_i2c_slave(pythonic_slave):
c_slave = _pyhailort.I2CSlaveConfig()
c_slave.endianness = pythonic_slave.endianness
c_slave.slave_address = pythonic_slave.slave_address
c_slave.register_address_size = pythonic_slave.register_address_size
c_slave.bus_index = pythonic_slave.bus_index
return c_slave
def i2c_write(self, slave, register_address, data):
"""Write data to an I2C slave.
Args:
slave (:class:`hailo_platform.pyhailort.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register to which the data will be written.
data (str): The data that will be written.
"""
c_slave = HcpControl._create_c_i2c_slave(slave)
with ExceptionWrapper():
return self._device.i2c_write(c_slave, register_address, data, len(data))
def i2c_read(self, slave, register_address, data_length):
"""Read data from an I2C slave.
Args:
slave (:class:`hailo_platform.pyhailort.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register from which the data will be read.
data_length (int): The number of bytes to read.
Returns:
str: Data read from the I2C slave.
"""
c_slave = HcpControl._create_c_i2c_slave(slave)
with ExceptionWrapper():
return self._device.i2c_read(c_slave, register_address, data_length)
def read_register(self, address):
"""Read the value of a register from a given address.
Args:
address (int): Address to read register from.
Returns:
int: Value of the register
"""
register_value, = struct.unpack('!I', self.read_memory(address, type(self).WORD_SIZE))
return register_value
def set_bit(self, address, bit_index):
"""Set (turn on) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be set.
"""
register_value = self.read_register(address)
register_value |= 1 << bit_index
self.write_memory(address, struct.pack('!I', register_value))
def reset_bit(self, address, bit_index):
"""Reset (turn off) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be reset.
"""
register_value = self.read_register(address)
register_value &= ~(1 << bit_index)
self.write_memory(address, struct.pack('!I', register_value))
def firmware_update(self, firmware_binary, should_reset=True):
"""Update firmware binary on the flash.
Args:
firmware_binary (bytes): firmware binary stream.
should_reset (bool): Should a reset be performed after the update (to load the new firmware)
"""
with ExceptionWrapper():
return self._device.firmware_update(firmware_binary, len(firmware_binary), should_reset)
def second_stage_update(self, second_stage_binary):
"""Update second stage binary on the flash
Args:
second_stage_binary (bytes): second stage binary stream.
"""
with ExceptionWrapper():
return self._device.second_stage_update(second_stage_binary, len(second_stage_binary))
def store_sensor_config(self, section_index, reset_data_size, sensor_type, config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor configuration to Hailo chip flash memory.
Args:
section_index (int): Flash section index to write to. [0-6]
reset_data_size (int): Size of reset configuration.
sensor_type (:class:`~hailo_platform.pyhailort.pyhailort.SensorConfigTypes`): Sensor type.
config_file_path (str): Sensor configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
with ExceptionWrapper():
return self._device.sensor_store_config(section_index, reset_data_size, sensor_type, config_file_path,
config_height, config_width, config_fps, config_name)
def store_isp_config(self, reset_config_size, isp_static_config_file_path, isp_runtime_config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor isp configuration to Hailo chip flash memory.
Args:
reset_config_size (int): Size of reset configuration.
isp_static_config_file_path (str): Sensor isp static configuration file path.
isp_runtime_config_file_path (str): Sensor isp runtime configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
with ExceptionWrapper():
return self._device.store_isp_config(reset_config_size, config_height, config_width,
config_fps, isp_static_config_file_path, isp_runtime_config_file_path, config_name)
def get_sensor_sections_info(self):
"""Get sensor sections info from Hailo chip flash memory.
Returns:
Sensor sections info read from the chip flash memory.
"""
with ExceptionWrapper():
return self._device.sensor_get_sections_info()
def sensor_set_generic_i2c_slave(self, slave_address, register_address_size, bus_index, should_hold_bus, endianness):
"""Set a generic I2C slave for sensor usage.
Args:
sequence (int): Request/response sequence.
slave_address (int): The address of the I2C slave.
register_address_size (int): The size of the offset (in bytes).
bus_index (int): The number of the bus the I2C slave is behind.
should_hold_bus (bool): Hold the bus during the read.
endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`):
Big or little endian.
"""
with ExceptionWrapper():
return self._device.sensor_set_generic_i2c_slave(slave_address, register_address_size, bus_index, should_hold_bus, endianness)
def set_sensor_i2c_bus_index(self, sensor_type, i2c_bus_index):
"""Set the I2C bus to which the sensor of the specified type is connected.
Args:
sensor_type (:class:`~hailo_platform.pyhailort.pyhailort.SensorConfigTypes`): The sensor type.
i2c_bus_index (int): The I2C bus index of the sensor.
"""
with ExceptionWrapper():
return self._device.sensor_set_i2c_bus_index(sensor_type, i2c_bus_index)
def load_and_start_sensor(self, section_index):
"""Load the configuration with I2C in the section index.
Args:
section_index (int): Flash section index to load config from. [0-6]
"""
with ExceptionWrapper():
return self._device.sensor_load_and_start_config(section_index)
def reset_sensor(self, section_index):
"""Reset the sensor that is related to the section index config.
Args:
section_index (int): Flash section index to reset. [0-6]
"""
with ExceptionWrapper():
return self._device.sensor_reset(section_index)
def wd_enable(self, cpu_id):
"""Enable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.wd_enable(cpu_id)
def wd_disable(self, cpu_id):
"""Disable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.wd_disable(cpu_id)
def wd_config(self, cpu_id, wd_cycles, wd_mode):
"""Configure a firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
wd_cycles (int): number of cycles until watchdog is triggered.
wd_mode (int): 0 - HW/SW mode, 1 - HW only mode
"""
with ExceptionWrapper():
return self._device.wd_config(cpu_id, wd_cycles, wd_mode)
def previous_system_state(self, cpu_id):
"""Read the FW previous system state.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.previous_system_state(cpu_id)
def get_chip_temperature(self):
"""Returns the latest temperature measurements from the 2 internal temperature sensors of the Hailo chip.
Returns:
:class:`~hailo_platform.pyhailort.pyhailort.TemperatureInfo`:
Temperature in celsius of the 2 internal temperature sensors (TS), and a sample
count (a running 16-bit counter)
"""
with ExceptionWrapper():
return self._device.get_chip_temperature()
def get_extended_device_information(self):
with ExceptionWrapper():
response = self._device.get_extended_device_information()
device_information = ExtendedDeviceInformation(response.neural_network_core_clock_rate,
response.supported_features, response.boot_source, response.lcs, response.soc_id, response.eth_mac_address , response.unit_level_tracking_id, response.soc_pm_values)
return device_information
def _get_health_information(self):
with ExceptionWrapper():
response = self._device._get_health_information()
health_information = HealthInformation(response.overcurrent_protection_active, response.current_overcurrent_zone, response.red_overcurrent_threshold,
response.orange_overcurrent_threshold, response.temperature_throttling_active, response.current_temperature_zone, response.current_temperature_throttling_level,
response.temperature_throttling_levels, response.orange_temperature_threshold, response.orange_hysteresis_temperature_threshold,
response.red_temperature_threshold, response.red_hysteresis_temperature_threshold)
return health_information
def set_pause_frames(self, rx_pause_frames_enable):
"""Enable/Disable Pause frames.
Args:
rx_pause_frames_enable (bool): False for disable, True for enable.
"""
with ExceptionWrapper():
return self._device.set_pause_frames(rx_pause_frames_enable)
def test_chip_memories(self):
"""test all chip memories using smart BIST
"""
with ExceptionWrapper():
return self._device.test_chip_memories()
def _get_device_handle(self):
return self._device
class UdpHcpControl(HcpControl):
"""Control object that uses a HCP over UDP controller interface."""
@@ -688,58 +37,32 @@ class UdpHcpControl(HcpControl):
response_timeout_seconds (float, optional): Number of seconds to wait until a response is received.
ignore_socket_errors (bool, optional): Ignore socket error (might be usefull for debugging).
"""
super(UdpHcpControl, self).__init__()
# In the C API we define the total amount of attempts, instead of the amount of retries.
max_number_of_attempts = retries + 1
response_timeout_milliseconds = int(response_timeout_seconds * 1000)
if device is None:
with ExceptionWrapper():
self.device = _pyhailort.Device.create_eth(remote_ip, remote_control_port,
device = _pyhailort.Device.create_eth(remote_ip, remote_control_port,
response_timeout_milliseconds, max_number_of_attempts)
else:
self._device = device.device
self._device_id = self.identify()
# Needs to get the _pyhailort.Device object
device = device.device
super().__init__(device)
class PcieHcpControl(HcpControl):
"""Control object that uses a HCP over PCIe controller interface."""
def __init__(self, device=None, device_info=None):
"""Initializes a new HailoPcieController object."""
super(PcieHcpControl, self).__init__()
if device_info is None:
device_info = InternalPcieDevice.scan_devices()[0]
if device is None:
with ExceptionWrapper():
self._device = _pyhailort.Device.create_pcie(device_info)
device = _pyhailort.Device.create_pcie(device_info)
else:
self._device = device.device
self._device_id = self.identify()
def set_notification_callback(self, callback_func, notification_id, opaque):
"""Set a callback function to be called when a notification is received.
# Needs to get the _pyhailort.Device object
device = device.device
Args:
callback_func (function): Callback function with the parameters (device, notification, opaque).
Note that throwing exceptions is not supported and will cause the program to terminate with an error!
notification_id (NotificationId): Notification ID to register the callback to.
opauqe (object): User defined data.
Note:
The notifications thread is started and closed in the use_device() context, so
notifications can only be received there.
"""
with ExceptionWrapper():
return self._device.set_notification_callback(callback_func, notification_id, opaque)
def remove_notification_callback(self, notification_id):
"""Remove a notification callback which was already set.
Args:
notification_id (NotificationId): Notification ID to remove the callback from.
"""
with ExceptionWrapper():
return self._device.remove_notification_callback(notification_id)
super().__init__(device)

View File

@@ -4,320 +4,9 @@
:synopsis: Implements a Hailo Control Protocol message.
"""
from builtins import object
from enum import Enum, IntEnum
import struct
# Supported protocol and Firmware version of current SDK.
SUPPORTED_PROTOCOL_VERSION = 2
SUPPORTED_FW_MAJOR = 4
SUPPORTED_FW_MINOR = 8
SUPPORTED_FW_REVISION = 1
MEGA_MULTIPLIER = 1000.0 * 1000.0
class HailoControlProtocolException(Exception):
pass
class DeviceArchitectureTypes(IntEnum):
HAILO8_A0 = 0
HAILO8_B0 = 1
MERCURY_CA = 2
def __str__(self):
return self.name
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):
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.logger_version = logger_version
self.board_name = board_name
self.is_release = is_release
self.device_architecture = DeviceArchitectureTypes(device_architecture)
self.serial_number = serial_number
self.part_number = part_number
self.product_name = product_name
def _string_field_str(self, string_field):
# Return <Not Configured> if the string field is empty
return string_field.rstrip('\x00') or "<Not Configured>"
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Control Protocol Version: {}\n' \
'Firmware Version: {}\n' \
'Logger Version: {}\n' \
'Board Name: {}\n' \
'Device Architecture: {}\n' \
'Serial Number: {}\n' \
'Part Number: {}\n' \
'Product Name: {}\n'.format(
self.protocol_version,
self.firmware_version,
self.logger_version,
self.board_name.rstrip('\x00'),
str(self.device_architecture),
self._string_field_str(self.serial_number),
self._string_field_str(self.part_number),
self._string_field_str(self.product_name))
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
@staticmethod
def get_hw_arch_str(device_arch):
if device_arch == DeviceArchitectureTypes.HAILO8_B0:
return 'hailo8'
elif device_arch == DeviceArchitectureTypes.MERCURY_CA:
return 'mercury'
else:
raise HailoControlProtocolException("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)
self.is_release = is_release
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Core Firmware Version: {}'.format(
self.firmware_version)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class TemperatureThrottlingLevel(object):
def __init__(self, level_number, temperature_threshold, hysteresis_temperature_threshold, throttling_nn_clock_freq):
self.level_number = level_number
self.temperature_threshold = temperature_threshold
self.hysteresis_temperature_threshold = hysteresis_temperature_threshold
self.throttling_nn_clock_freq = throttling_nn_clock_freq
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Temperature Throttling Level {}: \n' \
'Temperature Threshold: {}\n' \
'Hysteresis Temperature Threshold: {}\n' \
'Throttling NN Clock Frequency: {}\n' \
.format(self.level_number, self.temperature_threshold, self.hysteresis_temperature_threshold, self.throttling_nn_clock_freq)
def __repr__(self):
return self.__str__()
class HealthInformation(object):
def __init__(self, overcurrent_protection_active, current_overcurrent_zone, red_overcurrent_threshold, orange_overcurrent_threshold,
temperature_throttling_active, current_temperature_zone, current_temperature_throttling_level,
temperature_throttling_levels, orange_temperature_threshold, orange_hysteresis_temperature_threshold,
red_temperature_threshold, red_hysteresis_temperature_threshold):
self.overcurrent_protection_active = overcurrent_protection_active
self.current_overcurrent_zone = current_overcurrent_zone
self.red_overcurrent_threshold = red_overcurrent_threshold
self.orange_overcurrent_threshold = orange_overcurrent_threshold
self.temperature_throttling_active = temperature_throttling_active
self.current_temperature_zone = current_temperature_zone
self.current_temperature_throttling_level = current_temperature_throttling_level
self.orange_temperature_threshold = orange_temperature_threshold
self.orange_hysteresis_temperature_threshold = orange_hysteresis_temperature_threshold
self.red_temperature_threshold = red_temperature_threshold
self.red_hysteresis_temperature_threshold = red_hysteresis_temperature_threshold
# Add TemperatureThrottlingLevel in case it has new throttling_nn_clock_freq. level_number can be used as only last
# levels can be with the same freq
self.temperature_throttling_levels = []
if self.temperature_throttling_active:
throttling_nn_clock_frequencies = []
for level_number, temperature_throttling_level in enumerate(temperature_throttling_levels):
if temperature_throttling_level.throttling_nn_clock_freq not in throttling_nn_clock_frequencies:
throttling_nn_clock_frequencies.append(temperature_throttling_level.throttling_nn_clock_freq)
self.temperature_throttling_levels.append(TemperatureThrottlingLevel(level_number,
temperature_throttling_level.temperature_threshold,
temperature_throttling_level.hysteresis_temperature_threshold,
temperature_throttling_level.throttling_nn_clock_freq))
def __repr__(self):
return self.__str__()
def __str__(self):
"""Returns:
str: Human readable string.
"""
temperature_throttling_levels_str = "\n".join(["\n\n{}\n".format(str(temperature_throttling_level)) for temperature_throttling_level in self.temperature_throttling_levels]) \
if self.temperature_throttling_active else "<Temperature throttling is disabled>"
return 'Overcurrent Protection Active: {}\n' \
'Overcurrent Protection Current Overcurrent Zone: {}\n' \
'Overcurrent Protection Red Threshold: {}\n' \
'Overcurrent Protection Orange Threshold: {}\n' \
'Temperature Protection Red Threshold: {}\n' \
'Temperature Protection Red Hysteresis Threshold: {}\n' \
'Temperature Protection Orange Threshold: {}\n' \
'Temperature Protection Orange Hysteresis Threshold: {}\n' \
'Temperature Protection Throttling State: {}\n' \
'Temperature Protection Current Zone: {}\n' \
'Temperature Protection Current Throttling Level: {}\n' \
'Temperature Protection Throttling Levels: {}' \
.format(self.overcurrent_protection_active, self.current_overcurrent_zone, self.red_overcurrent_threshold,
self.orange_overcurrent_threshold, self.red_temperature_threshold,
self.red_hysteresis_temperature_threshold, self.orange_temperature_threshold,
self.orange_hysteresis_temperature_threshold, self.temperature_throttling_active,
self.current_temperature_zone, self.current_temperature_throttling_level, temperature_throttling_levels_str)
class ExtendedDeviceInformation(object):
def __init__(self, neural_network_core_clock_rate, supported_features, boot_source, lcs, soc_id, eth_mac_address, unit_level_tracking_id, soc_pm_values):
self.neural_network_core_clock_rate = neural_network_core_clock_rate
self.supported_features = SupportedFeatures(supported_features)
self.boot_source = boot_source
self.lcs = lcs
self.soc_id = soc_id
self.eth_mac_address = eth_mac_address
self.unit_level_tracking_id = unit_level_tracking_id
self.soc_pm_values = soc_pm_values
def __str__(self):
"""Returns:
str: Human readable string.
"""
string = 'Neural Network Core Clock Rate: {}MHz\n' \
'{}' \
'Boot source: {}\n' \
'LCS: {}\n'.format(
self.neural_network_core_clock_rate / MEGA_MULTIPLIER,
str(self.supported_features),
str(self.boot_source.name),
str(self.lcs))
if any(self.soc_id):
string += 'SoC ID: ' + (self.soc_id.hex())
if any(self.eth_mac_address):
string += '\nMAC Address: ' + (":".join("{:02X}".format(i) for i in self.eth_mac_address))
if any(self.unit_level_tracking_id):
string += '\nULT ID: ' + (self.unit_level_tracking_id.hex())
if any(self.soc_pm_values):
string += '\nPM Values: ' + (self.soc_pm_values.hex())
return string
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class HailoFirmwareMode(Enum):
"""Indication that firmware version is stable and official """
DEVELOP = 'develop'
RELEASE = 'release'
class HailoFirmwareType(Enum):
"""Indication the firmware type """
CORE = 'core'
APP = 'app'
class HailoFirmwareVersion(object):
"""Represents a Hailo chip firmware version."""
DEV_BIT = 0x80000000
CORE_BIT = 0x08000000
FW_VERSION_FORMAT = '<III'
def __init__(self, firmware_version_buffer, is_release, 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
"""
self.major, self.minor, self.revision = struct.unpack(
self.FW_VERSION_FORMAT,
firmware_version_buffer)
self.fw_type = fw_type
self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
self.revision &= ~(self.CORE_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)
@classmethod
def construct_from_params(cls, major, minor, revision, is_release, 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)
@property
def comparable_value(self):
"""A value that could be compared to other firmware versions."""
return (self.major << 64) + (self.minor << 32) + (self.revision)
def __hash__(self):
return self.comparable_value
def __eq__(self, other):
return self.comparable_value == other.comparable_value
# TODO: Required for Python2 BW compatibility (SDK-10038)
# This impl' comes by default in Python3
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self.comparable_value < other.comparable_value
def check_protocol_compatibility(self, other):
return ((self.major == other.major) and (self.minor == other.minor))
class SupportedFeatures(object):
def __init__(self, supported_features):
self.ethernet = supported_features.ethernet
self.mipi = supported_features.mipi
self.pcie = supported_features.pcie
self.current_monitoring = supported_features.current_monitoring
self.mdio = supported_features.mdio
def _feature_str(self, feature_name, is_feature_enabled):
return '{}: {}\n'.format(feature_name, 'Enabled' if is_feature_enabled else 'Disabled')
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Device supported features: \n' + \
self._feature_str('Ethernet', self.ethernet) + \
self._feature_str('MIPI', self.mipi) + \
self._feature_str('PCIE', self.pcie) + \
self._feature_str('Current Monitoring', self.current_monitoring) + \
self._feature_str('MDIO', self.mdio)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
def _is_feature_enabled(self, feature):
return (self.supported_features & feature) != 0
from hailo_platform.pyhailort.pyhailort import (SUPPORTED_PROTOCOL_VERSION, SUPPORTED_FW_MAJOR, SUPPORTED_FW_MINOR, # noqa F401
SUPPORTED_FW_REVISION, DeviceArchitectureTypes, ExtendedDeviceInformation, BoardInformation, # noqa F401
CoreInformation, TemperatureThrottlingLevel, HealthInformation, HailoFirmwareMode, HailoFirmwareType, # noqa F401
HailoFirmwareVersion, SupportedFeatures) # noqa F401
import warnings
warnings.warn('Importing hailo_control_protocol directly is deprecated. One should use direct hailo_platform instead')

View File

@@ -10,9 +10,9 @@ from contextlib import contextmanager
from hailo_platform.pyhailort.control_object import UdpHcpControl, PcieHcpControl
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.pyhailort.hailo_control_protocol import BoardInformation
from hailo_platform.pyhailort.pyhailort import ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice, HailoRTTransformUtils, HailoUdpScan, HailoRTException
from hailo_platform.pyhailort.pyhailort import (ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice,
HailoRTTransformUtils, HailoUdpScan, HailoRTException, BoardInformation)
class InferenceTargets(object):
@@ -385,7 +385,7 @@ class EthernetDevice(HailoChipObject):
self._open_device()
self._id = "{}".format(self._remote_ip)
identity = self._control_object._device_id
identity = self._control_object._identify_info
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod
@@ -450,7 +450,7 @@ class PcieDevice(HailoChipObject):
# At this point self._device_info is already initialized
self._id = "{}".format(self._device_info)
identity = self._control_object._device_id
identity = self._control_object._identify_info
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod

View File

@@ -1,14 +1,5 @@
from hailo_platform.pyhailort.pyhailort import (DvmTypes, PowerMeasurementTypes, # noqa F401
SamplingPeriod, AveragingFactor,
HailoPowerMeasurementUtils, MeasurementBufferIndex, HailoRTException)
# https://github.com/pybind/pybind11/issues/253
import re
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")
SamplingPeriod, AveragingFactor,
HailoPowerMeasurementUtils, MeasurementBufferIndex, HailoRTException)
import warnings
warnings.warn('Importing power_measurements directly is deprecated. One should use direct hailo_platform instead')

View File

@@ -45,7 +45,8 @@
"temperature_orange_threshold": {"size": 1, "deserialize_as": "int"},
"temperature_orange_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
"temperature_throttling_enable": {"size": 1, "deserialize_as": "bool"},
"overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"}
"deprecated__overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"},
"overcurrent_throttling_enable": {"size": 1, "deserialize_as": "bool"}
}
},
"control":

View File

@@ -1,5 +1,11 @@
import os
import subprocess
import pathlib
import sys
import hailo_platform
from hailo_platform.tools.hailocli.base_utils import HailortCliUtil
import pkg_resources
"""
HailoRTCLI matching commands in Hailo-CLI tool.
@@ -67,4 +73,63 @@ class SSBUpdaterCLI(HailortCliUtil):
class UDPRateLimiterCLI(HailortCliUtil):
"""CLI tool for UDP rate limitation."""
def __init__(self, parser):
super().__init__(parser, 'udp-rate-limiter')
super().__init__(parser, 'udp-rate-limiter')
class TutorialRequired(Exception):
pass
class TutorialRunnerCLI():
TUTORIALS_DIR = os.path.join(pathlib.Path(hailo_platform.__file__).parent.parent, 'hailo_tutorials/notebooks/')
TUTORIALS_REQUIREMENTS = ["jupyter"]
ERROR_MSG = """
Jupyter or one of its dependencies are not installed in this Python environment. These packages
are not mandatory for pyHailoRT itself, but they are required in order to run the Python API tutorial
notebooks. Please run the following command to install the missing Python packages:
"""
def __init__(self, parser):
parser.add_argument('--ip', type=str, default=None, help='the ip parameter passed to jupyter-notebook.')
parser.add_argument('--port', type=str, default=None, help='the port parameter passed to jupyter-notebook.')
parser.set_defaults(func=self.run)
def _check_requirements(self):
missing_pkgs = []
working_set = pkg_resources.WorkingSet()
for req in self.TUTORIALS_REQUIREMENTS:
try:
working_set.require(req)
except pkg_resources.DistributionNotFound:
missing_pkgs.append(req)
if missing_pkgs:
sys.tracebacklimit = 0
raise TutorialRequired(f"\n{self.ERROR_MSG}\n {'; '.join([f'pip install {pkg}' for pkg in missing_pkgs])}")
def run(self, args):
self._check_requirements()
exec_string = f'jupyter-notebook {self.TUTORIALS_DIR}'
if args.ip is not None:
exec_string += f" --ip={args.ip}"
if args.port is not None:
exec_string += f" --port={args.port}"
return subprocess.run(
exec_string,
shell=True,
check=True,
env=os.environ.copy(),
)
class ParseHEFCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'parse-hef')
class MonitorCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'monitor')

View File

@@ -8,7 +8,8 @@ import hailo_platform
from hailo_platform.tools.hailocli.base_utils import HailortCliUtil, Helper, HailortCliUtilError
from hailo_platform.tools.hailocli.hailocli_commands import (FWUpdaterCLI, SSBUpdaterCLI, ControlCommandCLI, ScanCommandCLI,
LoggerCommandCLI, MeasurePowerCommandCLI, RunCommandCLI, SensorConfigCommandCLI,
FWConfigCommandCLI, BenchmarkCommandCLI, UDPRateLimiterCLI)
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:
@@ -18,19 +19,23 @@ class PlatformCommands:
'fw-update': ('Firmware update tool', FWUpdaterCLI),
'ssb-update': ('Second stage boot update tool', SSBUpdaterCLI),
'fw-config': ('Firmware configuration tool', FWConfigCommandCLI),
'udp-limiter': ('UDP rate limitation tool', UDPRateLimiterCLI),
'udp': ('Alias to udp-limiter', UDPRateLimiterCLI),
'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),
'scan': ('Scans for devices (Ethernet or PCIE)', ScanCommandCLI),
'sensor-config': ('Sensor configuration tool', SensorConfigCommandCLI),
'run': ('Run a compiled network', RunCommandCLI),
'benchmark': ('Measure basic performance on compiled network', BenchmarkCommandCLI),
'monitor': ("Monitor of networks - Presents information about the running networks. To enable monitor, set in the application process the environment variable 'SCHEDULER_MONITOR' to 1.", MonitorCommandCLI),
'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),
}
def __init__(self):
self.parser = argparse.ArgumentParser(description=self._get_description())
self.parser = argparse.ArgumentParser(description=self._get_generic_description())
self.subparsers = self.parser.add_subparsers(help='Hailo utilities aimed to help with everything you need')
self.COMMANDS = {}
self.COMMANDS.update(type(self).PLATFORM_COMMANDS)
@@ -46,6 +51,10 @@ class PlatformCommands:
def _get_description():
return 'Hailo Platform SW v{} command line utilities'.format(hailo_platform.__version__)
@staticmethod
def _get_generic_description():
return 'Hailo Command Line Utility'
def run(self):
argv = sys.argv[1:]
return self._run(argv)
@@ -70,6 +79,10 @@ 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

@@ -24,7 +24,7 @@
"core HW, using HailoRT. This way we can use the Hailo hardware without Tensorflow, and\n",
"even without the Hailo SDK (after the HEF is built).\n",
"\n",
"An HEF is Hailos binary format for neural networks. The HEF files contain:\n",
"An HEF is Hailo's binary format for neural networks. The HEF files contain:\n",
"\n",
"* Target HW configuration\n",
"* Weights\n",

View File

@@ -68,6 +68,6 @@ if __name__ == "__main__":
"linux_aarch64",
],
url="https://hailo.ai/",
version="4.8.1",
version="4.10.0",
zip_safe=False,
)

View File

@@ -19,6 +19,7 @@ pybind11_add_module(_pyhailort
device_api.cpp
hef_api.cpp
vstream_api.cpp
quantization_api.cpp
${HAILORT_COMMON_CPP_SOURCES}
)

View File

@@ -14,6 +14,20 @@
namespace hailort
{
std::vector<std::string> DeviceWrapper::scan()
{
auto device_ids = Device::scan();
VALIDATE_EXPECTED(device_ids);
return device_ids.release();
}
DeviceWrapper DeviceWrapper::create(const std::string &device_id)
{
auto device = Device::create(device_id);
VALIDATE_EXPECTED(device);
return DeviceWrapper(device.release());
}
DeviceWrapper DeviceWrapper::create_pcie(hailo_pcie_device_info_t &device_info)
{
auto device = Device::create_pcie(device_info);
@@ -22,7 +36,7 @@ DeviceWrapper DeviceWrapper::create_pcie(hailo_pcie_device_info_t &device_info)
return DeviceWrapper(device.release());
}
DeviceWrapper DeviceWrapper::create_eth(std::string &device_address, uint16_t port,
DeviceWrapper DeviceWrapper::create_eth(const std::string &device_address, uint16_t port,
uint32_t timeout_milliseconds, uint8_t max_number_of_attempts)
{
hailo_eth_device_info_t device_info = {};
@@ -52,14 +66,6 @@ DeviceWrapper DeviceWrapper::create_eth(std::string &device_address, uint16_t po
return DeviceWrapper(device.release());
}
DeviceWrapper DeviceWrapper::create_core()
{
auto device = Device::create_core_device();
VALIDATE_EXPECTED(device);
return DeviceWrapper(device.release());
}
void DeviceWrapper::release()
{
m_device.reset();
@@ -458,13 +464,21 @@ py::bytes DeviceWrapper::direct_read_memory(uint32_t address, uint32_t size)
return py::bytes(buffer_str);
}
const char *DeviceWrapper::get_dev_id() const
{
return device().get_dev_id();
}
void DeviceWrapper::add_to_python_module(py::module &m)
{
py::class_<DeviceWrapper>(m, "Device")
// Scan
.def("scan", &DeviceWrapper::scan)
// C'tors
.def("create", &DeviceWrapper::create)
.def("create_pcie", &DeviceWrapper::create_pcie)
.def("create_eth", &DeviceWrapper::create_eth)
.def("create_core", &DeviceWrapper::create_core)
.def("release", &DeviceWrapper::release)
//HEF
@@ -514,6 +528,7 @@ void DeviceWrapper::add_to_python_module(py::module &m)
.def("_get_overcurrent_state", &DeviceWrapper::get_overcurrent_state)
.def("direct_write_memory", &DeviceWrapper::direct_write_memory)
.def("direct_read_memory", &DeviceWrapper::direct_read_memory)
.def_property_readonly("device_id", &DeviceWrapper::get_dev_id)
.def("read_log", &DeviceWrapper::read_log, py::return_value_policy::move)
.def("set_notification_callback", &DeviceWrapper::set_notification_callback)

View File

@@ -44,10 +44,11 @@ class DeviceWrapper final
{
public:
static std::vector<std::string> scan();
static DeviceWrapper create(const std::string &device_id);
static DeviceWrapper create_pcie(hailo_pcie_device_info_t &device_info);
static DeviceWrapper create_eth(std::string &device_address, uint16_t port,
static DeviceWrapper create_eth(const std::string &device_address, uint16_t port,
uint32_t timeout_milliseconds, uint8_t max_number_of_attempts);
static DeviceWrapper create_core();
void release();
Device& device()
@@ -56,6 +57,12 @@ public:
return *(m_device.get());
}
const Device& device() const
{
VALIDATE_NOT_NULL(m_device);
return *(m_device.get());
}
Device& operator*() // Used for control_internals
{
return device();
@@ -117,6 +124,7 @@ public:
py::bytes read_log(size_t byte_count, hailo_cpu_id_t cpu_id);
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;
static void add_to_python_module(py::module &m);

View File

@@ -257,7 +257,7 @@ void HefWrapper::initialize_python_module(py::module &m)
py::class_<ConfiguredNetworkGroup>(m, "ConfiguredNetworkGroup")
.def("get_name", [](ConfiguredNetworkGroup& self)
{
return self.get_network_group_name();
return self.name();
})
.def("get_default_streams_interface", [](ConfiguredNetworkGroup& self)
{

View File

@@ -21,7 +21,17 @@ target_include_directories(_pyhailort_internal
$<BUILD_INTERFACE:${DRIVER_INC_DIR}>
)
target_link_libraries(_pyhailort_internal PRIVATE libhailort hef_proto spdlog::spdlog readerwriterqueue microprofile)
target_link_libraries(_pyhailort_internal PRIVATE
libhailort
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)
endif()
if(WIN32)
target_link_libraries(_pyhailort_internal PRIVATE Ws2_32 Iphlpapi Shlwapi)
endif()

View File

@@ -183,7 +183,7 @@ PYBIND11_MODULE(_pyhailort_internal, m) {
return self.format.order;
})
.def_readonly("direction", &LayerInfo::direction)
.def_readonly("sys_index", &LayerInfo::index)
.def_readonly("sys_index", &LayerInfo::stream_index)
.def_readonly("name", &LayerInfo::name)
.def_readonly("quant_info", &LayerInfo::quant_info)
// For backwards compatibility (accessing qp through layer_info directly)
@@ -207,8 +207,14 @@ PYBIND11_MODULE(_pyhailort_internal, m) {
.def_readonly("height_gcd", &LayerInfo::height_gcd)
.def_readonly("height_ratios", &LayerInfo::height_ratios)
.def_readonly("buffer_indices", &LayerInfo::buffer_indices)
.def_readonly("core_bytes_per_buffer", &LayerInfo::core_bytes_per_buffer)
.def_readonly("core_buffers_per_frame", &LayerInfo::core_buffers_per_frame)
.def_property_readonly("core_bytes_per_buffer", [](LayerInfo& self)
{
return self.nn_stream_config.core_bytes_per_buffer;
})
.def_property_readonly("core_buffers_per_frame", [](LayerInfo& self)
{
return self.nn_stream_config.core_buffers_per_frame;
})
.def_readonly("network_name", &LayerInfo::network_name)
;
}

View File

@@ -14,6 +14,7 @@ using namespace std;
#include "vstream_api.hpp"
#include "vdevice_api.hpp"
#include "device_api.hpp"
#include "quantization_api.hpp"
#include "utils.hpp"
#include "utils.h"
@@ -73,7 +74,13 @@ std::list<std::string> UdpScan::scan_devices(char* interface_name, uint32_t time
return device_addresses;
}
std::vector<hailo_pcie_device_info_t> scan_pcie_devices(void)
class PcieScan {
public:
PcieScan() = default;
std::vector<hailo_pcie_device_info_t> scan_devices(void);
};
std::vector<hailo_pcie_device_info_t> PcieScan::scan_devices(void)
{
auto scan_result = Device::scan_pcie();
VALIDATE_EXPECTED(scan_result);
@@ -81,242 +88,6 @@ std::vector<hailo_pcie_device_info_t> scan_pcie_devices(void)
return scan_result.release();
}
// Quantization
void dequantize_output_buffer_from_uint8(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::dequantize_output_buffer<uint8_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer<uint16_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_from_uint16(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer<uint16_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_from_float32(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, float32_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_from_uint8_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::dequantize_output_buffer_in_place<uint8_t, uint8_t>(
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer_in_place<uint16_t, uint8_t>(
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, uint8_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_from_uint16_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer_in_place<uint16_t, uint16_t>(
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, uint16_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_from_float32_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, float32_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer_in_place(py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
dequantize_output_buffer_from_uint8_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
dequantize_output_buffer_from_uint16_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
dequantize_output_buffer_from_float32_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void dequantize_output_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
dequantize_output_buffer_from_uint8(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
dequantize_output_buffer_from_uint16(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
dequantize_output_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void quantize_input_buffer_from_uint8(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<uint8_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type uint8 to dst format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void quantize_input_buffer_from_uint16(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<uint16_t, uint8_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::quantize_input_buffer<uint16_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void quantize_input_buffer_from_float32(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<float32_t, uint8_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::quantize_input_buffer<float32_t, uint16_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void quantize_input_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
quantize_input_buffer_from_uint8(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
quantize_input_buffer_from_uint16(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
quantize_input_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported for src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
std::string get_status_message(uint32_t status_in)
{
auto status_str = hailo_get_status_message((hailo_status)status_in);
@@ -413,10 +184,9 @@ PYBIND11_MODULE(_pyhailort, m) {
validate_versions_match();
m.def("get_status_message", &get_status_message);
m.def("scan_pcie_devices", &scan_pcie_devices);
m.def("dequantize_output_buffer_in_place", &dequantize_output_buffer_in_place);
m.def("dequantize_output_buffer", &dequantize_output_buffer);
m.def("quantize_input_buffer", &quantize_input_buffer);
m.def("dequantize_output_buffer_in_place", &QuantizationBindings::dequantize_output_buffer_in_place);
m.def("dequantize_output_buffer", &QuantizationBindings::dequantize_output_buffer);
m.def("quantize_input_buffer", &QuantizationBindings::quantize_input_buffer);
m.def("get_format_data_bytes", &HailoRTCommon::get_format_data_bytes);
m.def("get_dtype", &HailoRTBindingsCommon::get_dtype);
@@ -443,6 +213,10 @@ PYBIND11_MODULE(_pyhailort, m) {
.def(py::init<>())
.def("scan_devices", &UdpScan::scan_devices)
;
py::class_<PcieScan>(m, "PcieScan")
.def(py::init<>())
.def("scan_devices", &PcieScan::scan_devices)
;
py::class_<PowerMeasurementData>(m, "PowerMeasurementData")
.def_readonly("average_value", &PowerMeasurementData::m_average_value, "float, The average value of the samples that were sampled")
@@ -456,7 +230,8 @@ PYBIND11_MODULE(_pyhailort, m) {
py::enum_<hailo_device_architecture_t>(m, "DeviceArchitecture")
.value("HAILO8_A0", HAILO_ARCH_HAILO8_A0)
.value("HAILO8_B0", HAILO_ARCH_HAILO8_B0)
.value("HAILO8", HAILO_ARCH_HAILO8)
.value("HAILO8L", HAILO_ARCH_HAILO8L)
.value("MERCURY_CA", HAILO_ARCH_MERCURY_CA)
;
@@ -530,8 +305,7 @@ PYBIND11_MODULE(_pyhailort, m) {
;
py::enum_<hailo_overcurrent_protection_overcurrent_zone_t>(m, "OvercurrentAlertState")
.value("OVERCURRENT_ZONE_NONE", HAILO_OVERCURRENT_PROTECTION_OVERCURRENT_ZONE__NONE)
.value("OVERCURRENT_ZONE_ORANGE", HAILO_OVERCURRENT_PROTECTION_OVERCURRENT_ZONE__ORANGE)
.value("OVERCURRENT_ZONE_GREEN", HAILO_OVERCURRENT_PROTECTION_OVERCURRENT_ZONE__GREEN)
.value("OVERCURRENT_ZONE_RED", HAILO_OVERCURRENT_PROTECTION_OVERCURRENT_ZONE__RED)
;
@@ -572,7 +346,7 @@ PYBIND11_MODULE(_pyhailort, m) {
py::class_<hailo_health_monitor_overcurrent_alert_notification_message_t>(m, "HealthMonitorOvercurrentAlertNotificationMessage")
.def_readonly("overcurrent_zone", &hailo_health_monitor_overcurrent_alert_notification_message_t::overcurrent_zone)
.def_readonly("exceeded_alert_threshold", &hailo_health_monitor_overcurrent_alert_notification_message_t::exceeded_alert_threshold)
.def_readonly("sampled_current_during_alert", &hailo_health_monitor_overcurrent_alert_notification_message_t::sampled_current_during_alert)
.def_readonly("is_last_overcurrent_violation_reached", &hailo_health_monitor_overcurrent_alert_notification_message_t::is_last_overcurrent_violation_reached)
;
py::class_<hailo_health_monitor_lcu_ecc_error_notification_message_t>(m, "HealthMonitorLcuEccErrorNotificationMessage")
@@ -997,11 +771,29 @@ PYBIND11_MODULE(_pyhailort, m) {
});
;
py::class_<hailo_vdevice_params_t>(m, "VDeviceParams")
py::class_<VDeviceParamsWrapper>(m, "VDeviceParams")
.def(py::init<>())
.def_readwrite("device_count", &hailo_vdevice_params_t::device_count)
.def_property("device_count",
[](const VDeviceParamsWrapper& params) -> uint32_t {
return params.orig_params.device_count;
},
[](VDeviceParamsWrapper& params, const uint32_t& device_count) {
params.orig_params.device_count = device_count;
}
)
.def_property("group_id",
[](const VDeviceParamsWrapper& params) -> py::str {
return std::string(params.orig_params.group_id);
},
[](VDeviceParamsWrapper& params, const std::string& group_id) {
params.group_id_str = group_id;
params.orig_params.group_id = params.group_id_str.c_str();
}
)
.def_static("default", []() {
return HailoRTDefaults::get_vdevice_params();
auto orig_params = HailoRTDefaults::get_vdevice_params();
VDeviceParamsWrapper params_wrapper{orig_params, ""};
return params_wrapper;
});
;
@@ -1070,7 +862,7 @@ PYBIND11_MODULE(_pyhailort, m) {
.def_readonly("overcurrent_protection_active", &hailo_health_info_t::overcurrent_protection_active)
.def_readonly("current_overcurrent_zone", &hailo_health_info_t::current_overcurrent_zone)
.def_readonly("red_overcurrent_threshold", &hailo_health_info_t::red_overcurrent_threshold)
.def_readonly("orange_overcurrent_threshold", &hailo_health_info_t::orange_overcurrent_threshold)
.def_readonly("overcurrent_throttling_active", &hailo_health_info_t::overcurrent_throttling_active)
.def_readonly("temperature_throttling_active", &hailo_health_info_t::temperature_throttling_active)
.def_readonly("current_temperature_zone", &hailo_health_info_t::current_temperature_zone)
.def_readonly("current_temperature_throttling_level", &hailo_health_info_t::current_temperature_throttling_level)
@@ -1086,6 +878,8 @@ PYBIND11_MODULE(_pyhailort, m) {
.def_readonly("orange_hysteresis_temperature_threshold", &hailo_health_info_t::orange_hysteresis_temperature_threshold)
.def_readonly("red_temperature_threshold", &hailo_health_info_t::red_temperature_threshold)
.def_readonly("red_hysteresis_temperature_threshold", &hailo_health_info_t::red_hysteresis_temperature_threshold)
.def_readonly("requested_overcurrent_clock_freq", &hailo_health_info_t::requested_overcurrent_clock_freq)
.def_readonly("requested_temperature_clock_freq", &hailo_health_info_t::requested_temperature_clock_freq)
;
py::class_<hailo_extended_device_information_t>(m, "ExtendedDeviceInformation")
@@ -1148,10 +942,6 @@ PYBIND11_MODULE(_pyhailort, m) {
.value("CPU1", HAILO_CPU_ID_1)
;
py::enum_<hailo_bootloader_version_t>(m, "BootloaderVersion")
.value("UNSIGNED", BOOTLOADER_VERSION_HAILO8_B0_UNSIGNED)
.value("SIGNED", BOOTLOADER_VERSION_HAILO8_B0_SIGNED)
;
py::class_<uint32_t>(m, "HailoRTDefaults")
.def_static("HAILO_INFINITE", []() { return HAILO_INFINITE;} )
@@ -1160,6 +950,7 @@ PYBIND11_MODULE(_pyhailort, m) {
.def_static("DEVICE_BASE_INPUT_STREAM_PORT", []() { return HailoRTCommon::ETH_INPUT_BASE_PORT;} )
.def_static("DEVICE_BASE_OUTPUT_STREAM_PORT", []() { return HailoRTCommon::ETH_OUTPUT_BASE_PORT;} )
.def_static("PCIE_ANY_DOMAIN", []() { return HAILO_PCIE_ANY_DOMAIN;} )
.def_static("HAILO_UNIQUE_VDEVICE_GROUP_ID", []() { return std::string(HAILO_UNIQUE_VDEVICE_GROUP_ID); } )
;
py::class_<hailo_network_group_info_t>(m, "NetworkGroupInfo", py::module_local())

View File

@@ -0,0 +1,251 @@
/**
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file quantization_api.cpp
* @brief Quantization python bindings functions
**/
#include "quantization_api.hpp"
#include "bindings_common.hpp"
namespace hailort
{
void QuantizationBindings::dequantize_output_buffer_from_uint8(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::dequantize_output_buffer<uint8_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer<uint16_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_from_uint16(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer<uint16_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_from_float32(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer<float32_t, float32_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_from_uint8_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::dequantize_output_buffer_in_place<uint8_t, uint8_t>(
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer_in_place<uint16_t, uint8_t>(
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, uint8_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_from_uint16_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT16:
Quantization::dequantize_output_buffer_in_place<uint16_t, uint16_t>(
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, uint16_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_from_float32_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_FLOAT32:
Quantization::dequantize_output_buffer_in_place<float32_t, float32_t>(
static_cast<float32_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer_in_place(py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
QuantizationBindings::dequantize_output_buffer_from_uint8_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
QuantizationBindings::dequantize_output_buffer_from_uint16_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
QuantizationBindings::dequantize_output_buffer_from_float32_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::dequantize_output_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
QuantizationBindings::dequantize_output_buffer_from_uint8(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
QuantizationBindings::dequantize_output_buffer_from_uint16(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
QuantizationBindings::dequantize_output_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::quantize_input_buffer_from_uint8(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<uint8_t, uint8_t>(static_cast<uint8_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type uint8 to dst format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::quantize_input_buffer_from_uint16(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<uint16_t, uint8_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::quantize_input_buffer<uint16_t, uint16_t>(static_cast<uint16_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type uint16 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::quantize_input_buffer_from_float32(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (dst_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
Quantization::quantize_input_buffer<float32_t, uint8_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
Quantization::quantize_input_buffer<float32_t, uint16_t>(static_cast<float32_t*>(src_buffer.mutable_data()),
static_cast<uint16_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported from src format type float32 to dst format type = {}",
HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
void QuantizationBindings::quantize_input_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info)
{
switch (src_dtype) {
case HAILO_FORMAT_TYPE_UINT8:
QuantizationBindings::quantize_input_buffer_from_uint8(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_UINT16:
QuantizationBindings::quantize_input_buffer_from_uint16(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
case HAILO_FORMAT_TYPE_FLOAT32:
QuantizationBindings::quantize_input_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
break;
default:
LOGGER__ERROR("Input quantization isn't supported for src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
break;
}
}
} /* namespace hailort */

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file quantization_api.hpp
* @brief Quantization python bindings functions
**/
#ifndef _HAILO_QUANTIZATION_API_HPP_
#define _HAILO_QUANTIZATION_API_HPP_
#include "hailo/hailort.hpp"
#include "utils.hpp"
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace hailort
{
class QuantizationBindings
{
public:
static void quantize_input_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_in_place(py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &src_dtype,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
private:
static void dequantize_output_buffer_from_uint8(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_from_uint16(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_from_float32(py::array src_buffer, py::array dst_buffer,
const hailo_format_type_t &dst_dtype, uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_from_uint8_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_from_uint16_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void dequantize_output_buffer_from_float32_in_place(py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void quantize_input_buffer_from_uint8(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void quantize_input_buffer_from_uint16(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
static void quantize_input_buffer_from_float32(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
uint32_t shape_size, const hailo_quant_info_t &quant_info);
};
} /* namespace hailort */
#endif /* _HAILO_QUANTIZATION_API_HPP_ */

View File

@@ -30,6 +30,11 @@
namespace hailort
{
struct VDeviceParamsWrapper {
hailo_vdevice_params_t orig_params;
std::string group_id_str;
};
class VDeviceWrapper {
public:
static VDeviceWrapper create(const hailo_vdevice_params_t &params)
@@ -37,13 +42,15 @@ public:
return VDeviceWrapper(params);
};
static VDeviceWrapper create_from_infos(const std::vector<hailo_pcie_device_info_t> &device_infos)
static VDeviceWrapper create(const VDeviceParamsWrapper &params)
{
hailo_vdevice_params_t params = {};
params.device_count = static_cast<uint32_t>(device_infos.size());
params.device_infos = const_cast<hailo_pcie_device_info_t*>(device_infos.data());
return VDeviceWrapper(params);
};
return VDeviceWrapper(params.orig_params);
}
static VDeviceWrapper create_from_ids(const std::vector<std::string> &device_ids)
{
return VDeviceWrapper(device_ids);
}
VDeviceWrapper(const hailo_vdevice_params_t &params)
{
@@ -53,13 +60,21 @@ public:
m_vdevice = vdevice_expected.release();
};
py::list get_physical_devices_infos()
VDeviceWrapper(const std::vector<std::string> &device_ids)
{
auto phys_devs_infos = m_vdevice->get_physical_devices_infos();
VALIDATE_EXPECTED(phys_devs_infos);
auto vdevice_expected = VDevice::create(device_ids);
VALIDATE_EXPECTED(vdevice_expected);
return py::cast(phys_devs_infos.value());
};
m_vdevice = vdevice_expected.release();
}
py::list get_physical_devices_ids() const
{
const auto phys_devs_ids = m_vdevice->get_physical_devices_ids();
VALIDATE_EXPECTED(phys_devs_ids);
return py::cast(phys_devs_ids.value());
}
py::list configure(const HefWrapper &hef,
const NetworkGroupsParamsMap &configure_params={})
@@ -88,9 +103,10 @@ private:
void VDevice_api_initialize_python_module(py::module &m)
{
py::class_<VDeviceWrapper>(m, "VDevice")
.def("create", &VDeviceWrapper::create)
.def("create_from_infos", &VDeviceWrapper::create_from_infos)
.def("get_physical_devices_infos", &VDeviceWrapper::get_physical_devices_infos)
.def("create", py::overload_cast<const hailo_vdevice_params_t&>(&VDeviceWrapper::create))
.def("create", py::overload_cast<const VDeviceParamsWrapper&>(&VDeviceWrapper::create))
.def("create_from_ids", &VDeviceWrapper::create_from_ids)
.def("get_physical_devices_ids", &VDeviceWrapper::get_physical_devices_ids)
.def("configure", &VDeviceWrapper::configure)
.def("release", &VDeviceWrapper::release)
;

View File

@@ -56,7 +56,8 @@ InputVStreamsWrapper InputVStreamsWrapper::create(ConfiguredNetworkGroup &net_gr
std::unordered_map<std::string, std::shared_ptr<InputVStream>> input_vstreams;
for (auto &input : input_vstreams_expected.value()) {
input_vstreams.emplace(input.name(), make_shared_nothrow<InputVStream>(std::move(input)));
auto input_name = input.name();
input_vstreams.emplace(input_name, make_shared_nothrow<InputVStream>(std::move(input)));
}
return InputVStreamsWrapper(input_vstreams);
}
@@ -168,7 +169,8 @@ OutputVStreamsWrapper OutputVStreamsWrapper::create(ConfiguredNetworkGroup &net_
std::unordered_map<std::string, std::shared_ptr<OutputVStream>> output_vstreams;
for (auto &output : output_vstreams_expected.value()) {
output_vstreams.emplace(output.name(), make_shared_nothrow<OutputVStream>(std::move(output)));
auto output_name = output.name();
output_vstreams.emplace(output_name, make_shared_nothrow<OutputVStream>(std::move(output)));
}
return OutputVStreamsWrapper(output_vstreams);
}

View File

@@ -9,4 +9,4 @@ set(CMAKE_LINKER arm-linux-gnueabi-ld)
add_compile_options(-march=armv7-a)
# pybind is not supported in this platform
set(HAILO_BUILD_PYBIND 0)
set(HAILO_BUILD_PYBIND "OFF" CACHE STRING "hailo_build_pybind" FORCE)

View File

@@ -9,4 +9,4 @@ set(CMAKE_LINKER arm-linux-gnueabihf-ld)
add_compile_options(-march=armv7-a)
# pybind is not supported in this platform
set(HAILO_BUILD_PYBIND 0)
set(HAILO_BUILD_PYBIND "OFF" CACHE STRING "hailo_build_pybind" FORCE)

View File

@@ -47,6 +47,10 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "so_linker_flags")
# pybind is not supported in this platform
set(HAILO_BUILD_PYBIND 0)
set(HAILO_BUILD_PYBIND "OFF" CACHE STRING "hailo_build_pybind" FORCE)
# GStreamer does not work on QNX currently
set(HAILO_BUILD_GSTREAMER 0)
set(HAILO_BUILD_GSTREAMER "OFF" CACHE STRING "hailo_build_gstreamer" FORCE)
# Hailort service does not work on QNX currently
set(HAILO_BUILD_SERVICE "OFF" CACHE STRING "hailo_build_service" FORCE)
# Set little endian flag for protobuf to work correctly on QNX
add_definitions("-D__LITTLE_ENDIAN__")

View File

@@ -47,6 +47,10 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "so_linker_flags")
# pybind is not supported in this platform
set(HAILO_BUILD_PYBIND 0)
set(HAILO_BUILD_PYBIND "OFF" CACHE STRING "hailo_build_pybind" FORCE)
# GStreamer does not work on QNX currently
set(HAILO_BUILD_GSTREAMER 0)
set(HAILO_BUILD_GSTREAMER "OFF" CACHE STRING "hailo_build_gstreamer" FORCE)
# Hailort service does not work on QNX currently
set(HAILO_BUILD_SERVICE "OFF" CACHE STRING "hailo_build_service" FORCE)
# Set little endian flag for protobuf to work correctly on QNX
add_definitions("-D__LITTLE_ENDIAN__")

View File

@@ -5,7 +5,7 @@ project(hailort-examples)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(HailoRT 4.8.1 EXACT REQUIRED)
find_package(HailoRT 4.10.0 EXACT REQUIRED)
add_library(example_base INTERFACE)
target_link_libraries(example_base INTERFACE HailoRT::libhailort Threads::Threads)

View File

@@ -37,12 +37,14 @@ The following examples are provided, demonstrating the HailoRT 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.
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
Examples are configured and compiled using the following commands:
```sh
cmake -H. -Bbuild
cmake --build build
cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
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.

View File

@@ -44,7 +44,7 @@ hailo_status infer(hailo_configured_network_group configured_network_group,
src_data = malloc(input_buffer.raw_buffer.size);
REQUIRE_ACTION(src_data != NULL, status = HAILO_OUT_OF_HOST_MEMORY, l_free_buffers, "Failed to allocate input buffer");
// Prepare src data here
for (size_t j = 0; j < frame_size; j++) {
for (size_t j = 0; j < input_buffer.raw_buffer.size; j++) {
src_data[j] = (uint8_t)(rand() % 256);
}

View File

@@ -1,14 +1,6 @@
/**
* Copyright 2020 (C) Hailo Technologies Ltd.
* All rights reserved.
*
* Hailo Technologies Ltd. ("Hailo") disclaims any warranties, including, but not limited to,
* the implied warranties of merchantability and fitness for a particular purpose.
* This software is provided on an "AS IS" basis, and Hailo has no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
* You may use this software in the development of any project.
* You shall not reproduce, modify or distribute this software without prior written permission.
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file multi_device_example.c
@@ -23,7 +15,7 @@
#define INFER_FRAME_COUNT (100)
#define MAX_EDGE_LAYERS (16)
#define MAX_PCIE_DEVICES (16)
#define MAX_DEVICES (16)
#define HEF_FILE ("hefs/shortcut_net.hef")
@@ -136,8 +128,8 @@ int main()
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_vdevice vdevice = NULL;
hailo_pcie_device_info_t device_infos[MAX_PCIE_DEVICES];
size_t actual_count = 0;
hailo_device_id_t device_ids[MAX_DEVICES];
size_t actual_count = MAX_DEVICES;
hailo_vdevice_params_t params = {0};
hailo_hef hef = NULL;
hailo_configure_params_t config_params = {0};
@@ -151,8 +143,8 @@ int main()
hailo_input_vstream input_vstreams[MAX_EDGE_LAYERS] = {NULL};
hailo_output_vstream output_vstreams[MAX_EDGE_LAYERS] = {NULL};
status = hailo_scan_pcie_devices(device_infos, MAX_PCIE_DEVICES, &actual_count);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan pcie_device");
status = hailo_scan_devices(NULL, device_ids, &actual_count);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan devices");
status = hailo_init_vdevice_params(&params);
REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");

View File

@@ -18,7 +18,7 @@
#define MEASUREMENT_BUFFER_INDEX (HAILO_MEASUREMENT_BUFFER_INDEX_0)
#define MEASUREMENTS_DURATION_SECS (5)
#define MAX_PCIE_DEVICES (16)
#define MAX_DEVICES (16)
#define MEASUREMENT_UNITS(__type) \
((HAILO_POWER_MEASUREMENT_TYPES__POWER == __type) ? ("W") : ("mA"))
@@ -80,17 +80,17 @@ int main(int argc, char **argv)
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_vdevice vdevice = NULL;
hailo_pcie_device_info_t device_infos[MAX_PCIE_DEVICES];
size_t actual_device_count = 0;
hailo_device_id_t device_ids[MAX_DEVICES];
size_t actual_device_count = MAX_DEVICES;
hailo_vdevice_params_t params = {0};
hailo_device physical_devices[MAX_PCIE_DEVICES];
hailo_power_measurement_data_t measurement_result[MAX_PCIE_DEVICES] = {0};
hailo_device physical_devices[MAX_DEVICES];
hailo_power_measurement_data_t measurement_result[MAX_DEVICES] = {0};
hailo_power_measurement_types_t measurement_type = {0};
parse_arguments(argc, argv, &measurement_type);
status = hailo_scan_pcie_devices(device_infos, MAX_PCIE_DEVICES, &actual_device_count);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan pcie_device");
status = hailo_scan_devices(NULL, device_ids, &actual_device_count);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan devices");
status = hailo_init_vdevice_params(&params);
REQUIRE_SUCCESS(status, l_exit, "Failed to init vdevice_params");

View File

@@ -5,7 +5,7 @@
/**
* @file raw_streams_example.c
* This example demonstrates basic usage of HailoRT streaming api.
* It loads an HEF network with multiple inputs and multiple outputs into a Hailo PCIe device and performs a
* It loads an HEF network with multiple inputs and multiple outputs into a Hailo device and performs a
* short inference.
**/
@@ -170,6 +170,8 @@ l_cleanup:
int main()
{
hailo_status status = HAILO_UNINITIALIZED;
hailo_device_id_t device_id = {0};
size_t actual_devices_count = 1;
hailo_device device = NULL;
hailo_hef hef = NULL;
hailo_configure_params_t configure_params = {0};
@@ -184,13 +186,13 @@ int main()
size_t number_output_streams = 0;
size_t index = 0;
status = hailo_create_pcie_device(NULL, &device);
/*
For simplicity, passing NULL as `device_info` - This function will fail in case more than one PCIe device is present.
See `hailo_scan_pcie_devices` and `hailo_create_pcie_device` functions documentation.
*/
REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
status = hailo_scan_devices(NULL, &device_id, &actual_devices_count);
REQUIRE_SUCCESS(status, l_exit, "Failed to scan devices");
REQUIRE_ACTION(1 == actual_devices_count, status = HAILO_INVALID_OPERATION, l_exit,
"Only 1 device on the system is supported on the example");
status = hailo_create_device_by_id(&device_id, &device);
REQUIRE_SUCCESS(status, l_exit, "Failed to create device");
status = hailo_create_hef_file(&hef, HEF_FILE);
REQUIRE_SUCCESS(status, l_release_device, "Failed creating hef file %s", HEF_FILE);

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