diff --git a/.hailort.png b/.hailort.png
new file mode 100644
index 0000000..fdc8497
Binary files /dev/null and b/.hailort.png differ
diff --git a/.logo.svg b/.logo.svg
deleted file mode 100644
index 62315a5..0000000
--- a/.logo.svg
+++ /dev/null
@@ -1,212 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 68b135b..06f1154 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,13 @@
cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYBIND "Build Python binding" OFF)
-option(HAILO_BUILD_PYHAILORT_VENV "Build pyhailort in venv" ON)
+option(HAILO_BUILD_PYHAILORT_VENV "Build pyhailort in venv. Only used if HAILO_BUILD_PYBIND is on" ON)
option(HAILO_BUILD_EMULATOR "Build hailort for emulator" OFF)
option(HAILO_BUILD_UT "Build Unit Tests" OFF)
option(HAILO_BUILD_GSTREAMER "Compile gstreamer plugins" OFF)
option(HAILO_BUILD_EXAMPLES "Build examples" OFF)
+option(HAILO_OFFLINE_COMPILATION "Don't download external dependencies" OFF)
+option(HAILO_MICROPROFILE "Microprofile code" OFF)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
@@ -14,6 +16,13 @@ endif()
project(HailoRT)
+# Prevent in-tree building
+if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
+ message(FATAL_ERROR "In-source builds are not allowed.
+ Please remove the `CMakeCache.txt` file and `CMakeFiles` directory from `${CMAKE_SOURCE_DIR}`
+ In order to build, please create a new `build` directory and run `cmake ..` from there.")
+endif()
+
# Check build type
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Debug")
@@ -35,23 +44,11 @@ if(WIN32)
/wd4251 # C++ ABI with STL
)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Disable "unsafe function" warnings
-
- if (CMAKE_BUILD_TYPE STREQUAL "Release")
- set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} /O2 /DNDEBUG /Zi)
- elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
- set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} /Od /Zi /DDEBUG)
- else()
- message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
- endif()
- add_link_options("$<$>:/DEBUG>")
- add_link_options("$<$>:/OPT:REF>")
- add_link_options("$<$>:/OPT:ICF>")
-
elseif(UNIX)
- if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "QCC")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra -Wconversion)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra
+ set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra
# TODO: remove me warnings
-Wno-conversion
-Wno-deprecated-declarations
@@ -60,14 +57,6 @@ elseif(UNIX)
else()
message(FATAL_ERROR "Invalid value for CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
endif()
-
- if (CMAKE_BUILD_TYPE STREQUAL "Release")
- set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -O3 -DNDEBUG)
- elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
- set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -O0 -g -DDEBUG)
- else()
- message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
- endif()
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
@@ -80,23 +69,8 @@ if(HAILO_BUILD_EMULATOR)
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -DHAILO_EMULATOR)
endif()
-# Prevent in-tree building
-if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
- message(FATAL_ERROR "In-source builds are not allowed.
- Please remove the `CMakeCache.txt` file and `CMakeFiles` directory from `${CMAKE_SOURCE_DIR}`
- In order to build, please create a new `build` directory and run `cmake ..` from there.")
-endif()
-
# Enable output of compile commands during generation
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-# Set validation dir
-set(PLATFORM_VALIDATION_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/platform_internals/hailo_platform_internals/validation")
-
-if (NOT DEFINED HEFS_DIR)
- set(HEFS_DIR "${PLATFORM_VALIDATION_DIRECTORY}/hefs/latest")
- message(STATUS "No HEFS_DIR provided, using default ('${HEFS_DIR}')")
-endif()
-
# Add subdirectories
add_subdirectory(hailort)
diff --git a/README.md b/README.md
index edc09bf..69fb8cb 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
diff --git a/common/include/context_switch_defs.h b/common/include/context_switch_defs.h
index b993a3b..ef432a4 100644
--- a/common/include/context_switch_defs.h
+++ b/common/include/context_switch_defs.h
@@ -23,7 +23,6 @@ extern "C" {
#define CONTEXT_SWITCH_DEFS__TIMESTAMP_INIT_VALUE (0xFFFFFFFF)
#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_ADDRESS (1)
#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_COUNT (2)
-#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_BATCH_SIZE (1)
#define CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_LCU_INDEX_SHIFT (0)
#define CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_LCU_INDEX_WIDTH (4)
@@ -57,7 +56,7 @@ typedef enum : uint8_t {
#else
typedef enum __attribute__((packed)) {
#endif
- CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS = 0,
+ CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS = 0,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_TRIGGER_SEQUENCER,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_DATA_FROM_VDMA_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT,
@@ -85,6 +84,8 @@ typedef enum __attribute__((packed)) {
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_DMA_IDLE_ACTION,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS_IDLE,
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,
/* Must be last */
CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT
@@ -116,9 +117,18 @@ typedef struct {
* | | | .last_executed = ; |
* | | | .sub_action_type = CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT; |
* | | | } |
- * | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=; } |
- * | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=; } |
- * | V | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=; } |
+ * | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
+ * | | | .packed_lcu_id=; |
+ * | | | .network_index= |
+ * | | | } |
+ * | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
+ * | | | .packed_lcu_id=; |
+ * | | | .network_index= |
+ * | | | } |
+ * | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
+ * | | | .packed_lcu_id=; |
+ * | | | .network_index= |
+ * | V | } |
* | ... | (Next action starting with CONTEXT_SWITCH_DEFS__common_action_header_t) |
* |-------------------------------------------------------------------------------------------------------|
* See also: "CONTROL_PROTOCOL__REPEATED_ACTION_t" in "control_protocol.h"
@@ -132,7 +142,7 @@ typedef struct {
typedef struct {
uint16_t descriptors_count;
uint8_t cfg_channel_number;
-} CONTEXT_SWITCH_DEFS__read_vdma_action_data_t;
+} CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t;
typedef struct {
uint16_t ccw_bursts;
@@ -146,6 +156,7 @@ typedef struct {
typedef struct {
uint8_t packed_lcu_id;
+ uint8_t network_index;
uint16_t kernel_done_address;
uint32_t kernel_done_count;
} CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t;
@@ -153,6 +164,7 @@ typedef struct {
/* Default action - kernel_done_address and kernel_done_count has default values */
typedef struct {
uint8_t packed_lcu_id;
+ uint8_t network_index;
} CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t;
typedef struct {
@@ -163,14 +175,27 @@ typedef struct {
uint8_t vdma_channel_index;
uint8_t edge_layer_direction;
bool is_inter_context;
+ uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
+ uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t;
+typedef struct {
+ uint8_t vdma_channel_index;
+ uint8_t edge_layer_direction;
+ bool is_inter_context;
+ bool is_single_context_network_group;
+ uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
+ uint32_t initial_credit_size;
+} CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t;
+
typedef struct {
uint8_t vdma_channel_index;
uint8_t stream_index;
- uint32_t channel_credits;
+ uint8_t network_index;
+ uint32_t frame_periph_size;
uint8_t credit_type;
uint16_t periph_bytes_per_buffer;
+ uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t, relevant only for descriptors credit.
} CONTEXT_SWITCH_DEFS__fetch_data_action_data_t;
typedef struct {
@@ -182,7 +207,8 @@ typedef struct {
typedef struct {
uint8_t h2d_vdma_channel_index;
uint8_t d2h_vdma_channel_index;
- uint32_t descriptors_per_batch;
+ uint8_t network_index;
+ uint32_t descriptors_per_frame;
uint16_t programmed_descriptors_count;
} CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t;
@@ -227,16 +253,17 @@ typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
+ uint32_t initial_credit_size;
bool is_single_context_app;
} CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t;
typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
+ uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
- uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
- uint8_t desc_list_depth;
+ CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
+ uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t;
typedef struct {
@@ -244,9 +271,8 @@ typedef struct {
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
uint8_t desc_list_depth;
- bool fw_managed_channel;
+ uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t;
typedef struct {
@@ -260,13 +286,9 @@ typedef struct {
typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
+ uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
- // TODO: add this to CONTEXT_SWITCH_DEFS__stream_reg_info_t
- uint32_t frame_credits_in_bytes;
- uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
- uint16_t desc_page_size;
- uint8_t desc_list_depth;
+ CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t;
typedef struct {
@@ -275,16 +297,14 @@ typedef struct {
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint32_t frame_credits_in_bytes;
uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
uint16_t desc_page_size;
uint8_t desc_list_depth;
- bool fw_managed_channel;
+ uint32_t buffered_rows_count;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t;
typedef struct {
uint8_t channel_index;
- uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
+ CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_cfg_channel_t;
typedef struct {
diff --git a/common/include/control_protocol.h b/common/include/control_protocol.h
index 627ee04..a5d9e36 100644
--- a/common/include/control_protocol.h
+++ b/common/include/control_protocol.h
@@ -59,6 +59,11 @@ extern "C" {
#define CONTROL_PROTOCOL__REQUEST_BASE_SIZE (sizeof(CONTROL_PROTOCOL__request_header_t) + sizeof(uint32_t))
#define CONTROL_PROTOCOL__OPCODE_INVALID 0xFFFFFFFF
+/* If a control accepts a dynamic_batch_size and this value is passed, the
+ * dynamic_batch_size will be ignored. The pre-configured batch_size will be used.
+ */
+#define CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE (0)
+
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_SHIFT (0)
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_BIT_MASK (0x000000FF)
#define CONTROL_PROTOCOL__TRIGGER_INDEX_SHIFT (16)
@@ -862,21 +867,24 @@ typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_VER_V1_0_0 = 0x010000,
} CONTROL_PROTOCOL__CONTEXT_SWITCH_VERSION_t;
+typedef struct {
+ bool is_abbale_supported;
+} CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t;
+
+typedef struct {
+ bool preliminary_run_asap;
+} CONTROL_PROTOCOL__INFER_FEATURE_LIST_t;
+
typedef struct {
uint8_t dynamic_contexts_count;
uint32_t host_boundary_channels_bitmap;
- uint32_t host_ddr_channels_bitmap;
- uint8_t cfg_channels_count;
uint8_t cfg_channel_numbers[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint8_t power_mode; // CONTROL_PROTOCOL__power_mode_t
+ CONTROL_PROTOCOL__INFER_FEATURE_LIST_t infer_features;
uint8_t networks_count;
uint16_t batch_size[CONTROL_PROTOCOL__MAX_NETWORKS_PER_NETWORK_GROUP];
} CONTROL_PROTOCOL__application_header_t;
-typedef struct {
- bool is_abbale_supported;
-} CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t;
-
typedef struct {
uint32_t context_switch_version_length;
uint32_t context_switch_version;
@@ -960,6 +968,7 @@ typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_REPEATED,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_FETCH_CCW_BURSTS,
+ CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_BURST_CREDITS_TASK_START,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_COUNT,
@@ -1026,6 +1035,25 @@ typedef enum {
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_COUNT
} CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_t;
+typedef enum {
+ CONTROL_PROTOCOL__HOST_BUFFER_TYPE_EXTERNAL_DESC = 0,
+ CONTROL_PROTOCOL__HOST_BUFFER_TYPE_CCB,
+
+ // The buffer uses external descriptors that is host managed - the firmware don't need to config this buffer
+ CONTROL_PROTOCOL__HOST_BUFFER_TYPE_HOST_MANAGED_EXTERNAL_DESC,
+
+ /* must be last*/
+ CONTROL_PROTOCOL__HOST_BUFFER_TYPE_COUNT
+} CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t;
+
+typedef struct {
+ uint8_t buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
+ uint64_t dma_address;
+ uint16_t desc_page_size;
+ uint32_t total_desc_count;
+ uint32_t bytes_in_pattern;
+} CONTROL_PROTOCOL__host_buffer_info_t;
+
typedef struct {
uint8_t communication_type;
uint8_t edge_connection_type;
@@ -1040,7 +1068,6 @@ typedef struct {
typedef struct {
uint64_t host_descriptors_base_address;
- uint16_t initial_host_available_descriptors;
uint8_t desc_list_depth;
} CONTROL_PROTOCOL__host_desc_address_info_t;
@@ -1052,9 +1079,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;
} CONTROL_PROTOCOL__inter_context_output_t;
typedef struct {
@@ -1062,7 +1087,7 @@ typedef struct {
uint32_t frame_credits_in_bytes;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
uint16_t desc_page_size;
- bool fw_managed_channel;
+ uint32_t buffered_rows_count;
} CONTROL_PROTOCOL__ddr_buffer_output_t;
@@ -1073,19 +1098,19 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint16_t desc_page_size;
+ uint32_t initial_credit_size;
} CONTROL_PROTOCOL__network_boundary_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
- CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
- uint16_t desc_page_size;
- uint16_t context_credits_in_descriptors;
+ CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
+ uint32_t initial_credit_size;
} CONTROL_PROTOCOL__inter_context_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
- bool fw_managed_channel;
+ uint32_t initial_credit_size;
} CONTROL_PROTOCOL__ddr_buffer_input_t;
typedef struct {
@@ -1106,10 +1131,10 @@ typedef struct {
uint8_t is_first_control_per_context;
uint32_t is_last_control_per_context_length;
uint8_t is_last_control_per_context;
- uint32_t context_cfg_base_address_length;
- uint64_t context_cfg_base_address[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
- uint32_t context_cfg_total_descriptors_length;
- uint16_t context_cfg_total_descriptors[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
+ 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 context_stream_remap_data_length;
CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
uint32_t number_of_edge_layers_length;
@@ -1155,16 +1180,19 @@ typedef struct {
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = ; |
* | | | .lcu_index = ; |
+ * | | | .network_index = ; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = ; |
* | | | .lcu_index = ; |
+ * | | | .network_index = ; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = ; |
* | | | .lcu_index = ; |
+ * | | | .network_index = ; |
* | V | } |
* | ... | (Next action control) |
* |--------------------------------------------------------------------------------------------------|
@@ -1236,6 +1264,7 @@ typedef struct {
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
uint8_t lcu_index;
+ uint8_t network_index;
} CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t;
typedef struct {
@@ -1265,6 +1294,11 @@ typedef struct {
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__ADD_DDR_BUFFERING_START_ACTION_t;
+typedef struct {
+ /* Must be first */
+ CONTROL_PROTOCOL__ACTION_HEADER_t header;
+} CONTROL_PROTOCOL__BURST_CREDITS_TASK_START_ACTION_T;
+
typedef struct {
CONTROL_PROTOCOL__TRIGGER_t trigger;
uint16_t triggers_action_count;
@@ -1324,6 +1358,8 @@ typedef struct {
uint8_t state_machine_status;
uint32_t application_index_length;
uint8_t application_index;
+ uint32_t dynamic_batch_size_length;
+ uint16_t dynamic_batch_size;
} CONTROL_PROTOCOL__change_context_switch_status_request_t;
typedef struct {
@@ -1338,6 +1374,8 @@ typedef struct {
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 {
@@ -1674,8 +1712,8 @@ typedef struct {
typedef struct {
bool is_first_control_per_context;
bool is_last_control_per_context;
- uint64_t context_cfg_base_address[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
- uint16_t context_cfg_total_descriptors[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
+ uint8_t cfg_channels_count;
+ CONTROL_PROTOCOL__host_buffer_info_t config_buffer_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;
diff --git a/common/include/firmware_status.h b/common/include/firmware_status.h
index 391213e..88350aa 100644
--- a/common/include/firmware_status.h
+++ b/common/include/firmware_status.h
@@ -395,6 +395,10 @@ Updating rules:
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_FAILED_SETTING_OVERCURRENT_STATE)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_CONTROL_UNSUPPORTED)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_CONTROL_DEPRECATED)\
+ FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_HOST_BUFFER_INFO)\
+ 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_MODULE__X(FIRMWARE_MODULE__POWER_MEASUREMENT)\
FIRMWARE_STATUS__X(HAILO_POWER_MEASUREMENT_STATUS_POWER_INIT_ERROR)\
@@ -537,6 +541,7 @@ Updating rules:
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_GLUE_LOGIC_CHANNEL_OUT_OF_RANGE)\
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_INVALID_H2D_CHANNEL_INDEX)\
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_INVALID_D2H_CHANNEL_INDEX)\
+ FIRMWARE_STATUS__X(PCIE_SERVICE_INVALID_INITIAL_CREDIT_SIZE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__FIRMWARE_UPDATE)\
FIRMWARE_STATUS__X(FIRMWARE_UPDATE_STATUS_INVALID_PARAMETERS)\
@@ -726,6 +731,10 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_CLUSTER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INTERFACE)\
+ FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_ACTION_IS_NOT_SUPPORTED)\
+ FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CFG_CHANNELS_COUNT)\
+ FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_HOST_BUFFER_TYPE)\
+ FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_BURST_CREDITS_TASK_IS_NOT_IDLE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\
@@ -940,6 +949,7 @@ Updating rules:
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_NOT_ENABLED_WHILE_TRYING_TO_FETCH_CONFIG)\
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_BURST_COUNTER_IS_NOT_ZERO)\
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_CREDIT_COUNTER_IS_NOT_ZERO)\
+ FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_FIFO_NOT_EMPTY)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__PCIE_CONFIG_MANAGER)\
FIRMWARE_STATUS__X(PCIE_CONFIG_MANAGER_STATUS_NOT_IMPLEMENTED)\
@@ -964,6 +974,16 @@ Updating rules:
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_NULL_ARG_PASSED)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CHANNEL_FAILED_TO_REACH_IDLE_STATE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_VDMA_MUST_BE_STOPPED_WHEN_CHECKING_IDLE)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_EXTERNAL_DESC_COUNT_MUST_BE_POWER_OF_2)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_TOO_MANY_DESCRIPTORS)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_HOST_BUFFER_TYPE)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_DESC_PAGE_SIZE_MUST_BE_POWER_OF_2)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INITIAL_DESC_BIGGER_EQ_THAN_TOTAL)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CCB_NOT_IMPLEMENTED_OVER_PCIE)\
+ FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CCB_BASE_ADDRESS_IS_NOT_IN_MASK)\
+ 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_MODULE__X(FIRMWARE_MODULE__MEMORY_LOGGER)\
FIRMWARE_STATUS__X(MEMORY_LOGGER_STATUS_DEBUG_INSUFFICIENT_MEMORY)\
@@ -980,6 +1000,13 @@ Updating rules:
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_SETUP_INTERRUPT_HANDLER_FAILED)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_BURST_CREDIT_SIZE_TOO_BIG)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_CHANNEL_DMA_ADDRESS)\
+ FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_DESC_PAGE_SIZE)\
+ FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_NUM_PAGES_IS_OUT_OF_RANGE)\
+ FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_INVALID_INITIAL_CREDIT_SIZE)\
+ FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_TOTAL_DESCS_COUNT_IS_OUT_OF_RANGE)\
+ 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_MODULE__X(FIRMWARE_MODULE__NN_CORE_SERVICE)\
FIRMWARE_STATUS__X(NN_CORE_SERVICE_STATUS_INVALID_ARG_PASSED)\
@@ -989,6 +1016,19 @@ Updating rules:
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_EDGE_LAYER_INDEX)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_DESC_PAGE_SIZE)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_EDGE_LAYER_DIRECTION)\
+ FIRMWARE_STATUS__X(DATA_STREAM_WRAPPER_STATUS_INVALID_CHANNEL_INDEX)\
+ 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_MODULE__X(FIRMWARE_MODULE__BURST_CREDITS_TASK)\
+ FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TRYING_TO_ADD_ACTION_WHILE_NOT_IN_IDLE_STATE)\
+ FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TOO_MANY_ACTIONS)\
+ FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TRYING_TO_CHANGE_STATE_TO_INFER_WHILE_ALREADY_IN_INFER)\
+ FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_INFER_REACHED_TIMEOUT)\
+ FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TASK_DEACTIVATED)\
+ \
+
typedef enum {
#define FIRMWARE_MODULE__X(module) module,
diff --git a/hailort/CMakeLists.txt b/hailort/CMakeLists.txt
index c189d11..63edd68 100644
--- a/hailort/CMakeLists.txt
+++ b/hailort/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
-add_definitions( -DFIRMWARE_VERSION_MINOR=6 )
+add_definitions( -DFIRMWARE_VERSION_MINOR=8 )
add_definitions( -DFIRMWARE_VERSION_REVISION=0 )
message(STATUS "Building pre_build")
@@ -15,13 +15,14 @@ execute_cmake(
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_LIST_DIR}/pre_build/install
-DHAILO_EXTERNAL_DIR=${HAILO_EXTERNAL_DIR}
+ -DHAILO_OFFLINE_COMPILATION=${HAILO_OFFLINE_COMPILATION}
BUILD_ARGS
--config ${CMAKE_BUILD_TYPE} --target install ${CMAKE_EXTRA_BUILD_ARGS}
PARALLEL_BUILD
)
-# BENCHMARK_ENABLE_TESTING can be used by other 3rd party projects, therefore we define it
-# before adding projects
+# BENCHMARK_ENABLE_TESTING can be used by other 3rd party projects, therefore we define it
+# before adding projects
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Enable testing of the benchmark library.")
add_subdirectory(external/benchmark EXCLUDE_FROM_ALL)
@@ -61,6 +62,17 @@ set(COMMON_INC_DIR ${PROJECT_SOURCE_DIR}/common/include)
set(DRIVER_INC_DIR ${PROJECT_SOURCE_DIR}/hailort/drivers/common)
if(HAILO_BUILD_PYBIND)
+ if(NOT PYTHON_EXECUTABLE AND PYBIND11_PYTHON_VERSION)
+ # PYBIND11_PYTHON_VERSION is prioritized (not virtual environment) if PYTHON_EXECUTABLE is not set.
+ # See https://pybind11.readthedocs.io/en/stable/changelog.html#v2-6-0-oct-21-2020
+ if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
+ find_package(PythonInterp ${PYBIND11_PYTHON_VERSION} REQUIRED)
+ set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
+ else()
+ find_package(Python3 ${PYBIND11_PYTHON_VERSION} REQUIRED EXACT COMPONENTS Interpreter Development)
+ set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
+ endif()
+ endif()
add_subdirectory(external/pybind11 EXCLUDE_FROM_ALL)
endif()
add_subdirectory(external/Catch2 EXCLUDE_FROM_ALL)
@@ -69,28 +81,39 @@ add_subdirectory(external/json EXCLUDE_FROM_ALL)
add_subdirectory(external/DotWriter EXCLUDE_FROM_ALL)
add_subdirectory(external/spdlog EXCLUDE_FROM_ALL)
set_target_properties(spdlog PROPERTIES POSITION_INDEPENDENT_CODE ON)
+if(CMAKE_SYSTEM_NAME STREQUAL QNX)
+ add_library(pevents STATIC EXCLUDE_FROM_ALL external/pevents/src/pevents.cpp)
+ target_include_directories(pevents PUBLIC external/pevents/src)
+ target_compile_definitions(pevents PRIVATE -DWFMO)
+endif()
+
+# microprofile
+if(HAILO_MICROPROFILE)
+ add_library(microprofile STATIC EXCLUDE_FROM_ALL external/microprofile/microprofile.cpp)
+ set_target_properties(microprofile PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ POSITION_INDEPENDENT_CODE ON
+ )
+ target_compile_definitions(microprofile
+ PRIVATE
+ -DMICROPROFILE_WEBSERVER=1
+ -DMICROPROFILE_GPU_TIMERS=0
+ -DMICROPROFILE_NAME_MAX_LEN=256
+ PUBLIC
+ -DMICROPROFILE_ENABLED=1
+ )
+ target_include_directories(microprofile PUBLIC external/microprofile)
+else()
+ add_library(microprofile INTERFACE)
+ target_compile_definitions(microprofile INTERFACE -DMICROPROFILE_ENABLED=0)
+ target_include_directories(microprofile INTERFACE external/microprofile)
+endif()
+
add_subdirectory(common)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
-# copy files to venv
-if(HAILO_BUILD_PYBIND AND HAILO_BUILD_PYHAILORT_VENV)
- set(VENV_DRIVERS_DIR ${CMAKE_SOURCE_DIR}/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/)
- set(PYHAILORT_FILES_TO_COPY
- $
- )
- set(VENV_PYHAILORT_INTERNAL_DIR ${CMAKE_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/)
- set(PYHAILORT_INTERNAL_FILES_TO_COPY
- $
- )
- add_custom_target(
- pyhailort_venv ALL
- COMMAND ${CMAKE_COMMAND} -E copy ${PYHAILORT_FILES_TO_COPY} ${VENV_DRIVERS_DIR}
- COMMAND ${CMAKE_COMMAND} -E copy ${PYHAILORT_INTERNAL_FILES_TO_COPY} ${VENV_PYHAILORT_INTERNAL_DIR}
- )
- add_dependencies(pyhailort_venv libhailort _pyhailort)
-endif()
-
if(HAILO_WIN_DRIVER)
add_subdirectory(drivers/win)
add_subdirectory(packaging)
diff --git a/hailort/LICENSE-3RD-PARTY.md b/hailort/LICENSE-3RD-PARTY.md
index c7e4576..9c86db7 100644
--- a/hailort/LICENSE-3RD-PARTY.md
+++ b/hailort/LICENSE-3RD-PARTY.md
@@ -3,11 +3,13 @@
| CLI11 | University of Cincinnati | 3-Clause BSD | 1.7 | Cloned entire package | https://github.com/CLIUtils/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 |
-| pybind11 | Wenzel Jakob | BSD | 2.3.0 | Cloned entire package | https://github.com/pybind/pybind11 |
+| 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 |
| 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 |
\ No newline at end of file
+| 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 |
diff --git a/hailort/common/circular_buffer.hpp b/hailort/common/circular_buffer.hpp
index c50b971..8df5461 100644
--- a/hailort/common/circular_buffer.hpp
+++ b/hailort/common/circular_buffer.hpp
@@ -97,6 +97,11 @@ public:
return CB_HEAD(m_circ) == CB_TAIL(m_circ);
}
+ bool full()
+ {
+ return 0 == CB_AVAIL(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ));
+ }
+
private:
circbuf_t m_circ;
std::vector m_array;
diff --git a/hailort/common/latency_meter.hpp b/hailort/common/latency_meter.hpp
index c839a0f..eaed098 100644
--- a/hailort/common/latency_meter.hpp
+++ b/hailort/common/latency_meter.hpp
@@ -125,6 +125,7 @@ private:
};
using LatencyMeterPtr = std::shared_ptr;
+using LatencyMetersMap = std::map;
} /* namespace hailort */
diff --git a/hailort/common/os/posix/filesystem.cpp b/hailort/common/os/posix/filesystem.cpp
index 00fce95..fd96ce2 100644
--- a/hailort/common/os/posix/filesystem.cpp
+++ b/hailort/common/os/posix/filesystem.cpp
@@ -52,7 +52,7 @@ dirent* Filesystem::DirWalker::next_file()
return readdir(m_dir);
}
-#if defined(__unix__)
+#if defined(__linux__)
Expected> Filesystem::get_files_in_dir_flat(const std::string &dir_path)
{
diff --git a/hailort/common/utils.hpp b/hailort/common/utils.hpp
index f4f74d7..a93c6aa 100644
--- a/hailort/common/utils.hpp
+++ b/hailort/common/utils.hpp
@@ -52,6 +52,24 @@ static inline bool contains(const std::set &container, T value)
return (container.find(value) != container.end());
}
+template
+class unlock_guard {
+public:
+ unlock_guard(T &lock) : m_lock(lock) {
+ m_lock.unlock();
+ }
+
+ ~unlock_guard() {
+ m_lock.lock();
+ }
+
+ unlock_guard(const unlock_guard&) = delete;
+ unlock_guard& operator=(const unlock_guard&) = delete;
+
+private:
+ T &m_lock;
+};
+
// From https://stackoverflow.com/questions/57092289/do-stdmake-shared-and-stdmake-unique-have-a-nothrow-version
template
static inline std::unique_ptr make_unique_nothrow(Args&&... args)
@@ -241,6 +259,18 @@ constexpr uint32_t get_nearest_powerof_2(uint32_t value, uint32_t min_power_of_2
return power_of_2;
}
+template
+static uint32_t get_max_value_of_unordered_map(const std::unordered_map &map)
+{
+ uint32_t max_count = 0;
+ for (auto &name_counter_pair : map) {
+ if (name_counter_pair.second > max_count) {
+ max_count = name_counter_pair.second;
+ }
+ }
+ return max_count;
+}
+
} /* namespace hailort */
#endif /* HAILO_UTILS_H_ */
\ No newline at end of file
diff --git a/hailort/drivers/common/hailo_ioctl_common.h b/hailort/drivers/common/hailo_ioctl_common.h
index 1177130..64603a1 100644
--- a/hailort/drivers/common/hailo_ioctl_common.h
+++ b/hailort/drivers/common/hailo_ioctl_common.h
@@ -29,11 +29,13 @@
#ifdef _MSC_VER
#if !defined(bool) && !defined(__cplusplus)
typedef uint8_t bool;
-#endif
+#endif // !defined(bool) && !defined(__cplusplus)
+
#if !defined(INT_MAX)
#define INT_MAX 0x7FFFFFFF
-#endif
-#else
+#endif // !defined(INT_MAX)
+
+#elif defined(__linux__) // #ifdef _MSC_VER
#ifndef __KERNEL__
// include the userspace headers only if this file is included by user space program
// It is discourged to include them when compiling the driver (https://lwn.net/Articles/113349/)
@@ -43,11 +45,9 @@ typedef uint8_t bool;
#include
#include
#include
-#endif
+#endif // ifndef __KERNEL__
-#if defined(__unix__)
#include
-#endif
#define _IOW_ _IOW
#define _IOR_ _IOR
@@ -57,6 +57,21 @@ typedef uint8_t bool;
#define HAILO_GENERAL_IOCTL_MAGIC 'g'
#define HAILO_VDMA_IOCTL_MAGIC 'v'
#define HAILO_WINDOWS_IOCTL_MAGIC 'w'
+
+#elif defined(__QNX__) // #ifdef _MSC_VER
+#include
+#include
+#include
+// defines for devctl
+#define _IOW_ __DIOF
+#define _IOR_ __DIOT
+#define _IOWR_ __DIOTF
+#define _IO_ __DION
+#define HAILO_GENERAL_IOCTL_MAGIC _DCMD_ALL
+#define HAILO_VDMA_IOCTL_MAGIC _DCMD_MISC
+
+#else // #ifdef _MSC_VER
+#error "unsupported platform!"
#endif
#pragma pack(push, 1)
@@ -181,6 +196,9 @@ struct hailo_fw_control {
};
/* structure used in ioctl HAILO_BAR_TRANSFER */
+// Max bar transfer size gotten from ATR0_TABLE_SIZE
+#define MAX_BAR_TRANSFER_LENGTH (4096)
+
enum hailo_transfer_direction {
TRANSFER_READ = 0,
TRANSFER_WRITE,
@@ -194,7 +212,7 @@ struct hailo_bar_transfer_params {
uint32_t bar_index; // in
off_t offset; // in
size_t count; // in
- void* buffer; // in/out
+ uint8_t buffer[MAX_BAR_TRANSFER_LENGTH]; // in/out
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_REGISTERS */
@@ -222,9 +240,11 @@ struct hailo_vdma_buffer_sync_params {
};
/* structure used in ioctl HAILO_READ_NOTIFICATION */
+#define MAX_NOTIFICATION_LENGTH (1500)
+
struct hailo_d2h_notification {
size_t buffer_len; // out
- uint8_t buffer[MAX_CONTROL_LENGTH]; // out
+ uint8_t buffer[MAX_NOTIFICATION_LENGTH]; // out
};
enum hailo_board_type {
@@ -254,14 +274,18 @@ struct hailo_driver_info {
uint32_t minor_version;
uint32_t revision_version;
};
+
+/* structure used in ioctl HAILO_READ_LOG */
+#define MAX_FW_LOG_BUFFER_LENGTH (512)
+
struct hailo_read_log_params {
- enum hailo_cpu_id cpu_id; // in
- uint8_t *buffer; // out
- size_t buffer_size; // in
- size_t read_bytes; // out
+ enum hailo_cpu_id cpu_id; // in
+ uint8_t buffer[MAX_FW_LOG_BUFFER_LENGTH]; // out
+ size_t buffer_size; // in
+ size_t read_bytes; // out
};
-struct hailo_allocate_buffer_params {
+struct hailo_allocate_low_memory_buffer_params {
size_t buffer_size; // in
uintptr_t buffer_handle; // out
};
@@ -270,6 +294,12 @@ struct hailo_mark_as_in_use_params {
bool in_use; // out
};
+struct hailo_allocate_continuous_buffer_params {
+ size_t buffer_size; // in
+ uintptr_t buffer_handle; // out
+ uint64_t dma_address; // out
+};
+
#pragma pack(pop)
enum hailo_general_ioctl_code {
@@ -286,7 +316,7 @@ enum hailo_general_ioctl_code {
HAILO_GENERAL_IOCTL_MAX_NR,
};
-#define HAILO_BAR_TRANSFER _IOW_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_BAR_TRANSFER_CODE, struct hailo_bar_transfer_params)
+#define HAILO_BAR_TRANSFER _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_BAR_TRANSFER_CODE, struct hailo_bar_transfer_params)
#define HAILO_FW_CONTROL _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_FW_CONTROL_CODE, struct hailo_fw_control)
#define HAILO_READ_NOTIFICATION _IOW_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_READ_NOTIFICATION_CODE, struct hailo_d2h_notification)
#define HAILO_DISABLE_NOTIFICATION _IO_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_DISABLE_NOTIFICATION_CODE)
@@ -311,6 +341,8 @@ enum hailo_vdma_ioctl_code {
HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC_CODE,
HAILO_VDMA_LOW_MEMORY_BUFFER_FREE_CODE,
HAILO_MARK_AS_IN_USE_CODE,
+ HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC_CODE,
+ HAILO_VDMA_CONTINUOUS_BUFFER_FREE_CODE,
// Must be last
HAILO_VDMA_IOCTL_MAX_NR,
@@ -331,11 +363,15 @@ enum hailo_vdma_ioctl_code {
#define HAILO_DESC_LIST_RELEASE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_RELEASE_CODE)
#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_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)
#define HAILO_VDMA_LOW_MEMORY_BUFFER_FREE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_LOW_MEMORY_BUFFER_FREE_CODE)
#define HAILO_MARK_AS_IN_USE _IOW_(HAILO_VDMA_IOCTL_MAGIC, HAILO_MARK_AS_IN_USE_CODE, struct hailo_mark_as_in_use_params)
+#define HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC_CODE, struct hailo_allocate_continuous_buffer_params)
+#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,
diff --git a/hailort/drivers/win/include/Public.h b/hailort/drivers/win/include/Public.h
new file mode 100644
index 0000000..96b442a
--- /dev/null
+++ b/hailort/drivers/win/include/Public.h
@@ -0,0 +1,124 @@
+/*++
+
+Module Name:
+
+ public.h
+
+Abstract:
+
+ This module contains the common declarations shared by driver
+ and user applications.
+
+Environment:
+
+ user and kernel
+
+--*/
+
+//
+// Define an Interface Guid so that apps can find the device and talk to it.
+//
+
+DEFINE_GUID (GUID_DEVINTERFACE_HailoKM,
+ 0xd88d31f1,0xfede,0x4e71,0xac,0x2a,0x6c,0xe0,0x01,0x8c,0x15,0x01);
+// {d88d31f1-fede-4e71-ac2a-6ce0018c1501}
+
+#define HAILO_IOCTL_COMMON CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_FUNC(x) (((x) >> 2) & 0xfff)
+#define NUMBER_OF_PARAMETERS(code) ((code) & 0xf)
+#define NUMBER_OF_PARAMETERS_FLEXIBLE 0xf
+
+struct tCommonHailoIoctlParam
+{
+ ULONG ulCode : 24;
+ ULONG fResponse : 1;
+ ULONG fUseLL : 1;
+ ULONG ulParamNum : 4;
+ union {
+ ULONG ulInputs[4];
+ ULONGLONG llInputs[2];
+ };
+ union {
+ ULONG ulOutputs[4];
+ ULONGLONG llOutputs[2];
+ };
+};
+
+#define HAILO_CMD_FW_LOAD 0x0010
+#define HAILO_CMD_READ_CFG 0x0011
+#define HAILO_CMD_SW_RESET 0x0020
+#define HAILO_CMD_READ_INTERRUPT_BAR 0x0021
+#define HAILO_CMD_READ_FW_STATUS 0x0030
+#define HAILO_CMD_READ_FIRMWARE_BAR 0x0031
+#define HAILO_CMD_CANCEL_READ 0x0040
+#define HAILO_CMD_READ_RP_CFG 0x0041
+#define HAILO_CMD_UNMAP_BUFFER 0x0050
+#define HAILO_CMD_MAP_BUFFER 0x0051
+#define HAILO_CMD_FREE_MEMORY 0x0060
+#define HAILO_CMD_ALLOC_MEMORY 0x0061
+#define HAILO_CMD_ABORT_ALL 0x0070
+
+#define HAILO_IOCTL_COMPATIBLE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
+struct tCompatibleHailoIoctlParam
+{
+ union {
+ struct {
+ ULONG Size : 16;
+ ULONG Code : 8;
+ ULONG Type : 6;
+ ULONG Read : 1;
+ ULONG Write : 1;
+ } bits;
+ ULONG value;
+ } u;
+};
+
+#define HAILO_GENERAL_IOCTL_MAGIC 0
+#define HAILO_VDMA_IOCTL_MAGIC 1
+#define HAILO_WINDOWS_IOCTL_MAGIC 2
+
+
+
+static ULONG FORCEINLINE _IOC_(ULONG nr, ULONG type, ULONG size, bool read, bool write)
+{
+ tCompatibleHailoIoctlParam param;
+ param.u.bits.Code = nr;
+ param.u.bits.Size = size;
+ param.u.bits.Type = type;
+ param.u.bits.Read = read ? 1 : 0;
+ param.u.bits.Write = write ? 1 : 0;
+ return param.u.value;
+}
+
+#define _IOW_(type,nr,size) _IOC_(nr, type, sizeof(size), true, false)
+#define _IOR_(type,nr,size) _IOC_(nr, type, sizeof(size), false, true)
+#define _IOWR_(type,nr,size) _IOC_(nr, type, sizeof(size), true, true)
+#define _IO_(type,nr) _IOC_(nr, type, 0, false, false)
+
+#include "..\..\common\hailo_ioctl_common.h"
+
+struct tCompatibleHailoIoctlData
+{
+ tCompatibleHailoIoctlParam Parameters;
+ ULONG_PTR Value;
+ union {
+ hailo_bar_transfer_params BarTransfer;
+ hailo_vdma_channel_enable_params ChannelEnable;
+ hailo_vdma_channel_disable_params ChannelDisable;
+ hailo_vdma_channel_wait_params ChannelWait;
+ hailo_vdma_channel_abort_params ChannelAbort;
+ hailo_vdma_channel_clear_abort_params ChannelClearAbort;
+ hailo_vdma_buffer_sync_params VdmaBufferSync;
+ hailo_fw_control FirmwareControl;
+ hailo_vdma_buffer_map_params VdmaBufferMap;
+ hailo_desc_list_create_params DescListCreate;
+ 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_read_log_params ReadLog;
+ hailo_mark_as_in_use_params MarkAsInUse;
+ } Buffer;
+};
diff --git a/hailort/drivers/win/include/hailo_pcie_version.h b/hailort/drivers/win/include/hailo_pcie_version.h
new file mode 100644
index 0000000..2dfaa33
--- /dev/null
+++ b/hailort/drivers/win/include/hailo_pcie_version.h
@@ -0,0 +1,10 @@
+#ifndef _HAILO_PCIE_VERSION_H_
+#define _HAILO_PCIE_VERSION_H_
+
+#include "..\..\common\hailo_pcie_version.h"
+
+#define STRINGIFY_EXPANDED( x ) #x
+#define STRINGIFY_NUMBER( x ) STRINGIFY_EXPANDED(x)
+#define HAILO_DRV_VER STRINGIFY_NUMBER(HAILO_DRV_VER_MAJOR) "." STRINGIFY_NUMBER(HAILO_DRV_VER_MINOR) "." STRINGIFY_NUMBER(HAILO_DRV_VER_REVISION)
+
+#endif /* _HAILO_PCIE_VERSION_H_ */
diff --git a/hailort/hailortcli/CMakeLists.txt b/hailort/hailortcli/CMakeLists.txt
index 4fb14ec..ba3dc6a 100644
--- a/hailort/hailortcli/CMakeLists.txt
+++ b/hailort/hailortcli/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0.0)
+include(GNUInstallDirs)
+
set(HAILORTCLI_CPP_FILES
hailortcli.cpp
command.cpp
@@ -29,7 +31,6 @@ if(UNIX)
udp_rate_limiter_command.cpp
# TODO: We dont compile download_action_list_command on windows, as it uses packed enums (HRT-5919)
download_action_list_command.cpp
-
)
endif()
@@ -50,11 +51,16 @@ 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") # Need to add "${CMAKE_INSTALL_LIBDIR}" when installing with cmake to /usr/local
+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)
+# TODO: Remove microprofile after removing pipeline.cpp from hailortcli sources
+target_link_libraries(hailortcli microprofile)
+
if(WIN32)
target_link_libraries(hailortcli Ws2_32 Iphlpapi Shlwapi)
+elseif(CMAKE_SYSTEM_NAME STREQUAL QNX)
+ target_link_libraries(hailortcli pevents)
endif()
target_include_directories(hailortcli
PRIVATE
diff --git a/hailort/hailortcli/benchmark_command.cpp b/hailort/hailortcli/benchmark_command.cpp
index 7b17de5..f7260f7 100644
--- a/hailort/hailortcli/benchmark_command.cpp
+++ b/hailort/hailortcli/benchmark_command.cpp
@@ -28,13 +28,20 @@ BenchmarkCommand::BenchmarkCommand(CLI::App &parent_app) :
m_app->add_option("hef", m_params.hef_path, "Path of the HEF to load")
->check(CLI::ExistingFile)
->required();
- m_app->add_option("-t, --time-to-run", m_time, "Measurement time in seconds per hw_only/streaming/latency measurement mode")
+ m_app->add_option("-t, --time-to-run", m_params.time_to_run, "Measurement time in seconds per hw_only/streaming/latency measurement mode")
->check(CLI::PositiveNumber)
->default_val(15);
m_app->add_option("--no-power", m_not_measure_power, "Skip power measurement, even if the platform supports it. The default value is False")
->default_val("false");
m_app->add_option("--batch-size", m_params.batch_size, "Inference batch size (default is 1)")
->default_val(1);
+ m_app->add_option("--power-mode", m_params.power_mode,
+ "Core power mode (PCIE only; ignored otherwise)")
+ ->transform(HailoCheckedTransformer({
+ { "performance", hailo_power_mode_t::HAILO_POWER_MODE_PERFORMANCE },
+ { "ultra_performance", hailo_power_mode_t::HAILO_POWER_MODE_ULTRA_PERFORMANCE }
+ }))
+ ->default_val("performance");
m_app->add_option("--input-files", m_params.inputs_name_and_file_path, " The input files need to be in UINT8 before transformations.")
->check(InputNameToFileMap);
m_app->add_option("--csv", m_csv_file_path, "If set print the output as csv to the specified path");
@@ -66,6 +73,7 @@ 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.
std::cout << "Measuring HW Latency" << std::endl;
auto latency_info = latency();
CHECK_EXPECTED_AS_STATUS(latency_info, "Latency measuring failed");
@@ -110,7 +118,6 @@ Expected BenchmarkCommand::hw_only_mode()
m_params.power_measurement.measure_power = false;
m_params.measure_latency = false;
m_params.mode = InferMode::HW_ONLY;
- m_params.time_to_run = m_time;
return run_command_hef(m_params);
}
@@ -121,7 +128,6 @@ Expected BenchmarkCommand::fps_streaming_mode()
m_params.measure_latency = false;
m_params.transform.transform = true;
m_params.transform.quantized = false;
- m_params.time_to_run = m_time;
return run_command_hef(m_params);
}
@@ -132,6 +138,5 @@ Expected BenchmarkCommand::latency()
m_params.mode = InferMode::STREAMING;
m_params.transform.transform = true;
m_params.transform.quantized = false;
- m_params.time_to_run = m_time;
return run_command_hef(m_params);
}
\ No newline at end of file
diff --git a/hailort/hailortcli/benchmark_command.hpp b/hailort/hailortcli/benchmark_command.hpp
index bffd401..38178e0 100644
--- a/hailort/hailortcli/benchmark_command.hpp
+++ b/hailort/hailortcli/benchmark_command.hpp
@@ -27,7 +27,6 @@ private:
inference_runner_params m_params;
bool m_not_measure_power;
- uint32_t m_time;
std::string m_csv_file_path;
};
diff --git a/hailort/hailortcli/command.cpp b/hailort/hailortcli/command.cpp
index 59ad875..49b1e04 100644
--- a/hailort/hailortcli/command.cpp
+++ b/hailort/hailortcli/command.cpp
@@ -41,6 +41,10 @@ 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 device = create_device(m_device_params);
if (!device) {
return device.status();
@@ -49,23 +53,24 @@ hailo_status DeviceCommand::execute()
return execute_on_device(*device.value());
}
-PcieDeviceCommand::PcieDeviceCommand(CLI::App *app) :
- Command(app)
+hailo_status DeviceCommand::execute_on_all_pcie_devices()
{
- auto group = app->add_option_group("PCIE Device Options");
-
- // PCIe options
- group->add_option("-s,--bdf", m_pcie_device_params.pcie_bdf,
- "Device id ([]::., same as in lspci command)")
- ->default_val("");
-}
-
-hailo_status PcieDeviceCommand::execute()
-{
- auto device = create_pcie_device(m_pcie_device_params);
- if (!device) {
- return device.status();
+ 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();
+ }
- return execute_on_device(*device.value());
+ auto execute_status = execute_on_device(*device.value());
+ if (HAILO_SUCCESS != execute_status) {
+ std::cerr << "Failed to execute on device: " << device.value()->get_dev_id() << ". status= " << execute_status << std::endl;
+ status = execute_status;
+ }
+ }
+ return status;
}
diff --git a/hailort/hailortcli/command.hpp b/hailort/hailortcli/command.hpp
index e92e999..9ad9f9c 100644
--- a/hailort/hailortcli/command.hpp
+++ b/hailort/hailortcli/command.hpp
@@ -26,11 +26,6 @@ public:
return m_app->parsed();
}
- void set_description(const std::string &new_desc)
- {
- m_app->description(new_desc);
- }
-
void set_footer(const std::string &new_footer)
{
m_app->footer(new_footer);
@@ -70,21 +65,10 @@ public:
protected:
virtual hailo_status execute_on_device(Device &device) = 0;
+ hailo_status execute_on_all_pcie_devices();
private:
hailo_device_params m_device_params;
};
-class PcieDeviceCommand : public Command {
-public:
- explicit PcieDeviceCommand(CLI::App *app);
- virtual hailo_status execute() override final;
-
-protected:
- virtual hailo_status execute_on_device(Device &device) = 0;
-
-private:
- hailo_pcie_params m_pcie_device_params;
-};
-
#endif /* _HAILO_COMMAND_HPP_ */
\ No newline at end of file
diff --git a/hailort/hailortcli/download_action_list_command.cpp b/hailort/hailortcli/download_action_list_command.cpp
index 3832338..6cb49ce 100644
--- a/hailort/hailortcli/download_action_list_command.cpp
+++ b/hailort/hailortcli/download_action_list_command.cpp
@@ -13,6 +13,7 @@
#include "md5.h"
#include
+#include
constexpr int DownloadActionListCommand::INVALID_NUMERIC_VALUE;
@@ -21,7 +22,7 @@ DownloadActionListCommand::DownloadActionListCommand(CLI::App &parent_app) :
{
static const char *JSON_SUFFIX = ".json";
m_app->add_option("--output-file", m_output_file_path, "Output file path")
- ->default_val("context_action_list.json")
+ ->default_val("runtime_data.json")
->check(FileSuffixValidator(JSON_SUFFIX));
}
@@ -59,6 +60,11 @@ hailo_status DownloadActionListCommand::execute(Device &device, const std::strin
return HAILO_SUCCESS;
}
+hailo_status DownloadActionListCommand::set_batch_to_measure(Device &device, uint16_t batch_to_measure)
+{
+ return device.set_context_action_list_timestamp_batch(batch_to_measure);
+}
+
hailo_status DownloadActionListCommand::execute_on_device(Device &device)
{
return execute(device, m_output_file_path);
@@ -101,7 +107,8 @@ Expected DownloadActionListCommand::calc_md5_hexdigest(const std::s
std::stringstream hexdigest;
for (uint32_t i = 0; i < ARRAY_ENTRIES(md5_sum); i++) {
// cast to int needed for proper formatting
- hexdigest << std::hex << static_cast(md5_sum[i]);
+ static const int NUM_HEX_DIGITS_IN_UNIT8 = 2;
+ hexdigest << std::hex << std::setfill('0') << std::setw(NUM_HEX_DIGITS_IN_UNIT8) << static_cast(md5_sum[i]);
}
return hexdigest.str();
@@ -180,9 +187,9 @@ Expected DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t);
break;
- case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS:
- data_json = *reinterpret_cast(action);
- action_length_local = sizeof(CONTEXT_SWITCH_DEFS__read_vdma_action_data_t);
+ case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS:
+ data_json = *reinterpret_cast(action);
+ action_length_local = sizeof(CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CCW_BURSTS:
data_json = *reinterpret_cast(action);
@@ -200,6 +207,10 @@ Expected DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t);
break;
+ case CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL:
+ data_json = *reinterpret_cast(action);
+ action_length_local = sizeof(CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t);
+ break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT:
data_json = *reinterpret_cast(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t);
@@ -248,6 +259,10 @@ Expected DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = json({});
action_length_local = 0;
break;
+ case CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START:
+ data_json = json({});
+ action_length_local = 0;
+ break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_CFG_CHANNEL:
data_json = *reinterpret_cast(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__activate_cfg_channel_t);
@@ -391,7 +406,7 @@ Expected DownloadActionListCommand::parse_network_groups(Device &d
return network_group_list_json;
}
-void to_json(json& j, const CONTEXT_SWITCH_DEFS__read_vdma_action_data_t& data) {
+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}};
}
diff --git a/hailort/hailortcli/download_action_list_command.hpp b/hailort/hailortcli/download_action_list_command.hpp
index bbbc330..e669982 100644
--- a/hailort/hailortcli/download_action_list_command.hpp
+++ b/hailort/hailortcli/download_action_list_command.hpp
@@ -27,6 +27,7 @@ public:
// To be used from external commands
static hailo_status execute(Device &device, const std::string &output_file_path,
const ConfiguredNetworkGroupVector &network_groups={}, const std::string &hef_file_path="");
+ static hailo_status set_batch_to_measure(Device &device, uint16_t batch_to_measure);
protected:
virtual hailo_status execute_on_device(Device &device) override;
@@ -62,7 +63,7 @@ private:
// JSON serialization
NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
- {CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS, "fetch_vdma_descriptors"},
+ {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"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT, "enable_lcu_default"},
@@ -75,9 +76,11 @@ NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_DDR_BUFFER_INPUT, "activate_ddr_buffer_input"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_DDR_BUFFER_OUTPUT, "activate_ddr_buffer_output"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DEACTIVATE_VDMA_CHANNEL, "deactivate_vdma_channel"},
+ {CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL, "validate_vdma_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_CHANGE_VDMA_TO_STREAM_MAPPING, "change_vdma_to_stream_mapping"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ADD_DDR_PAIR_INFO, "add_ddr_pair_info"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_START, "ddr_buffering_start"},
+ {CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START, "burst_credits_task_start"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_LCU_INTERRUPT, "lcu_interrupt"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_SEQUENCER_DONE_INTERRUPT, "sequencer_done_interrupt"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_INPUT_CHANNEL_TRANSFER_DONE_INTERRUPT, "input_channel_transfer_done_interrupt"},
@@ -97,6 +100,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
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);
@@ -118,7 +122,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t
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__read_vdma_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);
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/example_config.json b/hailort/hailortcli/example_config.json
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/example_config.json
rename to hailort/hailortcli/example_config.json
diff --git a/hailort/hailortcli/fw_control_command.cpp b/hailort/hailortcli/fw_control_command.cpp
index 3be6e9a..5124600 100644
--- a/hailort/hailortcli/fw_control_command.cpp
+++ b/hailort/hailortcli/fw_control_command.cpp
@@ -230,19 +230,9 @@ FwControlCommand::FwControlCommand(CLI::App &parent_app) :
{
add_subcommand();
add_subcommand();
-
- // TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)
- // Can also remove Command::set_description function after this, and the return value of `add_subcommand`
- auto &scan = add_subcommand();
- scan.set_description("Alias for root-level 'scan' command (i.e. 'hailortcli scan...')\n"
- "Note: 'scan' as a sub-command of 'fw-control' is deprecated; use 'hailortcli scan' instead\n"
- " (or 'hailo scan' when using the 'hailo' command).");
-
add_subcommand();
// TODO: Support on windows (HRT-5919)
#if defined(__GNUC__)
- // TODO: Unhide (HRT-6035)
- static const bool HIDDEN = true;
- add_subcommand(HIDDEN);
+ add_subcommand();
#endif
}
diff --git a/hailort/hailortcli/fw_control_command.hpp b/hailort/hailortcli/fw_control_command.hpp
index 7ffbcd4..d475bd3 100644
--- a/hailort/hailortcli/fw_control_command.hpp
+++ b/hailort/hailortcli/fw_control_command.hpp
@@ -12,8 +12,6 @@
#include "hailortcli.hpp"
#include "command.hpp"
-// TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)
-#include "scan_command.hpp"
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
#include "download_action_list_command.hpp"
diff --git a/hailort/hailortcli/hailortcli.cpp b/hailort/hailortcli/hailortcli.cpp
index ceabba7..5493222 100644
--- a/hailort/hailortcli/hailortcli.cpp
+++ b/hailort/hailortcli/hailortcli.cpp
@@ -120,25 +120,19 @@ void add_device_options(CLI::App *app, hailo_device_params &device_params)
auto group = app->add_option_group("Device Options");
- // TODO: `--target` and `udp` DeviceType::ETH are for backwards compatibility with the python implemention (`hailo`)
- // TODO: Remove them (HRT-2676)
const HailoCheckedTransformer device_type_transformer({
{ "pcie", DeviceType::PCIE },
{ "eth", DeviceType::ETH },
- { "udp", 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.\n"
- "Note: 'udp' is an alias for 'eth'.")
+ "Default is pcie.")
->transform(device_type_transformer);
- std::vector actions{ std::make_shared(device_type_option, "udp", "eth") };
- hailo_deprecate_options(app, actions, false);
-
// PCIe options
auto *pcie_bdf_option = group->add_option("-s,--bdf", device_params.pcie_params.pcie_bdf,
- "Device id ([]::., same as in lspci command)")
+ "Device id ([]::., 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
@@ -194,6 +188,28 @@ void add_vdevice_options(CLI::App *app, hailo_device_params &device_params) {
});
}
+static bool do_versions_match()
+{
+ hailo_version_t libhailort_version = {};
+ auto status = hailo_get_library_version(&libhailort_version);
+ if (HAILO_SUCCESS != status) {
+ std::cerr << "Failed to get libhailort version" << std::endl;
+ return false;
+ }
+
+ bool versions_match = ((HAILORT_MAJOR_VERSION == libhailort_version.major) &&
+ (HAILORT_MINOR_VERSION == libhailort_version.minor) &&
+ (HAILORT_REVISION_VERSION == libhailort_version.revision));
+ if (!versions_match) {
+ std::cerr << "libhailort version (" <<
+ libhailort_version.major << "." << libhailort_version.minor << "." << libhailort_version.revision <<
+ ") does not match HailoRT-CLI version (" <<
+ HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << ")" << std::endl;
+ return false;
+ }
+ return true;
+}
+
class HailoRTCLI : public ContainerCommand {
public:
HailoRTCLI(CLI::App *app) : ContainerCommand(app)
@@ -201,7 +217,7 @@ public:
m_app->add_flag_callback("-v,--version",
[] () {
- std::cout << "hailortcli version " <<
+ std::cout << "HailoRT-CLI version " <<
HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << std::endl;
// throw CLI::Success to stop parsing and not failing require_subcommand(1) we set earlier
throw (CLI::Success{});
@@ -235,6 +251,9 @@ public:
};
int main(int argc, char** argv) {
+ if (!do_versions_match()) {
+ return -1;
+ }
auto console_sink = std::make_shared();
console_sink->set_level(spdlog::level::info);
console_sink->set_pattern("[%n] [%^%l%$] %v");
diff --git a/hailort/hailortcli/hailortcli.hpp b/hailort/hailortcli/hailortcli.hpp
index 8edf17a..5c61bf6 100644
--- a/hailort/hailortcli/hailortcli.hpp
+++ b/hailort/hailortcli/hailortcli.hpp
@@ -28,7 +28,7 @@ using namespace hailort;
} while (0)
struct hailo_pcie_params {
- std::string pcie_bdf; // if empty use the first scanned
+ 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 {
diff --git a/hailort/hailortcli/power_measurement_command.cpp b/hailort/hailortcli/power_measurement_command.cpp
index 493e475..72c4793 100644
--- a/hailort/hailortcli/power_measurement_command.cpp
+++ b/hailort/hailortcli/power_measurement_command.cpp
@@ -10,9 +10,6 @@
#include "power_measurement_command.hpp"
#include
-#define POWER_MEASUREMENT_DELAY_MS(__sample_period, __average_factor) \
- (static_cast((__sample_period) / 1000.0 * (__average_factor) * 2 * 1.2))
-
PowerMeasurementSubcommand::PowerMeasurementSubcommand(CLI::App &parent_app) :
DeviceCommand(parent_app.add_subcommand("measure-power", "Measures power consumption")), m_params(),
@@ -120,19 +117,13 @@ Expected PowerMeasurementSubcommand::start_power_measureme
return make_unexpected(status);
}
- status = hailo_set_power_measurement(reinterpret_cast(&device), 0, dvm, measurement_type);
+ status = hailo_set_power_measurement(reinterpret_cast(&device), HAILO_MEASUREMENT_BUFFER_INDEX_0, dvm, measurement_type);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to set power measurement parameters, status " << status << std::endl;
return make_unexpected(status);
}
- uint32_t measurement_delay = POWER_MEASUREMENT_DELAY_MS(sampling_period, averaging_factor);
- // There is no logical way that measurement delay can be 0 - because sampling_period and averaging_factor cant be 0
- // Hence if it is 0 - it means it was 0.xx and we want to round up to 1 in that case
- if (0 == measurement_delay) {
- measurement_delay = 1;
- }
- status = hailo_start_power_measurement(reinterpret_cast(&device), measurement_delay,
+ status = hailo_start_power_measurement(reinterpret_cast(&device),
averaging_factor_enum, sampling_period_enum);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to start power measurement, status " << status << std::endl;
@@ -155,7 +146,7 @@ hailo_status LongPowerMeasurement::stop()
return status;
}
- status = hailo_get_power_measurement(reinterpret_cast(&m_device), 0, true, &m_data);
+ status = hailo_get_power_measurement(reinterpret_cast(&m_device), HAILO_MEASUREMENT_BUFFER_INDEX_0, true, &m_data);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to get power measurement results, status " << status << std::endl;
return status;
diff --git a/hailort/hailortcli/run_command.cpp b/hailort/hailortcli/run_command.cpp
index fc73096..f623b17 100644
--- a/hailort/hailortcli/run_command.cpp
+++ b/hailort/hailortcli/run_command.cpp
@@ -61,7 +61,7 @@ void user_signal_handler_func(int signum)
hailo_status wait_for_exit_with_timeout(std::chrono::seconds time_to_run)
{
-#if defined(__unix__)
+#if defined(__linux__)
sighandler_t prev_handler = signal(USER_SIGNAL, user_signal_handler_func);
CHECK(prev_handler != SIG_ERR, HAILO_INVALID_OPERATION, "signal failed, errno = {}", errno);
std::mutex mutex;
@@ -100,8 +100,6 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
auto hef_new = run_subcommand->add_option("hef", params.hef_path, "An existing HEF file/directory path")
->check(CLI::ExistingFile | CLI::ExistingDirectory);
- auto hef_old = run_subcommand->add_option("--hef", params.hef_path, "An existing HEF file/directory path")
- ->check(CLI::ExistingFile | CLI::ExistingDirectory);
// Allow multiple subcommands (see https://cliutils.github.io/CLI11/book/chapters/subcommands.html)
run_subcommand->require_subcommand(0, 0);
@@ -202,20 +200,20 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
// TODO: Support on windows (HRT-5919)
#if defined(__GNUC__)
- // TODO: Unhide (HRT-6035)
- // Unnamed "option groups" hide subcommands/options from the help message
- // (see https://github.com/CLIUtils/CLI11/blob/main/README.md)
- auto *hidden_group = run_subcommand->add_option_group("");
- auto *download_runtime_data_subcommand = hidden_group->add_subcommand("download-runtime-data",
- "Download runtime data to be used by the Profiler");
+ auto *collect_runtime_data_subcommand = run_subcommand->add_subcommand("collect-runtime-data",
+ "Collect runtime data to be used by the Profiler");
static const char *JSON_SUFFIX = ".json";
- download_runtime_data_subcommand->add_option("--output-path",
+ collect_runtime_data_subcommand->add_option("--output-path",
params.runtime_data.runtime_data_output_path, "Runtime data output file path")
- ->default_val("context_action_list.json")
+ ->default_val("runtime_data.json")
->check(FileSuffixValidator(JSON_SUFFIX));
- download_runtime_data_subcommand->parse_complete_callback([¶ms]() {
+ static const uint32_t DEFAULT_BATCH_TO_MEASURE = 2;
+ collect_runtime_data_subcommand->add_option("--batch-to-measure",
+ params.runtime_data.batch_to_measure, "Batch to be measured")
+ ->default_val(DEFAULT_BATCH_TO_MEASURE);
+ collect_runtime_data_subcommand->parse_complete_callback([¶ms]() {
// If this subcommand was parsed, then we need to download runtime_data
- params.runtime_data.download_runtime_data = true;
+ params.runtime_data.collect_runtime_data = true;
});
#endif
@@ -229,9 +227,9 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
run_subcommand->add_flag("--measure-temp", params.measure_temp, "Measure chip temperature");
- run_subcommand->parse_complete_callback([¶ms, hef_new, hef_old, power_sampling_period,
+ run_subcommand->parse_complete_callback([¶ms, hef_new, power_sampling_period,
power_averaging_factor, measure_power_opt, measure_current_opt]() {
- PARSE_CHECK(hef_new->empty() ^ hef_old->empty(), "Single HEF file/directory is required");
+ PARSE_CHECK(!hef_new->empty(), "Single HEF file/directory is required");
bool is_hw_only = InferMode::HW_ONLY == params.mode;
params.transform.transform = (!is_hw_only || (params.inputs_name_and_file_path.size() > 0));
PARSE_CHECK((!params.transform.quantized || (HAILO_FORMAT_TYPE_AUTO == params.transform.format_type)),
@@ -248,16 +246,22 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
!(params.power_measurement.measure_power || params.power_measurement.measure_current || params.measure_temp),
"Writing measurements in csv format is not supported for multiple devices");
+ PARSE_CHECK(("*" != params.device_params.pcie_params.pcie_bdf),
+ "Passing '*' as BDF is not supported for 'run' command. for multiple devices inference see '--device-count'");
+
if ((0 == params.time_to_run) && (0 == params.frames_count)) {
// Use default
params.time_to_run = DEFAULT_TIME_TO_RUN_SECONDS;
}
- });
- std::vector actions{
- std::make_shared(hef_old, "hef (positional)"),
- };
- hailo_deprecate_options(run_subcommand, actions, false);
+ if (params.runtime_data.collect_runtime_data) {
+ if ((0 != params.frames_count) && (params.frames_count < params.runtime_data.batch_to_measure)) {
+ LOGGER__WARNING("--frames-count ({}) is smaller than --batch-to-measure ({}), "
+ "hence timestamps will not be updated in runtime data", params.frames_count,
+ params.runtime_data.batch_to_measure);
+ }
+ }
+ });
}
std::map format_strings_to_key_value_pairs(const std::vector &key_value_pairs_str) {
@@ -1030,18 +1034,34 @@ Expected run_command_hef_single_device(const inference_
auto network_group_list = device.value()->configure(hef.value(), configure_params.value());
CHECK_EXPECTED(network_group_list, "Failed configure device from hef");
+ #if defined(__GNUC__)
+ // TODO: Support on windows (HRT-5919)
+ if (params.runtime_data.collect_runtime_data) {
+ DownloadActionListCommand::set_batch_to_measure(*device.value(), params.runtime_data.batch_to_measure);
+ }
+ #endif
+
// TODO: SDK-14842, for now this function supports only one network_group
auto network_group = network_group_list.value()[0];
auto inference_result = activate_network_group_and_run(*device.value().get(), network_group, params);
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
- if (params.runtime_data.download_runtime_data) {
+ if (params.runtime_data.collect_runtime_data) {
+ if ((0 == params.frames_count) && inference_result) {
+ const auto frames_count = inference_result->frames_count();
+ if (frames_count && (frames_count.value() < params.runtime_data.batch_to_measure)) {
+ LOGGER__WARNING("Number of frames sent ({}) is smaller than --batch-to-measure ({}), "
+ "hence timestamps will not be updated in runtime data", frames_count.value(),
+ params.runtime_data.batch_to_measure);
+ }
+ }
+
DownloadActionListCommand::execute(*device.value(), params.runtime_data.runtime_data_output_path,
network_group_list.value(), params.hef_path);
}
#endif
-
+ CHECK_EXPECTED(inference_result);
return inference_result;
}
diff --git a/hailort/hailortcli/run_command.hpp b/hailort/hailortcli/run_command.hpp
index 7cfcae6..85f45d9 100644
--- a/hailort/hailortcli/run_command.hpp
+++ b/hailort/hailortcli/run_command.hpp
@@ -45,8 +45,9 @@ struct pipeline_stats_measurement_params {
};
struct runtime_data_params {
- bool download_runtime_data;
+ bool collect_runtime_data;
std::string runtime_data_output_path;
+ uint16_t batch_to_measure;
};
struct inference_runner_params {
diff --git a/hailort/hailortcli/scan_command.cpp b/hailort/hailortcli/scan_command.cpp
index 073d3ae..2d9e4e2 100644
--- a/hailort/hailortcli/scan_command.cpp
+++ b/hailort/hailortcli/scan_command.cpp
@@ -17,39 +17,28 @@ ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("scan", "Shows all available devices")),
m_device_type(Device::Type::PCIE)
{
- // TODO: `--target` and `udp` Device::TYPE::ETH are for backwards compatibility with the python implemention (`hailo`)
- // TODO: Remove them (HRT-2676)
const HailoCheckedTransformer device_type_transformer({
{ "pcie", Device::Type::PCIE },
{ "eth", Device::Type::ETH },
- { "udp", Device::Type::ETH },
});
auto *device_type_option = m_app->add_option("-d,--device-type,--target", m_device_type,
- "Device type to use\n"
- "Note: 'udp' is an alias for 'eth'.")
+ "Device type to use.")
->transform(device_type_transformer)
->default_val("pcie");
// Ethernet options
auto *eth_options_group = m_app->add_option_group("Ethernet Device Options");
- // TODO: `--ip` is for backwards compatibility with the python implemention (`hailo`)
- // TODO: Remove it (HRT-2676)
auto *interface_ip_option = eth_options_group->add_option("--interface-ip", m_interface_ip_addr,
"Interface IP address to scan")
->default_val("")
->check(CLI::ValidIPV4);
- auto *ip_option = eth_options_group->add_option("--ip", m_interface_ip_addr)
- ->default_val("")
- ->excludes(interface_ip_option)
- ->check(CLI::ValidIPV4);
auto *interface_name_option = eth_options_group->add_option("--interface", m_interface_name, "Interface name to scan")
->default_val("")
- ->excludes(interface_ip_option)
- ->excludes(ip_option);
+ ->excludes(interface_ip_option);
- m_app->parse_complete_callback([this, device_type_option, interface_ip_option, ip_option, interface_name_option]() {
- bool eth_options_given = !interface_ip_option->empty() || !ip_option->empty() || !interface_name_option->empty();
+ 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()) {
@@ -71,12 +60,6 @@ ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
throw CLI::ParseError("Ethernet options set on non eth device", CLI::ExitCodes::InvalidError);
}
});
-
- std::vector actions{
- std::make_shared(device_type_option, "udp", "eth"),
- std::make_shared(ip_option, "--interface-ip")
- };
- hailo_deprecate_options(m_app, actions, false);
}
hailo_status ScanSubcommand::execute()
diff --git a/hailort/libhailort/CMakeLists.txt b/hailort/libhailort/CMakeLists.txt
index 393ad62..aff9879 100644
--- a/hailort/libhailort/CMakeLists.txt
+++ b/hailort/libhailort/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
-set(HAILORT_MINOR_VERSION 6)
+set(HAILORT_MINOR_VERSION 8)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found
diff --git a/hailort/libhailort/bindings/CMakeLists.txt b/hailort/libhailort/bindings/CMakeLists.txt
index 3388d7f..c803727 100644
--- a/hailort/libhailort/bindings/CMakeLists.txt
+++ b/hailort/libhailort/bindings/CMakeLists.txt
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
if(HAILO_BUILD_PYBIND)
add_subdirectory(python)
endif()
+
# QNX currently doesnt support GStreamer
if(HAILO_BUILD_GSTREAMER AND CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL QNX)
add_subdirectory(gstreamer)
diff --git a/hailort/libhailort/bindings/gstreamer/CMakeLists.txt b/hailort/libhailort/bindings/gstreamer/CMakeLists.txt
index 7094c83..c9fe743 100644
--- a/hailort/libhailort/bindings/gstreamer/CMakeLists.txt
+++ b/hailort/libhailort/bindings/gstreamer/CMakeLists.txt
@@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.0.0)
project(gsthailo)
+include(GNUInstallDirs)
+
if(NOT CMAKE_HOST_UNIX)
message(FATAL_ERROR "Only unix hosts are supported, stopping build")
endif()
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/")
-find_package(HailoRT)
+find_package(HailoRT 4.8.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")
diff --git a/hailort/libhailort/bindings/gstreamer/cmake/FindHailoRT.cmake b/hailort/libhailort/bindings/gstreamer/cmake/FindHailoRT.cmake
deleted file mode 100644
index 85906ac..0000000
--- a/hailort/libhailort/bindings/gstreamer/cmake/FindHailoRT.cmake
+++ /dev/null
@@ -1,28 +0,0 @@
-# - Try to find HailoRT
-# - If libhailort is defined (building as part of the build tree), use it
-# - Otherwise, find HAILORT_LIB and HAILORT_INCLUDE_DIR, and import libhailort
-
-if (NOT TARGET libhailort)
- # find_path finds a directory containing the named file
- find_path(HAILORT_INCLUDE_DIR "hailo/" PATH_SUFFIXES "include/")
-
- find_library(HAILORT_LIB "libhailort.so.4.6.0" PATH_SUFFIXES "lib/")
-
- include(FindPackageHandleStandardArgs)
- # Handle the QUIETLY and REQUIRED arguments and set HAILORT_FOUND to TRUE
- # if all listed variables are TRUE
- find_package_handle_standard_args(
- HailoRT
- DEFAULT_MSG
- HAILORT_LIB
- HAILORT_INCLUDE_DIR
- )
-
- add_library(HailoRT::libhailort SHARED IMPORTED)
- set_target_properties(HailoRT::libhailort PROPERTIES
- IMPORTED_LOCATION "${HAILORT_LIB}"
- INTERFACE_INCLUDE_DIRECTORIES "${HAILORT_INCLUDE_DIR}"
- )
-else()
- add_library(HailoRT::libhailort ALIAS libhailort)
-endif()
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/common.hpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/common.hpp
index 1ee88a3..8e8759e 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/common.hpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/common.hpp
@@ -51,6 +51,9 @@ using namespace hailort;
#define HAILO_SUPPORTED_FORMATS "{ RGB, YUY2 }"
#define HAILO_VIDEO_CAPS GST_VIDEO_CAPS_MAKE(HAILO_SUPPORTED_FORMATS)
+#define HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS (0)
+#define HAILO_DEFAULT_SCHEDULER_THRESHOLD (1)
+
#define GST_CHECK(cond, ret_val, element, domain, ...) \
do { \
if (!(cond)) { \
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailodevicestats.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailodevicestats.cpp
index 1049a16..f4a2f31 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailodevicestats.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailodevicestats.cpp
@@ -31,7 +31,6 @@ GST_DEBUG_CATEGORY_STATIC(gst_hailodevicestats_debug_category);
2 * sampling_period (1.1) * averaging_factor (256) [ms].
Therefore we want it to be the period of time that the core will sleep between samples,
plus a factor of 20 percent */
-#define POWER_MEASUREMENT_DELAY_MS (static_cast(1100 / 1000.0 * 256 * 2 * 1.2))
static void gst_hailodevicestats_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void gst_hailodevicestats_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -226,10 +225,10 @@ hailo_status HailoDeviceStatsImpl::run_measure_loop()
hailo_status status = m_device->stop_power_measurement();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Stopping power measurement failed, status = %d", status);
- status = m_device->set_power_measurement(0, HAILO_DVM_OPTIONS_AUTO, HAILO_POWER_MEASUREMENT_TYPES__AUTO);
+ status = m_device->set_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, HAILO_DVM_OPTIONS_AUTO, HAILO_POWER_MEASUREMENT_TYPES__AUTO);
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting power measurement parameters failed, status = %d", status);
- status = m_device->start_power_measurement(POWER_MEASUREMENT_DELAY_MS, HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
+ status = m_device->start_power_measurement(HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Starting power measurement failed, status = %d", status);
auto device_string = Device::pcie_device_info_to_string(m_device_info);
@@ -237,7 +236,7 @@ hailo_status HailoDeviceStatsImpl::run_measure_loop()
const char *device_raw_string = device_string->c_str();
while (m_is_thread_running.load()) {
- auto measurement = m_device->get_power_measurement(0, true);
+ auto measurement = m_device->get_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, true);
GST_CHECK_EXPECTED_AS_STATUS(measurement, m_element, RESOURCE, "Getting power measurement failed, status = %d", measurement.status());
if (!m_is_silent) {
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.cpp
index cd1fa98..b39e4e2 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.cpp
@@ -30,6 +30,28 @@
GST_DEBUG_CATEGORY_STATIC(gst_hailonet_debug_category);
#define GST_CAT_DEFAULT gst_hailonet_debug_category
+#define GST_TYPE_SCHEDULING_ALGORITHM (gst_scheduling_algorithm_get_type ())
+static GType
+gst_scheduling_algorithm_get_type (void)
+{
+ static GType scheduling_algorithm_type = 0;
+
+ /* Tightly coupled to hailo_scheduling_algorithm_e */
+
+ if (!scheduling_algorithm_type) {
+ static GEnumValue algorithm_types[] = {
+ { HAILO_SCHEDULING_ALGORITHM_NONE, "Scheduler is not active", "HAILO_SCHEDULING_ALGORITHM_NONE" },
+ { HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN, "Round robin", "HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN" },
+ { HAILO_SCHEDULING_ALGORITHM_MAX_ENUM, NULL, NULL },
+ };
+
+ scheduling_algorithm_type =
+ g_enum_register_static ("GstHailoSchedulingAlgorithms", algorithm_types);
+ }
+
+ return scheduling_algorithm_type;
+}
+
constexpr std::chrono::milliseconds WAIT_FOR_FLUSH_TIMEOUT_MS(1000);
static void gst_hailonet_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
@@ -53,7 +75,10 @@ enum
PROP_OUTPUTS_MAX_POOL_SIZE,
PROP_IS_ACTIVE,
PROP_DEVICE_COUNT,
- PROP_VDEVICE_KEY
+ PROP_VDEVICE_KEY,
+ PROP_SCHEDULING_ALGORITHM,
+ PROP_SCHEDULER_TIMEOUT_MS,
+ PROP_SCHEDULER_THRESHOLD,
};
G_DEFINE_TYPE(GstHailoNet, gst_hailonet, GST_TYPE_BIN);
@@ -116,9 +141,26 @@ static void gst_hailonet_class_init(GstHailoNetClass *klass)
DEFAULT_OUTPUTS_MAX_POOL_SIZE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_IS_ACTIVE,
g_param_spec_boolean("is-active", "Is Network Activated", "Controls whether this element should be active. "
- "By default, the hailonet element will not be active unless there is only one hailonet in the pipeline", false,
+ "By default, the hailonet element will not be active unless it is the only one. "
+ "Setting this property in combination with 'scheduling-algorithm' different than HAILO_SCHEDULING_ALGORITHM_NONE is not supported.", false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+ g_object_class_install_property(gobject_class, PROP_SCHEDULING_ALGORITHM,
+ g_param_spec_enum("scheduling-algorithm", "Scheduling policy for automatic network group switching", "Controls the Model Scheduler algorithm of HailoRT. "
+ "Gets values from the enum GstHailoSchedulingAlgorithms. "
+ "Using Model Scheduler algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE, excludes the property 'is-active'. "
+ "When using the same VDevice across multiple hailonets, all should have the same 'scheduling-algorithm'. "
+ "Currently only supported with 1 device (e.g. device-count=1).",
+ GST_TYPE_SCHEDULING_ALGORITHM, HAILO_SCHEDULING_ALGORITHM_NONE,
+ (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+ g_object_class_install_property(gobject_class, PROP_SCHEDULER_TIMEOUT_MS,
+ g_param_spec_uint("scheduler-timeout-ms", "Timeout for for scheduler in ms", "The maximum time period that may pass before getting run time from the scheduler,"
+ " as long as at least one send request has been sent.",
+ HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS, std::numeric_limits::max(), HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+ g_object_class_install_property(gobject_class, PROP_SCHEDULER_THRESHOLD,
+ g_param_spec_uint("scheduler-threshold", "Frames threshold for scheduler", "The minimum number of send requests required before the hailonet is considered ready to get run time from the scheduler.",
+ HAILO_DEFAULT_SCHEDULER_THRESHOLD, std::numeric_limits::max(), HAILO_DEFAULT_SCHEDULER_THRESHOLD, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
// See information about the "flush" signal in the element description
g_signal_new(
"flush",
@@ -333,6 +375,11 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
{
gboolean new_is_active = g_value_get_boolean(value);
+ if (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get()) {
+ g_error("scheduling-algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE in combination with 'is-active' is not supported.");
+ break;
+ }
+
if (m_has_called_activate) {
if (m_props.m_is_active.get() && !new_is_active) {
// Setting this to false before deactivating to signal hailosend and hailorecv to stop inferring
@@ -358,6 +405,39 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
}
break;
}
+ case PROP_SCHEDULING_ALGORITHM:
+ if (m_was_configured) {
+ g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
+ break;
+ }
+ if (m_props.m_is_active.was_changed() && (g_value_get_enum(value) != HAILO_SCHEDULING_ALGORITHM_NONE)) {
+ g_error("scheduling-algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE in combination with 'is-active' is not supported.");
+ break;
+ }
+ m_props.m_scheduling_algorithm = static_cast(g_value_get_enum(value));
+ break;
+ case PROP_SCHEDULER_TIMEOUT_MS:
+ if (m_was_configured) {
+ g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
+ break;
+ }
+ if (m_props.m_is_active.was_changed()) {
+ g_error("scheduler usage (scheduler-timeout-ms) in combination with 'is-active' is not supported.");
+ break;
+ }
+ m_props.m_scheduler_timeout_ms = g_value_get_uint(value);
+ break;
+ case PROP_SCHEDULER_THRESHOLD:
+ if (m_was_configured) {
+ g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
+ break;
+ }
+ if (m_props.m_is_active.was_changed()) {
+ g_error("scheduler usage (scheduler-threshold) in combination with 'is-active' is not supported.");
+ break;
+ }
+ m_props.m_scheduler_threshold = g_value_get_uint(value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -416,6 +496,15 @@ void HailoNetImpl::get_property(GObject *object, guint property_id, GValue *valu
case PROP_IS_ACTIVE:
g_value_set_boolean(value, m_props.m_is_active.get());
break;
+ case PROP_SCHEDULING_ALGORITHM:
+ g_value_set_enum(value, m_props.m_scheduling_algorithm.get());
+ break;
+ case PROP_SCHEDULER_TIMEOUT_MS:
+ g_value_set_uint(value, m_props.m_scheduler_timeout_ms.get());
+ break;
+ case PROP_SCHEDULER_THRESHOLD:
+ g_value_set_uint(value, m_props.m_scheduler_threshold.get());
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -428,7 +517,7 @@ hailo_status HailoNetImpl::set_hef()
GST_CHECK(nullptr != m_net_group_handle, HAILO_OUT_OF_HOST_MEMORY, m_element, RESOURCE, "Failed allocating memory for network handle!");
hailo_status status = m_net_group_handle->set_hef(m_props.m_device_id.get(), m_props.m_device_count.get(), m_props.m_vdevice_key.get(),
- m_props.m_hef_path.get());
+ m_props.m_scheduling_algorithm.get(), m_props.m_hef_path.get());
if (HAILO_SUCCESS != status) {
return status;
}
@@ -487,6 +576,15 @@ hailo_status HailoNetImpl::configure_network_group()
}
m_was_configured = true;
+ if (m_props.m_scheduler_timeout_ms.was_changed()) {
+ status = m_net_group_handle->set_scheduler_timeout(m_props.m_network_name.get(), m_props.m_scheduler_timeout_ms.get());
+ GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting scheduler timeout failed, status = %d", status);
+ }
+ if (m_props.m_scheduler_threshold.was_changed()) {
+ status = m_net_group_handle->set_scheduler_threshold(m_props.m_network_name.get(), m_props.m_scheduler_threshold.get());
+ 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);
GST_CHECK_EXPECTED_AS_STATUS(vstreams, m_element, RESOURCE, "Creating vstreams failed, status = %d", status);
@@ -498,8 +596,13 @@ hailo_status HailoNetImpl::configure_network_group()
return HAILO_SUCCESS;
}
-hailo_status HailoNetImpl::activate_network_group()
+hailo_status HailoNetImpl::activate_hailonet()
{
+ if (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get()) {
+ m_props.m_is_active = true;
+ return HAILO_SUCCESS;
+ }
+
if ((1 == m_hailonet_count) && (!m_props.m_is_active.was_changed())) {
m_props.m_is_active = true;
}
@@ -567,15 +670,21 @@ hailo_status HailoNetImpl::deactivate_network_group()
GST_CHECK_EXPECTED_AS_STATUS(was_deactivated, m_element, RESOURCE, "Failed removing network, status = %d", was_deactivated.status());
if (was_deactivated.value()) {
- if (nullptr != GST_HAILOSEND(m_hailosend)->impl) {
- hailo_status status = GST_HAILOSEND(m_hailosend)->impl->clear_vstreams();
- GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing input VStreams of hailosend, status = %d", status);
- }
+ return clear_vstreams();
+ }
+ return HAILO_SUCCESS;
+}
- if (nullptr != GST_HAILORECV(m_hailorecv)->impl) {
- hailo_status status = GST_HAILORECV(m_hailorecv)->impl->clear_vstreams();
- GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing output VStreams of hailorecv, status = %d", status);
- }
+hailo_status HailoNetImpl::clear_vstreams()
+{
+ if (nullptr != GST_HAILOSEND(m_hailosend)->impl) {
+ hailo_status status = GST_HAILOSEND(m_hailosend)->impl->clear_vstreams();
+ GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing input VStreams of hailosend, status = %d", status);
+ }
+
+ if (nullptr != GST_HAILORECV(m_hailorecv)->impl) {
+ hailo_status status = GST_HAILORECV(m_hailorecv)->impl->clear_vstreams();
+ GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing output VStreams of hailorecv, status = %d", status);
}
return HAILO_SUCCESS;
@@ -596,7 +705,7 @@ gboolean HailoNetImpl::src_pad_event(GstEvent *event)
GstPadProbeReturn HailoNetImpl::sink_probe()
{
- hailo_status status = activate_network_group();
+ hailo_status status = activate_hailonet();
GST_CHECK(HAILO_SUCCESS == status, GST_PAD_PROBE_REMOVE, m_element, RESOURCE, "Failed activating network, status = %d", status);
return GST_PAD_PROBE_REMOVE;
}
@@ -634,8 +743,33 @@ hailo_status HailoNetImpl::signal_was_flushed_event()
return m_was_flushed_event->signal();
}
+static bool do_versions_match(GstHailoNet *self)
+{
+ hailo_version_t libhailort_version = {};
+ auto status = hailo_get_library_version(&libhailort_version);
+ if (HAILO_SUCCESS != status) {
+ GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("Fetching libhailort version has failed! status = %d", status), (NULL));
+ return false;
+ }
+
+ bool versions_match = ((HAILORT_MAJOR_VERSION == libhailort_version.major) &&
+ (HAILORT_MINOR_VERSION == libhailort_version.minor) &&
+ (HAILORT_REVISION_VERSION == libhailort_version.revision));
+ if (!versions_match) {
+ GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("libhailort version (%d.%d.%d) does not match gsthailonet version (%d.%d.%d)",
+ libhailort_version.major, libhailort_version.minor, libhailort_version.revision,
+ HAILORT_MAJOR_VERSION, HAILORT_MINOR_VERSION, HAILORT_REVISION_VERSION), (NULL));
+ return false;
+ }
+ return true;
+}
+
static void gst_hailonet_init(GstHailoNet *self)
{
+ if (!do_versions_match(self)) {
+ return;
+ }
+
auto hailonet_impl = HailoNetImpl::create(self);
if (!hailonet_impl) {
GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("Creating hailonet implementation has failed! status = %d", hailonet_impl.status()), (NULL));
@@ -700,12 +834,15 @@ static GstStateChangeReturn gst_hailonet_change_state(GstElement *element, GstSt
}
case GST_STATE_CHANGE_READY_TO_NULL:
{
+ // VStreams are destructed in hailosend's/hailorecv's GST_STATE_CHANGE_READY_TO_NULL (which calls 'clear_abort' on low-level streams)
// We abort streams again because deactivation of the activated network group calls flush, and it can fail on timeout unless we call abort
hailo_status status = hailonet->abort_streams();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Aborting streams has failed, status = %d\n", status);
- status = hailonet->deactivate_network_group();
- GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Deactivating network group has failed, status = %d\n", status);
+ if (HAILO_SCHEDULING_ALGORITHM_NONE == hailonet->get_props().m_scheduling_algorithm.get()) {
+ status = hailonet->deactivate_network_group();
+ GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Deactivating network group failed, status = %d\n", status);
+ }
// Cleanup all of hailonet memory
hailonet.reset();
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.hpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.hpp
index 810e37d..7ff211d 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.hpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.hpp
@@ -52,7 +52,8 @@ struct HailoNetProperties final
{
public:
HailoNetProperties() : m_device_id(nullptr), m_hef_path(nullptr), m_network_name(nullptr), m_batch_size(HAILO_DEFAULT_BATCH_SIZE),
- m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY)
+ m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY), m_scheduling_algorithm(HAILO_SCHEDULING_ALGORITHM_NONE),
+ m_scheduler_timeout_ms(HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS), m_scheduler_threshold(HAILO_DEFAULT_SCHEDULER_THRESHOLD)
{}
HailoElemProperty m_device_id;
@@ -62,6 +63,9 @@ public:
HailoElemProperty m_is_active;
HailoElemProperty m_device_count;
HailoElemProperty m_vdevice_key;
+ HailoElemProperty m_scheduling_algorithm;
+ HailoElemProperty m_scheduler_timeout_ms;
+ HailoElemProperty m_scheduler_threshold;
};
class HailoNetImpl final
@@ -76,20 +80,27 @@ public:
hailo_status set_hef();
hailo_status link_elements();
hailo_status configure_network_group();
- hailo_status activate_network_group();
+ hailo_status activate_hailonet();
hailo_status abort_streams();
- hailo_status deactivate_network_group();
+
gboolean src_pad_event(GstEvent *event);
GstPadProbeReturn sink_probe();
gboolean is_active();
hailo_status flush();
hailo_status signal_was_flushed_event();
+ hailo_status deactivate_network_group();
+ HailoNetProperties &get_props() {
+ return m_props;
+ }
+
private:
void init_ghost_sink();
void init_ghost_src();
Expected get_network_group_name(const std::string &network_name);
+ hailo_status clear_vstreams();
+
static std::atomic_uint32_t m_hailonet_count;
static std::mutex m_mutex;
GstHailoNet *m_element;
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailorecv.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailorecv.cpp
index 34496e9..9c6835c 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailorecv.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailorecv.cpp
@@ -359,11 +359,9 @@ static GstFlowReturn gst_hailorecv_buffer_pool_acquire_callback(GstBufferPool *p
++hailo_pool->buffers_acquired;
GstStructure *pool_config = gst_buffer_pool_get_config(pool);
- GstCaps *caps = nullptr;
- guint size = 0;
- guint min_buffers = 0;
guint max_buffers = 0;
- gboolean result = gst_buffer_pool_config_get_params(pool_config, &caps, &size, &min_buffers, &max_buffers);
+ gboolean result = gst_buffer_pool_config_get_params(pool_config, NULL, NULL, NULL, &max_buffers);
+ gst_structure_free(pool_config);
if (!result) {
g_error("Failed getting config params from buffer pool!");
return GST_FLOW_ERROR;
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/hailo_buffer_flag_meta.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/hailo_buffer_flag_meta.cpp
index a500f17..e436de8 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/hailo_buffer_flag_meta.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/hailo_buffer_flag_meta.cpp
@@ -21,7 +21,8 @@
GType gst_hailo_buffer_flag_meta_api_get_type(void)
{
- static volatile GType type;
+ // https://github.com/vmware/open-vm-tools/commit/b2c8baeaa8ac365e1445f941cf1b80999ed89a9d
+ static GType type;
static const gchar *tags[] = {HAILO_BUFFER_FLAG_META_TAG, NULL};
if (g_once_init_enter(&type)) {
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/tensor_meta.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/tensor_meta.cpp
index 060ad6d..302a96d 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/tensor_meta.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/tensor_meta.cpp
@@ -24,7 +24,8 @@
GType gst_tensor_meta_api_get_type(void)
{
- static volatile GType type;
+ // https://github.com/vmware/open-vm-tools/commit/b2c8baeaa8ac365e1445f941cf1b80999ed89a9d
+ static GType type;
static const gchar *tags[] = {TENSOR_META_TAG, NULL};
if (g_once_init_enter(&type)) {
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.cpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.cpp
index eec733b..3453ebe 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.cpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.cpp
@@ -26,14 +26,16 @@ VDeviceManager NetworkGroupHandle::m_vdevice_manager;
NetworkGroupConfigManager NetworkGroupHandle::m_net_group_config_manager;
NetworkGroupActivationManager NetworkGroupHandle::m_net_group_activation_manager;
-Expected> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key)
+Expected> 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);
+ auto expected_device = m_vdevice_manager.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;
}
-hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, const char *hef_path)
+hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key,
+ hailo_scheduling_algorithm_t scheduling_algorithm, const char *hef_path)
{
if (0 == device_count) {
device_count = HAILO_DEFAULT_DEVICE_COUNT;
@@ -41,7 +43,7 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
std::string device_id_str = (nullptr == device_id) ? "" : device_id;
- auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key);
+ auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key, scheduling_algorithm);
GST_CHECK_EXPECTED_AS_STATUS(vdevice, m_element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
m_vdevice = vdevice.release();
@@ -77,13 +79,24 @@ hailo_status NetworkGroupHandle::configure_network_group(const char *net_group_n
return HAILO_SUCCESS;
}
+
+hailo_status NetworkGroupHandle::set_scheduler_timeout(const char *network_name, uint32_t timeout_ms)
+{
+ return m_cng->set_scheduler_timeout(std::chrono::milliseconds(timeout_ms), network_name);
+}
+
+hailo_status NetworkGroupHandle::set_scheduler_threshold(const char *network_name, uint32_t threshold)
+{
+ return m_cng->set_scheduler_threshold(threshold, network_name);
+}
+
Expected, std::vector>> NetworkGroupHandle::create_vstreams(const char *network_name,
const std::vector &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(m_network_name, m_element);
+ 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);
@@ -198,26 +211,28 @@ Expected NetworkGroupHandle::remove_network_group()
Expected> VDeviceManager::create_vdevice(const void *element, const std::string &device_id, uint16_t device_count,
- uint32_t vdevice_key)
+ uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm)
{
std::unique_lock lock(m_mutex);
if (!device_id.empty()) {
- return create_shared_vdevice(element, device_id);
+ return create_shared_vdevice(element, device_id, scheduling_algorithm);
}
if (DEFAULT_VDEVICE_KEY != vdevice_key) {
- return create_shared_vdevice(element, device_count, vdevice_key);
+ return create_shared_vdevice(element, device_count, vdevice_key, scheduling_algorithm);
}
- return create_unique_vdevice(element, device_count);
+ return create_unique_vdevice(element, device_count, scheduling_algorithm);
}
-Expected> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id)
+Expected> 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);
- if (found_vdevice) {
+ 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();
}
@@ -227,40 +242,48 @@ Expected> VDeviceManager::create_shared_vdevice(const v
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_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> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key)
+Expected> 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);
- if (found_vdevice) {
+ 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_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> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count)
+Expected> 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());
@@ -270,12 +293,23 @@ Expected> VDeviceManager::create_unique_vdevice(const v
return vdevice_ptr;
}
-Expected> VDeviceManager::get_vdevice(const std::string &device_id)
+Expected> 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;
}
@@ -300,15 +334,24 @@ Expected> NetworkGroupConfigManager::con
return std::move(network_group_list->at(0));
}
-hailo_status NetworkGroupConfigManager::add_network(const std::string &network_name, const GstElement *owner_element)
+hailo_status NetworkGroupConfigManager::add_network_to_shared_network_group(const std::string &shared_device_id, const std::string &network_name,
+ const GstElement *owner_element)
{
std::unique_lock lock(m_mutex);
- auto found = m_configured_networks.find(network_name);
- GST_CHECK(found == m_configured_networks.end(), HAILO_INVALID_OPERATION, owner_element, RESOURCE,
- "Network %s was already configured by %s!", network_name.c_str(), found->second.c_str());
+ if (shared_device_id.empty()) {
+ // the device is unique so we don't need to share anything
+ return HAILO_SUCCESS;
+ }
- m_configured_networks[network_name] = GST_ELEMENT_NAME(owner_element);
+ auto found_by_device = m_configured_networks.find(shared_device_id);
+ if (found_by_device != m_configured_networks.end()) {
+ auto found_network = found_by_device->second.find(network_name);
+ GST_CHECK(found_network == found_by_device->second.end(), HAILO_INVALID_OPERATION, owner_element, RESOURCE,
+ "Network %s was already configured by %s by the same device!", network_name.c_str(), found_network->second.c_str());
+ }
+
+ m_configured_networks[shared_device_id][network_name] = GST_ELEMENT_NAME(owner_element);
return HAILO_SUCCESS;
}
diff --git a/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.hpp b/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.hpp
index b83dd24..f402678 100644
--- a/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.hpp
+++ b/hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.hpp
@@ -31,23 +31,29 @@
class VDeviceManager final
{
public:
- VDeviceManager() : m_shared_vdevices(), m_unique_vdevices() {}
+ VDeviceManager() : m_shared_vdevices(), m_shared_vdevices_scheduling_algorithm(), m_unique_vdevices() {}
- Expected> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
+ Expected> 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> create_shared_vdevice(const void *element, const std::string &device_id);
- Expected> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key);
- Expected> create_unique_vdevice(const void *element, uint16_t device_count);
- Expected> get_vdevice(const std::string &device_id);
+ Expected> create_shared_vdevice(const void *element, const std::string &device_id,
+ hailo_scheduling_algorithm_t scheduling_algorithm);
+ Expected> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
+ hailo_scheduling_algorithm_t scheduling_algorithm);
+ Expected> create_unique_vdevice(const void *element, uint16_t device_count,
+ hailo_scheduling_algorithm_t scheduling_algorithm);
+ Expected> 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 "" or "-" */
std::unordered_map> m_shared_vdevices;
+ std::unordered_map m_shared_vdevices_scheduling_algorithm; // Used to check that 2 shared vdevices gets the same scheduling-algorithm
std::vector> m_unique_vdevices;
std::mutex m_mutex;
};
+using device_id_t = std::string;
using network_name_t = std::string;
using hailonet_name_t = std::string;
@@ -58,7 +64,8 @@ public:
Expected> configure_network_group(const void *element, const std::string &device_id,
const char *network_group_name, uint16_t batch_size, std::shared_ptr &vdevice, std::shared_ptr hef,
NetworkGroupsParamsMap &net_groups_params_map);
- hailo_status add_network(const std::string &network_name, const GstElement *owner_element);
+ 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);
@@ -69,7 +76,7 @@ private:
// TODO: change this map to store only the shared network_groups (used by multiple hailonets with the same vdevices)
std::unordered_map> m_configured_net_groups;
- std::unordered_map m_configured_networks;
+ std::unordered_map> m_configured_networks;
std::mutex m_mutex;
};
@@ -96,7 +103,8 @@ public:
NetworkGroupHandle(const GstElement *element) : m_element(element), m_shared_device_id(), m_net_group_name(), m_network_name(), m_batch_size(0),
m_vdevice(nullptr), m_hef(nullptr), m_cng(nullptr), m_ang(nullptr) {}
- hailo_status set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, const char *hef_path);
+ 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);
Expected, std::vector>> create_vstreams(const char *network_name,
const std::vector &output_formats);
@@ -104,6 +112,10 @@ public:
hailo_status abort_streams();
Expected remove_network_group();
+ hailo_status set_scheduler_timeout(const char *network_name, uint32_t timeout_ms);
+ hailo_status set_scheduler_threshold(const char *network_name, uint32_t threshold);
+
+
std::shared_ptr hef()
{
return m_hef;
@@ -111,13 +123,14 @@ public:
private:
Expected get_configure_params(Hef &hef, const char *net_group_name, uint16_t batch_size);
- Expected> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
+ Expected> 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 NetworkGroupConfigManager m_net_group_config_manager;
static NetworkGroupActivationManager m_net_group_activation_manager;
const GstElement *m_element;
- std::string m_shared_device_id;
+ std::string m_shared_device_id; // empty string when using unique device
std::string m_net_group_name;
std::string m_network_name;
uint16_t m_batch_size;
diff --git a/hailort/libhailort/bindings/python/CMakeLists.txt b/hailort/libhailort/bindings/python/CMakeLists.txt
index febd4f0..d38c6e8 100644
--- a/hailort/libhailort/bindings/python/CMakeLists.txt
+++ b/hailort/libhailort/bindings/python/CMakeLists.txt
@@ -1 +1,9 @@
add_subdirectory(src)
+
+# copy files to venv
+if(HAILO_BUILD_PYHAILORT_VENV)
+ add_custom_target(pyhailort_venv ALL
+ COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_LIST_DIR}/platform/hailo_platform/pyhailort/
+ )
+ add_dependencies(pyhailort_venv _pyhailort)
+endif()
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/examples/hef_infer_pipeline_vstream.py b/hailort/libhailort/bindings/python/examples/hef_infer_pipeline_vstream.py
index b01c038..c1896df 100644
--- a/hailort/libhailort/bindings/python/examples/hef_infer_pipeline_vstream.py
+++ b/hailort/libhailort/bindings/python/examples/hef_infer_pipeline_vstream.py
@@ -1,6 +1,6 @@
from hailo_platform import (HEF, PcieDevice, ConfigureParams, InferVStreams, InputVStreamParams,
OutputVStreamParams, FormatType)
-from hailo_platform.drivers.hailort.pyhailort import HailoStreamInterface
+from hailo_platform.pyhailort.pyhailort import HailoStreamInterface
import numpy as np
import argparse
@@ -25,6 +25,8 @@ def main():
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)
+
+ print('Inference ran successfully')
if __name__ == '__main__':
main()
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/__init__.py
index 1c6ca2e..610f878 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/__init__.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/__init__.py
@@ -4,40 +4,10 @@ import sys
import pathlib
import pprint
-from hailo_platform.common.paths_manager.version import get_version
-from hailo_platform.common.paths_manager.paths import PackingInfo, PackingStatus
-
class MissingPyHRTLib(Exception):
pass
-# This hack checks which modules the user has on his computer.
-# packing status set to "packed_client" if it can't import the PLATFORM_INTERNALS module
-# it set the packing status to "standalone_platform" if it can't import the SDK_COMMON module
-
-try:
- import hailo_platform_internals # noqa F401
-except ImportError:
- PackingInfo().status = PackingStatus.packed_client
-
-try:
- import hailo_sdk_common # noqa F401
-except:
- PackingInfo().status = PackingStatus.standalone_platform
-
-
-
-# This hack only affects internals users with hailo_validation installed.
-# It changes the packing status to PACKED if it thinks SDK was installed from
-# wheel.
-try:
- import hailo_validation # noqa F401
- if 'site-packages/hailo_sdk' in __path__[0] :
- PackingInfo().status = PackingStatus.packed_client
-except ImportError:
- pass
-
-
# Must appear before other imports:
def join_drivers_path(path):
_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -45,11 +15,8 @@ def join_drivers_path(path):
from hailo_platform.tools.udp_rate_limiter import UDPRateLimiter
-from hailo_platform.drivers.hw_object import PcieDevice, EthernetDevice
-from hailo_platform.drivers.hailo_controller.power_measurement import (DvmTypes,
- PowerMeasurementTypes,
- SamplingPeriod, AveragingFactor)
-from hailo_platform.drivers.hailort.pyhailort import (HEF, ConfigureParams,
+from hailo_platform.pyhailort.hw_object import PcieDevice, EthernetDevice
+from hailo_platform.pyhailort.pyhailort import (HEF, ConfigureParams,
FormatType, FormatOrder,
MipiDataTypeRx, MipiPixelsPerClock,
MipiClockSelection, MipiIspImageInOrder,
@@ -57,7 +24,8 @@ from hailo_platform.drivers.hailort.pyhailort import (HEF, ConfigureParams,
Endianness, HailoStreamInterface,
InputVStreamParams, OutputVStreamParams,
InputVStreams, OutputVStreams,
- InferVStreams, HailoStreamDirection, HailoFormatFlags, HailoCpuId, VDevice)
+ InferVStreams, HailoStreamDirection, HailoFormatFlags, HailoCpuId, VDevice,
+ DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex)
def _verify_pyhailort_lib_exists():
python_version = "".join(str(i) for i in sys.version_info[:2])
@@ -66,16 +34,29 @@ def _verify_pyhailort_lib_exists():
"nt": "pyd", # Windows
}[os.name]
- path = f"{__path__[0]}/drivers/hailort/"
+ path = f"{__path__[0]}/pyhailort/"
if next(pathlib.Path(path).glob(f"_pyhailort*.{lib_extension}"), None) is None:
raise MissingPyHRTLib(f"{path} should include a _pyhailort library (_pyhailort*{python_version}*.{lib_extension}). Includes: {pprint.pformat(list(pathlib.Path(path).iterdir()))}")
_verify_pyhailort_lib_exists()
+def get_version(package_name):
+ # See: https://packaging.python.org/guides/single-sourcing-package-version/ (Option 5)
+ # We assume that the installed package is actually the same one we import. This assumption may
+ # break in some edge cases e.g. if the user modifies sys.path manually.
+
+ # hailo_platform package has been renamed to hailort, but the import is still hailo_platform
+ if package_name == "hailo_platform":
+ package_name = "hailort"
+ try:
+ import pkg_resources
+ return pkg_resources.get_distribution(package_name).version
+ except:
+ return 'unknown'
__version__ = get_version('hailo_platform')
__all__ = ['EthernetDevice', 'DvmTypes', 'PowerMeasurementTypes',
- 'SamplingPeriod', 'AveragingFactor', 'UDPRateLimiter', 'PcieDevice', 'HEF',
+ 'SamplingPeriod', 'AveragingFactor', 'MeasurementBufferIndex', 'UDPRateLimiter', 'PcieDevice', 'HEF',
'ConfigureParams', 'FormatType', 'FormatOrder', 'MipiDataTypeRx', 'MipiPixelsPerClock', 'MipiClockSelection',
'MipiIspImageInOrder', 'MipiIspImageOutDataType', 'join_drivers_path', 'IspLightFrequency', 'HailoPowerMode',
'Endianness', 'HailoStreamInterface', 'InputVStreamParams', 'OutputVStreamParams',
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/compatibility/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/compatibility/__init__.py
deleted file mode 100644
index 3dd945d..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/compatibility/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-import six
-from io import IOBase
-
-# Based on: https://portingguide.readthedocs.io/en/latest/builtins.html#removed-file
-try:
- # Python 2
- file_types = (file, IOBase,)
-except NameError:
- # "file" isn't a built-in type in Python 3
- file_types = (IOBase,)
-
-# Exporting types and functions from six
-string_types = six.string_types
-integer_types = six.integer_types
-class_types = six.class_types
-text_type = six.text_type
-binary_type = six.binary_type
-
-def ensure_binary(s, encoding='utf-8', errors='strict'):
- return six.ensure_binary(s, encoding=encoding, errors=errors)
-
-def ensure_str(s, encoding='utf-8', errors='strict'):
- return six.ensure_str(s, encoding=encoding, errors=errors)
-
-def ensure_text(s, encoding='utf-8', errors='strict'):
- return six.ensure_text(s, encoding=encoding, errors=errors)
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/config.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/config.py
deleted file mode 100644
index 5e1d7fc..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/config.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python
-import os
-from configparser import ConfigParser
-from hailo_platform.common.paths_manager.paths import PackingInfo, PackingStatus, SDKPaths
-from hailo_platform.paths_manager.paths import PlatformPaths
-
-
-class ConfigFileNotFoundException(Exception):
- pass
-
-
-def get_home_hailo_dir():
- return os.path.expanduser('~/.hailo')
-
-def get_parsed_config_from_path(config_path=None):
- actual_config_path = _get_config_path_with_default(config_path)
- config = ConfigParser()
- with open(actual_config_path, 'r') as config_file:
- config.read_file(config_file)
- return config
-
-
-def _get_config_path_with_default(config_path=None):
- if config_path is not None and os.path.isfile(config_path):
- return config_path
- default_path = _get_config_path()
- if os.path.isfile(default_path):
- return default_path
- raise ConfigFileNotFoundException('Could not find configuration file at default path: {}.'.format(default_path))
-
-
-def _get_config_path():
- config_file_name = 'config'
-
- if PackingInfo().status in [PackingStatus.unpacked]:
- full_path = os.path.join(SDKPaths().join_sdk('../'), config_file_name)
- if os.path.exists(full_path):
- return full_path
- #This is a CI nightly workaround because we are in unpack mode but installing whl's
- #In this case SDKPaths() is inside the site packages and not the sdk root. the workaround is to look for local dir
- elif os.path.exists(config_file_name):
- return config_file_name
-
- elif PackingInfo().status in [PackingStatus.standalone_platform]:
- full_path = os.path.join(PlatformPaths().join_platform('../../'), config_file_name)
- if os.path.exists(full_path) and os.path.isfile(full_path):
- return full_path
-
- elif os.path.exists(config_file_name):
- return config_file_name
-
- return os.path.join(get_home_hailo_dir(), config_file_name)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/paths.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/paths.py
deleted file mode 100644
index 3dada52..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/paths.py
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/env python
-from builtins import object
-import os
-import shutil
-import copy
-from enum import Enum
-
-
-from hailo_platform.common.logger.logger import default_logger
-from future.utils import with_metaclass
-
-logger = default_logger()
-
-
-class ConfigStageNotSetException(Exception):
- pass
-
-class PackagingException(Exception):
- pass
-
-class Singleton(type):
- _instances = {}
-
- def __call__(cls, *args, **kwargs):
- if cls not in cls._instances:
- cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
- return cls._instances[cls]
-
-
-class PackingStatus(Enum):
- unpacked = 'unpacked'
- packed_server = 'packed_server'
- packed_client = 'packed_client'
- standalone_platform = 'standalone_platform'
-
-
-class PackingInfo(with_metaclass(Singleton, object)):
- def __init__(self):
- self._status = PackingStatus.unpacked
- self._has_graphviz = True
-
- def is_packed(self):
- return self._status not in [PackingStatus.unpacked]
-
- @property
- def status(self):
- return self._status
-
- @status.setter
- def status(self, val):
- self._status = val
-
- @property
- def has_graphviz(self):
- return self._has_graphviz
-
- @has_graphviz.setter
- def has_graphviz(self, val):
- self._has_graphviz = val
-
-
-class SDKPaths(with_metaclass(Singleton, object)):
- DEFAULT_BUILD_DIR = 'build'
-
- def __init__(self):
- self._build_dir_name = type(self).DEFAULT_BUILD_DIR
- self._build_dir_path = '.'
- self._custom_build_dir = None
-
- @property
- def _sdk_path(self):
- packaging_status = PackingInfo().status
- if packaging_status == PackingStatus.packed_server:
- import hailo_sdk_common
- return os.path.dirname(hailo_sdk_common.__path__[0])
- if packaging_status == PackingStatus.packed_client:
- return ''
- if packaging_status == PackingStatus.standalone_platform:
- raise PackagingException(
- 'the packaging status is \'standalone_platform\', and there was a call to a sdk method')
- import hailo_sdk_common
- return os.path.join(os.path.dirname(os.path.dirname(hailo_sdk_common.__path__[0])), 'sdk_server')
-
- @property
- def custom_build_dir(self):
- return self._custom_build_dir
-
- @custom_build_dir.setter
- def custom_build_dir(self, custom_build_dir):
- self._custom_build_dir = custom_build_dir
-
- def join_sdk(self, path):
- return os.path.join(self._sdk_path, path)
-
- def join_sdk_common(self, path):
- import hailo_sdk_common
- if PackingInfo().status == PackingStatus.packed_server:
- return self.join_sdk(os.path.join('hailo_sdk_common', path))
- return os.path.join(os.path.abspath(hailo_sdk_common.__path__[0]), path)
-
- def set_client_build_dir_path(self):
- if PackingInfo().status == PackingStatus.unpacked:
- self._build_dir_path = '../sdk_client'
-
- def set_server_build_dir_path(self):
- if PackingInfo().status == PackingStatus.unpacked:
- self._build_dir_path = '../sdk_server'
-
- def set_build_dir(self, build_dir_name=None, clean=False):
- self._build_dir_name = build_dir_name if build_dir_name is not None else type(self).DEFAULT_BUILD_DIR
- logger.debug('Build dir name: {}'.format(self._build_dir_name))
- build_dir = self.build_dir
- if os.path.exists(build_dir):
- if clean:
- logger.debug('Deleting build dir : {}'.format(build_dir))
- shutil.rmtree(build_dir)
- self._make_build_dir(build_dir)
- return
- self._make_build_dir(build_dir)
-
- @property
- def build_dir(self):
- if self._custom_build_dir:
- return self._custom_build_dir
- return os.path.join(self._sdk_path, self._build_dir_path, self._build_dir_name)
-
- def join_build_sdk(self, path):
- build_dir = self.build_dir
- if os.path.exists(build_dir):
- return os.path.join(build_dir, path)
- logger.debug('Creating build dir : {}'.format(build_dir))
- self._make_build_dir(build_dir)
- return os.path.join(build_dir, path)
-
- def _make_build_dir(self, build_dir):
- os.makedirs(build_dir)
-
-
-class BaseConfigDirs(object):
-
- DIRS_BUILD_ONLY = {
- 'outputs_dir': ['outputs'],
- 'bin_dir': ['bin'],
- 'weights_dir': ['data', 'weights'],
- 'inputs_dir': ['data', 'inputs'],
- }
-
- DIRS_SDK_ONLY = {}
-
- DIRS_BOTH = {}
-
- def __init__(self, hw_arch):
- self._hw_arch = hw_arch.name
- self._paths = SDKPaths()
- self._dirs = {}
- for d in [type(self).DIRS_BUILD_ONLY, type(self).DIRS_SDK_ONLY, type(self).DIRS_BOTH]:
- self._dirs.update(self._format_dirs(d))
-
- def get_dir(self, name, in_build=True):
- return self._join_base(self._dirs[name], in_build)
-
- def _format_dirs(self, input_dirs):
- result = {}
- for name, dir_path in input_dirs.items():
- result[name] = os.path.join(*dir_path).format(hw_arch=self._hw_arch)
- return result
-
- def _join_base(self, path, in_build=True):
- base_dir = self._paths.build_dir if in_build else 'microcode'
- whole_path = os.path.join(base_dir, path)
- return self._paths.join_sdk(whole_path)
-
- @property
- def build_dirs_keys(self):
- return list(type(self).DIRS_BUILD_ONLY.keys()) + list(type(self).DIRS_BOTH.keys())
-
-
-class BaseConfigPaths(BaseConfigDirs):
-
- PATHS = {
- 'bin': ['{bin_dir}', '{network_name}.mem'],
- }
-
- def __init__(self, hw_arch, model_name):
- super(BaseConfigPaths, self).__init__(hw_arch)
- self._model_name = model_name
- self._stage = None
- self._stage_only = False
-
- def set_stage(self, stage, stage_only=False):
- self._stage = stage
- self._stage_only = stage_only
-
- def get_path(self, path_name, in_build=True):
- template = os.path.join(*type(self).PATHS[path_name])
- if self._stage is None and '{network_name}' in template:
- raise ConfigStageNotSetException('Set the stage before trying to get paths')
- format_dict = copy.deepcopy(self._dirs)
- format_dict['model_name'] = self._model_name
- if self._stage_only:
- format_dict['network_name'] = self._stage
- else:
- format_dict['network_name'] = '{model_name}.{stage}'.format(
- model_name=self._model_name, stage=self._stage
- )
- config_path = template.format(**format_dict)
- return self._join_base(config_path, in_build)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/version.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/version.py
deleted file mode 100644
index 04d40ee..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-
-def get_version(package_name):
- # See: https://packaging.python.org/guides/single-sourcing-package-version/ (Option 5)
- # We assume that the installed package is actually the same one we import. This assumption may
- # break in some edge cases e.g. if the user modifies sys.path manually.
-
- # hailo_platform package has been renamed to hailort, but the import is still hailo_platform
- if package_name == "hailo_platform":
- package_name = "hailort"
- try:
- import pkg_resources
- return pkg_resources.get_distribution(package_name).version
- except:
- return 'unknown'
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/inference_targets.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/inference_targets.py
deleted file mode 100644
index 80335b4..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/inference_targets.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-from builtins import object
-import json
-
-from contextlib2 import contextmanager
-
-
-class InferenceTargetException(Exception):
- """Raised when an error related to the inference target has occurred."""
- pass
-
-
-class InferenceTargets(object):
- """Enum-like class with all inference targets supported by the Hailo SDK.
- See the classes themselves for details about each target.
- """
- UNINITIALIZED = 'uninitialized'
- SDK_NATIVE = 'sdk_native'
- SDK_NATIVE_CLIPPED = 'sdk_native_clipped'
- SDK_NUMERIC = 'sdk_numeric'
- SDK_DEBUG_PRECISE_NUMERIC = 'sdk_debug_precise_numeric'
- SDK_PARTIAL_NUMERIC = 'sdk_partial_numeric'
- SDK_FINE_TUNE = 'sdk_fine_tune'
- SDK_MIXED = 'sdk_mixed'
- HW_SIMULATION = 'hw_sim'
- HW_SIMULATION_MULTI_CLUSTER = 'hw_sim_mc'
- FPGA = 'fpga'
- UDP_CONTROLLER = 'udp'
- PCIE_CONTROLLER = 'pcie'
- HW_DRY = 'hw_dry'
- HW_DRY_UPLOAD = 'hw_dry_upload'
- UV_WORKER = 'uv'
- DANNOX = 'dannox'
-
-
-class InferenceObject(object):
- """Represents a target that can run models inference. The target can be either software based
- (eventually running on CPU/GPU), or Hailo hardware based.
-
- .. note:: This class should not be used directly. Use only its inherited classes.
- """
- NAME = InferenceTargets.UNINITIALIZED
- IS_NUMERIC = False
- IS_HARDWARE = False
- IS_SIMULATION = False
-
- def __new__(cls, *args, **kwargs):
- if cls.NAME == InferenceTargets.UNINITIALIZED:
- raise InferenceTargetException(
- '{} is an abstract target and cannot be used directly.'.format(cls.__name__))
- # object's __new__() takes no parameters
- return super(type(cls), cls).__new__(cls)
-
- def __init__(self):
- """Inference object constructor."""
- self._is_device_used = False
-
- def __eq__(self, other):
- return type(self).NAME == other
-
- # TODO: Required for Python2 BW compatibility (SDK-10038)
- # This impl' comes by default in Python3
- def __ne__(self, other):
- return not self.__eq__(other)
-
- @contextmanager
- def use_device(self, *args, **kwargs):
- """A context manager that should wrap any usage of the target."""
- self._is_device_used = True
- yield
- self._is_device_used = False
-
- @property
- def name(self):
- """str: The name of this target. Valid values are defined by
- :class:`InferenceObject `.
- """
- return type(self).NAME
-
- @property
- def is_numeric(self):
- """bool: Determines whether this target is working in numeric mode.
- """
- return type(self).IS_NUMERIC
-
- @property
- def is_hardware(self):
- """bool: Determines whether this target runs on a physical hardware device.
- """
- return type(self).IS_HARDWARE
-
- @property
- def is_simulation(self):
- """bool: Determines whether this target is used for HW simulation.
- """
- return type(self).IS_SIMULATION
-
- def _get_json_dict(self):
- json_dict = {'name': self.name,
- 'is_numeric': self.is_numeric,
- 'is_hardware': self.is_hardware,
- 'is_simulation': self.is_simulation}
- return json_dict
-
- def to_json(self):
- """Get a JSON representation of this object.
-
- Returns:
- str: A JSON dump.
- """
- return json.dumps(self._get_json_dict())
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/__init__.py
index 22a799f..e7a12fb 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/__init__.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/__init__.py
@@ -1,6 +1,4 @@
#!/usr/bin/env python
-""":class:`~hailo_platform.drivers.hw_object.HailoHWObject` is the high level base class of the
-platform API. :class:`~hailo_platform.drivers.hw_object.PcieDevice` inherits from it
-and implements control and dataflow over PCIe.
-"""
+from warnings import warn
+warn("Importing from 'hailo_platform.drivers' is deprecated, One should import from 'hailo_platform' module directly.", DeprecationWarning, stacklevel=2)
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/control_object.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/control_object.py
index 0e7d4f3..ddf2de4 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/control_object.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/control_object.py
@@ -1,655 +1 @@
-#!/usr/bin/env python
-
-"""Control operations for the Hailo hardware device."""
-import struct
-from builtins import object
-from abc import ABCMeta, abstractmethod
-from future.utils import with_metaclass
-
-from hailo_platform.drivers.hailo_controller.hailo_control_protocol import HailoResetTypes, DeviceArchitectureTypes
-from hailo_platform.drivers.hailo_controller.power_measurement import SamplingPeriod, AveragingFactor, DvmTypes, PowerMeasurementTypes, DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS
-from hailo_platform.drivers.hailort.pyhailort import Control, InternalPcieDevice
-from hailo_platform.common.logger.logger import default_logger
-
-class ControlObjectException(Exception):
- """Raised on illegal ContolObject operation."""
- pass
-
-
-class FirmwareUpdateException(Exception):
- pass
-
-
-class HailoControl(with_metaclass(ABCMeta, object)):
- """Control object that sends control operations to a Hailo hardware device."""
-
- def __init__(self):
- """Initializes a new HailoControl object."""
- self._logger = default_logger()
- self._controller = None
-
- @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.drivers.hailort.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.
- """
- return self._controller.configure_device_from_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, MAC 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)."""
- return self._controller.reset(reset_type=HailoResetTypes.CHIP)
-
- def nn_core_reset(self):
- """Resets the nn_core."""
- return self._controller.reset(reset_type=HailoResetTypes.NN_CORE)
-
- def soft_reset(self):
- """reloads the device firmware (soft reset)"""
- return self._controller.reset(reset_type=HailoResetTypes.SOFT)
-
- def forced_soft_reset(self):
- """reloads the device firmware (forced soft reset)"""
- return self._controller.reset(reset_type=HailoResetTypes.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
- """
- return self._controller.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.
- """
- return self._controller.write_memory(address, 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.drivers.hailort.pyhailort.DvmTypes`):
- Which DVM will be measured. Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
- Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
- It sums :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.VDD_CORE`,
- :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AVDD_H`.
- Only :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
- Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
- measurement_type
- (:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`):
- The type of the measurement.
-
- Returns:
- float: The measured power. \n
- For :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`: \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- - :class:`~hailo_platform.drivers.hailort.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.drivers.hailort.pyhailort.PowerMeasurementTypes`.
- """
- if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
- raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
- return self._controller.power_measurement(dvm, measurement_type)
-
- def start_power_measurement(self, delay=DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS, averaging_factor=AveragingFactor.AVERAGE_256, sampling_period=SamplingPeriod.PERIOD_1100us):
- """Start performing a long power measurement.
-
- Args:
- delay (int): Amount of time between each measurement interval (in milliseconds) This
- time period is sleep time of the core. The default value depends on the other
- default values, plus a factor of 20 percent.
- averaging_factor (:class:`~hailo_platform.drivers.hailort.pyhailort.AveragingFactor`):
- Number of samples per time period, sensor configuration value.
- sampling_period (:class:`~hailo_platform.drivers.hailort.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.
- """
- return self._controller.start_power_measurement(delay, 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.
- """
- return self._controller.stop_power_measurement()
-
- def set_power_measurement(self, index, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
- """Set parameters for long power measurement on an Hailo chip.
-
- Args:
- index (int): Index of the buffer on the firmware the data would be saved at.
- dvm (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes`):
- Which DVM will be measured. Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
- Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
- It sums :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.VDD_CORE`,
- :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AVDD_H`.
- Only :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
- Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
- measurement_type
- (:class:`~hailo_platform.drivers.hailort.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.drivers.hailort.pyhailort.PowerMeasurementTypes`
- """
- return self._controller.set_power_measurement(index, dvm, measurement_type)
-
- def get_power_measurement(self, index, should_clear=True):
- """Read measured power from a long power measurement
-
- Args:
- index (int): Index of the buffer on the firmware the data would be saved at.
- should_clear (bool): Flag indicating if the results saved at the firmware will be deleted after reading.
-
- Returns:
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementData`:
- Object containing measurement data \n
- For :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`: \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- - :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- - :class:`~hailo_platform.drivers.hailort.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.drivers.hailort.pyhailort.PowerMeasurementTypes`.
- """
- if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
- raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
- return self._controller.get_power_measurement(
- index,
- should_clear=should_clear)
-
- def _examine_user_config(self):
- return self._controller.examine_user_config()
-
- def read_user_config(self):
- """Read the user configuration section as binary data.
-
- Returns:
- str: User config as a binary buffer.
- """
- return self._controller.read_user_config()
-
- def write_user_config(self, configuration):
- """Write the user configuration.
-
- Args:
- configuration (str): A binary representation of a Hailo device configuration.
- """
- return self._controller.write_user_config(configuration)
-
- def _erase_user_config(self):
- return self._controller.erase_user_config()
-
- def read_board_config(self):
- """Read the board configuration section as binary data.
-
- Returns:
- str: Board config as a binary buffer.
- """
- return self._controller.read_board_config()
-
- def write_board_config(self, configuration):
- """Write the static confuration.
-
- Args:
- configuration (str): A binary representation of a Hailo device configuration.
- """
- return self._controller.write_board_config(configuration)
-
- def identify(self):
- """Gets the Hailo chip identification.
-
- Returns:
- class HailoIdentifyResponse with Protocol version.
- """
- return self._controller.identify()
-
- def core_identify(self):
- """Gets the Core Hailo chip identification.
-
- Returns:
- class HailoIdentifyResponse with Protocol version.
- """
- return self._controller.core_identify()
-
- 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).
- """
- return self._controller.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.
- """
- return self._controller.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.
- """
- return self._controller.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.
- """
- return self._controller._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.
- """
- return self._controller._get_overcurrent_state()
-
- def i2c_write(self, slave, register_address, data):
- """Write data to an I2C slave.
-
- Args:
- slave (:class:`hailo_platform.drivers.hailo_controller.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.
- """
- return self._controller.i2c_write(slave, register_address, data)
-
- def i2c_read(self, slave, register_address, data_length):
- """Read data from an I2C slave.
-
- Args:
- slave (:class:`hailo_platform.drivers.hailo_controller.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.
- """
- return self._controller.i2c_read(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)
- """
- return self._controller.firmware_update(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.
- """
- return self._controller.second_stage_update(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.drivers.hailort.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"
-
- return self._controller.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"
-
- return self._controller.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.
- """
- return self._controller.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.drivers.hailort.pyhailort.Endianness`):
- Big or little endian.
- """
- return self._controller.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.drivers.hailort.pyhailort.SensorConfigTypes`): The sensor type.
- i2c_bus_index (int): The I2C bus index of the sensor.
- """
- return self._controller.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]
- """
- return self._controller.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]
- """
- return self._controller.sensor_reset(section_index)
-
- def wd_enable(self, cpu_id):
- """Enable firmware watchdog.
-
- Args:
- cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
- """
- self._controller.wd_enable(cpu_id)
-
- def wd_disable(self, cpu_id):
- """Disable firmware watchdog.
-
- Args:
- cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
- """
- self._controller.wd_disable(cpu_id)
-
- def wd_config(self, cpu_id, wd_cycles, wd_mode):
- """Configure a firmware watchdog.
-
- Args:
- cpu_id (:class:`~hailo_platform.drivers.hailort.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
- """
- return self._controller.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.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
- """
- return self._controller.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.drivers.hailort.pyhailort.TemperatureInfo`:
- Temperature in celsius of the 2 internal temperature sensors (TS), and a sample
- count (a running 16-bit counter)
- """
- return self._controller.get_chip_temperature()
-
- def get_extended_device_information(self):
- return self._controller.get_extended_device_information()
-
- def _get_health_information(self):
- return self._controller._get_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.
- """
- self._controller.set_pause_frames(rx_pause_frames_enable)
-
- def test_chip_memories(self):
- """test all chip memories using smart BIST
-
- """
- self._controller.test_chip_memories()
-
- def _get_device_handle(self):
- return self._controller._get_device_handle()
-
-class UdpHcpControl(HcpControl):
- """Control object that uses a HCP over UDP controller interface."""
-
- def __init__(self, remote_ip, device=None, remote_control_port=22401, retries=2, response_timeout_seconds=10.0, ignore_socket_errors=False):
- """Initializes a new UdpControllerControl object.
-
- Args:
- remote_ip (str): The IPv4 address of the remote Hailo device (X.X.X.X).
- remote_control_port (int, optional): The port that the remote Hailo device listens on.
- 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
- self._controller = Control(Control.Type.ETH, remote_ip, remote_control_port, response_timeout_seconds=response_timeout_seconds, max_number_of_attempts=max_number_of_attempts)
- self.set_udp_device(device)
- self._device_id = self.identify()
-
- def set_udp_device(self, device):
- self._controller.set_device(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]
-
- self._controller = Control(Control.Type.PCIE, None, None, pcie_device_info=device_info)
- self.set_pcie_device(device)
- self._device_id = self.identify()
-
- def release(self):
- if self._controller is None:
- return
- self._controller.release()
- self._controller = None
-
- def set_pcie_device(self, pcie_device):
- """Prepare the pcie device to be used after creating it."""
- self._controller.set_device(pcie_device)
-
- def set_notification_callback(self, callback_func, notification_id, opaque):
- """Set a callback function to be called when a notification is received.
-
- 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.
- """
- return self._controller.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.
- """
- return self._controller.remove_notification_callback(notification_id)
+from hailo_platform.pyhailort.control_object import * # noqa F401
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/ethernet_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/ethernet_utils.py
index 0b0bb84..785a642 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/ethernet_utils.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/ethernet_utils.py
@@ -1,66 +1 @@
-#!/usr/bin/env python
-from builtins import str
-import netifaces as ni
-
-from netaddr import IPAddress, IPNetwork
-
-
-# As defined in sockios.h
-SIOCGIFTXQLEN = 0x8942
-# Interface name is 16 bytes (including NULL)
-SIOCGIFTXQLEN_FMT = "16sI"
-
-class NoInterfaceError(Exception):
- """Raised by get_interface_from_ip when no matching interface was found"""
- pass
-
-def get_interface_from_ip(ip_address):
- """Returns the interface name associated with the given ip addressself.
-
- Args:
- ip_address (str): the IP address to query.
-
- Returns:
- str: The name of the interface matching the given IP address.
- """
-
- skipped_ifaces = []
- for interface in ni.interfaces():
- if ni.AF_INET not in ni.ifaddresses(interface):
- skipped_ifaces.append(interface)
- continue
- af_inet_values = ni.ifaddresses(interface)[ni.AF_INET][0]
- ip_addr, netmask = af_inet_values['addr'], af_inet_values['netmask']
- if is_ip_in_network(ip_addr, netmask, ip_address):
- return str(interface)
-
- raise NoInterfaceError('No interface for {} found among {}'.format(ip_address, skipped_ifaces))
-
-
-def get_interface_address(interface_name):
- """Returns the interface address associated with the given interface name.
-
- Args:
- interface_name (str): the name of the interface to query.
-
- Returns:
- str: The IP address of the interface matching the given interface_name.
- """
- af_inet_values = ni.ifaddresses(interface_name)[ni.AF_INET][0]
- return af_inet_values['addr']
-
-
-def is_ip_in_network(network_ip, netmask, ip_in_question):
- """Checks whether an IP address is located in a given network.
-
- Args:
- network_ip (str): the IP address of the network interface.
- netmask (str): the netmask of the given networkself.
- ip_in_question (str): the IP address to compare against the network.
-
- Returns:
- bool: whether the IP address belongs to the given network.
- """
-
- netmask_bits = IPAddress(netmask).netmask_bits()
- return IPAddress(ip_in_question) in IPNetwork('{}/{}'.format(network_ip, netmask_bits))
+from hailo_platform.pyhailort.ethernet_utils import * # noqa F401
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/hailo_control_protocol.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/hailo_control_protocol.py
index bdfc8cf..af38579 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/hailo_control_protocol.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/hailo_control_protocol.py
@@ -1,331 +1,2 @@
#!/usr/bin/env python
-"""
-.. module:: hailo_control_protocol
- :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 = 6
-SUPPORTED_FW_REVISION = 0
-
-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 if the string field is empty
- return string_field.rstrip('\x00') or ""
-
- 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 ""
- 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 HailoResetTypes(Enum):
- """Defines the available reset types."""
- CHIP = 'chip'
- NN_CORE = 'nn_core'
- SOFT = 'soft'
- FORCED_SOFT = 'forced_soft'
-
-
-class HailoFirmwareVersion(object):
- """Represents a Hailo chip firmware version."""
- DEV_BIT = 0x80000000
- CORE_BIT = 0x08000000
- FW_VERSION_FORMAT = '> 1), switch_number=0, register_address_size=2,
- endianness=Endianness.BIG_ENDIAN)
-
-def set_i2c_switch(control_object, slave, slave_switch=None):
- """Set the I2C switch in order to perform actions from the I2C slave.
-
- Args:
- control_object (:class:`~hailo_platform.drivers.control_object.HcpControl`): Control object
- which communicates with the Hailo chip.
- slave (:class:`I2CSlave`): Slave which the switch is set for.
- slave_switch (:class:`I2CSlave`): The I2C slave for the switch it self. Defaults to
- :data:`I2C_SLAVE_SWITCH`.
- """
- I2C_SWITCH_REGISTER_SIZE = 1
- if NO_I2C_SWITCH != slave.switch_number:
- if not slave_switch:
- slave_switch = I2C_SLAVE_SWITCH
-
- # Set the switch value that should be written
- switch_value = 1 << slave.switch_number
-
- # Write new value to the switch
- control_object.i2c_write(slave_switch, switch_value, struct.pack('b', switch_value))
-
- # Read data from the switch, make sure write was successful
- read_data, = struct.unpack('b', control_object.i2c_read(slave_switch, switch_value, I2C_SWITCH_REGISTER_SIZE))
- if read_data != switch_value:
- raise I2CSlavesException("Switch writing has failed. Read data is different then expected %s != %s" % (
- read_data,
- switch_value))
+from hailo_platform.pyhailort.i2c_slaves import * # noqa F401
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/power_measurement.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/power_measurement.py
index b9da002..1732ad7 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/power_measurement.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/power_measurement.py
@@ -1,11 +1 @@
-from hailo_platform.drivers.hailort.pyhailort import (DvmTypes, PowerMeasurementTypes, # noqa F401
- SamplingPeriod, AveragingFactor,
- HailoPowerMeasurementUtils)
-
-""" Amount of time between each power measurement interval.
- The default values for provides by the sensor a new value every:
- 2 * sampling_period (1.1) * averaging_factor (256) [ms].
- Therefore we want it to be the period of time that the core will sleep between samples,
- plus a factor of 20 percent """
-DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS = int((HailoPowerMeasurementUtils.return_real_sampling_period(SamplingPeriod.PERIOD_1100us) / 1000.0 *
- HailoPowerMeasurementUtils.return_real_averaging_factor(AveragingFactor.AVERAGE_256) * 2) * 1.2)
\ No newline at end of file
+from hailo_platform.pyhailort.power_measurement import * # noqa F401
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/pyhailort.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/pyhailort.py
index ca2461e..a29dd95 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/pyhailort.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/pyhailort.py
@@ -1,2123 +1 @@
-import sys
-
-from hailo_platform.drivers.hailo_controller.hailo_control_protocol import BoardInformation, CoreInformation, HailoResetTypes, ExtendedDeviceInformation, HealthInformation
-
-from argparse import ArgumentTypeError
-import numpy
-import signal
-import time
-from hailo_platform.common.logger.logger import default_logger
-import gc
-import os
-
-import hailo_platform.drivers.hailort._pyhailort as _pyhailort
-from hailo_platform.drivers.hailort._pyhailort import (BootloaderVersion, TemperatureInfo, # noqa F401
- DvmTypes, PowerMeasurementTypes, # noqa F401
- PowerMeasurementData, NotificationId, # noqa F401
- OvercurrentAlertState,
- FormatOrder,
- AveragingFactor, SamplingPeriod,
- FormatType, WatchdogMode,
- MipiDataTypeRx, MipiPixelsPerClock,
- MipiClockSelection, MipiIspImageInOrder,
- MipiIspImageOutDataType, IspLightFrequency,
- BootSource, HailoSocketDefs, Endianness,
- MipiInputStreamParams, SensorConfigTypes,
- SensorConfigOpCode)
-
-BBOX_PARAMS = _pyhailort.HailoRTDefaults.BBOX_PARAMS()
-HAILO_DEFAULT_ETH_CONTROL_PORT = _pyhailort.HailoRTDefaults.HAILO_DEFAULT_ETH_CONTROL_PORT()
-INPUT_DATAFLOW_BASE_PORT = _pyhailort.HailoRTDefaults.DEVICE_BASE_INPUT_STREAM_PORT()
-OUTPUT_DATAFLOW_BASE_PORT = _pyhailort.HailoRTDefaults.DEVICE_BASE_OUTPUT_STREAM_PORT()
-PCIE_ANY_DOMAIN = _pyhailort.HailoRTDefaults.PCIE_ANY_DOMAIN()
-DEFAULT_VSTREAM_TIMEOUT_MS = 10000
-DEFAULT_VSTREAM_QUEUE_SIZE = 2
-
-class HailoSocket(object):
- MAX_UDP_PAYLOAD_SIZE = HailoSocketDefs.MAX_UDP_PAYLOAD_SIZE()
- MIN_UDP_PAYLOAD_SIZE = HailoSocketDefs.MIN_UDP_PAYLOAD_SIZE()
- MAX_UDP_PADDED_PAYLOAD_SIZE = HailoSocketDefs.MAX_UDP_PADDED_PAYLOAD_SIZE()
- MIN_UDP_PADDED_PAYLOAD_SIZE = HailoSocketDefs.MIN_UDP_PADDED_PAYLOAD_SIZE()
- MAX_ALIGNED_UDP_PAYLOAD_SIZE_RTP = HailoSocketDefs.MAX_ALIGNED_UDP_PAYLOAD_SIZE_RTP()
-
-
-class HailoRTException(Exception):
- pass
-
-class UdpRecvError(HailoRTException):
- pass
-
-class InvalidProtocolVersionException(HailoRTException):
- pass
-
-class HailoRTFirmwareControlFailedException(HailoRTException):
- pass
-
-class HailoRTInvalidFrameException(HailoRTException):
- pass
-
-class HailoRTUnsupportedOpcodeException(HailoRTException):
- pass
-
-class HailoRTTimeout(HailoRTException):
- pass
-
-class HailoRTStreamAborted(HailoRTException):
- pass
-
-class HailoRTInvalidOperationException(HailoRTException):
- pass
-
-class HailoRTInvalidArgumentException(HailoRTException):
- pass
-
-class HailoRTNotFoundException(HailoRTException):
- pass
-
-class HailoRTInvalidHEFException(HailoRTException):
- pass
-
-class HailoRTEthException(HailoRTException):
- pass
-
-class HailoRTPCIeDriverException(HailoRTException):
- pass
-
-class HailoRTNetworkGroupNotActivatedException(HailoRTException):
- pass
-
-class HailoStatusInvalidValueException(Exception):
- pass
-
-class ExceptionWrapper(object):
- def __enter__(self):
- pass
-
- def __exit__(self, exception_type, value, traceback):
- if value is not None:
- if exception_type is _pyhailort.HailoRTStatusException:
- self._raise_indicative_status_exception(int(value.args[0]))
- else:
- raise
-
- def _raise_indicative_status_exception(self, error_code):
- string_error_code = get_status_message(error_code)
- if string_error_code == "HAILO_ETH_RECV_FAILURE":
- raise UdpRecvError("Failed to receive data")
- if string_error_code == "HAILO_UNSUPPORTED_CONTROL_PROTOCOL_VERSION":
- raise InvalidProtocolVersionException("HailoRT has failed because an invalid protocol version was received from device")
- if string_error_code == "HAILO_FW_CONTROL_FAILURE":
- raise HailoRTFirmwareControlFailedException("libhailort control operation failed")
- if string_error_code == "HAILO_UNSUPPORTED_OPCODE":
- raise HailoRTUnsupportedOpcodeException("HailoRT has failed because an unsupported opcode was sent to device")
- if string_error_code == "HAILO_INVALID_FRAME":
- raise HailoRTInvalidFrameException("An invalid frame was received")
- if string_error_code == "HAILO_TIMEOUT":
- raise HailoRTTimeout("Received a timeout - hailort has failed because a timeout had occurred")
- if string_error_code == "HAILO_STREAM_ABORTED":
- raise HailoRTStreamAborted("Stream aborted due to an external event")
-
- if string_error_code == "HAILO_INVALID_OPERATION":
- raise HailoRTInvalidOperationException("Invalid operation. See hailort.log for more information")
- if string_error_code == "HAILO_INVALID_ARGUMENT":
- raise HailoRTInvalidArgumentException("Invalid argument. See hailort.log for more information")
- if string_error_code == "HAILO_NOT_FOUND":
- raise HailoRTNotFoundException("Item not found. See hailort.log for more information")
-
- if string_error_code == "HAILO_INVALID_HEF":
- raise HailoRTInvalidHEFException("Invalid HEF. See hailort.log for more information")
-
- if string_error_code == "HAILO_ETH_FAILURE":
- raise HailoRTEthException("Ethernet failure. See hailort.log for more information")
- if string_error_code == "HAILO_PCIE_DRIVER_FAIL":
- raise HailoRTPCIeDriverException("PCIe driver failure. run 'dmesg | grep hailo' for more information")
-
- if string_error_code == "HAILO_NETWORK_GROUP_NOT_ACTIVATED":
- raise HailoRTNetworkGroupNotActivatedException("Network group is not activated")
- else:
- raise HailoRTException("libhailort failed with error: {} ({})".format(error_code, string_error_code))
-
-def get_status_message(status_code):
- status_str = _pyhailort.get_status_message(status_code)
- if status_str == "":
- raise HailoStatusInvalidValueException("Value {} is not a valid status".format(status_code))
- return status_str
-
-class Control(object):
- class Type(object):
- PCIE = 0
- ETH = 1
-
- def __init__(self, control_type, address, port, pcie_device_info=None, response_timeout_seconds=10,
- max_number_of_attempts=3):
- self.device = None
- self.control_type = control_type
- self._eth_address = address
- self._eth_port = port
- self._eth_response_timeout_milliseconds = int(response_timeout_seconds * 1000)
- self._eth_max_number_of_attempts = max_number_of_attempts
- self._pcie_device_info = pcie_device_info
-
- if sys.platform != "win32":
- signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGWINCH])
-
- def ensure_device(method):
- def _ensure_device(self, *args, **kw):
- if self.device is not None:
- return method(self, *args, **kw)
-
- with ExceptionWrapper():
- if self.control_type == Control.Type.PCIE:
- self.device = _pyhailort.create_pcie_device(self._pcie_device_info)
- _pyhailort.identify(self.device)
- elif self.control_type == Control.Type.ETH:
- self.device = _pyhailort.create_eth_device(self._eth_address, len(self._eth_address), self._eth_port,
- self._eth_response_timeout_milliseconds, self._eth_max_number_of_attempts)
- else:
- raise HailoRTException("Unsupported control type")
- try:
- result = method(self, *args, **kw)
- finally:
- if self.device is not None:
- with ExceptionWrapper():
- _pyhailort.release_device(self.device)
- self.device = None
-
- return result
- return _ensure_device
-
- def set_device(self, device_object):
- if device_object is None:
- self.device = None
- else:
- self.device = device_object.device
-
- @ensure_device
- def identify(self):
- with ExceptionWrapper():
- response = _pyhailort.identify(self.device)
- 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
-
- @ensure_device
- def core_identify(self):
- with ExceptionWrapper():
- response = _pyhailort.core_identify(self.device)
- core_information = CoreInformation(response.fw_version.major, response.fw_version.minor,
- response.fw_version.revision, response.is_release)
- return core_information
-
- @ensure_device
- def set_fw_logger(self, level, interface_mask):
- with ExceptionWrapper():
- return _pyhailort.set_fw_logger(self.device, level, interface_mask)
-
- @ensure_device
- def set_throttling_state(self, should_activate):
- with ExceptionWrapper():
- return _pyhailort.set_throttling_state(self.device, should_activate)
-
- @ensure_device
- def get_throttling_state(self):
- with ExceptionWrapper():
- return _pyhailort.get_throttling_state(self.device)
-
- @ensure_device
- def _set_overcurrent_state(self, should_activate):
- with ExceptionWrapper():
- return _pyhailort._set_overcurrent_state(self.device, should_activate)
-
- @ensure_device
- def _get_overcurrent_state(self):
- with ExceptionWrapper():
- return _pyhailort._get_overcurrent_state(self.device)
-
- @ensure_device
- def read_memory(self, address, length):
- with ExceptionWrapper():
- return _pyhailort.read_memory(self.device, int(address), int(length))
-
- @ensure_device
- def write_memory(self, address, data):
- with ExceptionWrapper():
- return _pyhailort.write_memory(self.device, int(address), data, len(data))
-
- @ensure_device
- def configure_device_from_hef(self, hef, configure_params_by_name={}):
- with ExceptionWrapper():
- return _pyhailort.configure_device_from_hef(self.device, hef._hef, configure_params_by_name)
-
- @ensure_device
- def _create_c_i2c_slave(self, 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
-
- @ensure_device
- def i2c_write(self, pythonic_slave, register_address, data):
- c_slave = self._create_c_i2c_slave(pythonic_slave)
- with ExceptionWrapper():
- return _pyhailort.i2c_write(self.device, c_slave, register_address, data, len(data))
-
- @ensure_device
- def i2c_read(self, pythonic_slave, register_address, data_length):
- c_slave = self._create_c_i2c_slave(pythonic_slave)
- with ExceptionWrapper():
- return _pyhailort.i2c_read(self.device, c_slave, register_address, data_length)
-
- @ensure_device
- def power_measurement(self, dvm, measurement_type):
- with ExceptionWrapper():
- return _pyhailort.power_measurement(self.device, dvm, measurement_type)
-
- @ensure_device
- def start_power_measurement(self, delay_milliseconds, averaging_factor, sampling_period):
- with ExceptionWrapper():
- return _pyhailort.start_power_measurement(self.device, delay_milliseconds,
- averaging_factor, sampling_period)
-
- @ensure_device
- def set_power_measurement(self, index, dvm, measurement_type):
- with ExceptionWrapper():
- return _pyhailort.set_power_measurement(self.device, index, dvm, measurement_type)
-
- @ensure_device
- def get_power_measurement(self, index, should_clear):
- with ExceptionWrapper():
- return _pyhailort.get_power_measurement(self.device, index, should_clear)
-
- @ensure_device
- def stop_power_measurement(self):
- with ExceptionWrapper():
- return _pyhailort.stop_power_measurement(self.device)
-
- @ensure_device
- def examine_user_config(self):
- with ExceptionWrapper():
- return _pyhailort.examine_user_config(self.device)
-
- @ensure_device
- def read_user_config(self):
- with ExceptionWrapper():
- return _pyhailort.read_user_config(self.device)
-
- @ensure_device
- def write_user_config(self, data):
- with ExceptionWrapper():
- return _pyhailort.write_user_config(self.device, data)
-
- @ensure_device
- def erase_user_config(self):
- with ExceptionWrapper():
- return _pyhailort.erase_user_config(self.device)
-
- @ensure_device
- def read_board_config(self):
- with ExceptionWrapper():
- return _pyhailort.read_board_config(self.device)
-
- @ensure_device
- def write_board_config(self, data):
- with ExceptionWrapper():
- return _pyhailort.write_board_config(self.device, data)
-
- @ensure_device
- def reset(self, reset_type):
- map_mode = {
- HailoResetTypes.CHIP : _pyhailort.ResetDeviceMode.CHIP,
- HailoResetTypes.NN_CORE : _pyhailort.ResetDeviceMode.NN_CORE,
- HailoResetTypes.SOFT : _pyhailort.ResetDeviceMode.SOFT,
- HailoResetTypes.FORCED_SOFT : _pyhailort.ResetDeviceMode.FORCED_SOFT
- }
-
- mode = map_mode[reset_type]
- with ExceptionWrapper():
- return _pyhailort.reset(self.device, mode)
-
- @ensure_device
- def sensor_store_config(self, section_index, reset_data_size, sensor_type, config_file_path, config_height, config_width,
- config_fps, config_name):
- with ExceptionWrapper():
- return _pyhailort.sensor_store_config(self.device, section_index, reset_data_size, sensor_type, config_file_path,
- config_height, config_width, config_fps, config_name)
-
- @ensure_device
- def store_isp_config(self, reset_config_size, config_height, config_width, config_fps, isp_static_config_file_path,
- isp_runtime_config_file_path, config_name):
- with ExceptionWrapper():
- return _pyhailort.store_isp_config(self.device, reset_config_size, config_height, config_width, config_fps,
- isp_static_config_file_path, isp_runtime_config_file_path, config_name)
-
- @ensure_device
- def sensor_get_sections_info(self):
- with ExceptionWrapper():
- return _pyhailort.sensor_get_sections_info(self.device)
-
- @ensure_device
- def sensor_set_i2c_bus_index(self, sensor_type, bus_index):
- with ExceptionWrapper():
- return _pyhailort.sensor_set_i2c_bus_index(self.device, sensor_type, bus_index)
-
- @ensure_device
- def sensor_load_and_start_config(self, section_index):
- with ExceptionWrapper():
- return _pyhailort.sensor_load_and_start_config(self.device, section_index)
-
- @ensure_device
- def sensor_reset(self, section_index):
- with ExceptionWrapper():
- return _pyhailort.sensor_reset(self.device, section_index)
-
- @ensure_device
- def sensor_set_generic_i2c_slave(self, slave_address, register_address_size, bus_index, should_hold_bus, endianness):
- with ExceptionWrapper():
- return _pyhailort.sensor_set_generic_i2c_slave(self.device, slave_address, register_address_size, bus_index, should_hold_bus, endianness)
-
- @ensure_device
- def firmware_update(self, firmware_binary, should_reset):
- with ExceptionWrapper():
- return _pyhailort.firmware_update(self.device, firmware_binary, len(firmware_binary), should_reset)
-
- @ensure_device
- def second_stage_update(self, second_stage_binary):
- with ExceptionWrapper():
- return _pyhailort.second_stage_update(self.device, second_stage_binary, len(second_stage_binary))
-
- @ensure_device
- def set_pause_frames(self, rx_pause_frames_enable):
- with ExceptionWrapper():
- return _pyhailort.set_pause_frames(self.device, rx_pause_frames_enable)
-
- @ensure_device
- def wd_enable(self, cpu_id):
- with ExceptionWrapper():
- return _pyhailort.wd_enable(self.device, cpu_id)
-
- @ensure_device
- def wd_disable(self, cpu_id):
- with ExceptionWrapper():
- return _pyhailort.wd_disable(self.device, cpu_id)
-
- @ensure_device
- def wd_config(self, cpu_id, wd_cycles, wd_mode):
- with ExceptionWrapper():
- return _pyhailort.wd_config(self.device, cpu_id, wd_cycles, WatchdogMode(wd_mode))
-
- @ensure_device
- def previous_system_state(self, cpu_id):
- with ExceptionWrapper():
- return _pyhailort.previous_system_state(self.device, cpu_id)
-
- @ensure_device
- def get_chip_temperature(self):
- with ExceptionWrapper():
- return _pyhailort.get_chip_temperature(self.device)
-
- @ensure_device
- def get_extended_device_information(self):
- with ExceptionWrapper():
- response = _pyhailort.get_extended_device_information(self.device)
- 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
-
- @ensure_device
- def _get_health_information(self):
- with ExceptionWrapper():
- response = _pyhailort._get_health_information(self.device)
- 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
-
- @ensure_device
- def set_notification_callback(self, callback_func, notification_id, opaque):
- with ExceptionWrapper():
- _pyhailort.set_notification_callback(self.device, callback_func, notification_id, opaque)
-
- @ensure_device
- def remove_notification_callback(self, notification_id):
- with ExceptionWrapper():
- _pyhailort.remove_notification_callback(self.device, notification_id)
-
- @ensure_device
- def test_chip_memories(self):
- """
- Test chip memories using smart BIST mechanism.
- """
- with ExceptionWrapper():
- return _pyhailort.test_chip_memories(self.device)
-
- @ensure_device
- def _get_device_handle(self):
- return self.device
-
-class HailoUdpScan(object):
- def __init__(self):
- self._logger = default_logger()
- with ExceptionWrapper():
- self._scan = _pyhailort.UdpScan()
-
- def scan_devices(self, interface_name, timeout_seconds=3):
- self._logger.info('Scanning over interface {iface}'.format(iface=interface_name))
- timeout_milliseconds = int(timeout_seconds * 1000)
- device_ip_addresses = self._scan.scan_devices(interface_name, timeout_milliseconds)
- for ip in device_ip_addresses:
- self._logger.debug("Found board at: {}".format(ip))
- return device_ip_addresses
-
-
-class TrafficControl(object):
- def __init__(self, ip, port, rate_bytes_per_sec):
- if sys.platform != 'linux':
- raise HailoRTInvalidOperationException('TrafficControl is supported only on UNIX os')
- with ExceptionWrapper():
- self._tc_util = _pyhailort.TrafficControlUtil(ip, port, int(rate_bytes_per_sec))
-
- def set_rate_limit(self):
- self._tc_util.set_rate_limit()
-
- def reset_rate_limit(self):
- self._tc_util.reset_rate_limit()
-
- def get_interface_name(ip):
- "get the interface corresponding to the given ip"
- with ExceptionWrapper():
- return _pyhailort.TrafficControlUtil.get_interface_name(ip)
-
-
-class ConfigureParams(object):
-
- @staticmethod
- def create_from_hef(hef, interface):
- """Create configure params from HEF. These params affects the HEF configuration into a device.
-
- Args:
- hef (:class:`HEF`): The HEF to create the parameters from.
- interface (:class:`HailoStreamInterface`): The stream_interface to create stream_params for.
-
- Returns:
- dict: The created stream params. The keys are the network_group names in the HEF. The values are default params, which can be changed.
- """
- with ExceptionWrapper():
- return hef._hef.create_configure_params(interface)
-
- @staticmethod
- def create_mipi_inputs_from_hef(hef, output_interface, mipi_rx_id=0, data_type=MipiDataTypeRx.RAW_8,
- img_width_pixels=1920, img_height_pixels=1080,
- pixels_per_clock=MipiPixelsPerClock.PIXELS_PER_CLOCK_4, number_of_lanes=2,
- clock_selection=MipiClockSelection.SELECTION_AUTOMATIC, data_rate=260, virtual_channel_index=0,
- isp_enable=False, isp_img_in_order=MipiIspImageInOrder.GR_FIRST,
- isp_img_out_data_type=MipiIspImageOutDataType.RGB_888, isp_crop_enable=False,
- isp_crop_output_width_pixels=1920, isp_crop_output_height_pixels=1080,
- isp_crop_output_width_start_offset_pixels=0, isp_crop_output_height_start_offset_pixels=0,
- isp_test_pattern_enable=True, isp_configuration_bypass=False,
- isp_run_time_ae_enable=True, isp_run_time_awb_enable=True, isp_run_time_adt_enable=True,
- isp_run_time_af_enable=False, isp_run_time_calculations_interval_ms=0,
- isp_light_frequency=IspLightFrequency.LIGHT_FREQ_50_HZ):
- """Create configure params from HEF. These params affects the HEF configuration into a device.
-
- .. attention:: The ISP and its features are not officially supported yet.
-
- Args:
- hef (:class:`HEF`): The HEF to create the parameters from.
- output_interface (:class:`HailoStreamInterface`): The stream_interface to create output stream_params for.
- mipi_rx_id (int): Selection of which MIPI Rx device to use.
- data_type (:class:`~hailo_platform.drivers.hailort.pyhailort.MipiDataTypeRx`): The data type which will be passed over the MIPI.
- img_width_pixels (int): The width in pixels of the image that enter to the mipi CSI. The sensor output.
- When isp_enable and isp_crop_enable is false, is also the stream input.
- img_height_pixels (int): The height in pixels of the image that enter to the mipi CSI. The sensor output.
- When isp_enable and isp_crop_enable is false, is also the stream input.
- pixels_per_clock (:class:`~hailo_platform.drivers.hailort.pyhailort.MipiPixelsPerClock`): Number of pixels transmitted at each
- clock.
- number_of_lanes (int): Number of lanes to use.
- clock_selection (:class:`~hailo_platform.drivers.hailort.pyhailort.MipiClockSelection`): Selection of clock range that would be
- used. Setting :class:`~hailo_platform.drivers.hailort.pyhailort.MipiClockSelection.SELECTION_AUTOMATIC` means that the
- clock selection is calculated from the data rate.
- data_rate (int): Rate of the passed data (MHz).
- virtual_channel_index (int): The virtual channel index of the MIPI dphy.
- isp_enable (bool): Enable the ISP block in the MIPI dataflow. The ISP is not supported yet.
- isp_img_in_order (:class:`~hailo_platform.drivers.hailort.pyhailort.MipiIspImageInOrder`):
- The ISP Rx bayer pixel order. Only relevant when the ISP is enabled.
- isp_img_out_data_type (:class:`~hailo_platform.drivers.hailort.pyhailort.MipiIspImageOutDataType`):
- The data type that the mipi will take out. Only relevant when the ISP is enabled.
- isp_crop_enable (bool): Enable the crop feature in the ISP. Only relevant when the ISP is enabled.
- isp_crop_output_width_pixels (int): The width in pixels of the output window that the ISP take out. The stream input.
- Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
- isp_crop_output_height_pixels (int): The height in pixels of the output window that the ISP take out. The stream input.
- Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
- isp_crop_output_width_start_offset_pixels (int): The width start point of the output window that the ISP take out.
- Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
- isp_crop_output_height_start_offset_pixels (int): The height start point of the output window that the ISP take out.
- Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
- isp_test_pattern_enable (bool): Enable Test pattern from the ISP. Only relevant when the ISP is enabled.
- isp_configuration_bypass (bool): Don't load the ISP configuration file from the FLASH. Only relevant when the ISP is enabled.
- isp_run_time_ae_enable (bool): Enable the run-time Auto Exposure in the ISP. Only relevant when the ISP is enabled.
- isp_run_time_awb_enable (bool): Enable the run-time Auto White Balance in the ISP. Only relevant when the ISP is enabled.
- isp_run_time_adt_enable (bool): Enable the run-time Adaptive Function in the ISP. Only relevant when the ISP is enabled.
- isp_run_time_af_enable (bool): Enable the run-time Auto Focus in the ISP. Only relevant when the ISP is enabled.
- isp_run_time_calculations_interval_ms (int): Interval in milliseconds between ISP run time calculations. Only relevant when the ISP is enabled.
- isp_light_frequency (:class:`~hailo_platform.drivers.hailort.pyhailort.IspLightFrequency`):
- Selection of the light frequency. This parameter varies depending on the power grid of the country where
- the product is running. Only relevant when the ISP is enabled.
- Returns:
- dict: The created stream params. The keys are the network_group names in the HEF. The values are default params, which can be changed.
- """
-
- mipi_params = MipiInputStreamParams()
- mipi_params.mipi_rx_id = mipi_rx_id
- mipi_params.data_type = data_type
- mipi_params.isp_enable = isp_enable
- mipi_params.mipi_common_params.pixels_per_clock = pixels_per_clock
- mipi_params.mipi_common_params.number_of_lanes = number_of_lanes
- mipi_params.mipi_common_params.clock_selection = clock_selection
- mipi_params.mipi_common_params.virtual_channel_index = virtual_channel_index
- mipi_params.mipi_common_params.data_rate = data_rate
- mipi_params.mipi_common_params.img_width_pixels = img_width_pixels
- mipi_params.mipi_common_params.img_height_pixels = img_height_pixels
- mipi_params.isp_params.img_in_order = isp_img_in_order
- mipi_params.isp_params.img_out_data_type = isp_img_out_data_type
- mipi_params.isp_params.crop_enable = isp_crop_enable
- mipi_params.isp_params.crop_output_width_pixels = isp_crop_output_width_pixels
- mipi_params.isp_params.crop_output_height_pixels = isp_crop_output_height_pixels
- mipi_params.isp_params.crop_output_width_start_offset_pixels = isp_crop_output_width_start_offset_pixels
- mipi_params.isp_params.crop_output_height_start_offset_pixels = isp_crop_output_height_start_offset_pixels
- mipi_params.isp_params.test_pattern_enable = isp_test_pattern_enable
- mipi_params.isp_params.configuration_bypass = isp_configuration_bypass
- mipi_params.isp_params.run_time_ae_enable = isp_run_time_ae_enable
- mipi_params.isp_params.run_time_awb_enable = isp_run_time_awb_enable
- mipi_params.isp_params.run_time_adt_enable = isp_run_time_adt_enable
- mipi_params.isp_params.run_time_af_enable = isp_run_time_af_enable
- mipi_params.isp_params.isp_run_time_calculations_interval_ms = isp_run_time_calculations_interval_ms
- mipi_params.isp_params.isp_light_frequency = isp_light_frequency
- with ExceptionWrapper():
- return hef._hef.create_configure_params_mipi_input(output_interface, mipi_params)
-
-def _get_name_as_str(name):
- return name if name is not None else ""
-
-class HEF(object):
- """Python representation of the Hailo Executable Format, which contains one or more compiled
- models.
- """
-
- def __init__(self, hef_source):
- """Constructor for the HEF class.
-
- Args:
- hef_source (str or bytes): The source from which the HEF object will be created. If the
- source type is `str`, it is treated as a path to an hef file. If the source type is
- `bytes`, it is treated as a buffer. Any other type will raise a ValueError.
- """
-
- with ExceptionWrapper():
- if isinstance(hef_source, str):
- self._hef = _pyhailort.Hef.create_from_file(hef_source)
- self._path = hef_source
- elif isinstance(hef_source, bytes):
- self._hef = _pyhailort.Hef.create_from_buffer(hef_source)
- self._path = None
- else:
- raise ValueError("HEF can only be created from a file path (str) or a buffer (bytes)")
- self._sorted_output_names = {}
-
- def get_networks_names(self, network_group_name=None):
- """Gets the names of all networks in a specific network group.
-
- Args:
- network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
-
- Returns:
- list of str: The names of the networks.
- """
- name = _get_name_as_str(network_group_name)
- with ExceptionWrapper():
- return self._hef.get_networks_names(name)
-
- @property
- def path(self):
- """HEF file path."""
- return self._path
-
- def get_network_group_names(self):
- """Get the names of the network groups in this HEF."""
- with ExceptionWrapper():
- return self._hef.get_network_group_names()
-
- def get_network_groups_infos(self):
- """Get information about the network groups in this HEF."""
- with ExceptionWrapper():
- return self._hef.get_network_groups_infos()
-
- def get_input_vstream_infos(self, name=None):
- """Get input vstreams information.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams.
- """
- name = _get_name_as_str(name)
- return self._hef.get_input_vstream_infos(name)
-
- def get_output_vstream_infos(self, name=None):
- """Get output vstreams information.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
- """
- name = _get_name_as_str(name)
- return self._hef.get_output_vstream_infos(name)
-
- def get_all_vstream_infos(self, name=None):
- """Get input and output vstreams information.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
- """
- name = _get_name_as_str(name)
- return self._hef.get_all_vstream_infos(name)
-
- def get_input_stream_infos(self, name=None):
- """Get the input low-level streams information.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- List of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with information objects
- of all input low-level streams.
- """
- name = _get_name_as_str(name)
- return self._hef.get_input_stream_infos(name)
-
-
- def get_output_stream_infos(self, name=None):
- """Get the output low-level streams information of a specific network group.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- List of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with information objects
- of all output low-level streams.
- """
- name = _get_name_as_str(name)
- return self._hef.get_output_stream_infos(name)
-
- def get_all_stream_infos(self, name=None):
- """Get input and output streams information of a specific network group.
-
- Args:
- name (str, optional): The name of the network or network_group to access. In case network_group name is given,
- Address all networks of the given network_group. In case not given, first network_group is addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
- """
- name = _get_name_as_str(name)
- return self._hef.get_all_stream_infos(name)
-
- def get_sorted_output_names(self, network_group_name=None):
- """Get the names of the outputs in a network group. The order of names is determined by
- the SDK. If the network group is not given, the first one is used.
- """
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
-
- if network_group_name not in self._sorted_output_names:
- with ExceptionWrapper():
- self._sorted_output_names[network_group_name] = self._hef.get_sorted_output_names(network_group_name)
- return self._sorted_output_names[network_group_name]
-
- def bottleneck_fps(self, network_group_name=None):
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- bottleneck_fps = self._hef.get_bottleneck_fps(network_group_name)
- if bottleneck_fps == 0:
- raise HailoRTException("bottleneck_fps is zero")
- return bottleneck_fps
-
- def get_udp_rates_dict(self, fps, max_supported_rate_bytes, network_group_name=None):
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- return self._hef.get_udp_rates_dict(network_group_name, fps, int(max_supported_rate_bytes))
-
- def get_vstream_name_from_original_name(self, original_name, network_group_name=None):
- """Get vstream name from original layer name for a specific network group.
-
- Args:
- original_name (str): The original layer name.
- network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
-
- Returns:
- str: the matching vstream name for the provided original name.
- """
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- return self._hef.get_vstream_name_from_original_name(original_name, network_group_name)
-
- def get_original_names_from_vstream_name(self, vstream_name, network_group_name=None):
- """Get original names list from vstream name for a specific network group.
-
- Args:
- vstream_name (str): The stream name.
- network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
-
- Returns:
- list of str: all the matching original layers names for the provided vstream name.
- """
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- return self._hef.get_original_names_from_vstream_name(vstream_name, network_group_name)
-
- def get_vstream_names_from_stream_name(self, stream_name, network_group_name=None):
- """Get vstream names list from their underlying stream name for a specific network group.
-
- Args:
- stream_name (str): The underlying stream name.
- network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
-
- Returns:
- list of str: All the matching vstream names for the provided stream name.
- """
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- return self._hef.get_vstream_names_from_stream_name(stream_name, network_group_name)
-
- def get_stream_names_from_vstream_name(self, vstream_name, network_group_name=None):
- """Get stream name from vstream name for a specific network group.
-
- Args:
- vstream_name (str): The name of the vstreams.
- network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
-
- Returns:
- list of str: All the underlying streams names for the provided vstream name.
- """
- if network_group_name is None:
- network_group_name = self.get_network_group_names()[0]
- with ExceptionWrapper():
- return self._hef.get_stream_names_from_vstream_name(vstream_name, network_group_name)
-
-
-class ConfiguredNetwork(object):
- """Represents a network group loaded to the device."""
-
- def __init__(self, configured_network, target, hef):
- self._configured_network = configured_network
- self._target = target
- self._hef = hef
-
- def get_networks_names(self):
- return self._hef.get_networks_names(self.name)
-
- def activate(self, network_group_params=None):
- """Activate this network group in order to infer data through it.
-
- Args:
- network_group_params (:obj:`hailo_platform.drivers.hailort._pyhailort.ActivateNetworkGroupParams`, optional):
- Network group activation params. If not given, default params will be applied,
-
- Returns:
- :class:`ActivatedNetworkContextManager`: Context manager that returns the activated
- network group.
- """
- network_group_params = network_group_params or self.create_params()
-
- with ExceptionWrapper():
- return ActivatedNetworkContextManager(self,
- self._configured_network.activate(network_group_params),
- self._target, self._hef)
-
- def wait_for_activation(self, timeout_ms=None):
- """Block until activated, or until ``timeout_ms`` is passed.
-
- Args:
- timeout_ms (int, optional): Timeout value in milliseconds to wait for activation.
- Defaults to ``HAILO_INFINITE``.
-
- Raises:
- :class:`HailoRTTimeout`: In case of timeout.
- """
- MAX_INT = 0x7fffffff
- with ExceptionWrapper():
- if timeout_ms is None:
- timeout_ms = MAX_INT
- return self._configured_network.wait_for_activation(timeout_ms)
-
- @staticmethod
- def create_params():
- """Create activation params for network_group.
-
- Returns:
- :obj:`hailo_platform.drivers.hailort._pyhailort.ActivateNetworkGroupParams`.
- """
- return _pyhailort.ActivateNetworkGroupParams.default()
-
- @property
- def name(self):
- return self._configured_network.get_name()
-
- def get_output_shapes(self):
- name_to_shape = {vstream_info.name : vstream_info.shape for vstream_info in self.get_output_vstream_infos()}
- results = []
- for name in self.get_sorted_output_names():
- results.append(name_to_shape[name])
- return tuple(results)
-
- def get_sorted_output_names(self):
- return self._hef.get_sorted_output_names(self.name)
-
- def get_input_vstream_infos(self, network_name=None):
- """Get input vstreams information.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_input_vstream_infos(name)
-
- def get_output_vstream_infos(self, network_name=None):
- """Get output vstreams information.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_output_vstream_infos(name)
-
- def get_all_vstream_infos(self, network_name=None):
- """Get input and output vstreams information.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_all_vstream_infos(name)
-
- def get_input_stream_infos(self, network_name=None):
- """Get the input low-level streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- List of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with information objects
- of all input low-level streams.
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_input_stream_infos(name)
-
- def get_output_stream_infos(self, network_name=None):
- """Get the output low-level streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- List of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with information objects
- of all output low-level streams.
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_output_stream_infos(name)
-
- def get_all_stream_infos(self, network_name=None):
- """Get input and output streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
- """
-
- name = network_name if network_name is not None else self.name
- return self._hef.get_all_stream_infos(name)
-
- def get_udp_rates_dict(self, fps, max_supported_rate_bytes):
- with ExceptionWrapper():
- return self._configured_network.get_udp_rates_dict(int(fps), int(max_supported_rate_bytes))
-
- def _create_input_vstreams(self, input_vstreams_params):
- return self._configured_network.InputVStreams(input_vstreams_params)
-
- def _create_output_vstreams(self, output_vstreams_params):
- return self._configured_network.OutputVStreams(output_vstreams_params)
-
- def get_stream_names_from_vstream_name(self, vstream_name):
- """Get stream name from vstream name for a specific network group.
-
- Args:
- vstream_name (str): The name of the vstreams.
-
- Returns:
- list of str: All the underlying streams names for the provided vstream name.
- """
- with ExceptionWrapper():
- return self._hef.get_stream_names_from_vstream_name(vstream_name, self.name)
-
- def get_vstream_names_from_stream_name(self, stream_name):
- """Get vstream names list from their underlying stream name for a specific network group.
-
- Args:
- stream_name (str): The underlying stream name.
-
- Returns:
- list of str: All the matching vstream names for the provided stream name.
- """
- with ExceptionWrapper():
- return self._hef.get_vstream_names_from_stream_name(stream_name, self.name)
-
-
-class ActivatedNetworkContextManager(object):
- """A context manager that returns the activated network group upon enter."""
-
- def __init__(self, configured_network, activated_network, target, hef):
- self._configured_network = configured_network
- self._activated_network = activated_network
- self._target = target
- self._hef = hef
-
- def __enter__(self):
- with ExceptionWrapper():
- activated_network_group = ActivatedNetwork(self._configured_network, self._activated_network.__enter__(), self._target,
- self._hef)
- return activated_network_group
-
- def __exit__(self, *args):
- self._activated_network.__exit__(*args)
-
-
-class ActivatedNetwork(object):
- """The network group that is currently activated for inference."""
-
- def __init__(self, configured_network, activated_network, target, hef):
- self._configured_network = configured_network
- self._activated_network = activated_network
- self._target = target
- self._hef = hef
- self._last_number_of_invalid_frames_read = 0
-
- @property
- def target(self):
- return self._target
-
- @property
- def name(self):
- return self._configured_network.name
-
- def get_number_of_invalid_frames(self, clear=True):
- """Returns number of invalid frames.
-
- Args:
- clear (bool): If set, the returned value will be the number of invalid frames read since the last call to this function.
-
- Returns:
- int: Number of invalid frames.
- """
- total_invalid_frames_count = self._activated_network.get_invalid_frames_count()
- if clear:
- value = total_invalid_frames_count - self._last_number_of_invalid_frames_read
- self._last_number_of_invalid_frames_read = total_invalid_frames_count
- return value if clear else total_invalid_frames_count
-
- def validate_all_frames_are_valid(self):
- """Validates that all of the frames so far are valid (no invalid frames)."""
- number_of_invalid_frames = self.get_number_of_invalid_frames()
- if number_of_invalid_frames != 0:
- raise HailoRTException("There are {} invalid frames.".format(number_of_invalid_frames))
-
- def get_sorted_output_names(self):
- return self._hef.get_sorted_output_names(self.name)
-
- def _get_intermediate_buffer(self, src_context_index, src_stream_index):
- with ExceptionWrapper():
- return self._activated_network.get_intermediate_buffer(src_context_index, src_stream_index)
-
-
-class InferVStreams(object):
- """Pipeline that allows to call blocking inference, to be used as a context manager."""
-
- def __init__(self, configured_net_group, input_vstreams_params, output_vstreams_params,
- tf_nms_format=False):
- """Constructor for the InferVStreams class.
-
- Args:
- configured_net_group (:class:`ConfiguredNetwork`): The configured network group for
- which the pipeline is created.
- input_vstreams_params (dict from str to :class:`InputVStreamParams`): Params for the
- input vstreams in the pipeline. Only members of this dict will take part in the
- inference.
- output_vstreams_params (dict from str to :class:`OutputVStreamParams`): Params for the
- output vstreams in the pipeline. Only members of this dict will take part in the
- inference.
- tf_nms_format (bool, optional): indicates whether the returned nms outputs should be in
- Hailo format or TensorFlow format. Default is False (using Hailo format).
-
- * Hailo format -- list of :obj:`numpy.ndarray`. Each element represents the
- detections (bboxes) for the class, and its shape is
- ``[number_of_detections, BBOX_PARAMS]``
- * TensorFlow format -- :obj:`numpy.ndarray` of shape
- ``[class_count, BBOX_PARAMS, detections_count]`` padded with empty bboxes.
- """
-
- self._logger = default_logger()
- self._configured_net_group = configured_net_group
- self._net_group_name = configured_net_group.name
- self._input_vstreams_params = input_vstreams_params
- self._output_vstreams_params = output_vstreams_params
- self._tf_nms_format = tf_nms_format
- self._total_time = None
- self._hw_time = None
- self._network_name_to_outputs = InferVStreams._get_network_to_outputs_mapping(configured_net_group)
- self._input_name_to_network_name = InferVStreams._get_input_name_to_network_mapping(configured_net_group)
-
- @staticmethod
- def _get_input_name_to_network_mapping(configured_net_group):
- input_name_to_network_mapping = {}
- for network_name in configured_net_group.get_networks_names():
- for input_vstream_info in configured_net_group.get_input_vstream_infos(network_name):
- input_name_to_network_mapping[input_vstream_info.name] = network_name
- return input_name_to_network_mapping
-
- @staticmethod
- def _get_network_to_outputs_mapping(configured_net_group):
- network_to_outputs_mapping = {}
- for network_name in configured_net_group.get_networks_names():
- network_to_outputs_mapping[network_name] = set()
- for output_vstream_info in configured_net_group.get_output_vstream_infos(network_name):
- network_to_outputs_mapping[network_name].add(output_vstream_info.name)
- return network_to_outputs_mapping
-
- def _make_output_buffers_and_infos(self, input_data, batch_size):
- output_buffers = {}
- output_buffers_info = {}
- already_seen_networks = set()
- for input_name in input_data.keys():
- network_name = self._input_name_to_network_name[input_name]
- if (network_name not in already_seen_networks) :
- already_seen_networks.add(network_name)
- for output_name in self._network_name_to_outputs[network_name]:
- output_buffers_info[output_name] = OutputLayerUtils(self._configured_net_group._hef, output_name, self._infer_pipeline,
- self._net_group_name)
- output_tensor_info = output_buffers_info[output_name].output_tensor_info
- shape, dtype = output_tensor_info
- output_buffers[output_name] = numpy.empty([batch_size] + list(shape), dtype=dtype)
- return output_buffers, output_buffers_info
-
- def __enter__(self):
- self._infer_pipeline = _pyhailort.InferVStreams(self._configured_net_group._configured_network,
- self._input_vstreams_params, self._output_vstreams_params)
- return self
-
- def infer(self, input_data):
- """Run inference on the hardware device.
-
- Args:
- input_data (dict of :obj:`numpy.ndarray`): Where the key is the name of the input_layer,
- and the value is the data to run inference on.
-
- Returns:
- dict: Output tensors of all output layers. The keys are outputs names and the values
- are output data tensors as :obj:`numpy.ndarray` (or list of :obj:`numpy.ndarray` in case of nms output and tf_nms_format=False).
- """
-
- time_before_infer_calcs = time.time()
- if not isinstance(input_data, dict):
- input_stream_infos = self._configured_net_group.get_input_stream_infos()
- if len(input_stream_infos) != 1:
- raise Exception("when there is more than one input, the input_data should be of type dict,"
- " mapping between each input_name, and his input_data tensor. number of inputs: {}".format(len(input_stream_infos)))
- input_data = {input_stream_infos[0].name : input_data}
-
- batch_size = InferVStreams._get_number_of_frames(input_data)
- output_buffers, output_buffers_info = self._make_output_buffers_and_infos(input_data, batch_size)
-
- for input_layer_name in input_data:
- # TODO: Remove cast after tests are updated and are working
- self._cast_input_data_if_needed(input_layer_name, input_data)
- self._validate_input_data_format_type(input_layer_name, input_data)
- self._make_c_contiguous_if_needed(input_layer_name, input_data)
-
- with ExceptionWrapper():
- time_before_infer = time.time()
- self._infer_pipeline.infer(input_data, output_buffers, batch_size)
- self._hw_time = time.time() - time_before_infer
-
- for name, result_array in output_buffers.items():
- is_nms = output_buffers_info[name].is_nms
- if not is_nms:
- continue
- nms_shape = output_buffers_info[name].vstream_info.nms_shape
- if self._tf_nms_format:
- shape = [batch_size] + output_buffers_info[name].old_nms_fomrat_shape
- output_dtype = output_buffers_info[name].output_dtype
- quantized_empty_bbox = output_buffers_info[name].quantized_empty_bbox
- flat_result_array = result_array.reshape(-1)
- output_buffers[name] = HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format(flat_result_array, shape,
- output_dtype, quantized_empty_bbox)
- else:
- output_buffers[name] = HailoRTTransformUtils.output_raw_buffer_to_nms_format(result_array, nms_shape.number_of_classes)
-
- self._total_time = time.time() - time_before_infer_calcs
- return output_buffers
-
- def get_hw_time(self):
- """Get the hardware device operation time it took to run inference over the last batch.
-
- Returns:
- float: Time in seconds.
- """
- return self._hw_time
-
- def get_total_time(self):
- """Get the total time it took to run inference over the last batch.
-
- Returns:
- float: Time in seconds.
- """
- return self._total_time
-
- def _cast_input_data_if_needed(self, input_layer_name, input_data):
- input_dtype = input_data[input_layer_name].dtype
- with ExceptionWrapper():
- input_expected_dtype = self._infer_pipeline.get_host_dtype(input_layer_name)
- if input_dtype != input_expected_dtype:
-
- self._logger.warning("Given input data dtype ({}) is different than inferred dtype ({}). "
- "conversion for every frame will reduce performance".format(input_dtype,
- input_expected_dtype))
- input_data[input_layer_name] = input_data[input_layer_name].astype(input_expected_dtype)
-
- def _validate_input_data_format_type(self, input_layer_name, input_data):
- if input_layer_name not in self._input_vstreams_params:
- return
-
- input_data_format = self._input_vstreams_params[input_layer_name].user_buffer_format
- input_expected_item_size = _pyhailort.get_format_data_bytes(input_data_format)
- input_item_size = input_data[input_layer_name].dtype.itemsize
-
- # TODO: Add distinction between float32 and int32 and others
- if input_item_size != input_expected_item_size:
- raise HailoRTException("{} numpy array item size is {}, not {}".format(input_layer_name,
- input_item_size, input_expected_item_size))
-
- @staticmethod
- def _get_number_of_frames(input_data):
- # Checks that all the batch-sizes of the input_data are equals for all input layers
- if len(input_data) == 0:
- raise ValueError("Input_data can't be empty")
- batch_size_of_first_input = list(input_data.values())[0].shape[0]
- for name, input_data_tensor in input_data.items():
- if input_data_tensor.shape[0] != batch_size_of_first_input:
- raise ValueError(
- "The number of frames on all input_tensors should be equal! different sizes detected: {} != {}".format(
- batch_size_of_first_input, input_data_tensor.shape[0]))
- return batch_size_of_first_input
-
- def _make_c_contiguous_if_needed(self, input_layer_name, input_data):
- if not input_data[input_layer_name].flags.c_contiguous:
- self._logger.warning("Converting {} numpy array to be C_CONTIGUOUS".format(
- input_layer_name))
- input_data[input_layer_name] = numpy.asarray(input_data[input_layer_name], order='C')
-
- def __exit__(self, *args):
- self._infer_pipeline.release()
- return False
-
-
-class HailoRTTransformUtils(object):
- @staticmethod
- def get_dtype(data_bytes):
- """Get data type from the number of bytes."""
- if data_bytes == 1:
- return numpy.uint8
- elif data_bytes == 2:
- return numpy.uint16
- elif data_bytes == 4:
- return numpy.float32
- raise HailoRTException("unsupported data bytes value")
-
- @staticmethod
- def dequantize_output_buffer(src_buffer, dst_buffer, elements_count, quant_info):
- """De-quantize the data in input buffer `src_buffer` and output it to the buffer `dst_buffer`
-
- Args:
- src_buffer (:obj:`numpy.ndarray`): The input buffer containing the data to be de-quantized.
- The buffer's data type is the source data type.
- dst_buffer (:obj:`numpy.ndarray`): The buffer that will contain the de-quantized data.
- The buffer's data type is the destination data type.
- elements_count (int): The number of elements to de-quantize. This number must not exceed 'src_buffer' or 'dst_buffer' sizes.
- quant_info (:class:`~hailo_platform.drivers.hailort.pyhailort.QuantInfo`): The quantization info.
- """
- with ExceptionWrapper():
- src_format_type = HailoRTTransformUtils._get_format_type(src_buffer.dtype)
- dst_format_type = HailoRTTransformUtils._get_format_type(dst_buffer.dtype)
- _pyhailort.dequantize_output_buffer(src_buffer, dst_buffer, src_format_type, dst_format_type, elements_count, quant_info)
-
- @staticmethod
- def dequantize_output_buffer_in_place(raw_buffer, dst_dtype, elements_count, quant_info):
- """De-quantize the output buffer `raw_buffer` to data type `dst_dtype`.
-
- Args:
- raw_buffer (:obj:`numpy.ndarray`): The output buffer to be de-quantized. The buffer's data type is the source data type.
- dst_dtype (:obj:`numpy.dtype`): The data type to de-quantize `raw_buffer` to.
- elements_count (int): The number of elements to de-quantize. This number must not exceed 'raw_buffer' size.
- quant_info (:class:`~hailo_platform.drivers.hailort.pyhailort.QuantInfo`): The quantization info.
- """
- with ExceptionWrapper():
- src_format_type = HailoRTTransformUtils._get_format_type(raw_buffer.dtype)
- dst_format_type = HailoRTTransformUtils._get_format_type(dst_dtype)
- _pyhailort.dequantize_output_buffer_in_place(raw_buffer, src_format_type, dst_format_type, elements_count, quant_info)
-
- @staticmethod
- def quantize_input_buffer(src_buffer, dst_buffer, elements_count, quant_info):
- """Quantize the data in input buffer `src_buffer` and output it to the buffer `dst_buffer`
-
- Args:
- src_buffer (:obj:`numpy.ndarray`): The input buffer containing the data to be quantized.
- The buffer's data type is the source data type.
- dst_buffer (:obj:`numpy.ndarray`): The buffer that will contain the quantized data.
- The buffer's data type is the destination data type.
- elements_count (int): The number of elements to quantize. This number must not exceed 'src_buffer' or 'dst_buffer' sizes.
- quant_info (:class:`~hailo_platform.drivers.hailort.pyhailort.QuantInfo`): The quantization info.
- """
- with ExceptionWrapper():
- src_format_type = HailoRTTransformUtils._get_format_type(src_buffer.dtype)
- dst_format_type = HailoRTTransformUtils._get_format_type(dst_buffer.dtype)
- _pyhailort.quantize_input_buffer(src_buffer, dst_buffer, src_format_type, dst_format_type, elements_count, quant_info)
-
- @staticmethod
- def output_raw_buffer_to_nms_tf_format(raw_output_buffer, shape, dtype, quantized_empty_bbox):
- offset = 0
- # We create the tf_format buffer with reversed width/features for preformance optimization
- converted_output_buffer = numpy.empty([shape[0], shape[1], shape[3], shape[2]], dtype=dtype)
- for frame in range(converted_output_buffer.shape[0]):
- offset = frame * converted_output_buffer.shape[1] * (converted_output_buffer.shape[2] * converted_output_buffer.shape[3] + 1)
- HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format_single_frame(raw_output_buffer, converted_output_buffer[frame],
- converted_output_buffer.shape[1], converted_output_buffer.shape[2], quantized_empty_bbox, offset)
- converted_output_buffer = numpy.swapaxes(converted_output_buffer, 2, 3)
- return converted_output_buffer
-
- @staticmethod
- def output_raw_buffer_to_nms_tf_format_single_frame(raw_output_buffer, converted_output_frame, number_of_classes,
- max_bboxes_per_class, quantized_empty_bbox, offset=0):
- for class_i in range(number_of_classes):
- class_bboxes_amount = int(raw_output_buffer[offset])
- offset += 1
- if 0 != class_bboxes_amount:
- converted_output_frame[class_i][ : class_bboxes_amount][:] = raw_output_buffer[offset : offset + (BBOX_PARAMS * class_bboxes_amount)].reshape(class_bboxes_amount, BBOX_PARAMS)
- offset += BBOX_PARAMS * class_bboxes_amount
- converted_output_frame[class_i][class_bboxes_amount : max_bboxes_per_class][:] = quantized_empty_bbox
-
- @staticmethod
- def output_raw_buffer_to_nms_format(raw_output_buffer, number_of_classes):
- converted_output_buffer = []
- for frame in raw_output_buffer:
- converted_output_buffer.append(HailoRTTransformUtils.output_raw_buffer_to_nms_format_single_frame(frame, number_of_classes))
- return converted_output_buffer
-
- @staticmethod
- def output_raw_buffer_to_nms_format_single_frame(raw_output_buffer, number_of_classes, offset=0):
- converted_output_frame = []
- for class_i in range(number_of_classes):
- class_bboxes_amount = int(raw_output_buffer[offset])
- offset += 1
- if class_bboxes_amount == 0:
- converted_output_frame.append(numpy.empty([0, BBOX_PARAMS]))
- else:
- converted_output_frame.append(raw_output_buffer[offset : offset + (BBOX_PARAMS * class_bboxes_amount)].reshape(
- class_bboxes_amount, BBOX_PARAMS))
- offset += BBOX_PARAMS * class_bboxes_amount
- return converted_output_frame
-
- @staticmethod
- def _get_format_type(dtype):
- if dtype == numpy.uint8:
- return FormatType.UINT8
- elif dtype == numpy.uint16:
- return FormatType.UINT16
- elif dtype == numpy.float32:
- return FormatType.FLOAT32
- raise HailoRTException("unsupported data type {}".format(dtype))
-
-class InternalEthernetDevice(object):
- def __init__(self, address, port, response_timeout_seconds=10, max_number_of_attempts=3):
- self.device = None
- self._address = address
- self._port = port
- self._response_timeout_milliseconds = int(response_timeout_seconds * 1000)
- self._max_number_of_attempts = max_number_of_attempts
- with ExceptionWrapper():
- self.device = _pyhailort.create_eth_device(self._address, len(self._address), self._port,
- self._response_timeout_milliseconds, self._max_number_of_attempts)
-
- def __del__(self):
- self.release()
-
- def release(self):
- if self.device is None:
- return
- with ExceptionWrapper():
- _pyhailort.release_device(self.device)
- self.device = None
-
-
-class PcieDeviceInfo(_pyhailort.PcieDeviceInfo):
- """Represents pcie device info, includeing domain, bus, device and function.
- """
-
- BOARD_LOCATION_HELP_STRING = 'Board location in the format of the command: "lspci -d 1e60: | cut -d\' \' -f1" ([]::.). If not specified the first board is taken.'
-
- def __init__(self, bus, device, func, domain=None):
- super(PcieDeviceInfo, self).__init__()
- self.bus = bus
- self.device = device
- self.func = func
- if domain is None:
- self.domain = PCIE_ANY_DOMAIN
- else:
- self.domain = domain
-
- def __eq__(self, other):
- return (self.domain, self.bus, self.device, self.func) == (other.domain, other.bus, other.device, other.func)
-
- def __str__(self):
- with ExceptionWrapper():
- return super().__str__()
-
- def __repr__(self):
- return 'PcieDeviceInfo({})'.format(str(self))
-
- @classmethod
- def from_string(cls, board_location_str):
- """Parse pcie device info BDF from string. The format is []::."""
- with ExceptionWrapper():
- device_info = _pyhailort.PcieDeviceInfo._parse(board_location_str)
- return PcieDeviceInfo(device_info.bus, device_info.device, device_info.func, device_info.domain)
-
- @classmethod
- def argument_type(cls, board_location_str):
- """PcieDeviceInfo Argument type for argparse parsers"""
- try:
- return cls.from_string(board_location_str)
- except HailoRTException:
- raise ArgumentTypeError('Invalid device info string, format is []::.')
-
-
-class InternalPcieDevice(object):
- def __init__(self, device_info=None, send_identify=True):
- self.device = None
- if device_info is None:
- device_info = InternalPcieDevice.scan_devices()[0]
- self._device_handle = None
- self._device_info = device_info
- with ExceptionWrapper():
- self.device = _pyhailort.create_pcie_device(self._device_info)
- self._device_handle = _pyhailort.get_hlpcie_device(self.device)
- if send_identify:
- _pyhailort.identify(self.device)
-
- def __del__(self):
- self.release()
-
- def release(self):
- if self.device is None:
- return
- with ExceptionWrapper():
- _pyhailort.release_device(self.device)
- self._device_handle = None
- self.device = None
-
- @staticmethod
- def scan_devices():
- with ExceptionWrapper():
- return [PcieDeviceInfo(dev_info.bus, dev_info.device, dev_info.func, dev_info.domain)
- for dev_info in _pyhailort.scan_pcie_devices()]
-
- def create_debug_log(self):
- return PcieDebugLog(self)
-
- def write_memory(self, address, data):
- with ExceptionWrapper():
- _pyhailort.direct_write_memory(self.device, address, data)
-
- def read_memory(self, address, size):
- with ExceptionWrapper():
- return _pyhailort.direct_read_memory(self.device, address, size)
-
-
-class PcieDebugLog(object):
- def __init__(self, pci_device):
- self._pcie_device = pci_device
-
- def read(self, count, cpu_id):
- with ExceptionWrapper():
- return _pyhailort.read_log(self._pcie_device.device, count, cpu_id)
-
-
-class HailoPowerMeasurementUtils(object):
- @staticmethod
- def return_real_sampling_period(sampling_period):
- """Get a sampling period from the enum."""
- SamplingPeriodDictionary = dict([
- (SamplingPeriod.PERIOD_140us, 140),
- (SamplingPeriod.PERIOD_204us, 204),
- (SamplingPeriod.PERIOD_332us, 332),
- (SamplingPeriod.PERIOD_588us, 588),
- (SamplingPeriod.PERIOD_1100us, 1100),
- (SamplingPeriod.PERIOD_2116us, 2116),
- (SamplingPeriod.PERIOD_4156us, 4156),
- (SamplingPeriod.PERIOD_8244us, 8244),
- ])
- return SamplingPeriodDictionary[sampling_period]
-
- @staticmethod
- def return_real_averaging_factor(averaging_factor):
- """Get an averaging factor from the enum."""
- AveragingFactorDictionary = dict([
- (AveragingFactor.AVERAGE_1, 1),
- (AveragingFactor.AVERAGE_4, 4),
- (AveragingFactor.AVERAGE_16, 16),
- (AveragingFactor.AVERAGE_64, 64),
- (AveragingFactor.AVERAGE_128, 128),
- (AveragingFactor.AVERAGE_256, 256),
- (AveragingFactor.AVERAGE_512, 512),
- (AveragingFactor.AVERAGE_1024, 1024),
- ])
- return AveragingFactorDictionary[averaging_factor]
-
-
-class HailoPowerMode(_pyhailort.PowerMode):
- pass
-
-class HailoStreamInterface(_pyhailort.StreamInterface):
- pass
-
-class HailoStreamDirection(_pyhailort.StreamDirection):
- pass
-
-class HailoCpuId(_pyhailort.CpuId):
- pass
-
-class HailoFormatFlags(_pyhailort.FormatFlags):
- pass
-
-
-class VDevice(object):
- """Hailo virtual device representation."""
-
- def __init__(
- self,
- params=None, device_infos=None):
-
- """Create the Hailo virtual device object.
-
- Args:
- params (:obj:`hailo_platform.drivers.hailort.pyhailort.VDeviceParams`, optional): VDevice params, call
- :func:`VDevice.create_params` to get default params. Excludes 'device_infos'.
- device_infos (list of :obj:`hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`, optional): pcie devices infos to create VDevice from,
- call :func:`PcieDevice.scan_devices` to get list of all available devices. Excludes 'params'.
- """
- gc.collect()
- self._id = "VDevice"
- self._params = params
- self._device_infos = device_infos
- if self._device_infos is not None:
- if self._params is not None:
- raise HailoRTException("VDevice can be created from params or device_infos. Both parameters was passed to the c'tor")
- self._vdevice = None
- self._loaded_network_groups = []
- if self._vdevice is None:
- self._open_vdevice()
-
- self._creation_pid = os.getpid()
-
- def _open_vdevice(self):
- if self._device_infos is not None:
- with ExceptionWrapper():
- self._vdevice = _pyhailort.VDevice.create_from_infos(self._device_infos)
- else:
- if self._params is None:
- self._params = VDevice.create_params()
- with ExceptionWrapper():
- self._vdevice = _pyhailort.VDevice.create(self._params)
-
- def __enter__(self):
- if self._vdevice is None:
- self._open_vdevice()
- return self
-
- def release(self):
- if self._vdevice is not None:
- self._vdevice.release()
- self._vdevice = None
-
- def __exit__(self, *args):
- self.release()
- return False
-
- def __del__(self):
- self.release()
-
- @staticmethod
- def create_params():
- with ExceptionWrapper():
- return _pyhailort.VDeviceParams.default()
-
- def configure(self, hef, configure_params_by_name={}):
- """Configures target vdevice from HEF object.
-
- Args:
- hef (:class:`~hailo_platform.drivers.hailort.pyhailort.HEF`): HEF to configure the vdevice from
- configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
- """
- if self._creation_pid != os.getpid():
- raise HailoRTException("VDevice can only be configured from the process it was created in.")
- with ExceptionWrapper():
- configured_apps = self._vdevice.configure(hef._hef, configure_params_by_name)
- configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
- self._loaded_network_groups.extend(configured_networks)
- return configured_networks
-
- def get_physical_devices(self):
- """Gets the underlying physical devices.
-
- Return:
- list of :obj:`~hailo_platform.drivers.hw_object.PcieDevice`: The underlying physical devices.
- """
- with ExceptionWrapper():
- phys_dev_infos = self._vdevice.get_physical_devices_infos()
- pythonic_dev_infos = [PcieDeviceInfo(dev_info.bus, dev_info.device, dev_info.func, dev_info.domain)
- for dev_info in phys_dev_infos]
-
- from hailo_platform.drivers.hw_object import PcieDevice
- return [PcieDevice(info) for info in pythonic_dev_infos]
-
- def get_physical_devices_infos(self):
- """Gets the physical devices infos.
-
- Return:
- list of :obj:`~hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`: The underlying physical devices infos.
- """
- with ExceptionWrapper():
- return self._vdevice.get_physical_devices_infos()
-
-
-class InputVStreamParams(object):
- """Parameters of an input virtual stream (host to device)."""
-
- @staticmethod
- def make(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
- """Create input virtual stream params from a configured network group. These params determine the format of the
- data that will be fed into the network group.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the params are created.
- quantized (bool): Whether the data fed into the chip is already quantized. True means
- the data is already quantized. False means it's HailoRT's responsibility to quantize
- (scale) the data. Defaults to True.
- format_type (:class:`~hailo_platform.drivers.hailort.pyhailort.FormatType`): The
- default format type of the data for all input virtual streams. If quantized is False,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.FLOAT32`. Otherwise,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.AUTO`,
- which means the data is fed in the same format expected by the device (usually
- uint8).
- timeout_ms (int): The default timeout in milliseconds for all input virtual streams.
- Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
- queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
- network_name (str): Network name of the requested virtual stream params.
- If not passed, all the networks in the network group will be addressed.
-
- Returns:
- dict: The created virtual streams params. The keys are the vstreams names. The values are the
- params.
- """
- if format_type is None:
- if not quantized:
- format_type = FormatType.FLOAT32
- else:
- format_type = FormatType.AUTO
- if timeout_ms is None:
- timeout_ms = DEFAULT_VSTREAM_TIMEOUT_MS
- if queue_size is None:
- queue_size = DEFAULT_VSTREAM_QUEUE_SIZE
- name = network_name if network_name is not None else configured_network.name
- with ExceptionWrapper():
- return configured_network._hef._hef.get_input_vstreams_params(name, quantized,
- format_type, timeout_ms, queue_size)
-
- @staticmethod
- def make_from_network_group(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
- """Create input virtual stream params from a configured network group. These params determine the format of the
- data that will be fed into the network group.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the params are created.
- quantized (bool): Whether the data fed into the chip is already quantized. True means
- the data is already quantized. False means it's HailoRT's responsibility to quantize
- (scale) the data. Defaults to True.
- format_type (:class:`~hailo_platform.drivers.hailort.pyhailort.FormatType`): The
- default format type of the data for all input virtual streams. If quantized is False,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.FLOAT32`. Otherwise,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.AUTO`,
- which means the data is fed in the same format expected by the device (usually
- uint8).
- timeout_ms (int): The default timeout in milliseconds for all input virtual streams.
- Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
- queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
- network_name (str): Network name of the requested virtual stream params.
- If not passed, all the networks in the network group will be addressed.
-
- Returns:
- dict: The created virtual streams params. The keys are the vstreams names. The values are the
- params.
- """
- return InputVStreamParams.make(configured_network, quantized, format_type, timeout_ms, queue_size, network_name)
-
-
-class OutputVStreamParams(object):
- """Parameters of an output virtual stream (device to host)."""
-
- @staticmethod
- def make(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
- """Create output virtual stream params from a configured network group. These params determine the format of the
- data that will be fed into the network group.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the params are created.
- quantized (bool): Whether the data fed into the chip is already quantized. True means
- the data is already quantized. False means it's HailoRT's responsibility to quantize
- (scale) the data. Defaults to True.
- format_type (:class:`~hailo_platform.drivers.hailort.pyhailort.FormatType`): The
- default format type of the data for all output virtual streams. If quantized is False,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.FLOAT32`. Otherwise,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.AUTO`,
- which means the data is fed in the same format expected by the device (usually
- uint8).
- timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
- Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
- queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
- network_name (str): Network name of the requested virtual stream params.
- If not passed, all the networks in the network group will be addressed.
-
- Returns:
- dict: The created virtual streams params. The keys are the vstreams names. The values are the
- params.
- """
- if format_type is None:
- if not quantized:
- format_type = FormatType.FLOAT32
- else:
- format_type = FormatType.AUTO
- if timeout_ms is None:
- timeout_ms = DEFAULT_VSTREAM_TIMEOUT_MS
- if queue_size is None:
- queue_size = DEFAULT_VSTREAM_QUEUE_SIZE
- name = network_name if network_name is not None else configured_network.name
- with ExceptionWrapper():
- return configured_network._hef._hef.get_output_vstreams_params(name, quantized,
- format_type, timeout_ms, queue_size)
-
- @staticmethod
- def make_from_network_group(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
- """Create output virtual stream params from a configured network group. These params determine the format of the
- data that will be fed into the network group.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the params are created.
- quantized (bool): Whether the data fed into the chip is already quantized. True means
- the data is already quantized. False means it's HailoRT's responsibility to quantize
- (scale) the data. Defaults to True.
- format_type (:class:`~hailo_platform.drivers.hailort.pyhailort.FormatType`): The
- default format type of the data for all output virtual streams. If quantized is False,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.FLOAT32`. Otherwise,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.AUTO`,
- which means the data is fed in the same format expected by the device (usually
- uint8).
- timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
- Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
- queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
- network_name (str): Network name of the requested virtual stream params.
- If not passed, all the networks in the network group will be addressed.
-
- Returns:
- dict: The created virtual streams params. The keys are the vstreams names. The values are the
- params.
- """
- return OutputVStreamParams.make(configured_network, quantized, format_type, timeout_ms, queue_size, network_name)
-
- @staticmethod
- def make_groups(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None):
- """Create output virtual stream params from a configured network group. These params determine the format of the
- data that will be fed into the network group. The params groups are splitted with respect to their underlying streams for multi process usges.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the params are created.
- quantized (bool): Whether the data fed into the chip is already quantized. True means
- the data is already quantized. False means it's HailoRT's responsibility to quantize
- (scale) the data. Defaults to True.
- format_type (:class:`~hailo_platform.drivers.hailort.pyhailort.FormatType`): The
- default format type of the data for all output virtual streams. If quantized is False,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.FLOAT32`. Otherwise,
- the default is :attr:`~hailo_platform.drivers.hailort.pyhailort.FormatType.AUTO`,
- which means the data is fed in the same format expected by the device (usually
- uint8).
- timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
- Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
- queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
-
- Returns:
- list of dicts: Each element in the list represent a group of params, where the keys are the vstreams names, and the values are the
- params. The params groups are splitted with respect to their underlying streams for multi process usges.
- """
- all_params = OutputVStreamParams.make(configured_network, quantized=quantized, format_type=format_type, timeout_ms=timeout_ms, queue_size=queue_size)
- low_level_streams_names = [stream_info.name for stream_info in configured_network.get_output_stream_infos()]
- stream_name_to_vstream_names = {stream_name: configured_network.get_vstream_names_from_stream_name(stream_name) for stream_name in low_level_streams_names}
- results = []
- for low_level_stream_name, vstream_names in stream_name_to_vstream_names.items():
- params_group = {}
- for vstream_name in vstream_names:
- # Vstreams that were already seen should not be added to another params_group
- if all_params[vstream_name] is not None:
- params_group[vstream_name] = all_params[vstream_name]
- all_params[vstream_name] = None
- if 0 < len(params_group):
- results.append(params_group)
- return results
-
-
-class InputVStream(object):
- """Represents a single virtual stream in the host to device direction."""
-
- def __init__(self, send_object):
- self._send_object = send_object
- self._input_dtype = self._send_object.dtype
-
- @property
- def shape(self):
- return self._send_object.shape
-
- @property
- def dtype(self):
- return self._send_object.dtype
-
- @property
- def name(self):
- return self._send_object.info.name
-
- @property
- def network_name(self):
- return self._send_object.info.network_name
-
- def send(self, input_data):
- """Send frames to inference.
-
- Args:
- input_data (:obj:`numpy.ndarray`): Data to run inference on.
- """
-
- if input_data.dtype != self._input_dtype:
- input_data = input_data.astype(self._input_dtype)
-
- if not input_data.flags.c_contiguous:
- logger = default_logger()
- logger.warning("Warning - Converting input numpy array to be C_CONTIGUOUS")
- input_data = numpy.asarray(input_data, order='C')
-
- batch_number = 0
- batch_size = 1
- while batch_number < input_data.shape[0]:
- data = input_data[batch_number:batch_number + batch_size]
- with ExceptionWrapper():
- self._send_object.send(data)
- batch_number += batch_size
-
- def flush(self):
- """Blocks until there are no buffers in the input VStream pipeline."""
- with ExceptionWrapper():
- self._send_object.flush()
-
- @property
- def info(self):
- with ExceptionWrapper():
- return self._send_object.info
-
-class InputVStreams(object):
- """Input vstreams pipelines that allows to send data, to be used as a context manager."""
-
- def __init__(self, configured_network, input_vstreams_params):
- """Constructor for the InputVStreams class.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which the pipeline is created.
- input_vstreams_params (dict from str to :class:`InputVStreamParams`): Params for the input vstreams in the pipeline.
- """
- self._configured_network = configured_network
- self._input_vstreams_params = input_vstreams_params
- self._vstreams = {}
-
- def __enter__(self):
- self._input_vstreams_holder = self._configured_network._create_input_vstreams(self._input_vstreams_params)
- self._input_vstreams_holder.__enter__()
- for name, vstream in self._input_vstreams_holder.get_all_inputs().items():
- self._vstreams[name] = InputVStream(vstream)
- return self
-
- def get(self, name=None):
- """Return a single input vstream by its name.
-
- Args:
- name (str): The vstream name. If name=None and there is a single input vstream, that single (:class:`InputVStream`) will be returned.
- Otherwise, if name=None and there are multiple input vstreams, an exception will be thrown.
-
- Returns:
- :class:`InputVStream`: The (:class:`InputVStream`) that corresponds to the given name.
- """
- if name is None:
- if len(self._vstreams) != 1:
- raise HailoRTException("There is no single input vStream. You must give a name")
- name = list(self._vstreams.keys())[0]
- return self._vstreams[name]
-
- def clear(self):
- """Clears the vstreams' pipeline buffers."""
- with ExceptionWrapper():
- self._input_vstreams_holder.clear()
-
- def __exit__(self, *args):
- self._input_vstreams_holder.__exit__(*args)
- return False
-
- def __iter__(self):
- return iter(self._vstreams.values())
-
-class OutputLayerUtils(object):
- def __init__(self, hef, vstream_name, pipeline, net_group_name=""):
- self._hef = hef
- self._net_group_name = net_group_name
- self._vstream_info = self._get_vstream_info(vstream_name)
-
- if isinstance(pipeline, (_pyhailort.InferVStreams)):
- # TODO: HRT-5754 - Save user buffer instead of dtype and flags.
- self._output_dtype = pipeline.get_host_dtype(vstream_name)
- self._output_shape = pipeline.get_shape(vstream_name)
- self._output_flags = pipeline.get_user_buffer_format(vstream_name).flags
- else:
- self._output_dtype = pipeline.dtype
- self._output_shape = pipeline.shape
- self._output_flags = pipeline.get_user_buffer_format().flags
-
- self._is_nms = (self._vstream_info.format.order == FormatOrder.HAILO_NMS)
- if self._is_nms:
- self._quantized_empty_bbox = numpy.asarray([0] * BBOX_PARAMS, dtype=self._output_dtype)
- if not (self._output_flags & _pyhailort.FormatFlags.QUANTIZED):
- HailoRTTransformUtils.dequantize_output_buffer_in_place(self._quantized_empty_bbox, self._output_dtype,
- BBOX_PARAMS, self._vstream_info.quant_info)
-
- @property
- def output_dtype(self):
- return self._output_dtype
-
- @property
- def output_shape(self):
- return self._output_shape
-
- @property
- def vstream_info(self):
- return self._vstream_info
-
- @property
- def output_tensor_info(self):
- return self.output_shape, self.output_dtype
-
- @property
- def is_nms(self):
- return self._is_nms
-
- @property
- def quantized_empty_bbox(self):
- return self._quantized_empty_bbox
-
- def _get_vstream_info(self, name):
- output_vstream_infos = self._hef.get_output_vstream_infos(self._net_group_name)
- for info in output_vstream_infos:
- if info.name == name:
- return info
- raise HailoRTException("No vstream matches the given name {}".format(name))
-
- @property
- def old_nms_fomrat_shape(self):
- nms_shape = self._vstream_info.nms_shape
- return [nms_shape.number_of_classes, BBOX_PARAMS,
- nms_shape.max_bboxes_per_class]
-
-class OutputVStream(object):
- """Represents a single output virtual stream in the device to host direction."""
-
- def __init__(self, configured_network, recv_object, name, tf_nms_format=False, net_group_name=""):
- self._recv_object = recv_object
- self._output_layer_utils = OutputLayerUtils(configured_network._hef, name, self._recv_object, net_group_name)
- self._output_dtype = self._output_layer_utils.output_dtype
- self._vstream_info = self._output_layer_utils._vstream_info
- self._output_tensor_info = self._output_layer_utils.output_tensor_info
- self._is_nms = self._output_layer_utils.is_nms
- if self._is_nms:
- self._quantized_empty_bbox = self._output_layer_utils.quantized_empty_bbox
- self._tf_nms_format = tf_nms_format
-
- @property
- def shape(self):
- return self._recv_object.shape
-
- @property
- def dtype(self):
- return self._recv_object.dtype
-
- @property
- def name(self):
- return self._vstream_info.name
-
- @property
- def network_name(self):
- return self._vstream_info.network_name
-
- def recv(self):
- """Receive frames after inference.
-
- Returns:
- :obj:`numpy.ndarray`: The output of the inference for a single frame. The returned
- tensor does not include the batch dimension.
- In case of nms output and tf_nms_format=False, returns list of :obj:`numpy.ndarray`.
- """
- result_array = None
- with ExceptionWrapper():
- result_array = self._recv_object.recv()
-
- if self._is_nms:
- nms_shape = self._vstream_info.nms_shape
- if self._tf_nms_format:
- nms_results_tesnor = result_array
- # We create the tf_format buffer with reversed width/features for preformance optimization
- shape = self._output_layer_utils.old_nms_fomrat_shape
- result_array = numpy.empty([shape[0], shape[2], shape[1]], dtype=self._output_dtype)
- HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format_single_frame(nms_results_tesnor, result_array,
- nms_shape.number_of_classes,
- nms_shape.max_bboxes_per_class, self._quantized_empty_bbox)
- result_array = numpy.swapaxes(result_array, 1, 2)
- else:
- result_array = HailoRTTransformUtils.output_raw_buffer_to_nms_format_single_frame(result_array,
- nms_shape.number_of_classes)
- return result_array
-
- @property
- def info(self):
- with ExceptionWrapper():
- return self._recv_object.info
-
-class OutputVStreams(object):
- """Output virtual streams pipelines that allows to receive data, to be used as a context manager."""
-
- def __init__(self, configured_network, output_vstreams_params, tf_nms_format=False):
- """Constructor for the OutputVStreams class.
-
- Args:
- configured_network (:class:`ConfiguredNetwork`): The configured network group for which
- the pipeline is created.
- output_vstreams_params (dict from str to :class:`OutputVStreamParams`): Params for the
- output vstreams in the pipeline.
- tf_nms_format (bool, optional): indicates whether the returned nms outputs should be in
- Hailo format or TensorFlow format. Default is False (using Hailo format).
-
- * Hailo format -- list of :obj:`numpy.ndarray`. Each element represents th
- detections (bboxes) for the class, and its shape is
- ``[number_of_detections, BBOX_PARAMS]``
- * TensorFlow format -- :obj:`numpy.ndarray` of shape
- ``[class_count, BBOX_PARAMS, detections_count]`` padded with empty bboxes.
- """
- self._configured_network = configured_network
- self._net_group_name = configured_network.name
- self._output_vstreams_params = output_vstreams_params
- self._output_tensor_info = {}
- self._tf_nms_format = tf_nms_format
- self._vstreams = {}
-
- def __enter__(self):
- self._output_vstreams_holder = self._configured_network._create_output_vstreams(self._output_vstreams_params)
- self._output_vstreams_holder.__enter__()
- for name, vstream in self._output_vstreams_holder.get_all_outputs().items():
- self._vstreams[name] = OutputVStream(self._configured_network, vstream, name,
- tf_nms_format=self._tf_nms_format, net_group_name=self._net_group_name)
- return self
-
- def get(self, name=None):
- """Return a single output vstream by its name.
-
- Args:
- name (str): The vstream name. If name=None and there is a single output vstream, that single (:class:`OutputVStream`) will be returned.
- Otherwise, if name=None and there are multiple output vstreams, an exception will be thrown.
-
- Returns:
- :class:`OutputVStream`: The (:class:`OutputVStream`) that corresponds to the given name.
- """
- if name is None:
- if len(self._vstreams) != 1:
- raise HailoRTException("There is no single output vStream. You must give a name")
- name = list(self._vstreams.keys())[0]
- return self._vstreams[name]
-
- def clear(self):
- """Clears the vstreams' pipeline buffers."""
- with ExceptionWrapper():
- self._output_vstreams_holder.clear()
-
- def __exit__(self, *args):
- self._output_vstreams_holder.__exit__(*args)
- return False
-
- def __iter__(self):
- return iter(self._vstreams.values())
+from hailo_platform.pyhailort.pyhailort import * # noqa F401
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hw_object.py b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hw_object.py
index c285caf..c70c019 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hw_object.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hw_object.py
@@ -1,465 +1 @@
-#!/usr/bin/env python
-
-"""Hailo hardware API"""
-from __future__ import division
-
-import gc
-import os
-
-from contextlib import contextmanager
-
-from hailo_platform.drivers.control_object import UdpHcpControl, PcieHcpControl
-from hailo_platform.common.compatibility import ensure_str
-from hailo_platform.common.targets.inference_targets import InferenceTargets, InferenceObject, InferenceTargetException
-from hailo_platform.common.logger.logger import default_logger
-from hailo_platform.drivers.hailo_controller.hailo_control_protocol import BoardInformation
-
-from hailo_platform.drivers.hailort.pyhailort import ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice, HailoRTTransformUtils, HailoUdpScan, HailoRTException
-
-
-class HailoHWObjectException(InferenceTargetException):
- """Raised in any error related to Hailo hardware."""
- pass
-
-
-class HailoHWObject(InferenceObject):
- """Abstract Hailo hardware device representation."""
-
- IS_NUMERIC = True
-
- def __init__(self):
- """Create the Hailo hardware object."""
- super(HailoHWObject, self).__init__()
- self._last_interact_time = None
- self._total_time = None
- self._id = None
- self._hw_arch = None
- self._logger = default_logger()
- self._debug = False
- self._is_device_used = False
- self._hef_loaded = False
-
- @property
- def device_id(self):
- """Getter for the device_id.
-
- Returns:
- str: A string ID of the device. BDF for PCIe devices, MAC address for Ethernet devices, "Core" for core devices.
- """
- return self._id
-
- @property
- def sorted_output_layer_names(self):
- """Getter for the property sorted_output_names.
-
- Returns:
- list of str: Sorted list of the output layer names.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to sorted_output_layer_names is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_sorted_output_names()
-
- @contextmanager
- def use_device(self, *args, **kwargs):
- """A context manager that wraps the usage of the device (deprecated)."""
- self._is_device_used = True
- yield
- self._is_device_used = False
-
- def get_output_device_layer_to_original_layer_map(self):
- """Get a mapping between the device outputs to the layers' names they represent.
-
- Returns:
- dict: Keys are device output names and values are lists of layers' names.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
- return {stream_info.name : self._loaded_network_groups[0].get_vstream_names_from_stream_name(stream_info.name)
- for stream_info in self.get_output_stream_infos()}
-
- def get_original_layer_to_device_layer_map(self):
- """Get a mapping between the layer names and the device outputs that contain them.
-
- Returns:
- dict: Keys are the names of the layers and values are device outputs names.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
- return {vstream_info.name : self._loaded_network_groups[0].get_stream_names_from_vstream_name(vstream_info.name)
- for vstream_info in self.get_output_vstream_infos()}
-
- @property
- def device_input_layers(self):
- """Get a list of the names of the device's inputs."""
- return [layer.name for layer in self.get_input_stream_infos()]
-
- @property
- def device_output_layers(self):
- """Get a list of the names of the device's outputs."""
- return [layer.name for layer in self.get_output_stream_infos()]
-
- def hef_loaded(self):
- """Return True if this object has loaded the model HEF to the hardware device."""
- return self._hef_loaded
-
- def outputs_count(self):
- """Return the amount of output tensors that are returned from the hardware device for every
- input image.
- """
- return len(self.get_output_vstream_infos())
-
- def _clear_shapes(self):
- self._hw_consts = None
-
- @property
- def model_name(self):
- """Get the name of the current model.
-
- Returns:
- str: Model name.
- """
- if len(self._loaded_network_groups) == 1:
- return self._loaded_network_groups[0].name
- raise HailoHWObjectException(
- "This function is only supported when there is exactly 1 loaded network group. one should use HEF.get_network_group_names() / ConfiguredNetwork.name / ActivatedNetwork.name")
-
- def get_output_shapes(self):
- """Get the model output shapes, as returned to the user (without any hardware padding).
-
- Returns:
- Tuple of output shapes, sorted by the output names.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Calling get_output_shapes is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_output_shapes()
-
-
-class HailoChipObject(HailoHWObject):
- """Hailo hardware device representation"""
- IS_NUMERIC = True
- IS_HARDWARE = True
-
- def __init__(self):
- """Create the Hailo Chip hardware object."""
- super(HailoChipObject, self).__init__()
- self._id = "Generic Hailo Device"
- self._control_object = None
- self._loaded_network_groups = []
- self._creation_pid = os.getpid()
-
- @property
- def control(self):
- """:class:`HailoControl `: Returns
- the control object of this device, which implements the control API of the Hailo device.
-
- .. attention:: Use the low level control API with care.
- """
- return self._control_object
-
- def get_all_input_layers_dtype(self):
- """Get the model inputs dtype.
-
- Returns:
- dict of :obj:'numpy.dtype': where the key is model input_layer name, and the value is dtype as the device expect to get for this input.
- """
- return {stream.name: HailoRTTransformUtils.get_dtype(stream.data_bytes) for stream in self.get_input_stream_infos()}
-
- def get_input_vstream_infos(self, network_name=None):
- """Get input vstreams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
- """
-
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_input_vstream_infos(network_name=network_name)
-
- def get_output_vstream_infos(self, network_name=None):
- """Get output vstreams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
- """
-
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_output_vstream_infos(network_name=network_name)
-
- def get_all_vstream_infos(self, network_name=None):
- """Get input and output vstreams information.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
- """
-
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_all_vstream_infos(network_name=network_name)
-
- def get_input_stream_infos(self, network_name=None):
- """Get the input low-level streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with information objects
- of all input low-level streams.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_input_stream_infos(network_name=network_name)
-
- def get_output_stream_infos(self, network_name=None):
- """Get the output low-level streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with information objects
- of all output low-level streams.
- """
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_output_stream_infos(network_name=network_name)
-
- def get_all_stream_infos(self, network_name=None):
- """Get input and output streams information of a specific network group.
-
- Args:
- network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
-
- Returns:
- If there is exactly one configured network group, returns a list of
- :obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
- """
-
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0].get_all_stream_infos(network_name=network_name)
-
- @property
- def loaded_network_groups(self):
- """Getter for the property _loaded_network_groups.
-
- Returns:
- list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
- """
- return self._loaded_network_groups
-
- @property
- def _loaded_network_group(self):
- if len(self._loaded_network_groups) != 1:
- raise HailoHWObjectException("Access to network layer info is only allowed when there is a single loaded network group")
- return self._loaded_network_groups[0]
-
- def configure(self, hef, configure_params_by_name={}):
- """Configures target device from HEF object.
-
- Args:
- hef (:class:`~hailo_platform.drivers.hailort.pyhailort.HEF`): HEF to configure the device from
- configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
- """
- if self._creation_pid != os.getpid():
- raise HailoRTException("Device can only be configured from the process it was created in.")
- configured_apps = self._control_object.configure(hef, configure_params_by_name)
- self._hef_loaded = True
- configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
- self._loaded_network_groups.extend(configured_networks)
- return configured_networks
-
- def get_input_shape(self, name=None):
- """Get the input shape (not padded) of a network.
-
- Args:
- name (str, optional): The name of the desired input. If a name is not provided, return
- the first input_dataflow shape.
-
- Returns:
- Tuple of integers representing the input_shape.
- """
- if name is None:
- name = self.get_input_vstream_infos()[0].name
-
- for input_vstream in self.get_input_vstream_infos():
- if input_vstream.name == name:
- return input_vstream.shape
-
- raise HailoHWObjectException("There is no input named {}! the input names are: {}".format(name,
- [input_vstream.name for input_vstream in self.get_input_vstream_infos()]))
-
- def get_index_from_name(self, name):
- """Get the index in the output list from the name.
-
- Args:
- name (str): The name of the output.
-
- Returns:
- int: The index of the layer name in the output list.
- """
- try:
- return self.sorted_output_layer_names.index(ensure_str(name))
- except ValueError:
- if len(self.sorted_output_layer_names) == 1:
- # Case regard to SDK-9366 - see Jira for details.
- self._logger.warning('Incorrect meta item - layer defuse_name does not match layer name.')
- return 0
- else:
- raise HailoHWObjectException("Could not get index for outputs properly.")
-
-
-class EthernetDevice(HailoChipObject):
- """Represents any Hailo hardware device that supports UDP control and dataflow."""
-
- NAME = InferenceTargets.UDP_CONTROLLER
-
- def __init__(
- self,
- remote_ip,
- remote_control_port=22401):
- """Create the Hailo UDP hardware object.
-
- Args:
- remote_ip (str): Device IP address.
- remote_control_port (int, optional): UDP port to which the device listens for control.
- Defaults to 22401.
- """
-
- super(EthernetDevice, self).__init__()
-
- self._remote_ip = remote_ip
- gc.collect()
- self._remote_control_port = remote_control_port
- # EthernetDevice __del__ function tries to release self._eth_device.
- # to avoid AttributeError if the __init__ func fails, we set it to None first.
- # https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
- self._eth_device = None
- self._id = "{}".format(self._remote_ip)
-
- if not self.hef_loaded():
- self._open_device()
-
- identity = self._control_object._device_id
- self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
-
- @staticmethod
- def scan_devices(interface_name, timeout_seconds=3):
- """Scans for all eth devices on a specific network interface.
-
- Args:
- interface_name (str): Interface to scan.
- timeout_seconds (int, optional): timeout for scan operation. Defaults to 3.
- Returns:
- list of str: IPs of scanned devices.
- """
- udp_scanner = HailoUdpScan()
- return udp_scanner.scan_devices(interface_name, timeout_seconds=timeout_seconds)
-
- def _open_device(self):
- self._eth_device = InternalEthernetDevice(self._remote_ip, self._remote_control_port)
- self._control_object = UdpHcpControl(self._remote_ip, device=self._eth_device, remote_control_port=self._remote_control_port)
-
- def _close(self):
- if self._eth_device is not None:
- self._eth_device.release()
- self._eth_device = None
-
- def __enter__(self):
- if not self.hef_loaded:
- return None
- self._open_device()
- return self
-
- def __exit__(self, *args):
- self._close()
- return False
-
- def __del__(self):
- self._close()
-
- @property
- def remote_ip(self):
- """Return the IP of the remote device."""
- return self._remote_ip
-
-
-class PcieDevice(HailoChipObject):
- """Hailo PCIe production device representation."""
-
- NAME = InferenceTargets.PCIE_CONTROLLER
-
- def __init__(
- self,
- device_info=None):
-
- """Create the Hailo PCIe hardware object.
-
- Args:
- device_info (:obj:`hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`, optional): Device info to create, call
- :func:`PcieDevice.scan_devices` to get list of all available devices.
- """
- super(PcieDevice, self).__init__()
-
- gc.collect()
- # PcieDevice __del__ function tries to release self._pcie_device.
- # to avoid AttributeError if the __init__ func fails, we set it to None first.
- # https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
- self._pcie_device = None
- self._device_info = device_info
-
- if not self.hef_loaded():
- self._open_device()
-
- # At this point self._device_info is already initialized
- self._id = "{}".format(self._device_info)
-
- identity = self._control_object._device_id
- self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
-
- @staticmethod
- def scan_devices():
- """Scans for all pcie devices on the system.
-
- Returns:
- list of :obj:`hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`
- """
- return InternalPcieDevice.scan_devices()
-
- def _open_device(self):
- self._pcie_device = InternalPcieDevice(self._device_info)
- self._device_info = self._pcie_device._device_info
- self._control_object = PcieHcpControl(device=self._pcie_device, device_info=self._device_info)
-
- def _close(self):
- if self._pcie_device is not None:
- self._pcie_device.release()
- self._pcie_device = None
-
- def __enter__(self):
- if not self.hef_loaded:
- return None
- self._open_device()
- return self
-
- def __exit__(self, *args):
- self._close()
- return False
-
- def __del__(self):
- self._close()
+from hailo_platform.pyhailort.hw_object import * # noqa F401
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/paths.py b/hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/paths.py
deleted file mode 100644
index 6855145..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/paths.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-import hailo_platform
-from hailo_platform.common.paths_manager.paths import SDKPaths, Singleton
-import os
-from future.utils import with_metaclass
-
-
-class PlatformPaths(with_metaclass(Singleton, SDKPaths)):
- def join_platform(self, path):
- return os.path.join(os.path.abspath(hailo_platform.__path__[0]), path)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/__init__.py
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/__init__.py
rename to hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/__init__.py
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/control_object.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/control_object.py
new file mode 100644
index 0000000..f4b3e20
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/control_object.py
@@ -0,0 +1,745 @@
+#!/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
+
+import hailo_platform.pyhailort._pyhailort as _pyhailort
+
+
+class ControlObjectException(Exception):
+ """Raised on illegal ContolObject operation."""
+ pass
+
+
+class FirmwareUpdateException(Exception):
+ pass
+
+
+class HailoControl(with_metaclass(ABCMeta, object)):
+ """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."""
+
+ def __init__(self, remote_ip, device=None, remote_control_port=22401, retries=2, response_timeout_seconds=10.0, ignore_socket_errors=False):
+ """Initializes a new UdpControllerControl object.
+
+ Args:
+ remote_ip (str): The IPv4 address of the remote Hailo device (X.X.X.X).
+ remote_control_port (int, optional): The port that the remote Hailo device listens on.
+ 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,
+ response_timeout_milliseconds, max_number_of_attempts)
+ else:
+ self._device = device.device
+ self._device_id = self.identify()
+
+
+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)
+ 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.
+
+ 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)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/ethernet_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/ethernet_utils.py
new file mode 100644
index 0000000..0b0bb84
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/ethernet_utils.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+from builtins import str
+import netifaces as ni
+
+from netaddr import IPAddress, IPNetwork
+
+
+# As defined in sockios.h
+SIOCGIFTXQLEN = 0x8942
+# Interface name is 16 bytes (including NULL)
+SIOCGIFTXQLEN_FMT = "16sI"
+
+class NoInterfaceError(Exception):
+ """Raised by get_interface_from_ip when no matching interface was found"""
+ pass
+
+def get_interface_from_ip(ip_address):
+ """Returns the interface name associated with the given ip addressself.
+
+ Args:
+ ip_address (str): the IP address to query.
+
+ Returns:
+ str: The name of the interface matching the given IP address.
+ """
+
+ skipped_ifaces = []
+ for interface in ni.interfaces():
+ if ni.AF_INET not in ni.ifaddresses(interface):
+ skipped_ifaces.append(interface)
+ continue
+ af_inet_values = ni.ifaddresses(interface)[ni.AF_INET][0]
+ ip_addr, netmask = af_inet_values['addr'], af_inet_values['netmask']
+ if is_ip_in_network(ip_addr, netmask, ip_address):
+ return str(interface)
+
+ raise NoInterfaceError('No interface for {} found among {}'.format(ip_address, skipped_ifaces))
+
+
+def get_interface_address(interface_name):
+ """Returns the interface address associated with the given interface name.
+
+ Args:
+ interface_name (str): the name of the interface to query.
+
+ Returns:
+ str: The IP address of the interface matching the given interface_name.
+ """
+ af_inet_values = ni.ifaddresses(interface_name)[ni.AF_INET][0]
+ return af_inet_values['addr']
+
+
+def is_ip_in_network(network_ip, netmask, ip_in_question):
+ """Checks whether an IP address is located in a given network.
+
+ Args:
+ network_ip (str): the IP address of the network interface.
+ netmask (str): the netmask of the given networkself.
+ ip_in_question (str): the IP address to compare against the network.
+
+ Returns:
+ bool: whether the IP address belongs to the given network.
+ """
+
+ netmask_bits = IPAddress(netmask).netmask_bits()
+ return IPAddress(ip_in_question) in IPNetwork('{}/{}'.format(network_ip, netmask_bits))
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hailo_control_protocol.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hailo_control_protocol.py
new file mode 100644
index 0000000..2754cc8
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hailo_control_protocol.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python
+"""
+.. module:: hailo_control_protocol
+ :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 = 0
+
+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 if the string field is empty
+ return string_field.rstrip('\x00') or ""
+
+ 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 ""
+ 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 = '`: Returns
+ the control object of this device, which implements the control API of the Hailo device.
+
+ .. attention:: Use the low level control API with care.
+ """
+ if self._control_object is None:
+ raise HailoRTException(
+ "The device has been released and is not usable."
+ " Device is released when the function `release()` is called explicitly, or when created using a context manager and goes out of scope.")
+ return self._control_object
+
+ def get_all_input_layers_dtype(self):
+ """Get the model inputs dtype.
+
+ Returns:
+ dict of :obj:'numpy.dtype': where the key is model input_layer name, and the value is dtype as the device expect to get for this input.
+ """
+ return {stream.name: HailoRTTransformUtils.get_dtype(stream.data_bytes) for stream in self.get_input_stream_infos()}
+
+ def get_input_vstream_infos(self, network_name=None):
+ """Get input vstreams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
+ """
+
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_input_vstream_infos(network_name=network_name)
+
+ def get_output_vstream_infos(self, network_name=None):
+ """Get output vstreams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
+ """
+
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_output_vstream_infos(network_name=network_name)
+
+ def get_all_vstream_infos(self, network_name=None):
+ """Get input and output vstreams information.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
+ """
+
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_all_vstream_infos(network_name=network_name)
+
+ def get_input_stream_infos(self, network_name=None):
+ """Get the input low-level streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
+ of all input low-level streams.
+ """
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_input_stream_infos(network_name=network_name)
+
+ def get_output_stream_infos(self, network_name=None):
+ """Get the output low-level streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
+ of all output low-level streams.
+ """
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_output_stream_infos(network_name=network_name)
+
+ def get_all_stream_infos(self, network_name=None):
+ """Get input and output streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ If there is exactly one configured network group, returns a list of
+ :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
+ """
+
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0].get_all_stream_infos(network_name=network_name)
+
+ @property
+ def loaded_network_groups(self):
+ """Getter for the property _loaded_network_groups.
+
+ Returns:
+ list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
+ """
+ return self._loaded_network_groups
+
+ @property
+ def _loaded_network_group(self):
+ if len(self._loaded_network_groups) != 1:
+ raise HailoHWObjectException("Access to network layer info is only allowed when there is a single loaded network group")
+ return self._loaded_network_groups[0]
+
+ def configure(self, hef, configure_params_by_name={}):
+ """Configures target device from HEF object.
+
+ Args:
+ hef (:class:`~hailo_platform.pyhailort.pyhailort.HEF`): HEF to configure the device from
+ configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
+ """
+ if self._creation_pid != os.getpid():
+ raise HailoRTException("Device can only be configured from the process it was created in.")
+ configured_apps = self.control.configure(hef, configure_params_by_name)
+ self._hef_loaded = True
+ configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
+ self._loaded_network_groups.extend(configured_networks)
+ return configured_networks
+
+ def get_input_shape(self, name=None):
+ """Get the input shape (not padded) of a network.
+
+ Args:
+ name (str, optional): The name of the desired input. If a name is not provided, return
+ the first input_dataflow shape.
+
+ Returns:
+ Tuple of integers representing the input_shape.
+ """
+ if name is None:
+ name = self.get_input_vstream_infos()[0].name
+
+ for input_vstream in self.get_input_vstream_infos():
+ if input_vstream.name == name:
+ return input_vstream.shape
+
+ raise HailoHWObjectException("There is no input named {}! the input names are: {}".format(name,
+ [input_vstream.name for input_vstream in self.get_input_vstream_infos()]))
+
+ def get_index_from_name(self, name):
+ """Get the index in the output list from the name.
+
+ Args:
+ name (str): The name of the output.
+
+ Returns:
+ int: The index of the layer name in the output list.
+ """
+ try:
+ return self.sorted_output_layer_names.index(name)
+ except ValueError:
+ if len(self.sorted_output_layer_names) == 1:
+ # Case regard to SDK-9366 - see Jira for details.
+ self._logger.warning('Incorrect meta item - layer defuse_name does not match layer name.')
+ return 0
+ else:
+ raise HailoHWObjectException("Could not get index for outputs properly.")
+
+ def release(self):
+ """
+ Release the allocated resources of the device. This function should be called when working with the device not as context-manager.
+ Note: After calling this function, the device will not be usable.
+ """
+ if self._device is not None:
+ self._device.release()
+ self._device = None
+ self._control_object = None
+
+
+class EthernetDevice(HailoChipObject):
+ """Represents any Hailo hardware device that supports UDP control and dataflow."""
+
+ NAME = InferenceTargets.UDP_CONTROLLER
+
+ def __init__(
+ self,
+ remote_ip,
+ remote_control_port=22401):
+ """Create the Hailo UDP hardware object.
+
+ Args:
+ remote_ip (str): Device IP address.
+ remote_control_port (int, optional): UDP port to which the device listens for control.
+ Defaults to 22401.
+ """
+
+ super(EthernetDevice, self).__init__()
+
+ gc.collect()
+
+ self._remote_ip = remote_ip
+ self._remote_control_port = remote_control_port
+ # EthernetDevice __del__ function tries to release self._device.
+ # to avoid AttributeError if the __init__ func fails, we set it to None first.
+ # https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
+ self._device = None
+ self._control_object = None
+
+ self._open_device()
+
+ self._id = "{}".format(self._remote_ip)
+ identity = self._control_object._device_id
+ self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
+
+ @staticmethod
+ def scan_devices(interface_name, timeout_seconds=3):
+ """Scans for all eth devices on a specific network interface.
+
+ Args:
+ interface_name (str): Interface to scan.
+ timeout_seconds (int, optional): timeout for scan operation. Defaults to 3.
+ Returns:
+ list of str: IPs of scanned devices.
+ """
+ udp_scanner = HailoUdpScan()
+ return udp_scanner.scan_devices(interface_name, timeout_seconds=timeout_seconds)
+
+ def _open_device(self):
+ self._device = InternalEthernetDevice(self._remote_ip, self._remote_control_port)
+ self._control_object = UdpHcpControl(self._remote_ip, device=self._device, remote_control_port=self._remote_control_port)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.release()
+ return False
+
+ def __del__(self):
+ self.release()
+
+ @property
+ def remote_ip(self):
+ """Return the IP of the remote device."""
+ return self._remote_ip
+
+
+class PcieDevice(HailoChipObject):
+ """Hailo PCIe production device representation."""
+
+ NAME = InferenceTargets.PCIE_CONTROLLER
+
+ def __init__(
+ self,
+ device_info=None):
+
+ """Create the Hailo PCIe hardware object.
+
+ Args:
+ device_info (:obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`, optional): Device info to create, call
+ :func:`PcieDevice.scan_devices` to get list of all available devices.
+ """
+ super(PcieDevice, self).__init__()
+
+ gc.collect()
+ # PcieDevice __del__ function tries to release self._device.
+ # to avoid AttributeError if the __init__ func fails, we set it to None first.
+ # https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
+ self._device = None
+ self._device_info = None
+ self._control_object = None
+
+ self._open_device(device_info)
+
+ # At this point self._device_info is already initialized
+ self._id = "{}".format(self._device_info)
+ identity = self._control_object._device_id
+ self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
+
+ @staticmethod
+ def scan_devices():
+ """Scans for all pcie devices on the system.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`
+ """
+ return InternalPcieDevice.scan_devices()
+
+ def _open_device(self, device_info):
+ self._device = InternalPcieDevice(device_info)
+ self._device_info = self._device._device_info # Handeling a case where device_info is None
+ self._control_object = PcieHcpControl(device=self._device, device_info=self._device_info)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.release()
+ return False
+
+ def __del__(self):
+ self.release()
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/i2c_slaves.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/i2c_slaves.py
new file mode 100644
index 0000000..b70dde8
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/i2c_slaves.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+from builtins import object
+import struct
+
+from hailo_platform.common.logger.logger import default_logger
+from hailo_platform.pyhailort.pyhailort import Endianness
+logger = default_logger()
+
+#: Variable which defines that the I2C slave is not behind a switch.
+NO_I2C_SWITCH = 5
+
+class I2CSlavesException(Exception):
+ pass
+
+
+class I2CSlave(object):
+ def __init__(self, name, bus_index, slave_address, switch_number=NO_I2C_SWITCH,
+ register_address_size=1, endianness=Endianness.LITTLE_ENDIAN,
+ should_hold_bus=False):
+ """Initialize a class which describes an I2C slave.
+
+ Args:
+ name (str): The name of the I2C slave.
+ bus_index (int): The bus number the I2C slave is connected to.
+ slave_address (int): The address of the I2C slave.
+ switch_number (int): The number of the switch the i2c salve is connected to.
+ register_address_size (int): Slave register address length (in bytes).
+ endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`): The endianness of the slave.
+ should_hold_bus (bool): Should hold the bus during the read.
+
+ """
+ self._name = name
+ self._bus_index = bus_index
+ self._slave_address = slave_address
+ self._switch_number = switch_number
+ self._register_address_size = register_address_size
+ self._endianness = endianness
+ self._should_hold_bus = should_hold_bus
+
+ def __repr__(self):
+ # Returning '' for the sphinx doc
+ return ''
+
+ @property
+ def name(self):
+ """Get the name of the I2C slave.
+
+ Returns:
+ str: Name of the I2C slave.
+ """
+ return self._name
+
+ @property
+ def bus_index(self):
+ """Get bus index the I2C slave is connected to.
+
+ Returns:
+ int: Index of the bus the I2C slave is connected to.
+ """
+ return self._bus_index
+
+ @property
+ def slave_address(self):
+ """Get the address of the salve.
+
+ Returns:
+ int: The address of the I2C slave.
+ """
+ return self._slave_address
+
+ @property
+ def register_address_size(self):
+ """Get the slave register address length (in bytes). This number represents how many bytes are in the
+ register address the slave can access.
+
+ Returns:
+ int: Slave register address length.
+
+ Note:
+ Pay attention to the slave endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`).
+ """
+ return self._register_address_size
+
+ @property
+ def switch_number(self):
+ """Get the switch number the slave is connected to.
+
+ Returns:
+ int: The number of the switch the I2C is behind.
+
+ Note:
+ If :data:`NO_I2C_SWITCH` is returned, it means the slave is not behind a switch.
+ """
+ return self._switch_number
+
+ @property
+ def endianness(self):
+ """Get the slave endianness.
+
+ Returns:
+ :class:`~hailo_platform.pyhailort.pyhailort.Endianness`: The slave endianness.
+ """
+ return self._endianness
+
+ @property
+ def should_hold_bus(self):
+ """Returns a Boolean indicating if the bus will be held while reading from the slave.
+
+ Returns:
+ bool: True if the bus would be held, otherwise False.
+ """
+ return self._should_hold_bus
+
+# DVM's
+#: Class which represents the MIPI AVDD I2C slave.
+I2C_SLAVE_MIPI_AVDD = I2CSlave("DVM_MIPI_AVDD", 0, 0x40)
+#: Class which represents the USB AVDD IO slave.
+I2C_SLAVE_USB_AVDD_IO = I2CSlave("DVM_USB_AVDD_IO", 0, 0x41)
+#: Class which represents the V_CORE slave.
+I2C_SLAVE_VDD_CORE = I2CSlave("DVM_VDD_CORE", 0, 0x42)
+#: Class which represents the VDD TOP slave.
+I2C_SLAVE_VDD_TOP = I2CSlave("DVM_VDD_TOP", 0, 0x43)
+#: Class which represents the MIPI AVDD_H I2C slave.
+I2C_SLAVE_MIPI_AVDD_H = I2CSlave("DVM_MIPI_AVDD_H", 0, 0x44)
+#: Class which represents the DVM USB AVDD IO HV slave.
+I2C_SLAVE_USB_AVDD_IO_HV = I2CSlave("DVM_USB_AVDD_IO_HV", 0, 0x45)
+#: Class which represents the DVM_VDDIO slave.
+I2C_SLAVE_VDD_IO = I2CSlave("DVM_VDD_IO", 0, 0x46)
+#: Class which represents the DVM_AVDD_H slave.
+I2C_SLAVE_AVDD_H = I2CSlave("DVM_AVDD_H", 0, 0x47)
+#: Class which represents the DVM_SDIO_VDDIO slave.
+I2C_SLAVE_SDIO_VDD_IO = I2CSlave("DVM_SDIO_VDD_IO", 0, 0x4d)
+
+#: Class which represents the DVM_SDIO_VDDIO slave.
+I2C_SLAVE_M_DOT_2_OVERCURREN_PROTECTION = I2CSlave("M_DOT_2_OVERCURREN_PROTECTION", 0, 0x40)
+
+#: Class which represents the I2S codec I2C slave.
+I2C_SLAVE_I2S_CODEC = I2CSlave("I2S_codec", 1, 0x18, should_hold_bus=True)
+
+#: Class which represents the I2C to gpio I2C slave.
+I2C_SLAVE_I2C_TO_GPIO = I2CSlave("I2C_to_GPIO", 0, 0x22)
+#: Class which represents the I2C switch slave.
+I2C_SLAVE_SWITCH = I2CSlave("I2C_SWITCH", 1, 0x70)
+
+#: Class which represents the I2C TEMP_sensor_0 slave.
+I2C_SLAVE_TEMP_SENSOR_0 = I2CSlave("TEMP_sensor_0", 0, 0x29)
+#: Class which represents the I2S TEMP_sensor_1 slave.
+I2C_SLAVE_TEMP_SENSOR_1 = I2CSlave("TEMP_sensor_1", 0, 0x2A)
+
+#: Class which represents the EEPROM I2C slave.
+I2C_SLAVE_EEPROM = I2CSlave("EEPROM", 0, 0x50, register_address_size=2,
+ endianness=Endianness.BIG_ENDIAN)
+
+# External hardware
+#: Class which represents the raspicam I2C slave.
+I2C_SLAVE_RASPICAM = I2CSlave("RaspiCam", 1, 0x36, switch_number=1, register_address_size=2,
+ endianness=Endianness.BIG_ENDIAN)
+
+I2C_SLAVE_ONSEMI_CAMERA_AR0220 = I2CSlave('Onsemi', 1, 0x10, switch_number=0, register_address_size=2,
+ endianness=Endianness.BIG_ENDIAN)
+
+I2C_SLAVE_ONSEMI_CAMERA_AS0149 = I2CSlave('Onsemi', 1, (0x90 >> 1), switch_number=0, register_address_size=2,
+ endianness=Endianness.BIG_ENDIAN)
+
+def set_i2c_switch(control_object, slave, slave_switch=None):
+ """Set the I2C switch in order to perform actions from the I2C slave.
+
+ Args:
+ control_object (:class:`~hailo_platform.pyhailort.control_object.HcpControl`): Control object
+ which communicates with the Hailo chip.
+ slave (:class:`I2CSlave`): Slave which the switch is set for.
+ slave_switch (:class:`I2CSlave`): The I2C slave for the switch it self. Defaults to
+ :data:`I2C_SLAVE_SWITCH`.
+ """
+ I2C_SWITCH_REGISTER_SIZE = 1
+ if NO_I2C_SWITCH != slave.switch_number:
+ if not slave_switch:
+ slave_switch = I2C_SLAVE_SWITCH
+
+ # Set the switch value that should be written
+ switch_value = 1 << slave.switch_number
+
+ # Write new value to the switch
+ control_object.i2c_write(slave_switch, switch_value, struct.pack('b', switch_value))
+
+ # Read data from the switch, make sure write was successful
+ read_data, = struct.unpack('b', control_object.i2c_read(slave_switch, switch_value, I2C_SWITCH_REGISTER_SIZE))
+ if read_data != switch_value:
+ raise I2CSlavesException("Switch writing has failed. Read data is different then expected %s != %s" % (
+ read_data,
+ switch_value))
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/power_measurement.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/power_measurement.py
new file mode 100644
index 0000000..b0612af
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/power_measurement.py
@@ -0,0 +1,14 @@
+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")
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/pyhailort.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/pyhailort.py
new file mode 100644
index 0000000..8351041
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/pyhailort.py
@@ -0,0 +1,1805 @@
+import pkg_resources
+# hailo_platform package has been renamed to hailort, but the import is still hailo_platform
+__version__ = pkg_resources.get_distribution("hailort").version
+
+import sys
+
+from argparse import ArgumentTypeError
+import numpy
+import time
+from hailo_platform.common.logger.logger import default_logger
+import gc
+import os
+
+import hailo_platform.pyhailort._pyhailort as _pyhailort
+if _pyhailort.__version__ != __version__:
+ raise ImportError("_pyhailort version ({}) does not match pyhailort version ({})".format(_pyhailort.__version__, __version__))
+
+from hailo_platform.pyhailort._pyhailort import (BootloaderVersion, TemperatureInfo, # noqa F401
+ DvmTypes, PowerMeasurementTypes, # noqa F401
+ PowerMeasurementData, NotificationId, # noqa F401
+ OvercurrentAlertState,
+ FormatOrder,
+ AveragingFactor, SamplingPeriod, MeasurementBufferIndex,
+ FormatType, WatchdogMode,
+ MipiDataTypeRx, MipiPixelsPerClock,
+ MipiClockSelection, MipiIspImageInOrder,
+ MipiIspImageOutDataType, IspLightFrequency,
+ BootSource, HailoSocketDefs, Endianness,
+ MipiInputStreamParams, SensorConfigTypes,
+ SensorConfigOpCode)
+
+BBOX_PARAMS = _pyhailort.HailoRTDefaults.BBOX_PARAMS()
+HAILO_DEFAULT_ETH_CONTROL_PORT = _pyhailort.HailoRTDefaults.HAILO_DEFAULT_ETH_CONTROL_PORT()
+INPUT_DATAFLOW_BASE_PORT = _pyhailort.HailoRTDefaults.DEVICE_BASE_INPUT_STREAM_PORT()
+OUTPUT_DATAFLOW_BASE_PORT = _pyhailort.HailoRTDefaults.DEVICE_BASE_OUTPUT_STREAM_PORT()
+PCIE_ANY_DOMAIN = _pyhailort.HailoRTDefaults.PCIE_ANY_DOMAIN()
+DEFAULT_VSTREAM_TIMEOUT_MS = 10000
+DEFAULT_VSTREAM_QUEUE_SIZE = 2
+
+class HailoSocket(object):
+ MAX_UDP_PAYLOAD_SIZE = HailoSocketDefs.MAX_UDP_PAYLOAD_SIZE()
+ MIN_UDP_PAYLOAD_SIZE = HailoSocketDefs.MIN_UDP_PAYLOAD_SIZE()
+ MAX_UDP_PADDED_PAYLOAD_SIZE = HailoSocketDefs.MAX_UDP_PADDED_PAYLOAD_SIZE()
+ MIN_UDP_PADDED_PAYLOAD_SIZE = HailoSocketDefs.MIN_UDP_PADDED_PAYLOAD_SIZE()
+ MAX_ALIGNED_UDP_PAYLOAD_SIZE_RTP = HailoSocketDefs.MAX_ALIGNED_UDP_PAYLOAD_SIZE_RTP()
+
+
+class HailoRTException(Exception):
+ pass
+
+class UdpRecvError(HailoRTException):
+ pass
+
+class InvalidProtocolVersionException(HailoRTException):
+ pass
+
+class HailoRTFirmwareControlFailedException(HailoRTException):
+ pass
+
+class HailoRTInvalidFrameException(HailoRTException):
+ pass
+
+class HailoRTUnsupportedOpcodeException(HailoRTException):
+ pass
+
+class HailoRTTimeout(HailoRTException):
+ pass
+
+class HailoRTStreamAborted(HailoRTException):
+ pass
+
+class HailoRTInvalidOperationException(HailoRTException):
+ pass
+
+class HailoRTInvalidArgumentException(HailoRTException):
+ pass
+
+class HailoRTNotFoundException(HailoRTException):
+ pass
+
+class HailoRTInvalidHEFException(HailoRTException):
+ pass
+
+class HailoRTEthException(HailoRTException):
+ pass
+
+class HailoRTPCIeDriverException(HailoRTException):
+ pass
+
+class HailoRTNetworkGroupNotActivatedException(HailoRTException):
+ pass
+
+class HailoStatusInvalidValueException(Exception):
+ pass
+
+class ExceptionWrapper(object):
+ def __enter__(self):
+ pass
+
+ def __exit__(self, exception_type, value, traceback):
+ if value is not None:
+ if exception_type is _pyhailort.HailoRTStatusException:
+ self._raise_indicative_status_exception(int(value.args[0]))
+ else:
+ raise
+
+ def _raise_indicative_status_exception(self, error_code):
+ string_error_code = get_status_message(error_code)
+ if string_error_code == "HAILO_ETH_RECV_FAILURE":
+ raise UdpRecvError("Failed to receive data")
+ if string_error_code == "HAILO_UNSUPPORTED_CONTROL_PROTOCOL_VERSION":
+ raise InvalidProtocolVersionException("HailoRT has failed because an invalid protocol version was received from device")
+ if string_error_code == "HAILO_FW_CONTROL_FAILURE":
+ raise HailoRTFirmwareControlFailedException("libhailort control operation failed")
+ if string_error_code == "HAILO_UNSUPPORTED_OPCODE":
+ raise HailoRTUnsupportedOpcodeException("HailoRT has failed because an unsupported opcode was sent to device")
+ if string_error_code == "HAILO_INVALID_FRAME":
+ raise HailoRTInvalidFrameException("An invalid frame was received")
+ if string_error_code == "HAILO_TIMEOUT":
+ raise HailoRTTimeout("Received a timeout - hailort has failed because a timeout had occurred")
+ if string_error_code == "HAILO_STREAM_ABORTED":
+ raise HailoRTStreamAborted("Stream aborted due to an external event")
+
+ if string_error_code == "HAILO_INVALID_OPERATION":
+ raise HailoRTInvalidOperationException("Invalid operation. See hailort.log for more information")
+ if string_error_code == "HAILO_INVALID_ARGUMENT":
+ raise HailoRTInvalidArgumentException("Invalid argument. See hailort.log for more information")
+ if string_error_code == "HAILO_NOT_FOUND":
+ raise HailoRTNotFoundException("Item not found. See hailort.log for more information")
+
+ if string_error_code == "HAILO_INVALID_HEF":
+ raise HailoRTInvalidHEFException("Invalid HEF. See hailort.log for more information")
+
+ if string_error_code == "HAILO_ETH_FAILURE":
+ raise HailoRTEthException("Ethernet failure. See hailort.log for more information")
+ if string_error_code == "HAILO_PCIE_DRIVER_FAIL":
+ raise HailoRTPCIeDriverException("PCIe driver failure. run 'dmesg | grep hailo' for more information")
+
+ if string_error_code == "HAILO_NETWORK_GROUP_NOT_ACTIVATED":
+ raise HailoRTNetworkGroupNotActivatedException("Network group is not activated")
+ else:
+ raise HailoRTException("libhailort failed with error: {} ({})".format(error_code, string_error_code))
+
+def get_status_message(status_code):
+ status_str = _pyhailort.get_status_message(status_code)
+ if status_str == "":
+ raise HailoStatusInvalidValueException("Value {} is not a valid status".format(status_code))
+ return status_str
+
+
+class HailoUdpScan(object):
+ def __init__(self):
+ self._logger = default_logger()
+ with ExceptionWrapper():
+ self._scan = _pyhailort.UdpScan()
+
+ def scan_devices(self, interface_name, timeout_seconds=3):
+ self._logger.info('Scanning over interface {iface}'.format(iface=interface_name))
+ timeout_milliseconds = int(timeout_seconds * 1000)
+ device_ip_addresses = self._scan.scan_devices(interface_name, timeout_milliseconds)
+ for ip in device_ip_addresses:
+ self._logger.debug("Found board at: {}".format(ip))
+ return device_ip_addresses
+
+
+class TrafficControl(object):
+ def __init__(self, ip, port, rate_bytes_per_sec):
+ if sys.platform != 'linux':
+ raise HailoRTInvalidOperationException('TrafficControl is supported only on UNIX os')
+ with ExceptionWrapper():
+ self._tc_util = _pyhailort.TrafficControlUtil(ip, port, int(rate_bytes_per_sec))
+
+ def set_rate_limit(self):
+ self._tc_util.set_rate_limit()
+
+ def reset_rate_limit(self):
+ self._tc_util.reset_rate_limit()
+
+ def get_interface_name(ip):
+ "get the interface corresponding to the given ip"
+ with ExceptionWrapper():
+ return _pyhailort.TrafficControlUtil.get_interface_name(ip)
+
+
+class ConfigureParams(object):
+
+ @staticmethod
+ def create_from_hef(hef, interface):
+ """Create configure params from HEF. These params affects the HEF configuration into a device.
+
+ Args:
+ hef (:class:`HEF`): The HEF to create the parameters from.
+ interface (:class:`HailoStreamInterface`): The stream_interface to create stream_params for.
+
+ Returns:
+ dict: The created stream params. The keys are the network_group names in the HEF. The values are default params, which can be changed.
+ """
+ with ExceptionWrapper():
+ return hef._hef.create_configure_params(interface)
+
+ @staticmethod
+ def create_mipi_inputs_from_hef(hef, output_interface, mipi_rx_id=0, data_type=MipiDataTypeRx.RAW_8,
+ img_width_pixels=1920, img_height_pixels=1080,
+ pixels_per_clock=MipiPixelsPerClock.PIXELS_PER_CLOCK_4, number_of_lanes=2,
+ clock_selection=MipiClockSelection.SELECTION_AUTOMATIC, data_rate=260, virtual_channel_index=0,
+ isp_enable=False, isp_img_in_order=MipiIspImageInOrder.GR_FIRST,
+ isp_img_out_data_type=MipiIspImageOutDataType.RGB_888, isp_crop_enable=False,
+ isp_crop_output_width_pixels=1920, isp_crop_output_height_pixels=1080,
+ isp_crop_output_width_start_offset_pixels=0, isp_crop_output_height_start_offset_pixels=0,
+ isp_test_pattern_enable=True, isp_configuration_bypass=False,
+ isp_run_time_ae_enable=True, isp_run_time_awb_enable=True, isp_run_time_adt_enable=True,
+ isp_run_time_af_enable=False, isp_run_time_calculations_interval_ms=0,
+ isp_light_frequency=IspLightFrequency.LIGHT_FREQ_50_HZ):
+ """Create configure params from HEF. These params affects the HEF configuration into a device.
+
+ .. attention:: The ISP and its features are not officially supported yet.
+
+ Args:
+ hef (:class:`HEF`): The HEF to create the parameters from.
+ output_interface (:class:`HailoStreamInterface`): The stream_interface to create output stream_params for.
+ mipi_rx_id (int): Selection of which MIPI Rx device to use.
+ data_type (:class:`~hailo_platform.pyhailort.pyhailort.MipiDataTypeRx`): The data type which will be passed over the MIPI.
+ img_width_pixels (int): The width in pixels of the image that enter to the mipi CSI. The sensor output.
+ When isp_enable and isp_crop_enable is false, is also the stream input.
+ img_height_pixels (int): The height in pixels of the image that enter to the mipi CSI. The sensor output.
+ When isp_enable and isp_crop_enable is false, is also the stream input.
+ pixels_per_clock (:class:`~hailo_platform.pyhailort.pyhailort.MipiPixelsPerClock`): Number of pixels transmitted at each
+ clock.
+ number_of_lanes (int): Number of lanes to use.
+ clock_selection (:class:`~hailo_platform.pyhailort.pyhailort.MipiClockSelection`): Selection of clock range that would be
+ used. Setting :class:`~hailo_platform.pyhailort.pyhailort.MipiClockSelection.SELECTION_AUTOMATIC` means that the
+ clock selection is calculated from the data rate.
+ data_rate (int): Rate of the passed data (MHz).
+ virtual_channel_index (int): The virtual channel index of the MIPI dphy.
+ isp_enable (bool): Enable the ISP block in the MIPI dataflow. The ISP is not supported yet.
+ isp_img_in_order (:class:`~hailo_platform.pyhailort.pyhailort.MipiIspImageInOrder`):
+ The ISP Rx bayer pixel order. Only relevant when the ISP is enabled.
+ isp_img_out_data_type (:class:`~hailo_platform.pyhailort.pyhailort.MipiIspImageOutDataType`):
+ The data type that the mipi will take out. Only relevant when the ISP is enabled.
+ isp_crop_enable (bool): Enable the crop feature in the ISP. Only relevant when the ISP is enabled.
+ isp_crop_output_width_pixels (int): The width in pixels of the output window that the ISP take out. The stream input.
+ Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
+ isp_crop_output_height_pixels (int): The height in pixels of the output window that the ISP take out. The stream input.
+ Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
+ isp_crop_output_width_start_offset_pixels (int): The width start point of the output window that the ISP take out.
+ Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
+ isp_crop_output_height_start_offset_pixels (int): The height start point of the output window that the ISP take out.
+ Useful when isp_crop_enable is True. Only relevant when the ISP is enabled.
+ isp_test_pattern_enable (bool): Enable Test pattern from the ISP. Only relevant when the ISP is enabled.
+ isp_configuration_bypass (bool): Don't load the ISP configuration file from the FLASH. Only relevant when the ISP is enabled.
+ isp_run_time_ae_enable (bool): Enable the run-time Auto Exposure in the ISP. Only relevant when the ISP is enabled.
+ isp_run_time_awb_enable (bool): Enable the run-time Auto White Balance in the ISP. Only relevant when the ISP is enabled.
+ isp_run_time_adt_enable (bool): Enable the run-time Adaptive Function in the ISP. Only relevant when the ISP is enabled.
+ isp_run_time_af_enable (bool): Enable the run-time Auto Focus in the ISP. Only relevant when the ISP is enabled.
+ isp_run_time_calculations_interval_ms (int): Interval in milliseconds between ISP run time calculations. Only relevant when the ISP is enabled.
+ isp_light_frequency (:class:`~hailo_platform.pyhailort.pyhailort.IspLightFrequency`):
+ Selection of the light frequency. This parameter varies depending on the power grid of the country where
+ the product is running. Only relevant when the ISP is enabled.
+ Returns:
+ dict: The created stream params. The keys are the network_group names in the HEF. The values are default params, which can be changed.
+ """
+
+ mipi_params = MipiInputStreamParams()
+ mipi_params.mipi_rx_id = mipi_rx_id
+ mipi_params.data_type = data_type
+ mipi_params.isp_enable = isp_enable
+ mipi_params.mipi_common_params.pixels_per_clock = pixels_per_clock
+ mipi_params.mipi_common_params.number_of_lanes = number_of_lanes
+ mipi_params.mipi_common_params.clock_selection = clock_selection
+ mipi_params.mipi_common_params.virtual_channel_index = virtual_channel_index
+ mipi_params.mipi_common_params.data_rate = data_rate
+ mipi_params.mipi_common_params.img_width_pixels = img_width_pixels
+ mipi_params.mipi_common_params.img_height_pixels = img_height_pixels
+ mipi_params.isp_params.img_in_order = isp_img_in_order
+ mipi_params.isp_params.img_out_data_type = isp_img_out_data_type
+ mipi_params.isp_params.crop_enable = isp_crop_enable
+ mipi_params.isp_params.crop_output_width_pixels = isp_crop_output_width_pixels
+ mipi_params.isp_params.crop_output_height_pixels = isp_crop_output_height_pixels
+ mipi_params.isp_params.crop_output_width_start_offset_pixels = isp_crop_output_width_start_offset_pixels
+ mipi_params.isp_params.crop_output_height_start_offset_pixels = isp_crop_output_height_start_offset_pixels
+ mipi_params.isp_params.test_pattern_enable = isp_test_pattern_enable
+ mipi_params.isp_params.configuration_bypass = isp_configuration_bypass
+ mipi_params.isp_params.run_time_ae_enable = isp_run_time_ae_enable
+ mipi_params.isp_params.run_time_awb_enable = isp_run_time_awb_enable
+ mipi_params.isp_params.run_time_adt_enable = isp_run_time_adt_enable
+ mipi_params.isp_params.run_time_af_enable = isp_run_time_af_enable
+ mipi_params.isp_params.isp_run_time_calculations_interval_ms = isp_run_time_calculations_interval_ms
+ mipi_params.isp_params.isp_light_frequency = isp_light_frequency
+ with ExceptionWrapper():
+ return hef._hef.create_configure_params_mipi_input(output_interface, mipi_params)
+
+def _get_name_as_str(name):
+ return name if name is not None else ""
+
+class HEF(object):
+ """Python representation of the Hailo Executable Format, which contains one or more compiled
+ models.
+ """
+
+ def __init__(self, hef_source):
+ """Constructor for the HEF class.
+
+ Args:
+ hef_source (str or bytes): The source from which the HEF object will be created. If the
+ source type is `str`, it is treated as a path to an hef file. If the source type is
+ `bytes`, it is treated as a buffer. Any other type will raise a ValueError.
+ """
+
+ with ExceptionWrapper():
+ if isinstance(hef_source, str):
+ self._hef = _pyhailort.Hef.create_from_file(hef_source)
+ self._path = hef_source
+ elif isinstance(hef_source, bytes):
+ self._hef = _pyhailort.Hef.create_from_buffer(hef_source)
+ self._path = None
+ else:
+ raise ValueError("HEF can only be created from a file path (str) or a buffer (bytes)")
+ self._sorted_output_names = {}
+
+ def get_networks_names(self, network_group_name=None):
+ """Gets the names of all networks in a specific network group.
+
+ Args:
+ network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
+
+ Returns:
+ list of str: The names of the networks.
+ """
+ name = _get_name_as_str(network_group_name)
+ with ExceptionWrapper():
+ return self._hef.get_networks_names(name)
+
+ @property
+ def path(self):
+ """HEF file path."""
+ return self._path
+
+ def get_network_group_names(self):
+ """Get the names of the network groups in this HEF."""
+ with ExceptionWrapper():
+ return self._hef.get_network_group_names()
+
+ def get_network_groups_infos(self):
+ """Get information about the network groups in this HEF."""
+ with ExceptionWrapper():
+ return self._hef.get_network_groups_infos()
+
+ def get_input_vstream_infos(self, name=None):
+ """Get input vstreams information.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams.
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_input_vstream_infos(name)
+
+ def get_output_vstream_infos(self, name=None):
+ """Get output vstreams information.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_output_vstream_infos(name)
+
+ def get_all_vstream_infos(self, name=None):
+ """Get input and output vstreams information.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_all_vstream_infos(name)
+
+ def get_input_stream_infos(self, name=None):
+ """Get the input low-level streams information.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ List of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with information objects
+ of all input low-level streams.
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_input_stream_infos(name)
+
+
+ def get_output_stream_infos(self, name=None):
+ """Get the output low-level streams information of a specific network group.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ List of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with information objects
+ of all output low-level streams.
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_output_stream_infos(name)
+
+ def get_all_stream_infos(self, name=None):
+ """Get input and output streams information of a specific network group.
+
+ Args:
+ name (str, optional): The name of the network or network_group to access. In case network_group name is given,
+ Address all networks of the given network_group. In case not given, first network_group is addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
+ """
+ name = _get_name_as_str(name)
+ return self._hef.get_all_stream_infos(name)
+
+ def get_sorted_output_names(self, network_group_name=None):
+ """Get the names of the outputs in a network group. The order of names is determined by
+ the SDK. If the network group is not given, the first one is used.
+ """
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+
+ if network_group_name not in self._sorted_output_names:
+ with ExceptionWrapper():
+ self._sorted_output_names[network_group_name] = self._hef.get_sorted_output_names(network_group_name)
+ return self._sorted_output_names[network_group_name]
+
+ def bottleneck_fps(self, network_group_name=None):
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ bottleneck_fps = self._hef.get_bottleneck_fps(network_group_name)
+ if bottleneck_fps == 0:
+ raise HailoRTException("bottleneck_fps is zero")
+ return bottleneck_fps
+
+ def get_udp_rates_dict(self, fps, max_supported_rate_bytes, network_group_name=None):
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ return self._hef.get_udp_rates_dict(network_group_name, fps, int(max_supported_rate_bytes))
+
+ def get_vstream_name_from_original_name(self, original_name, network_group_name=None):
+ """Get vstream name from original layer name for a specific network group.
+
+ Args:
+ original_name (str): The original layer name.
+ network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
+
+ Returns:
+ str: the matching vstream name for the provided original name.
+ """
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ return self._hef.get_vstream_name_from_original_name(original_name, network_group_name)
+
+ def get_original_names_from_vstream_name(self, vstream_name, network_group_name=None):
+ """Get original names list from vstream name for a specific network group.
+
+ Args:
+ vstream_name (str): The stream name.
+ network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
+
+ Returns:
+ list of str: all the matching original layers names for the provided vstream name.
+ """
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ return self._hef.get_original_names_from_vstream_name(vstream_name, network_group_name)
+
+ def get_vstream_names_from_stream_name(self, stream_name, network_group_name=None):
+ """Get vstream names list from their underlying stream name for a specific network group.
+
+ Args:
+ stream_name (str): The underlying stream name.
+ network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
+
+ Returns:
+ list of str: All the matching vstream names for the provided stream name.
+ """
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ return self._hef.get_vstream_names_from_stream_name(stream_name, network_group_name)
+
+ def get_stream_names_from_vstream_name(self, vstream_name, network_group_name=None):
+ """Get stream name from vstream name for a specific network group.
+
+ Args:
+ vstream_name (str): The name of the vstreams.
+ network_group_name (str, optional): The name of the network group to access. If not given, first network_group is addressed.
+
+ Returns:
+ list of str: All the underlying streams names for the provided vstream name.
+ """
+ if network_group_name is None:
+ network_group_name = self.get_network_group_names()[0]
+ with ExceptionWrapper():
+ return self._hef.get_stream_names_from_vstream_name(vstream_name, network_group_name)
+
+
+class ConfiguredNetwork(object):
+ """Represents a network group loaded to the device."""
+
+ def __init__(self, configured_network, target, hef):
+ self._configured_network = configured_network
+ self._target = target
+ self._hef = hef
+
+ def get_networks_names(self):
+ return self._hef.get_networks_names(self.name)
+
+ def activate(self, network_group_params=None):
+ """Activate this network group in order to infer data through it.
+
+ Args:
+ network_group_params (:obj:`hailo_platform.pyhailort._pyhailort.ActivateNetworkGroupParams`, optional):
+ Network group activation params. If not given, default params will be applied,
+
+ Returns:
+ :class:`ActivatedNetworkContextManager`: Context manager that returns the activated
+ network group.
+ """
+ network_group_params = network_group_params or self.create_params()
+
+ with ExceptionWrapper():
+ return ActivatedNetworkContextManager(self,
+ self._configured_network.activate(network_group_params),
+ self._target, self._hef)
+
+ def wait_for_activation(self, timeout_ms=None):
+ """Block until activated, or until ``timeout_ms`` is passed.
+
+ Args:
+ timeout_ms (int, optional): Timeout value in milliseconds to wait for activation.
+ Defaults to ``HAILO_INFINITE``.
+
+ Raises:
+ :class:`HailoRTTimeout`: In case of timeout.
+ """
+ MAX_INT = 0x7fffffff
+ with ExceptionWrapper():
+ if timeout_ms is None:
+ timeout_ms = MAX_INT
+ return self._configured_network.wait_for_activation(timeout_ms)
+
+ @staticmethod
+ def create_params():
+ """Create activation params for network_group.
+
+ Returns:
+ :obj:`hailo_platform.pyhailort._pyhailort.ActivateNetworkGroupParams`.
+ """
+ return _pyhailort.ActivateNetworkGroupParams.default()
+
+ @property
+ def name(self):
+ return self._configured_network.get_name()
+
+ def get_output_shapes(self):
+ name_to_shape = {vstream_info.name : vstream_info.shape for vstream_info in self.get_output_vstream_infos()}
+ results = []
+ for name in self.get_sorted_output_names():
+ results.append(name_to_shape[name])
+ return tuple(results)
+
+ def get_sorted_output_names(self):
+ return self._hef.get_sorted_output_names(self.name)
+
+ def get_input_vstream_infos(self, network_name=None):
+ """Get input vstreams information.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_input_vstream_infos(name)
+
+ def get_output_vstream_infos(self, network_name=None):
+ """Get output vstreams information.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_output_vstream_infos(name)
+
+ def get_all_vstream_infos(self, network_name=None):
+ """Get input and output vstreams information.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_all_vstream_infos(name)
+
+ def get_input_stream_infos(self, network_name=None):
+ """Get the input low-level streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ List of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with information objects
+ of all input low-level streams.
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_input_stream_infos(name)
+
+ def get_output_stream_infos(self, network_name=None):
+ """Get the output low-level streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ List of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with information objects
+ of all output low-level streams.
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_output_stream_infos(name)
+
+ def get_all_stream_infos(self, network_name=None):
+ """Get input and output streams information of a specific network group.
+
+ Args:
+ network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
+
+ Returns:
+ list of :obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
+ """
+
+ name = network_name if network_name is not None else self.name
+ return self._hef.get_all_stream_infos(name)
+
+ def get_udp_rates_dict(self, fps, max_supported_rate_bytes):
+ with ExceptionWrapper():
+ return self._configured_network.get_udp_rates_dict(int(fps), int(max_supported_rate_bytes))
+
+ def _create_input_vstreams(self, input_vstreams_params):
+ return self._configured_network.InputVStreams(input_vstreams_params)
+
+ def _create_output_vstreams(self, output_vstreams_params):
+ return self._configured_network.OutputVStreams(output_vstreams_params)
+
+ def get_stream_names_from_vstream_name(self, vstream_name):
+ """Get stream name from vstream name for a specific network group.
+
+ Args:
+ vstream_name (str): The name of the vstreams.
+
+ Returns:
+ list of str: All the underlying streams names for the provided vstream name.
+ """
+ with ExceptionWrapper():
+ return self._hef.get_stream_names_from_vstream_name(vstream_name, self.name)
+
+ def get_vstream_names_from_stream_name(self, stream_name):
+ """Get vstream names list from their underlying stream name for a specific network group.
+
+ Args:
+ stream_name (str): The underlying stream name.
+
+ Returns:
+ list of str: All the matching vstream names for the provided stream name.
+ """
+ with ExceptionWrapper():
+ return self._hef.get_vstream_names_from_stream_name(stream_name, self.name)
+
+
+class ActivatedNetworkContextManager(object):
+ """A context manager that returns the activated network group upon enter."""
+
+ def __init__(self, configured_network, activated_network, target, hef):
+ self._configured_network = configured_network
+ self._activated_network = activated_network
+ self._target = target
+ self._hef = hef
+
+ def __enter__(self):
+ with ExceptionWrapper():
+ activated_network_group = ActivatedNetwork(self._configured_network, self._activated_network.__enter__(), self._target,
+ self._hef)
+ return activated_network_group
+
+ def __exit__(self, *args):
+ self._activated_network.__exit__(*args)
+
+
+class ActivatedNetwork(object):
+ """The network group that is currently activated for inference."""
+
+ def __init__(self, configured_network, activated_network, target, hef):
+ self._configured_network = configured_network
+ self._activated_network = activated_network
+ self._target = target
+ self._hef = hef
+ self._last_number_of_invalid_frames_read = 0
+
+ @property
+ def target(self):
+ return self._target
+
+ @property
+ def name(self):
+ return self._configured_network.name
+
+ def get_number_of_invalid_frames(self, clear=True):
+ """Returns number of invalid frames.
+
+ Args:
+ clear (bool): If set, the returned value will be the number of invalid frames read since the last call to this function.
+
+ Returns:
+ int: Number of invalid frames.
+ """
+ total_invalid_frames_count = self._activated_network.get_invalid_frames_count()
+ if clear:
+ value = total_invalid_frames_count - self._last_number_of_invalid_frames_read
+ self._last_number_of_invalid_frames_read = total_invalid_frames_count
+ return value if clear else total_invalid_frames_count
+
+ def validate_all_frames_are_valid(self):
+ """Validates that all of the frames so far are valid (no invalid frames)."""
+ number_of_invalid_frames = self.get_number_of_invalid_frames()
+ if number_of_invalid_frames != 0:
+ raise HailoRTException("There are {} invalid frames.".format(number_of_invalid_frames))
+
+ def get_sorted_output_names(self):
+ return self._hef.get_sorted_output_names(self.name)
+
+ def _get_intermediate_buffer(self, src_context_index, src_stream_index):
+ with ExceptionWrapper():
+ return self._activated_network.get_intermediate_buffer(src_context_index, src_stream_index)
+
+
+class InferVStreams(object):
+ """Pipeline that allows to call blocking inference, to be used as a context manager."""
+
+ def __init__(self, configured_net_group, input_vstreams_params, output_vstreams_params,
+ tf_nms_format=False):
+ """Constructor for the InferVStreams class.
+
+ Args:
+ configured_net_group (:class:`ConfiguredNetwork`): The configured network group for
+ which the pipeline is created.
+ input_vstreams_params (dict from str to :class:`InputVStreamParams`): Params for the
+ input vstreams in the pipeline. Only members of this dict will take part in the
+ inference.
+ output_vstreams_params (dict from str to :class:`OutputVStreamParams`): Params for the
+ output vstreams in the pipeline. Only members of this dict will take part in the
+ inference.
+ tf_nms_format (bool, optional): indicates whether the returned nms outputs should be in
+ Hailo format or TensorFlow format. Default is False (using Hailo format).
+
+ * Hailo format -- list of :obj:`numpy.ndarray`. Each element represents the
+ detections (bboxes) for the class, and its shape is
+ ``[number_of_detections, BBOX_PARAMS]``
+ * TensorFlow format -- :obj:`numpy.ndarray` of shape
+ ``[class_count, BBOX_PARAMS, detections_count]`` padded with empty bboxes.
+ """
+
+ self._logger = default_logger()
+ self._configured_net_group = configured_net_group
+ self._net_group_name = configured_net_group.name
+ self._input_vstreams_params = input_vstreams_params
+ self._output_vstreams_params = output_vstreams_params
+ self._tf_nms_format = tf_nms_format
+ self._total_time = None
+ self._hw_time = None
+ self._network_name_to_outputs = InferVStreams._get_network_to_outputs_mapping(configured_net_group)
+ self._input_name_to_network_name = InferVStreams._get_input_name_to_network_mapping(configured_net_group)
+
+ @staticmethod
+ def _get_input_name_to_network_mapping(configured_net_group):
+ input_name_to_network_mapping = {}
+ for network_name in configured_net_group.get_networks_names():
+ for input_vstream_info in configured_net_group.get_input_vstream_infos(network_name):
+ input_name_to_network_mapping[input_vstream_info.name] = network_name
+ return input_name_to_network_mapping
+
+ @staticmethod
+ def _get_network_to_outputs_mapping(configured_net_group):
+ network_to_outputs_mapping = {}
+ for network_name in configured_net_group.get_networks_names():
+ network_to_outputs_mapping[network_name] = set()
+ for output_vstream_info in configured_net_group.get_output_vstream_infos(network_name):
+ network_to_outputs_mapping[network_name].add(output_vstream_info.name)
+ return network_to_outputs_mapping
+
+ def _make_output_buffers_and_infos(self, input_data, batch_size):
+ output_buffers = {}
+ output_buffers_info = {}
+ already_seen_networks = set()
+ for input_name in input_data.keys():
+ network_name = self._input_name_to_network_name[input_name]
+ if (network_name not in already_seen_networks) :
+ already_seen_networks.add(network_name)
+ for output_name in self._network_name_to_outputs[network_name]:
+ output_buffers_info[output_name] = OutputLayerUtils(self._configured_net_group._hef, output_name, self._infer_pipeline,
+ self._net_group_name)
+ output_tensor_info = output_buffers_info[output_name].output_tensor_info
+ shape, dtype = output_tensor_info
+ output_buffers[output_name] = numpy.empty([batch_size] + list(shape), dtype=dtype)
+ return output_buffers, output_buffers_info
+
+ def __enter__(self):
+ self._infer_pipeline = _pyhailort.InferVStreams(self._configured_net_group._configured_network,
+ self._input_vstreams_params, self._output_vstreams_params)
+ return self
+
+ def infer(self, input_data):
+ """Run inference on the hardware device.
+
+ Args:
+ input_data (dict of :obj:`numpy.ndarray`): Where the key is the name of the input_layer,
+ and the value is the data to run inference on.
+
+ Returns:
+ dict: Output tensors of all output layers. The keys are outputs names and the values
+ are output data tensors as :obj:`numpy.ndarray` (or list of :obj:`numpy.ndarray` in case of nms output and tf_nms_format=False).
+ """
+
+ time_before_infer_calcs = time.time()
+ if not isinstance(input_data, dict):
+ input_stream_infos = self._configured_net_group.get_input_stream_infos()
+ if len(input_stream_infos) != 1:
+ raise Exception("when there is more than one input, the input_data should be of type dict,"
+ " mapping between each input_name, and his input_data tensor. number of inputs: {}".format(len(input_stream_infos)))
+ input_data = {input_stream_infos[0].name : input_data}
+
+ batch_size = InferVStreams._get_number_of_frames(input_data)
+ output_buffers, output_buffers_info = self._make_output_buffers_and_infos(input_data, batch_size)
+
+ for input_layer_name in input_data:
+ # TODO: Remove cast after tests are updated and are working
+ self._cast_input_data_if_needed(input_layer_name, input_data)
+ self._validate_input_data_format_type(input_layer_name, input_data)
+ self._make_c_contiguous_if_needed(input_layer_name, input_data)
+
+ with ExceptionWrapper():
+ time_before_infer = time.time()
+ self._infer_pipeline.infer(input_data, output_buffers, batch_size)
+ self._hw_time = time.time() - time_before_infer
+
+ for name, result_array in output_buffers.items():
+ is_nms = output_buffers_info[name].is_nms
+ if not is_nms:
+ continue
+ nms_shape = output_buffers_info[name].vstream_info.nms_shape
+ if self._tf_nms_format:
+ shape = [batch_size] + output_buffers_info[name].tf_nms_fomrat_shape
+ output_dtype = output_buffers_info[name].output_dtype
+ quantized_empty_bbox = output_buffers_info[name].quantized_empty_bbox
+ flat_result_array = result_array.reshape(-1)
+ output_buffers[name] = HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format(flat_result_array, shape,
+ output_dtype, quantized_empty_bbox)
+ else:
+ output_buffers[name] = HailoRTTransformUtils.output_raw_buffer_to_nms_format(result_array, nms_shape.number_of_classes)
+
+ self._total_time = time.time() - time_before_infer_calcs
+ return output_buffers
+
+ def get_hw_time(self):
+ """Get the hardware device operation time it took to run inference over the last batch.
+
+ Returns:
+ float: Time in seconds.
+ """
+ return self._hw_time
+
+ def get_total_time(self):
+ """Get the total time it took to run inference over the last batch.
+
+ Returns:
+ float: Time in seconds.
+ """
+ return self._total_time
+
+ def _cast_input_data_if_needed(self, input_layer_name, input_data):
+ input_dtype = input_data[input_layer_name].dtype
+ with ExceptionWrapper():
+ input_expected_dtype = self._infer_pipeline.get_host_dtype(input_layer_name)
+ if input_dtype != input_expected_dtype:
+
+ self._logger.warning("Given input data dtype ({}) is different than inferred dtype ({}). "
+ "conversion for every frame will reduce performance".format(input_dtype,
+ input_expected_dtype))
+ input_data[input_layer_name] = input_data[input_layer_name].astype(input_expected_dtype)
+
+ def _validate_input_data_format_type(self, input_layer_name, input_data):
+ if input_layer_name not in self._input_vstreams_params:
+ return
+
+ input_data_format = self._input_vstreams_params[input_layer_name].user_buffer_format
+ input_expected_item_size = _pyhailort.get_format_data_bytes(input_data_format)
+ input_item_size = input_data[input_layer_name].dtype.itemsize
+
+ # TODO: Add distinction between float32 and int32 and others
+ if input_item_size != input_expected_item_size:
+ raise HailoRTException("{} numpy array item size is {}, not {}".format(input_layer_name,
+ input_item_size, input_expected_item_size))
+
+ @staticmethod
+ def _get_number_of_frames(input_data):
+ # Checks that all the batch-sizes of the input_data are equals for all input layers
+ if len(input_data) == 0:
+ raise ValueError("Input_data can't be empty")
+ batch_size_of_first_input = list(input_data.values())[0].shape[0]
+ for name, input_data_tensor in input_data.items():
+ if input_data_tensor.shape[0] != batch_size_of_first_input:
+ raise ValueError(
+ "The number of frames on all input_tensors should be equal! different sizes detected: {} != {}".format(
+ batch_size_of_first_input, input_data_tensor.shape[0]))
+ return batch_size_of_first_input
+
+ def _make_c_contiguous_if_needed(self, input_layer_name, input_data):
+ if not input_data[input_layer_name].flags.c_contiguous:
+ self._logger.warning("Converting {} numpy array to be C_CONTIGUOUS".format(
+ input_layer_name))
+ input_data[input_layer_name] = numpy.asarray(input_data[input_layer_name], order='C')
+
+ def __exit__(self, *args):
+ self._infer_pipeline.release()
+ return False
+
+
+class HailoRTTransformUtils(object):
+ @staticmethod
+ def get_dtype(data_bytes):
+ """Get data type from the number of bytes."""
+ if data_bytes == 1:
+ return numpy.uint8
+ elif data_bytes == 2:
+ return numpy.uint16
+ elif data_bytes == 4:
+ return numpy.float32
+ raise HailoRTException("unsupported data bytes value")
+
+ @staticmethod
+ def dequantize_output_buffer(src_buffer, dst_buffer, elements_count, quant_info):
+ """De-quantize the data in input buffer `src_buffer` and output it to the buffer `dst_buffer`
+
+ Args:
+ src_buffer (:obj:`numpy.ndarray`): The input buffer containing the data to be de-quantized.
+ The buffer's data type is the source data type.
+ dst_buffer (:obj:`numpy.ndarray`): The buffer that will contain the de-quantized data.
+ The buffer's data type is the destination data type.
+ elements_count (int): The number of elements to de-quantize. This number must not exceed 'src_buffer' or 'dst_buffer' sizes.
+ quant_info (:class:`~hailo_platform.pyhailort.pyhailort.QuantInfo`): The quantization info.
+ """
+ with ExceptionWrapper():
+ src_format_type = HailoRTTransformUtils._get_format_type(src_buffer.dtype)
+ dst_format_type = HailoRTTransformUtils._get_format_type(dst_buffer.dtype)
+ _pyhailort.dequantize_output_buffer(src_buffer, dst_buffer, src_format_type, dst_format_type, elements_count, quant_info)
+
+ @staticmethod
+ def dequantize_output_buffer_in_place(raw_buffer, dst_dtype, elements_count, quant_info):
+ """De-quantize the output buffer `raw_buffer` to data type `dst_dtype`.
+
+ Args:
+ raw_buffer (:obj:`numpy.ndarray`): The output buffer to be de-quantized. The buffer's data type is the source data type.
+ dst_dtype (:obj:`numpy.dtype`): The data type to de-quantize `raw_buffer` to.
+ elements_count (int): The number of elements to de-quantize. This number must not exceed 'raw_buffer' size.
+ quant_info (:class:`~hailo_platform.pyhailort.pyhailort.QuantInfo`): The quantization info.
+ """
+ with ExceptionWrapper():
+ src_format_type = HailoRTTransformUtils._get_format_type(raw_buffer.dtype)
+ dst_format_type = HailoRTTransformUtils._get_format_type(dst_dtype)
+ _pyhailort.dequantize_output_buffer_in_place(raw_buffer, src_format_type, dst_format_type, elements_count, quant_info)
+
+ @staticmethod
+ def quantize_input_buffer(src_buffer, dst_buffer, elements_count, quant_info):
+ """Quantize the data in input buffer `src_buffer` and output it to the buffer `dst_buffer`
+
+ Args:
+ src_buffer (:obj:`numpy.ndarray`): The input buffer containing the data to be quantized.
+ The buffer's data type is the source data type.
+ dst_buffer (:obj:`numpy.ndarray`): The buffer that will contain the quantized data.
+ The buffer's data type is the destination data type.
+ elements_count (int): The number of elements to quantize. This number must not exceed 'src_buffer' or 'dst_buffer' sizes.
+ quant_info (:class:`~hailo_platform.pyhailort.pyhailort.QuantInfo`): The quantization info.
+ """
+ with ExceptionWrapper():
+ src_format_type = HailoRTTransformUtils._get_format_type(src_buffer.dtype)
+ dst_format_type = HailoRTTransformUtils._get_format_type(dst_buffer.dtype)
+ _pyhailort.quantize_input_buffer(src_buffer, dst_buffer, src_format_type, dst_format_type, elements_count, quant_info)
+
+ @staticmethod
+ def output_raw_buffer_to_nms_tf_format(raw_output_buffer, shape, dtype, quantized_empty_bbox):
+ offset = 0
+ # We create the tf_format buffer with reversed width/features for preformance optimization
+ converted_output_buffer = numpy.empty([shape[0], shape[1], shape[3], shape[2]], dtype=dtype)
+ for frame in range(converted_output_buffer.shape[0]):
+ offset = frame * converted_output_buffer.shape[1] * (converted_output_buffer.shape[2] * converted_output_buffer.shape[3] + 1)
+ HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format_single_frame(raw_output_buffer, converted_output_buffer[frame],
+ converted_output_buffer.shape[1], converted_output_buffer.shape[2], quantized_empty_bbox, offset)
+ converted_output_buffer = numpy.swapaxes(converted_output_buffer, 2, 3)
+ return converted_output_buffer
+
+ @staticmethod
+ def output_raw_buffer_to_nms_tf_format_single_frame(raw_output_buffer, converted_output_frame, number_of_classes,
+ max_bboxes_per_class, quantized_empty_bbox, offset=0):
+ for class_i in range(number_of_classes):
+ class_bboxes_amount = int(raw_output_buffer[offset])
+ offset += 1
+ if 0 != class_bboxes_amount:
+ converted_output_frame[class_i][ : class_bboxes_amount][:] = raw_output_buffer[offset : offset + (BBOX_PARAMS * class_bboxes_amount)].reshape(class_bboxes_amount, BBOX_PARAMS)
+ offset += BBOX_PARAMS * class_bboxes_amount
+ converted_output_frame[class_i][class_bboxes_amount : max_bboxes_per_class][:] = quantized_empty_bbox
+
+ @staticmethod
+ def output_raw_buffer_to_nms_format(raw_output_buffer, number_of_classes):
+ converted_output_buffer = []
+ for frame in raw_output_buffer:
+ converted_output_buffer.append(HailoRTTransformUtils.output_raw_buffer_to_nms_format_single_frame(frame, number_of_classes))
+ return converted_output_buffer
+
+ @staticmethod
+ def output_raw_buffer_to_nms_format_single_frame(raw_output_buffer, number_of_classes, offset=0):
+ converted_output_frame = []
+ for class_i in range(number_of_classes):
+ class_bboxes_amount = int(raw_output_buffer[offset])
+ offset += 1
+ if class_bboxes_amount == 0:
+ converted_output_frame.append(numpy.empty([0, BBOX_PARAMS]))
+ else:
+ converted_output_frame.append(raw_output_buffer[offset : offset + (BBOX_PARAMS * class_bboxes_amount)].reshape(
+ class_bboxes_amount, BBOX_PARAMS))
+ offset += BBOX_PARAMS * class_bboxes_amount
+ return converted_output_frame
+
+ @staticmethod
+ def _get_format_type(dtype):
+ if dtype == numpy.uint8:
+ return FormatType.UINT8
+ elif dtype == numpy.uint16:
+ return FormatType.UINT16
+ elif dtype == numpy.float32:
+ return FormatType.FLOAT32
+ raise HailoRTException("unsupported data type {}".format(dtype))
+
+class InternalEthernetDevice(object):
+ def __init__(self, address, port, response_timeout_seconds=10, max_number_of_attempts=3):
+ self.device = None
+ self._address = address
+ self._port = port
+ self._response_timeout_milliseconds = int(response_timeout_seconds * 1000)
+ self._max_number_of_attempts = max_number_of_attempts
+ with ExceptionWrapper():
+ self.device = _pyhailort.Device.create_eth(self._address, self._port,
+ self._response_timeout_milliseconds, self._max_number_of_attempts)
+
+ def __del__(self):
+ self.release()
+
+ def release(self):
+ if self.device is None:
+ return
+ with ExceptionWrapper():
+ self.device.release()
+ self.device = None
+
+
+class PcieDeviceInfo(_pyhailort.PcieDeviceInfo):
+ """Represents pcie device info, includeing domain, bus, device and function.
+ """
+
+ BOARD_LOCATION_HELP_STRING = 'Board location in the format of the command: "lspci -d 1e60: | cut -d\' \' -f1" ([]::.). If not specified the first board is taken.'
+
+ def __init__(self, bus, device, func, domain=None):
+ super(PcieDeviceInfo, self).__init__()
+ self.bus = bus
+ self.device = device
+ self.func = func
+ if domain is None:
+ self.domain = PCIE_ANY_DOMAIN
+ else:
+ self.domain = domain
+
+ def __eq__(self, other):
+ return (self.domain, self.bus, self.device, self.func) == (other.domain, other.bus, other.device, other.func)
+
+ def __str__(self):
+ with ExceptionWrapper():
+ return super().__str__()
+
+ def __repr__(self):
+ return 'PcieDeviceInfo({})'.format(str(self))
+
+ @classmethod
+ def from_string(cls, board_location_str):
+ """Parse pcie device info BDF from string. The format is []::."""
+ with ExceptionWrapper():
+ device_info = _pyhailort.PcieDeviceInfo._parse(board_location_str)
+ return PcieDeviceInfo(device_info.bus, device_info.device, device_info.func, device_info.domain)
+
+ @classmethod
+ def argument_type(cls, board_location_str):
+ """PcieDeviceInfo Argument type for argparse parsers"""
+ try:
+ return cls.from_string(board_location_str)
+ except HailoRTException:
+ raise ArgumentTypeError('Invalid device info string, format is []::.')
+
+
+class InternalPcieDevice(object):
+ def __init__(self, device_info=None):
+ self.device = None
+ if device_info is None:
+ device_info = InternalPcieDevice.scan_devices()[0]
+ self._device_info = device_info
+ with ExceptionWrapper():
+ self.device = _pyhailort.Device.create_pcie(self._device_info)
+
+ def __del__(self):
+ self.release()
+
+ def release(self):
+ if self.device is None:
+ return
+ with ExceptionWrapper():
+ self.device.release()
+ self.device = None
+
+ @staticmethod
+ def scan_devices():
+ with ExceptionWrapper():
+ return [PcieDeviceInfo(dev_info.bus, dev_info.device, dev_info.func, dev_info.domain)
+ for dev_info in _pyhailort.scan_pcie_devices()]
+
+ def create_debug_log(self):
+ return PcieDebugLog(self)
+
+ def write_memory(self, address, data):
+ with ExceptionWrapper():
+ self.device.direct_write_memory(address, data)
+
+ def read_memory(self, address, size):
+ with ExceptionWrapper():
+ return self.device.direct_read_memory(address, size)
+
+
+class PcieDebugLog(object):
+ def __init__(self, pci_device):
+ self._pcie_device = pci_device
+
+ def read(self, count, cpu_id):
+ with ExceptionWrapper():
+ return self._pcie_device.device.read_log(count, cpu_id)
+
+
+class HailoPowerMeasurementUtils(object):
+ @staticmethod
+ def return_real_sampling_period(sampling_period):
+ """Get a sampling period from the enum."""
+ SamplingPeriodDictionary = dict([
+ (SamplingPeriod.PERIOD_140us, 140),
+ (SamplingPeriod.PERIOD_204us, 204),
+ (SamplingPeriod.PERIOD_332us, 332),
+ (SamplingPeriod.PERIOD_588us, 588),
+ (SamplingPeriod.PERIOD_1100us, 1100),
+ (SamplingPeriod.PERIOD_2116us, 2116),
+ (SamplingPeriod.PERIOD_4156us, 4156),
+ (SamplingPeriod.PERIOD_8244us, 8244),
+ ])
+ return SamplingPeriodDictionary[sampling_period]
+
+ @staticmethod
+ def return_real_averaging_factor(averaging_factor):
+ """Get an averaging factor from the enum."""
+ AveragingFactorDictionary = dict([
+ (AveragingFactor.AVERAGE_1, 1),
+ (AveragingFactor.AVERAGE_4, 4),
+ (AveragingFactor.AVERAGE_16, 16),
+ (AveragingFactor.AVERAGE_64, 64),
+ (AveragingFactor.AVERAGE_128, 128),
+ (AveragingFactor.AVERAGE_256, 256),
+ (AveragingFactor.AVERAGE_512, 512),
+ (AveragingFactor.AVERAGE_1024, 1024),
+ ])
+ return AveragingFactorDictionary[averaging_factor]
+
+class HailoPowerMode(_pyhailort.PowerMode):
+ pass
+
+class HailoStreamInterface(_pyhailort.StreamInterface):
+ pass
+
+class HailoStreamDirection(_pyhailort.StreamDirection):
+ pass
+
+class HailoCpuId(_pyhailort.CpuId):
+ pass
+
+class HailoFormatFlags(_pyhailort.FormatFlags):
+ pass
+
+
+class VDevice(object):
+ """Hailo virtual device representation."""
+
+ def __init__(
+ self,
+ params=None, device_infos=None):
+
+ """Create the Hailo virtual device object.
+
+ Args:
+ params (:obj:`hailo_platform.pyhailort.pyhailort.VDeviceParams`, optional): VDevice params, call
+ :func:`VDevice.create_params` to get default params. Excludes 'device_infos'.
+ device_infos (list of :obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`, optional): pcie devices infos to create VDevice from,
+ call :func:`PcieDevice.scan_devices` to get list of all available devices. Excludes 'params'.
+ """
+ gc.collect()
+ self._id = "VDevice"
+ self._params = params
+ self._device_infos = device_infos
+ if self._device_infos is not None:
+ if self._params is not None:
+ raise HailoRTException("VDevice can be created from params or device_infos. Both parameters was passed to the c'tor")
+ self._vdevice = None
+ self._loaded_network_groups = []
+ self._open_vdevice()
+
+ self._creation_pid = os.getpid()
+
+ def _open_vdevice(self):
+ if self._device_infos is not None:
+ with ExceptionWrapper():
+ self._vdevice = _pyhailort.VDevice.create_from_infos(self._device_infos)
+ else:
+ if self._params is None:
+ self._params = VDevice.create_params()
+ with ExceptionWrapper():
+ self._vdevice = _pyhailort.VDevice.create(self._params)
+
+ def __enter__(self):
+ return self
+
+ def release(self):
+ """Release the allocated resources of the device. This function should be called when working with the device not as context-manager."""
+ if self._vdevice is not None:
+ self._vdevice.release()
+ self._vdevice = None
+
+ def __exit__(self, *args):
+ self.release()
+ return False
+
+ def __del__(self):
+ self.release()
+
+ @staticmethod
+ def create_params():
+ with ExceptionWrapper():
+ return _pyhailort.VDeviceParams.default()
+
+ def configure(self, hef, configure_params_by_name={}):
+ """Configures target vdevice from HEF object.
+
+ Args:
+ hef (:class:`~hailo_platform.pyhailort.pyhailort.HEF`): HEF to configure the vdevice from
+ configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
+ """
+ if self._creation_pid != os.getpid():
+ raise HailoRTException("VDevice can only be configured from the process it was created in.")
+ with ExceptionWrapper():
+ configured_apps = self._vdevice.configure(hef._hef, configure_params_by_name)
+ configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
+ self._loaded_network_groups.extend(configured_networks)
+ return configured_networks
+
+ def get_physical_devices(self):
+ """Gets the underlying physical devices.
+
+ Return:
+ list of :obj:`~hailo_platform.pyhailort.hw_object.PcieDevice`: The underlying physical devices.
+ """
+ with ExceptionWrapper():
+ phys_dev_infos = self._vdevice.get_physical_devices_infos()
+ pythonic_dev_infos = [PcieDeviceInfo(dev_info.bus, dev_info.device, dev_info.func, dev_info.domain)
+ for dev_info in phys_dev_infos]
+
+ from hailo_platform.pyhailort.hw_object import PcieDevice
+ return [PcieDevice(info) for info in pythonic_dev_infos]
+
+ def get_physical_devices_infos(self):
+ """Gets the physical devices infos.
+
+ Return:
+ list of :obj:`~hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`: The underlying physical devices infos.
+ """
+ with ExceptionWrapper():
+ return self._vdevice.get_physical_devices_infos()
+
+
+class InputVStreamParams(object):
+ """Parameters of an input virtual stream (host to device)."""
+
+ @staticmethod
+ def make(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
+ """Create input virtual stream params from a configured network group. These params determine the format of the
+ data that will be fed into the network group.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the params are created.
+ quantized (bool): Whether the data fed into the chip is already quantized. True means
+ the data is already quantized. False means it's HailoRT's responsibility to quantize
+ (scale) the data. Defaults to True.
+ format_type (:class:`~hailo_platform.pyhailort.pyhailort.FormatType`): The
+ default format type of the data for all input virtual streams. If quantized is False,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.FLOAT32`. Otherwise,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.AUTO`,
+ which means the data is fed in the same format expected by the device (usually
+ uint8).
+ timeout_ms (int): The default timeout in milliseconds for all input virtual streams.
+ Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
+ queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
+ network_name (str): Network name of the requested virtual stream params.
+ If not passed, all the networks in the network group will be addressed.
+
+ Returns:
+ dict: The created virtual streams params. The keys are the vstreams names. The values are the
+ params.
+ """
+ if format_type is None:
+ if not quantized:
+ format_type = FormatType.FLOAT32
+ else:
+ format_type = FormatType.AUTO
+ if timeout_ms is None:
+ timeout_ms = DEFAULT_VSTREAM_TIMEOUT_MS
+ if queue_size is None:
+ queue_size = DEFAULT_VSTREAM_QUEUE_SIZE
+ name = network_name if network_name is not None else configured_network.name
+ with ExceptionWrapper():
+ return configured_network._hef._hef.get_input_vstreams_params(name, quantized,
+ format_type, timeout_ms, queue_size)
+
+ @staticmethod
+ def make_from_network_group(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
+ """Create input virtual stream params from a configured network group. These params determine the format of the
+ data that will be fed into the network group.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the params are created.
+ quantized (bool): Whether the data fed into the chip is already quantized. True means
+ the data is already quantized. False means it's HailoRT's responsibility to quantize
+ (scale) the data. Defaults to True.
+ format_type (:class:`~hailo_platform.pyhailort.pyhailort.FormatType`): The
+ default format type of the data for all input virtual streams. If quantized is False,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.FLOAT32`. Otherwise,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.AUTO`,
+ which means the data is fed in the same format expected by the device (usually
+ uint8).
+ timeout_ms (int): The default timeout in milliseconds for all input virtual streams.
+ Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
+ queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
+ network_name (str): Network name of the requested virtual stream params.
+ If not passed, all the networks in the network group will be addressed.
+
+ Returns:
+ dict: The created virtual streams params. The keys are the vstreams names. The values are the
+ params.
+ """
+ return InputVStreamParams.make(configured_network, quantized, format_type, timeout_ms, queue_size, network_name)
+
+
+class OutputVStreamParams(object):
+ """Parameters of an output virtual stream (device to host)."""
+
+ @staticmethod
+ def make(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
+ """Create output virtual stream params from a configured network group. These params determine the format of the
+ data that will be fed into the network group.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the params are created.
+ quantized (bool): Whether the data fed into the chip is already quantized. True means
+ the data is already quantized. False means it's HailoRT's responsibility to quantize
+ (scale) the data. Defaults to True.
+ format_type (:class:`~hailo_platform.pyhailort.pyhailort.FormatType`): The
+ default format type of the data for all output virtual streams. If quantized is False,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.FLOAT32`. Otherwise,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.AUTO`,
+ which means the data is fed in the same format expected by the device (usually
+ uint8).
+ timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
+ Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
+ queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
+ network_name (str): Network name of the requested virtual stream params.
+ If not passed, all the networks in the network group will be addressed.
+
+ Returns:
+ dict: The created virtual streams params. The keys are the vstreams names. The values are the
+ params.
+ """
+ if format_type is None:
+ if not quantized:
+ format_type = FormatType.FLOAT32
+ else:
+ format_type = FormatType.AUTO
+ if timeout_ms is None:
+ timeout_ms = DEFAULT_VSTREAM_TIMEOUT_MS
+ if queue_size is None:
+ queue_size = DEFAULT_VSTREAM_QUEUE_SIZE
+ name = network_name if network_name is not None else configured_network.name
+ with ExceptionWrapper():
+ return configured_network._hef._hef.get_output_vstreams_params(name, quantized,
+ format_type, timeout_ms, queue_size)
+
+ @staticmethod
+ def make_from_network_group(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None, network_name=None):
+ """Create output virtual stream params from a configured network group. These params determine the format of the
+ data that will be fed into the network group.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the params are created.
+ quantized (bool): Whether the data fed into the chip is already quantized. True means
+ the data is already quantized. False means it's HailoRT's responsibility to quantize
+ (scale) the data. Defaults to True.
+ format_type (:class:`~hailo_platform.pyhailort.pyhailort.FormatType`): The
+ default format type of the data for all output virtual streams. If quantized is False,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.FLOAT32`. Otherwise,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.AUTO`,
+ which means the data is fed in the same format expected by the device (usually
+ uint8).
+ timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
+ Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
+ queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
+ network_name (str): Network name of the requested virtual stream params.
+ If not passed, all the networks in the network group will be addressed.
+
+ Returns:
+ dict: The created virtual streams params. The keys are the vstreams names. The values are the
+ params.
+ """
+ return OutputVStreamParams.make(configured_network, quantized, format_type, timeout_ms, queue_size, network_name)
+
+ @staticmethod
+ def make_groups(configured_network, quantized=True, format_type=None, timeout_ms=None, queue_size=None):
+ """Create output virtual stream params from a configured network group. These params determine the format of the
+ data that will be fed into the network group. The params groups are splitted with respect to their underlying streams for multi process usges.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the params are created.
+ quantized (bool): Whether the data fed into the chip is already quantized. True means
+ the data is already quantized. False means it's HailoRT's responsibility to quantize
+ (scale) the data. Defaults to True.
+ format_type (:class:`~hailo_platform.pyhailort.pyhailort.FormatType`): The
+ default format type of the data for all output virtual streams. If quantized is False,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.FLOAT32`. Otherwise,
+ the default is :attr:`~hailo_platform.pyhailort.pyhailort.FormatType.AUTO`,
+ which means the data is fed in the same format expected by the device (usually
+ uint8).
+ timeout_ms (int): The default timeout in milliseconds for all output virtual streams.
+ Defaults to DEFAULT_VSTREAM_TIMEOUT_MS. In case of timeout, :class:`HailoRTTimeout` will be raised.
+ queue_size (int): The pipeline queue size. Defaults to DEFAULT_VSTREAM_QUEUE_SIZE.
+
+ Returns:
+ list of dicts: Each element in the list represent a group of params, where the keys are the vstreams names, and the values are the
+ params. The params groups are splitted with respect to their underlying streams for multi process usges.
+ """
+ all_params = OutputVStreamParams.make(configured_network, quantized=quantized, format_type=format_type, timeout_ms=timeout_ms, queue_size=queue_size)
+ low_level_streams_names = [stream_info.name for stream_info in configured_network.get_output_stream_infos()]
+ stream_name_to_vstream_names = {stream_name: configured_network.get_vstream_names_from_stream_name(stream_name) for stream_name in low_level_streams_names}
+ results = []
+ for low_level_stream_name, vstream_names in stream_name_to_vstream_names.items():
+ params_group = {}
+ for vstream_name in vstream_names:
+ # Vstreams that were already seen should not be added to another params_group
+ if all_params[vstream_name] is not None:
+ params_group[vstream_name] = all_params[vstream_name]
+ all_params[vstream_name] = None
+ if 0 < len(params_group):
+ results.append(params_group)
+ return results
+
+
+class InputVStream(object):
+ """Represents a single virtual stream in the host to device direction."""
+
+ def __init__(self, send_object):
+ self._send_object = send_object
+ self._input_dtype = self._send_object.dtype
+
+ @property
+ def shape(self):
+ return self._send_object.shape
+
+ @property
+ def dtype(self):
+ return self._send_object.dtype
+
+ @property
+ def name(self):
+ return self._send_object.info.name
+
+ @property
+ def network_name(self):
+ return self._send_object.info.network_name
+
+ def send(self, input_data):
+ """Send frames to inference.
+
+ Args:
+ input_data (:obj:`numpy.ndarray`): Data to run inference on.
+ """
+
+ if input_data.dtype != self._input_dtype:
+ input_data = input_data.astype(self._input_dtype)
+
+ if not input_data.flags.c_contiguous:
+ logger = default_logger()
+ logger.warning("Warning - Converting input numpy array to be C_CONTIGUOUS")
+ input_data = numpy.asarray(input_data, order='C')
+
+ batch_number = 0
+ batch_size = 1
+ while batch_number < input_data.shape[0]:
+ data = input_data[batch_number:batch_number + batch_size]
+ with ExceptionWrapper():
+ self._send_object.send(data)
+ batch_number += batch_size
+
+ def flush(self):
+ """Blocks until there are no buffers in the input VStream pipeline."""
+ with ExceptionWrapper():
+ self._send_object.flush()
+
+ @property
+ def info(self):
+ with ExceptionWrapper():
+ return self._send_object.info
+
+class InputVStreams(object):
+ """Input vstreams pipelines that allows to send data, to be used as a context manager."""
+
+ def __init__(self, configured_network, input_vstreams_params):
+ """Constructor for the InputVStreams class.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which the pipeline is created.
+ input_vstreams_params (dict from str to :class:`InputVStreamParams`): Params for the input vstreams in the pipeline.
+ """
+ self._configured_network = configured_network
+ self._input_vstreams_params = input_vstreams_params
+ self._vstreams = {}
+
+ def __enter__(self):
+ self._input_vstreams_holder = self._configured_network._create_input_vstreams(self._input_vstreams_params)
+ self._input_vstreams_holder.__enter__()
+ for name, vstream in self._input_vstreams_holder.get_all_inputs().items():
+ self._vstreams[name] = InputVStream(vstream)
+ return self
+
+ def get(self, name=None):
+ """Return a single input vstream by its name.
+
+ Args:
+ name (str): The vstream name. If name=None and there is a single input vstream, that single (:class:`InputVStream`) will be returned.
+ Otherwise, if name=None and there are multiple input vstreams, an exception will be thrown.
+
+ Returns:
+ :class:`InputVStream`: The (:class:`InputVStream`) that corresponds to the given name.
+ """
+ if name is None:
+ if len(self._vstreams) != 1:
+ raise HailoRTException("There is no single input vStream. You must give a name")
+ name = list(self._vstreams.keys())[0]
+ return self._vstreams[name]
+
+ def clear(self):
+ """Clears the vstreams' pipeline buffers."""
+ with ExceptionWrapper():
+ self._input_vstreams_holder.clear()
+
+ def __exit__(self, *args):
+ self._input_vstreams_holder.__exit__(*args)
+ return False
+
+ def __iter__(self):
+ return iter(self._vstreams.values())
+
+class OutputLayerUtils(object):
+ def __init__(self, hef, vstream_name, pipeline, net_group_name=""):
+ self._hef = hef
+ self._vstream_info = self._get_vstream_info(net_group_name, vstream_name)
+
+ if isinstance(pipeline, (_pyhailort.InferVStreams)):
+ self._user_buffer_format = pipeline.get_user_buffer_format(vstream_name)
+ self._output_shape = pipeline.get_shape(vstream_name)
+ else:
+ self._user_buffer_format = pipeline.get_user_buffer_format()
+ self._output_shape = pipeline.shape
+
+ self._is_nms = (self._user_buffer_format.order == FormatOrder.HAILO_NMS)
+
+ if self._is_nms:
+ self._quantized_empty_bbox = numpy.asarray([0] * BBOX_PARAMS, dtype=self.output_dtype)
+ if not (self._user_buffer_format.flags & _pyhailort.FormatFlags.QUANTIZED):
+ HailoRTTransformUtils.dequantize_output_buffer_in_place(self._quantized_empty_bbox, self.output_dtype,
+ BBOX_PARAMS, self._vstream_info.quant_info)
+
+ @property
+ def output_dtype(self):
+ return _pyhailort.get_dtype(self._user_buffer_format.type)
+
+ @property
+ def output_shape(self):
+ return self._output_shape
+
+ @property
+ def vstream_info(self):
+ return self._vstream_info
+
+ @property
+ def output_tensor_info(self):
+ return self.output_shape, self.output_dtype
+
+ @property
+ def is_nms(self):
+ return self._is_nms
+
+ @property
+ def quantized_empty_bbox(self):
+ if not self.is_nms:
+ raise HailoRTException("Requested NMS info for non-NMS layer")
+ return self._quantized_empty_bbox
+
+ def _get_vstream_info(self, net_group_name, vstream_name):
+ output_vstream_infos = self._hef.get_output_vstream_infos(net_group_name)
+ for info in output_vstream_infos:
+ if info.name == vstream_name:
+ return info
+ raise HailoRTException("No vstream matches the given name {}".format(vstream_name))
+
+ @property
+ def tf_nms_fomrat_shape(self):
+ if not self.is_nms:
+ raise HailoRTException("Requested NMS info for non-NMS layer")
+ nms_shape = self._vstream_info.nms_shape
+ return [nms_shape.number_of_classes, BBOX_PARAMS,
+ nms_shape.max_bboxes_per_class]
+
+class OutputVStream(object):
+ """Represents a single output virtual stream in the device to host direction."""
+
+ def __init__(self, configured_network, recv_object, name, tf_nms_format=False, net_group_name=""):
+ self._recv_object = recv_object
+ self._output_layer_utils = OutputLayerUtils(configured_network._hef, name, self._recv_object, net_group_name)
+ self._output_dtype = self._output_layer_utils.output_dtype
+ self._vstream_info = self._output_layer_utils._vstream_info
+ self._output_tensor_info = self._output_layer_utils.output_tensor_info
+ self._is_nms = self._output_layer_utils.is_nms
+ if self._is_nms:
+ self._quantized_empty_bbox = self._output_layer_utils.quantized_empty_bbox
+ self._tf_nms_format = tf_nms_format
+
+ @property
+ def shape(self):
+ return self._recv_object.shape
+
+ @property
+ def dtype(self):
+ return self._recv_object.dtype
+
+ @property
+ def name(self):
+ return self._vstream_info.name
+
+ @property
+ def network_name(self):
+ return self._vstream_info.network_name
+
+ def recv(self):
+ """Receive frames after inference.
+
+ Returns:
+ :obj:`numpy.ndarray`: The output of the inference for a single frame. The returned
+ tensor does not include the batch dimension.
+ In case of nms output and tf_nms_format=False, returns list of :obj:`numpy.ndarray`.
+ """
+ result_array = None
+ with ExceptionWrapper():
+ result_array = self._recv_object.recv()
+
+ if self._is_nms:
+ nms_shape = self._vstream_info.nms_shape
+ if self._tf_nms_format:
+ nms_results_tesnor = result_array
+ # We create the tf_format buffer with reversed width/features for preformance optimization
+ shape = self._output_layer_utils.tf_nms_fomrat_shape
+ result_array = numpy.empty([shape[0], shape[2], shape[1]], dtype=self._output_dtype)
+ HailoRTTransformUtils.output_raw_buffer_to_nms_tf_format_single_frame(nms_results_tesnor, result_array,
+ nms_shape.number_of_classes,
+ nms_shape.max_bboxes_per_class, self._quantized_empty_bbox)
+ result_array = numpy.swapaxes(result_array, 1, 2)
+ else:
+ result_array = HailoRTTransformUtils.output_raw_buffer_to_nms_format_single_frame(result_array,
+ nms_shape.number_of_classes)
+ return result_array
+
+ @property
+ def info(self):
+ with ExceptionWrapper():
+ return self._recv_object.info
+
+class OutputVStreams(object):
+ """Output virtual streams pipelines that allows to receive data, to be used as a context manager."""
+
+ def __init__(self, configured_network, output_vstreams_params, tf_nms_format=False):
+ """Constructor for the OutputVStreams class.
+
+ Args:
+ configured_network (:class:`ConfiguredNetwork`): The configured network group for which
+ the pipeline is created.
+ output_vstreams_params (dict from str to :class:`OutputVStreamParams`): Params for the
+ output vstreams in the pipeline.
+ tf_nms_format (bool, optional): indicates whether the returned nms outputs should be in
+ Hailo format or TensorFlow format. Default is False (using Hailo format).
+
+ * Hailo format -- list of :obj:`numpy.ndarray`. Each element represents th
+ detections (bboxes) for the class, and its shape is
+ ``[number_of_detections, BBOX_PARAMS]``
+ * TensorFlow format -- :obj:`numpy.ndarray` of shape
+ ``[class_count, BBOX_PARAMS, detections_count]`` padded with empty bboxes.
+ """
+ self._configured_network = configured_network
+ self._net_group_name = configured_network.name
+ self._output_vstreams_params = output_vstreams_params
+ self._output_tensor_info = {}
+ self._tf_nms_format = tf_nms_format
+ self._vstreams = {}
+
+ def __enter__(self):
+ self._output_vstreams_holder = self._configured_network._create_output_vstreams(self._output_vstreams_params)
+ self._output_vstreams_holder.__enter__()
+ for name, vstream in self._output_vstreams_holder.get_all_outputs().items():
+ self._vstreams[name] = OutputVStream(self._configured_network, vstream, name,
+ tf_nms_format=self._tf_nms_format, net_group_name=self._net_group_name)
+ return self
+
+ def get(self, name=None):
+ """Return a single output vstream by its name.
+
+ Args:
+ name (str): The vstream name. If name=None and there is a single output vstream, that single (:class:`OutputVStream`) will be returned.
+ Otherwise, if name=None and there are multiple output vstreams, an exception will be thrown.
+
+ Returns:
+ :class:`OutputVStream`: The (:class:`OutputVStream`) that corresponds to the given name.
+ """
+ if name is None:
+ if len(self._vstreams) != 1:
+ raise HailoRTException("There is no single output vStream. You must give a name")
+ name = list(self._vstreams.keys())[0]
+ return self._vstreams[name]
+
+ def clear(self):
+ """Clears the vstreams' pipeline buffers."""
+ with ExceptionWrapper():
+ self._output_vstreams_holder.clear()
+
+ def __exit__(self, *args):
+ self._output_vstreams_holder.__exit__(*args)
+ return False
+
+ def __iter__(self):
+ return iter(self._vstreams.values())
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/benchmark_command.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/benchmark_command.py
deleted file mode 100644
index cc5eb6a..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/benchmark_command.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-class BenchmarkCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'benchmark')
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/configure_firmware.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/configure_firmware.py
deleted file mode 100644
index d1e6bf8..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/configure_firmware.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-
-"""Parses a configuration file that contains user or board configurations.
-"""
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-class FWConfigCommandCLI(HailortCliUtil):
- """CLI tool for changing the FW configuration (User Config)"""
- def __init__(self, parser):
- super().__init__(parser, 'fw-config')
-
-class BoardConfigCommandCLI(HailortCliUtil):
- """CLI tool for changing the FW configuration (Board Config)"""
- def __init__(self, parser):
- super().__init__(parser, 'board-config')
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/firmware_config.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/firmware_config.py
deleted file mode 100644
index 7b5738a..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/firmware_config.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#!/usr/bin/env python
-
-"""Parses a configuration file that contains the definitions of possible user configurations
- Availabe in the firmware.
-"""
-
-from builtins import object
-import json
-
-from abc import ABCMeta
-from collections import OrderedDict
-from future.utils import with_metaclass
-
-
-
-class ConfigSyntaxException(Exception):
- """Raised when there is a syntax error in the configuration file."""
- pass
-
-
-class UnsupportedConfigVersionException(Exception):
- """Raised when the version of the configuration file is not supported."""
- pass
-
-
-class ConfigFormattingException(Exception):
- """Raised when there is a formatting error in the firmware's configuration."""
- pass
-
-class ConfigDeserializationException(Exception):
- """Raised when there is an error while parsing a binary configuration."""
- pass
-
-
-class ConfigLine(with_metaclass(ABCMeta, object)):
- """An abstract config line class. Implements logic that is shared between a few types
- of configuration lines.
- """
-
- def __init__(self, config_name, config_id):
- """Initializes a new ConfigLine object.
-
- Args:
- config_name(str): Name defined for the configuration in the line.
- config_id(int): Config ID (the integer representing the config).
- """
- self._name = None
- self.name = config_name
- self._id = config_id
-
- @property
- def name(self):
- """Returns:
- str: Name of the category.
- """
- return self._name
-
- @name.setter
- def name(self, config_name):
- if not (config_name.isalnum() or config_name[0].isalpha()):
- raise ConfigSyntaxException('Configuration name must be alphanumeric (with a first '
- 'alphabetical character) received: {}'.format(
- config_name))
- self._name = config_name.lower()
-
- @property
- def id_value(self):
- """Returns:
- int: Value of the entry's ID.
- """
- return self._id
-
-
-class ConfigEntry(ConfigLine):
- """A configuration entry."""
-
- _PRIMITIVE_TYPES = {
- 1: 'int8_t',
- 2: 'int16_t',
- 4: 'int32_t'}
-
- def __init__(self, entry_name, entry_id, category_id, size, length, sign, deserializer, length_before_serialization=None):
- """Initializes a new ConfigEntry object.
-
- Args:
- entry_name(str): Entry name.
- entry_id(int): Entry ID (the integer representing the entry). (Should be 0-65535)
- category_id(int): ID of the category that contains this entry. (Should be 0-65535)
- size(int): Size of the entry in bytes. Only primitive sizes are supported.
- length(int): Length of the entry, defined as an array if different than 0.
- sign(bool): Is the primitive signed.
- deserializer(str): The formatter to use when deserializing the entry.
- length_before_serialization(int): Length of the entry before serialization, should be given only if this length
- is different than size
- """
- super(ConfigEntry, self).__init__(entry_name, entry_id)
- self._category_id = category_id
- if size not in self._PRIMITIVE_TYPES:
- raise ConfigSyntaxException(
- 'Unsupported entry size. Supported sizes {}.'.format(list(self._PRIMITIVE_TYPES.keys())))
- self._size = size
- self._length = length
- self._sign = sign
- self._deserializer = deserializer
- if length_before_serialization is None:
- self._length_before_serialization = size
- else:
- self._length_before_serialization = length_before_serialization
-
- @property
- def deserializer(self):
- """Returns:
- str: The formatter to use when deserializing the entry.
- """
- return self._deserializer
-
- @property
- def primitive_type(self):
- """Returns:
- str: The string representing the primitve C type of the entry.
- """
- var_type = self._PRIMITIVE_TYPES[self._size]
- if not self._sign:
- var_type = 'u{}'.format(var_type)
- return var_type
-
- @property
- def category_id(self):
- """Returns:
- int: Entry id value.
- """
- return self._category_id
-
- @property
- def length(self):
- """Returns:
- int: Length of the entry, if this is different than zero, then the entry is an array.
- """
- return self._length
-
- @property
- def total_size(self):
- """Returns:
- int: Entry's total size in bytes.
- """
- if self._length == 0:
- return self._size
- else:
- return self._length * self._size
-
- @property
- def length_before_serialization(self):
- """Returns:
- int: The length of the entry before serialization
- """
- return self._length_before_serialization
-
-class ConfigCategory(ConfigLine):
- """A configuration category that contains multiple configuration IDs"""
-
- def __init__(self, category_name, category_id):
- """Initializes a new ConfigCategory object.
-
- Args:
- category_name(str): Category name.
- category_id(int): Category ID (the integer representing the category).
- """
- super(ConfigCategory, self).__init__(category_name, category_id)
- self._config_entries = OrderedDict()
- self._current_entry_id = 0
-
- def append(self, entry_name, size, deserialize_as, length=0, sign=False, length_before_serialization=None):
- """Adds a new entry to the category
-
- Args:
- entry_name(str): Name of the appended configuration entry.
- size(int): Size of the entry in bytes. Only primitive sizes are supported.
- length(int): Length of the entry, defined as an array if different than 0.
- sign(bool): Is the primitive signed.
- deserialize_as(str): The formatter to use when deserializing the entry.
- """
- config_entry = ConfigEntry(
- entry_name,
- self._current_entry_id,
- self._id,
- size,
- length,
- sign,
- deserialize_as,
- length_before_serialization)
- self._config_entries[config_entry.name] = config_entry
- self._current_entry_id += 1
-
- @property
- def entries(self):
- """Returns:
- list of :obj:`ConfigEntry`: The entries in this category object.
- """
- return self._config_entries
-
- def __getitem__(self, key):
- """Returns:
- int: The ID value of the requested entry key.
- """
- return self._config_entries[key.lower()]
-
-
-class FirmwareConfig(object):
- """This class wraps the configuration file that defines the firmware user config."""
- _SUPPORTED_VERSION = [0]
- _MAGIC_NUMBER = 0x1FF6A40B
-
- def __init__(self, config_path):
- """Initializes a new FirmwareConfig object.
-
- Args:
- config_path(str): Path to a configuration file.
- """
- config_file = open(config_path, 'r')
- config_json = json.load(config_file, object_pairs_hook=OrderedDict)
- self._current_category = None
- self._next_category_id = 0
- self._categories = OrderedDict()
- self._parse_config_json(config_json)
-
- def _parse_config_json(self, config_json):
- """Parses a json dictionary containing the configuration and assigns it to the
- object attributes.
-
- Args:
- config_json(dict of str): A dictionary containing the configration file's content.
- """
- try:
- version = config_json['version']
- except KeyError:
- raise ConfigSyntaxException('Error: Version definition not found.')
- if version not in self._SUPPORTED_VERSION:
- raise UnsupportedConfigVersionException('Unsupported version: {}.\n'
- 'Supported versions: {}'.format(
- version, self._SUPPORTED_VERSION))
- self.version = version
-
- try:
- categories = config_json['categories']
- except KeyError:
- raise ConfigSyntaxException('Error: Categories definition not found.')
-
- for i, category in enumerate(categories):
- category_object = ConfigCategory(category, i)
- try:
- entries = config_json['categories'][category]['entries']
- except KeyError:
- raise ConfigSyntaxException('Error: Category {} does not contain entries.'.format(
- category))
- for entry in entries:
- category_object.append(entry, **entries[entry])
- self._categories[category_object.name] = category_object
-
- @property
- def supported_version(self):
- """Returns:
- list of int: A list containing the supported configuration version.
- """
- return self._SUPPORTED_VERSION
-
- @property
- def magic(self):
- """Returns:
- int: Firmware configuration magic number value.
- """
- return self._MAGIC_NUMBER
-
- @property
- def categories(self):
- """Returns:
- list of :obj:`ConfigCategory`: List of configuration categories contained in the
- firmware configuration.
- """
- return self._categories
-
- def __getitem__(self, key):
- """Returns:
- :class:`sdk_client.hailo_sdk_client.tools.firmware.ConfigCategory: The category
- corresponding to the requested key.
- """
- return self._categories[key]
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/sensor_config.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/sensor_config.py
deleted file mode 100644
index 3588e28..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/sensor_config.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-
-"""Parses a configuration file that contains camera sensor configurations in the FW.
-"""
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-class SensorConfigCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'sensor-config')
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_firmware.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_firmware.py
deleted file mode 100644
index a15d218..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_firmware.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-
-class FWUpdaterCLI(HailortCliUtil):
- """Cli tool for firmware updates"""
- def __init__(self, parser):
- super().__init__(parser, 'fw-update')
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_second_stage.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_second_stage.py
deleted file mode 100644
index 653d0d0..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_second_stage.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-
-class SSBUpdaterCLI(HailortCliUtil):
- """Cli tool for second stage boot updates"""
- def __init__(self, parser):
- super().__init__(parser, 'ssb-update')
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/fw_control.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/fw_control.py
deleted file mode 100644
index d169039..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/fw_control.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-
-class ScanCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'scan')
-
-
-class ControlCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'fw-control')
-
-class LoggerCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'fw-logger')
-
-class MeasurePowerCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'measure-power')
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/__init__.py
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/__init__.py
rename to hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/__init__.py
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/base_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/base_utils.py
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/base_utils.py
rename to hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/base_utils.py
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/config_definitions.json b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/config_definitions.json
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/config_definitions.json
rename to hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/config_definitions.json
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/example_config.json b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/example_config.json
new file mode 100644
index 0000000..f1a08bf
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/example_config.json
@@ -0,0 +1,14 @@
+{
+ "network":
+ {
+ "static_netmask": "255.255.255.0",
+ "should_use_dhcp": false,
+ "mac_address": "80:00:DE:AD:BE:EF"
+ },
+ "system":
+ {
+ "name": "Hailo-8",
+ "supported_aspm_states": "ASPM L1 ONLY",
+ "temperature_throttling_enable": true
+ }
+}
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/hailo_device_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailo_device_utils.py
similarity index 91%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/hailo_device_utils.py
rename to hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailo_device_utils.py
index fd33bb1..99be958 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/hailo_device_utils.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailo_device_utils.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python
from enum import Enum
-from hailo_platform.common.tools.cmd_utils.base_utils import CmdUtilsBaseUtil
-from hailo_platform.drivers.hw_object import EthernetDevice, PcieDevice
+from hailo_platform.tools.hailocli.base_utils import CmdUtilsBaseUtil
+from hailo_platform.pyhailort.hw_object import EthernetDevice, PcieDevice
from hailo_platform.common.logger.logger import default_logger
-from hailo_platform.drivers.hailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
+from hailo_platform.pyhailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
logger = default_logger()
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailocli_commands.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailocli_commands.py
new file mode 100644
index 0000000..d3a62fd
--- /dev/null
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailocli_commands.py
@@ -0,0 +1,70 @@
+
+from hailo_platform.tools.hailocli.base_utils import HailortCliUtil
+
+"""
+ HailoRTCLI matching commands in Hailo-CLI tool.
+"""
+
+class BenchmarkCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'benchmark')
+
+
+class FWConfigCommandCLI(HailortCliUtil):
+ """CLI tool for changing the FW configuration (User Config)"""
+ def __init__(self, parser):
+ super().__init__(parser, 'fw-config')
+
+
+class BoardConfigCommandCLI(HailortCliUtil):
+ """CLI tool for changing the FW configuration (Board Config)"""
+ def __init__(self, parser):
+ super().__init__(parser, 'board-config')
+
+
+class ScanCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'scan')
+
+
+class ControlCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'fw-control')
+
+
+class LoggerCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'fw-logger')
+
+
+class MeasurePowerCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'measure-power')
+
+
+class RunCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'run')
+
+
+class SensorConfigCommandCLI(HailortCliUtil):
+ def __init__(self, parser):
+ super().__init__(parser, 'sensor-config')
+
+
+class FWUpdaterCLI(HailortCliUtil):
+ """Cli tool for firmware updates"""
+ def __init__(self, parser):
+ super().__init__(parser, 'fw-update')
+
+
+class SSBUpdaterCLI(HailortCliUtil):
+ """Cli tool for second stage boot updates"""
+ def __init__(self, parser):
+ super().__init__(parser, 'ssb-update')
+
+
+class UDPRateLimiterCLI(HailortCliUtil):
+ """CLI tool for UDP rate limitation."""
+ def __init__(self, parser):
+ super().__init__(parser, 'udp-rate-limiter')
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/main.py
similarity index 79%
rename from hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py
rename to hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/main.py
index 8133f35..0e329c4 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/main.py
@@ -5,17 +5,10 @@ import argcomplete
import sys
import hailo_platform
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil, Helper, HailortCliUtilError
-from hailo_platform.tools.firmware.update_firmware import FWUpdaterCLI
-from hailo_platform.tools.firmware.update_second_stage import SSBUpdaterCLI
-from hailo_platform.tools.udp_rate_limiter import UDPRateLimiterCLI
-from hailo_platform.tools.fw_control import ControlCommandCLI, ScanCommandCLI, LoggerCommandCLI, MeasurePowerCommandCLI
-from hailo_platform.tools.run_command import RunCommandCLI
-from hailo_platform.tools.infer_cli import InferCLI
-from hailo_platform.tools.firmware.sensor_config import SensorConfigCommandCLI
-from hailo_platform.tools.firmware.configure_firmware import FWConfigCommandCLI
-from hailo_platform.tools.benchmark_command import BenchmarkCommandCLI
-
+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)
# Note: PlatformCommands are external dependencies in phase2-sdk/demos repo; don't change!
class PlatformCommands:
@@ -30,9 +23,7 @@ class PlatformCommands:
'fw-control': ('Useful firmware control operations', ControlCommandCLI),
'fw-logger': ('Download fw logs to a file', LoggerCommandCLI),
'scan': ('Scans for devices (Ethernet or PCIE)', ScanCommandCLI),
- 'broadcast': ('Scans for devices on a given interface (alias to \'hailo scan\')', ScanCommandCLI),
'sensor-config': ('Sensor configuration tool', SensorConfigCommandCLI),
- 'infer': ('Run a compiled network - infer command is deprecated and will be removed in a future release. Please use \'hailo run\' instead.', InferCLI),
'run': ('Run a compiled network', RunCommandCLI),
'benchmark': ('Measure basic performance on compiled network', BenchmarkCommandCLI),
'measure-power': ('Measures power consumption', MeasurePowerCommandCLI),
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/infer_cli.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/infer_cli.py
deleted file mode 100644
index 153ea8d..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/infer_cli.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from enum import Enum
-
-from hailo_platform.common.tools.cmd_utils.hailo_device_utils import HailoDeviceCmdUtil
-from hailo_platform.common.logger.logger import default_logger
-from hailo_platform.tools.run_command import RunCommandCLI
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtilError
-
-logger = default_logger()
-
-class InferModes(Enum):
- simple = 'simple'
- performance = 'performance'
-
-class InferCLI(HailoDeviceCmdUtil):
- def __init__(self, parser):
- super().__init__(parser, set_target_args=False)
- self._hailortcli_run_command = RunCommandCLI(parser)
- self._parser = parser
- subparsers = parser.add_subparsers(title="Inference mode", dest="mode")
- subparsers.required = True
- simple_parser =subparsers.add_parser(InferModes.simple.value, help="'simple' mode is unsupported, please use 'hailo run' instead")
- simple_parser.add_argument('--input-data-path', type=str, default=None,
- help="unsupported argument.")
- simple_parser.add_argument('--results-path', type=str, default=None,
- help='Unsupported argument.')
- simple_parser.add_argument('--config-path', type=str, required=True, help='Path to config HEF to infer with')
- performance_parser = subparsers.add_parser(InferModes.performance.value,
- help="infer command is deprecated and will be removed in a future release, please use 'hailo run' instead")
- performance_parser.add_argument('--config-path', type=str, required=True,
- help='Path to config HEF to infer with')
- self.add_target_args(performance_parser)
- performance_parser.add_argument('-t', '--streaming-time', type=float, default=10.0, help='For how long to stream in performance mode')
- performance_parser.add_argument('--streaming-mode',
- choices=['hw-only', 'full'],
- default='full',
- help='Whether to skip pre-infer and post-infer steps on host (hw-only) or do them (full)')
- parser.set_defaults(func=self.run)
-
- def run(self, args):
- if InferModes[args.mode] == InferModes.simple:
- logger.info("mode simple is deprecated please use \'hailo run\' instead.\n"
- ".npz and .npy format are unsupported, use binary file instead, you can use the following example:\n"
- "\'hailo run --input-files [Input file path] [hef]\'.\n"
- "for more information use \'hailo run --help\'.")
- else:
- self.validate_args(args)
- argv = [args.config_path, "-t", str(int(args.streaming_time)), '-m', "streaming" if args.streaming_mode == 'full' else 'hw_only']
- if args.target == 'udp':
- argv += ['-d', args.target, '--ip', args.ip]
- try:
- self._hailortcli_run_command.run(argv)
- except HailortCliUtilError as e:
- print('\n'+ str(e))
- return
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/run_command.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/run_command.py
deleted file mode 100644
index 1b16bbc..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/run_command.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-
-class RunCommandCLI(HailortCliUtil):
- def __init__(self, parser):
- super().__init__(parser, 'run')
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/udp_rate_limiter.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/udp_rate_limiter.py
index 658edac..75967ef 100644
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/udp_rate_limiter.py
+++ b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/udp_rate_limiter.py
@@ -6,8 +6,7 @@ from __future__ import division
from builtins import object
-from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
-from hailo_platform.drivers.hailort.pyhailort import ConfiguredNetwork, HEF, TrafficControl, INPUT_DATAFLOW_BASE_PORT
+from hailo_platform.pyhailort.pyhailort import ConfiguredNetwork, HEF, TrafficControl, INPUT_DATAFLOW_BASE_PORT
DEFAULT_MAX_KBPS = 850e3
DEFAULT_MAX_KBPS_PAPRIKA_B0 = 160e3
@@ -41,7 +40,7 @@ class RateLimiterWrapper(object):
"""RateLimiterWrapper constructor.
Args:
- configured_network_group (:class:`~hailo_platform.drivers.hailort.pyhailort.ConfiguredNetwork`): The
+ configured_network_group (:class:`~hailo_platform.pyhailort.pyhailort.ConfiguredNetwork`): The
target network_group.
fps (int): Frame rate.
fps_factor (float): Safety factor by which to multiply the calculated UDP rate.
@@ -113,10 +112,4 @@ class UDPRateLimiter(object):
port = stream_info.sys_index + INPUT_DATAFLOW_BASE_PORT
results[port] = input_rates[stream_info.name] / BYTES_IN_Kbits
- return results
-
-
-class UDPRateLimiterCLI(HailortCliUtil):
- """CLI tool for UDP rate limitation."""
- def __init__(self, parser):
- super().__init__(parser, 'udp-rate-limiter')
+ return results
\ No newline at end of file
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/watchdog.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/watchdog.py
deleted file mode 100644
index acc485e..0000000
--- a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/watchdog.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from __future__ import print_function
-from builtins import object
-import threading
-
-
-class Watchdog(object):
- def __init__(self, queues_to_close, timeout=20):
- self.timeout = timeout
- self._queues_to_close = queues_to_close
- self._t = None
-
- def do_expire(self):
- for queue_to_close in self._queues_to_close:
- queue_to_close.close()
-
- def _expire(self):
- print("\nWatchdog expire")
- self.do_expire()
-
- def start(self):
- if self.timeout is not None:
- self._t = threading.Timer(self.timeout, self._expire)
- self._t.start()
- else:
- self._t = None
-
- def stop(self):
- if self._t is not None:
- self._t.cancel()
-
- def refresh(self):
- self.stop()
- self.start()
diff --git a/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Inference Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_0_Inference_Tutorial.ipynb
similarity index 100%
rename from hailort/libhailort/bindings/python/platform/tutorials/notebooks/Inference Tutorial.ipynb
rename to hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_0_Inference_Tutorial.ipynb
diff --git a/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb
similarity index 90%
rename from hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb
rename to hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb
index a180861..c55f7b1 100644
--- a/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb
+++ b/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb
@@ -35,8 +35,7 @@
"%matplotlib inline\n",
"import time\n",
"\n",
- "from hailo_platform.drivers.hailo_controller.power_measurement import DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor # noqa F401\n",
- "from hailo_platform import PcieDevice"
+ "from hailo_platform import PcieDevice, DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex # noqa F401\n"
]
},
{
@@ -88,7 +87,7 @@
"\n",
"In the following example, a periodic power measurement is taken.\n",
"\n",
- "A measurement index is selected. It is a number between 0 and 3. The DVM is not given so the default DVM will be used, as explained above.\n"
+ "A measurement index is selected. It is a member of the enum class MeasurementBufferIndex (between 0 and 3). The DVM is not given so the default DVM will be used, as explained above.\n"
]
},
{
@@ -97,8 +96,8 @@
"metadata": {},
"outputs": [],
"source": [
- "index = 0\n",
- "target.control.set_power_measurement(index)"
+ "buffer_index = MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0\n",
+ "target.control.set_power_measurement(buffer_index=buffer_index)"
]
},
{
@@ -153,7 +152,7 @@
"for _ in range(10):\n",
" time.sleep(1)\n",
" # Get saved power measurement values from the firmware.\n",
- " measurements = target.control.get_power_measurement(index, should_clear=should_clear)\n",
+ " measurements = target.control.get_power_measurement(buffer_index=buffer_index, should_clear=should_clear)\n",
" print('Average power is {} W. Min power is {} W. Max power is {} W.\\nAverage time between power samples is {} mS\\n'.format(measurements.average_value, measurements.min_value, measurements.max_value, measurements.average_time_value_milliseconds))\n",
" \n",
"# Stop performing periodic power measurement\n",
diff --git a/hailort/libhailort/bindings/python/platform/requirements.txt b/hailort/libhailort/bindings/python/platform/requirements.txt
index 10782be..08c3adb 100644
--- a/hailort/libhailort/bindings/python/platform/requirements.txt
+++ b/hailort/libhailort/bindings/python/platform/requirements.txt
@@ -9,7 +9,6 @@ importlib-resources==5.1.2
netaddr==0.8.0
netifaces==0.10.9
numpy==1.19.4
-six==1.15.0
typing_extensions==4.1.1
verboselogs==1.7
virtualenv==20.4.3
diff --git a/hailort/libhailort/bindings/python/platform/setup.py b/hailort/libhailort/bindings/python/platform/setup.py
index d269c63..04502e9 100644
--- a/hailort/libhailort/bindings/python/platform/setup.py
+++ b/hailort/libhailort/bindings/python/platform/setup.py
@@ -1,5 +1,5 @@
import os
-import sys
+import json
from setuptools import setup, find_packages
from wheel.bdist_wheel import bdist_wheel as orig_bdist_wheel
@@ -12,14 +12,27 @@ class NonPurePythonBDistWheel(orig_bdist_wheel):
self.root_is_pure = False
-def _get_pyhailort_lib():
+def _get_pyhailort_lib_path():
+ conf_file_path = os.path.join(os.path.abspath(os.path.dirname( __file__ )), "wheel_conf.json")
extension = {
"posix": "so",
"nt": "pyd", # Windows
}[os.name]
- py = "".join(map(str, sys.version_info[:2]))
+ if not os.path.isfile(conf_file_path):
+ return None
- return f"drivers/hailort/_pyhailort*{py}*.{extension}"
+ with open(conf_file_path, "r") as conf_file:
+ content = json.load(conf_file)
+ return f"../hailo_platform/pyhailort/_pyhailort*{content['py_version']}*{content['arch']}*.{extension}"
+
+def _get_package_paths():
+ packages = []
+ pyhailort_lib = _get_pyhailort_lib_path()
+ if pyhailort_lib:
+ packages.append(pyhailort_lib)
+ packages.append("../hailo_tutorials/notebooks/*")
+ packages.append("../hailo_tutorials/hefs/*")
+ return packages
if __name__ == "__main__":
@@ -32,7 +45,7 @@ if __name__ == "__main__":
description="HailoRT",
entry_points={
"console_scripts": [
- "hailo=hailo_platform.tools.cmd_utils.main:main",
+ "hailo=hailo_platform.tools.hailocli.main:main",
]
},
install_requires=[
@@ -41,16 +54,13 @@ if __name__ == "__main__":
"future",
"netaddr",
"netifaces",
- "six",
"verboselogs",
# Pinned versions
"numpy==1.19.4",
],
name="hailort",
package_data={
- "hailo_platform": [
- _get_pyhailort_lib(), # packs _pyhailort library for _pyhailort imports
- ],
+ "hailo_platform": _get_package_paths(),
},
packages=find_packages(),
platforms=[
@@ -58,6 +68,6 @@ if __name__ == "__main__":
"linux_aarch64",
],
url="https://hailo.ai/",
- version="4.6.0",
+ version="4.8.0",
zip_safe=False,
)
diff --git a/hailort/libhailort/bindings/python/src/CMakeLists.txt b/hailort/libhailort/bindings/python/src/CMakeLists.txt
index 0df9525..e1147b4 100644
--- a/hailort/libhailort/bindings/python/src/CMakeLists.txt
+++ b/hailort/libhailort/bindings/python/src/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0.0)
+option(HAILO_BUILD_PYHAILORT_INTERNAL OFF)
+
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
string(REPLACE "." "" dpython ${PYBIND11_PYTHON_VERSION}) # E.g "3.5" -> "35"
if(${dpython} LESS "38")
@@ -11,11 +13,20 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
endif()
set(PYHAILORT_DIR ${CMAKE_CURRENT_LIST_DIR})
-add_subdirectory(internal)
+
pybind11_add_module(_pyhailort
pyhailort.cpp
+ device_api.cpp
+ hef_api.cpp
+ vstream_api.cpp
${HAILORT_COMMON_CPP_SOURCES}
)
+
+set_target_properties(_pyhailort PROPERTIES
+ CXX_STANDARD 14
+ CXX_STANDARD_REQUIRED YES
+)
+
target_include_directories(_pyhailort
PRIVATE
$
@@ -30,3 +41,14 @@ if(WIN32)
endif()
target_compile_options(_pyhailort PRIVATE ${HAILORT_COMPILE_OPTIONS})
exclude_archive_libs_symbols(_pyhailort)
+
+if (HAILO_BUILD_PYHAILORT_INTERNAL)
+ add_subdirectory(internal)
+ # copy files to venv
+ if(HAILO_BUILD_PYHAILORT_VENV)
+ add_custom_target(pyhailort_internal_venv ALL
+ COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/
+ )
+ add_dependencies(pyhailort_internal_venv _pyhailort_internal)
+ endif()
+endif()
diff --git a/hailort/libhailort/bindings/python/src/bindings_common.hpp b/hailort/libhailort/bindings/python/src/bindings_common.hpp
index ea31187..95b60a9 100644
--- a/hailort/libhailort/bindings/python/src/bindings_common.hpp
+++ b/hailort/libhailort/bindings/python/src/bindings_common.hpp
@@ -18,52 +18,46 @@
namespace hailort
{
-
-int convert_format_type_to_int(const hailo_format_type_t& type)
+class HailoRTBindingsCommon
{
- switch (type) {
- case HAILO_FORMAT_TYPE_UINT8:
- return 1;
- case HAILO_FORMAT_TYPE_UINT16:
- return 2;
- case HAILO_FORMAT_TYPE_FLOAT32:
- return 4;
- default:
- throw HailoRTStatusException("Invalid format type.");
- }
-}
-
-std::string convert_format_type_to_string(const hailo_format_type_t& type)
-{
- switch (type) {
- case HAILO_FORMAT_TYPE_UINT8:
- return "uint8";
- case HAILO_FORMAT_TYPE_UINT16:
- return "uint16";
- case HAILO_FORMAT_TYPE_FLOAT32:
- return "float32";
- default:
- throw HailoRTStatusException("Invalid format type.");
- }
-}
-
-std::vector get_pybind_shape(const hailo_vstream_info_t& vstream_info, const hailo_format_t &user_format)
-{
- // We are using user_format instead of hw format inside the vstream_info
- const auto shape = vstream_info.shape;
- // TODO: support no transformations (i.e. use stream_info.hw_shape) (SDK-16811)
- switch (user_format.order)
+public:
+ static std::string convert_format_type_to_string(const hailo_format_type_t &type)
{
- case HAILO_FORMAT_ORDER_HAILO_NMS:
- return { HailoRTCommon::get_nms_host_shape_size(vstream_info.nms_shape) };
- case HAILO_FORMAT_ORDER_NC:
- return {shape.features};
- case HAILO_FORMAT_ORDER_NHW:
- return {shape.height, shape.width};
- default:
- return {shape.height, shape.width, shape.features};
+ switch (type) {
+ case HAILO_FORMAT_TYPE_UINT8:
+ return "uint8";
+ case HAILO_FORMAT_TYPE_UINT16:
+ return "uint16";
+ case HAILO_FORMAT_TYPE_FLOAT32:
+ return "float32";
+ default:
+ throw HailoRTStatusException("Invalid format type.");
+ }
}
-}
+
+ static std::vector get_pybind_shape(const hailo_vstream_info_t& vstream_info, const hailo_format_t &user_format)
+ {
+ // We are using user_format instead of hw format inside the vstream_info
+ const auto shape = vstream_info.shape;
+ // TODO: support no transformations (i.e. use stream_info.hw_shape) (SDK-16811)
+ switch (user_format.order)
+ {
+ case HAILO_FORMAT_ORDER_HAILO_NMS:
+ return { HailoRTCommon::get_nms_host_shape_size(vstream_info.nms_shape) };
+ case HAILO_FORMAT_ORDER_NC:
+ return {shape.features};
+ case HAILO_FORMAT_ORDER_NHW:
+ return {shape.height, shape.width};
+ default:
+ return {shape.height, shape.width, shape.features};
+ }
+ }
+
+ static py::dtype get_dtype(const hailo_format_type_t &type)
+ {
+ return py::dtype(HailoRTBindingsCommon::convert_format_type_to_string(type));
+ }
+};
} /* namespace hailort */
diff --git a/hailort/libhailort/bindings/python/src/device_api.cpp b/hailort/libhailort/bindings/python/src/device_api.cpp
new file mode 100644
index 0000000..d363ed4
--- /dev/null
+++ b/hailort/libhailort/bindings/python/src/device_api.cpp
@@ -0,0 +1,568 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file device_api.cpp
+ * @brief implementations of binding to hailo device
+ *
+ **/
+
+#include "device_api.hpp"
+
+
+namespace hailort
+{
+
+DeviceWrapper DeviceWrapper::create_pcie(hailo_pcie_device_info_t &device_info)
+{
+ auto device = Device::create_pcie(device_info);
+ VALIDATE_EXPECTED(device);
+
+ return DeviceWrapper(device.release());
+}
+
+DeviceWrapper DeviceWrapper::create_eth(std::string &device_address, uint16_t port,
+ uint32_t timeout_milliseconds, uint8_t max_number_of_attempts)
+{
+ hailo_eth_device_info_t device_info = {};
+
+ /* Validate address length */
+ if (INET_ADDRSTRLEN < device_address.size()) {
+ EXIT_WITH_ERROR("device_address is too long")
+ }
+
+ device_info.host_address.sin_family = AF_INET;
+ device_info.host_address.sin_port = HAILO_ETH_PORT_ANY;
+ auto status = Socket::pton(AF_INET, HAILO_ETH_ADDRESS_ANY, &(device_info.host_address.sin_addr));
+ VALIDATE_STATUS(status);
+
+ device_info.device_address.sin_family = AF_INET;
+ device_info.device_address.sin_port = port;
+ status = Socket::pton(AF_INET, device_address.c_str(), &(device_info.device_address.sin_addr));
+ VALIDATE_STATUS(status);
+
+ device_info.timeout_millis = timeout_milliseconds;
+ device_info.max_number_of_attempts = max_number_of_attempts;
+ device_info.max_payload_size = HAILO_DEFAULT_ETH_MAX_PAYLOAD_SIZE;
+
+ auto device = Device::create_eth(device_info);
+ VALIDATE_EXPECTED(device);
+
+ 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();
+}
+
+/* Controls */
+hailo_device_identity_t DeviceWrapper::identify()
+{
+ auto board_info = device().identify();
+ VALIDATE_EXPECTED(board_info);
+
+ return board_info.release();
+}
+
+hailo_core_information_t DeviceWrapper::core_identify()
+{
+ auto core_info = device().core_identify();
+ VALIDATE_EXPECTED(core_info);
+
+ return core_info.release();
+}
+
+void DeviceWrapper::set_fw_logger(hailo_fw_logger_level_t level, uint32_t interface_mask)
+{
+ auto status = device().set_fw_logger(level, interface_mask);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::set_throttling_state(bool should_activate)
+{
+ auto status = device().set_throttling_state(should_activate);
+ VALIDATE_STATUS(status);
+}
+
+bool DeviceWrapper::get_throttling_state()
+{
+
+ auto is_active_expected = device().get_throttling_state();
+ VALIDATE_EXPECTED(is_active_expected);
+
+ return is_active_expected.release();
+}
+
+void DeviceWrapper::set_overcurrent_state(bool should_activate)
+{
+ auto status = device().set_overcurrent_state(should_activate);
+ VALIDATE_STATUS(status);
+}
+
+bool DeviceWrapper::get_overcurrent_state()
+{
+ auto is_required_expected = device().get_overcurrent_state();
+ VALIDATE_EXPECTED(is_required_expected);
+
+ return is_required_expected.release();
+}
+
+py::bytes DeviceWrapper::read_memory(uint32_t address, uint32_t length)
+{
+ std::unique_ptr response = make_unique_nothrow(length, '\x00');
+ VALIDATE_NOT_NULL(response);
+
+ MemoryView data_view(const_cast(reinterpret_cast(response->data())), length);
+ auto status = device().read_memory(address, data_view);
+ VALIDATE_STATUS(status);
+
+ return *response;
+}
+
+void DeviceWrapper::write_memory(uint32_t address, py::bytes data, uint32_t length)
+{
+ auto status = device().write_memory(address, MemoryView(const_cast(reinterpret_cast(std::string(data).c_str())), length));
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::test_chip_memories()
+{
+ hailo_status status = device().test_chip_memories();
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::i2c_write(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, py::bytes data,
+ uint32_t length)
+{
+ VALIDATE_NOT_NULL(slave_config);
+
+ std::string data_str(data);
+ MemoryView data_view = MemoryView::create_const(data_str.c_str(), length);
+ auto status = device().i2c_write(*slave_config, register_address, data_view);
+ VALIDATE_STATUS(status);
+}
+
+py::bytes DeviceWrapper::i2c_read(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, uint32_t length)
+{
+ VALIDATE_NOT_NULL(slave_config);
+
+ std::unique_ptr response = make_unique_nothrow(length, '\x00');
+ VALIDATE_NOT_NULL(response);
+
+ MemoryView data_view(const_cast(reinterpret_cast(response->data())), length);
+ auto status = device().i2c_read(*slave_config, register_address, data_view);
+ VALIDATE_STATUS(status);
+
+ return *response;
+}
+
+float32_t DeviceWrapper::power_measurement(hailo_dvm_options_t dvm,
+ hailo_power_measurement_types_t measurement_type)
+{
+ auto measurement = device().power_measurement(dvm, measurement_type);
+ VALIDATE_EXPECTED(measurement);
+
+ return measurement.release();
+}
+
+void DeviceWrapper::start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
+{
+ auto status = device().start_power_measurement(averaging_factor, sampling_period);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm,
+ hailo_power_measurement_types_t measurement_type)
+{
+ auto status = device().set_power_measurement(buffer_index,
+ dvm, measurement_type);
+ VALIDATE_STATUS(status);
+}
+
+PowerMeasurementData DeviceWrapper::get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear)
+{
+ auto measurement_data = device().get_power_measurement(buffer_index,
+ should_clear);
+ VALIDATE_EXPECTED(measurement_data);
+
+ return PowerMeasurementData(measurement_data.release());
+}
+
+void DeviceWrapper::stop_power_measurement()
+{
+ auto status = device().stop_power_measurement();
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::reset(hailo_reset_device_mode_t mode)
+{
+ auto status = device().reset(mode);
+ VALIDATE_STATUS(status);
+}
+
+hailo_fw_user_config_information_t DeviceWrapper::examine_user_config()
+{
+ auto user_config_info = device().examine_user_config();
+ VALIDATE_EXPECTED(user_config_info);
+
+ return user_config_info.release();
+}
+
+py::bytes DeviceWrapper::read_user_config()
+{
+ auto config_buffer = device().read_user_config();
+ VALIDATE_EXPECTED(config_buffer);
+
+ std::unique_ptr response = make_unique_nothrow(
+ const_cast(reinterpret_cast(config_buffer->data())), config_buffer->size());
+ VALIDATE_NOT_NULL(response);
+
+ return *response;
+}
+
+void DeviceWrapper::write_user_config(py::bytes data)
+{
+ std::string data_str(data);
+ MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
+ auto status = device().write_user_config(data_view);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::erase_user_config()
+{
+ auto status = device().erase_user_config();
+ VALIDATE_STATUS(status);
+}
+
+py::bytes DeviceWrapper::read_board_config()
+{
+ auto config_buffer = device().read_board_config();
+ VALIDATE_EXPECTED(config_buffer);
+
+ std::unique_ptr response = make_unique_nothrow(
+ const_cast(reinterpret_cast(config_buffer->data())), config_buffer->size());
+ VALIDATE_NOT_NULL(response);
+
+ return *response;
+}
+
+void DeviceWrapper::write_board_config(py::bytes data)
+{
+ std::string data_str(data);
+ MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
+ auto status = device().write_board_config(data_view);
+ VALIDATE_STATUS(status);
+}
+
+hailo_extended_device_information_t DeviceWrapper::get_extended_device_information()
+{
+ auto extended_device_info = device().get_extended_device_information();
+ VALIDATE_EXPECTED(extended_device_info);
+
+ return extended_device_info.release();
+}
+
+hailo_health_info_t DeviceWrapper::get_health_information()
+{
+ auto health_info = device().get_health_information();
+ VALIDATE_EXPECTED(health_info);
+
+ return health_info.release();
+}
+
+void DeviceWrapper::sensor_store_config(uint32_t section_index, uint32_t reset_data_size, uint32_t sensor_type, const std::string &config_file_path,
+ uint16_t config_height, uint16_t config_width, uint16_t config_fps, const std::string &config_name)
+{
+ auto status = device().store_sensor_config(section_index, static_cast(sensor_type), reset_data_size,
+ config_height, config_width, config_fps, config_file_path, config_name);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::store_isp_config(uint32_t reset_config_size, uint16_t config_height, uint16_t config_width, uint16_t config_fps,
+ const std::string &isp_static_config_file_path, const std::string &isp_runtime_config_file_path, const std::string &config_name)
+{
+ auto status = 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);
+ VALIDATE_STATUS(status);
+}
+
+py::bytes DeviceWrapper::sensor_get_sections_info()
+{
+ auto buffer = device().sensor_get_sections_info();
+ VALIDATE_EXPECTED(buffer);
+
+ std::unique_ptr response = make_unique_nothrow(
+ const_cast(reinterpret_cast(buffer->data())), buffer->size());
+ VALIDATE_NOT_NULL(response);
+
+ return *response;
+}
+
+void DeviceWrapper::sensor_set_i2c_bus_index(uint32_t sensor_type, uint32_t bus_index)
+{
+ hailo_status status = device().sensor_set_i2c_bus_index(static_cast(sensor_type), bus_index);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::sensor_load_and_start_config(uint32_t section_index)
+{
+ auto status = device().sensor_load_and_start_config(section_index);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::sensor_reset(uint32_t section_index)
+{
+ auto status = device().sensor_reset(section_index);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::sensor_set_generic_i2c_slave(uint16_t slave_address,
+ uint8_t register_address_size, uint8_t bus_index, uint8_t should_hold_bus, uint8_t endianness)
+{
+ auto status = device().sensor_set_generic_i2c_slave(slave_address, register_address_size,
+ bus_index, should_hold_bus, endianness);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::firmware_update(py::bytes fw_bin, uint32_t fw_bin_length, bool should_reset)
+{
+ auto status = device().firmware_update(MemoryView::create_const(std::string(fw_bin).c_str(), fw_bin_length),
+ should_reset);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::second_stage_update(py::bytes second_stage_bin, uint32_t second_stage_bin_length)
+{
+ auto status = device().second_stage_update((uint8_t *)std::string(second_stage_bin).c_str(),
+ second_stage_bin_length);
+ VALIDATE_STATUS(status);
+}
+
+py::list DeviceWrapper::configure(const HefWrapper &hef,
+ const NetworkGroupsParamsMap &configure_params)
+{
+ auto network_groups = device().configure(*hef.hef_ptr(), configure_params);
+ VALIDATE_EXPECTED(network_groups);
+
+ py::list results;
+ for (const auto &network_group : network_groups.value()) {
+ results.append(network_group.get());
+ }
+
+ return results;
+}
+
+void DeviceWrapper::set_pause_frames(bool rx_pause_frames_enable)
+{
+ auto status = device().set_pause_frames(rx_pause_frames_enable);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::wd_enable(hailo_cpu_id_t cpu_id)
+{
+ hailo_status status = device().wd_enable(cpu_id);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::wd_disable(hailo_cpu_id_t cpu_id)
+{
+ hailo_status status = device().wd_disable(cpu_id);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::wd_config(hailo_cpu_id_t cpu_id, uint32_t wd_cycles, hailo_watchdog_mode_t wd_mode)
+{
+ auto status = device().wd_config(cpu_id, wd_cycles, wd_mode);
+ VALIDATE_STATUS(status);
+}
+
+uint32_t DeviceWrapper::previous_system_state(hailo_cpu_id_t cpu_id)
+{
+ auto system_state = device().previous_system_state(cpu_id);
+ VALIDATE_EXPECTED(system_state);
+
+ return system_state.release();
+}
+
+hailo_chip_temperature_info_t DeviceWrapper::get_chip_temperature()
+{
+ auto temp_info = device().get_chip_temperature();
+ VALIDATE_EXPECTED(temp_info);
+
+ return temp_info.release();
+}
+
+void DeviceWrapper::set_notification_callback(const std::function &callback,
+ hailo_notification_id_t notification_id, py::object opaque)
+{
+ // we capture opaque and move it because when opaque goes out of score it will be deleted,
+ // so capturing it ensures that it will not be deleted
+ hailo_status status = device().set_notification_callback(
+ [callback, op = std::move(opaque)] (Device &device, const hailo_notification_t ¬ification, void* opaque) {
+ (void)opaque;
+ callback((uintptr_t)(&device), notification, op);
+ }, notification_id, nullptr);
+ VALIDATE_STATUS(status);
+}
+
+void DeviceWrapper::remove_notification_callback(hailo_notification_id_t notification_id)
+{
+ auto status = device().remove_notification_callback(notification_id);
+ VALIDATE_STATUS(status);
+}
+
+py::bytes DeviceWrapper::read_log(size_t byte_count, hailo_cpu_id_t cpu_id)
+{
+ std::string response;
+
+ response.reserve(byte_count);
+ response.resize(byte_count);
+
+ MemoryView response_view ((&response[0]), byte_count);
+ auto response_size_expected = device().read_log(response_view, cpu_id);
+ VALIDATE_EXPECTED(response_size_expected);
+
+ response.resize(response_size_expected.release());
+ return py::bytes(response);
+}
+
+void DeviceWrapper::direct_write_memory(uint32_t address, py::bytes buffer)
+{
+ const auto buffer_str = static_cast(buffer);
+ hailo_status status = device().direct_write_memory(address, buffer_str.c_str(),
+ (uint32_t) (buffer_str.length()));
+ VALIDATE_STATUS(status);
+}
+
+py::bytes DeviceWrapper::direct_read_memory(uint32_t address, uint32_t size)
+{
+ std::string buffer_str;
+
+ buffer_str.reserve(size);
+ buffer_str.resize(size);
+
+ hailo_status status = device().direct_read_memory(address, (char*)buffer_str.c_str(), size);
+ VALIDATE_STATUS(status);
+
+ buffer_str.resize(size);
+ return py::bytes(buffer_str);
+}
+
+void DeviceWrapper::add_to_python_module(py::module &m)
+{
+ py::class_(m, "Device")
+ // C'tors
+ .def("create_pcie", &DeviceWrapper::create_pcie)
+ .def("create_eth", &DeviceWrapper::create_eth)
+ .def("create_core", &DeviceWrapper::create_core)
+ .def("release", &DeviceWrapper::release)
+
+ //HEF
+ .def("configure", &DeviceWrapper::configure)
+
+ // Controls
+ .def("identify", &DeviceWrapper::identify)
+ .def("core_identify", &DeviceWrapper::core_identify)
+ .def("set_fw_logger", &DeviceWrapper::set_fw_logger)
+ .def("read_memory", &DeviceWrapper::read_memory)
+ .def("write_memory", &DeviceWrapper::write_memory)
+ .def("power_measurement", &DeviceWrapper::power_measurement)
+ .def("start_power_measurement", &DeviceWrapper::start_power_measurement)
+ .def("stop_power_measurement", &DeviceWrapper::stop_power_measurement)
+ .def("set_power_measurement", &DeviceWrapper::set_power_measurement)
+ .def("get_power_measurement", &DeviceWrapper::get_power_measurement)
+ .def("firmware_update", &DeviceWrapper::firmware_update)
+ .def("second_stage_update", &DeviceWrapper::second_stage_update)
+ .def("examine_user_config", &DeviceWrapper::examine_user_config)
+ .def("read_user_config", &DeviceWrapper::read_user_config)
+ .def("write_user_config", &DeviceWrapper::write_user_config)
+ .def("erase_user_config", &DeviceWrapper::erase_user_config)
+ .def("read_board_config", &DeviceWrapper::read_board_config)
+ .def("write_board_config", &DeviceWrapper::write_board_config)
+ .def("i2c_write", &DeviceWrapper::i2c_write)
+ .def("i2c_read", &DeviceWrapper::i2c_read)
+ .def("sensor_store_config", &DeviceWrapper::sensor_store_config)
+ .def("store_isp_config", &DeviceWrapper::store_isp_config)
+ .def("sensor_set_i2c_bus_index", &DeviceWrapper::sensor_set_i2c_bus_index)
+ .def("sensor_load_and_start_config", &DeviceWrapper::sensor_load_and_start_config)
+ .def("sensor_reset", &DeviceWrapper::sensor_reset)
+ .def("sensor_set_generic_i2c_slave", &DeviceWrapper::sensor_set_generic_i2c_slave)
+ .def("sensor_get_sections_info", &DeviceWrapper::sensor_get_sections_info)
+ .def("reset", &DeviceWrapper::reset)
+ .def("wd_enable", &DeviceWrapper::wd_enable)
+ .def("wd_disable", &DeviceWrapper::wd_disable)
+ .def("wd_config", &DeviceWrapper::wd_config)
+ .def("previous_system_state", &DeviceWrapper::previous_system_state)
+ .def("get_chip_temperature", &DeviceWrapper::get_chip_temperature)
+ .def("get_extended_device_information", &DeviceWrapper::get_extended_device_information)
+ .def("set_pause_frames", &DeviceWrapper::set_pause_frames)
+ .def("test_chip_memories", &DeviceWrapper::test_chip_memories)
+ .def("_get_health_information", &DeviceWrapper::get_health_information)
+ .def("set_throttling_state", &DeviceWrapper::set_throttling_state)
+ .def("get_throttling_state", &DeviceWrapper::get_throttling_state)
+ .def("_set_overcurrent_state", &DeviceWrapper::set_overcurrent_state)
+ .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("read_log", &DeviceWrapper::read_log, py::return_value_policy::move)
+
+ .def("set_notification_callback", &DeviceWrapper::set_notification_callback)
+ .def("remove_notification_callback", &DeviceWrapper::remove_notification_callback)
+ ;
+}
+
+PowerMeasurementData::PowerMeasurementData(hailo_power_measurement_data_t &&c_power_data)
+{
+ m_average_value = c_power_data.average_value;
+ m_average_time_value_milliseconds = c_power_data.average_time_value_milliseconds;
+ m_min_value = c_power_data.min_value;
+ m_max_value = c_power_data.max_value;
+ m_total_number_of_samples = c_power_data.total_number_of_samples;
+}
+
+/* Return a tuple that fully encodes the state of the object */
+py::tuple PowerMeasurementData::get_state(const PowerMeasurementData &power_measurement_data)
+{
+ return py::make_tuple(
+ power_measurement_data.m_average_value,
+ power_measurement_data.m_average_time_value_milliseconds,
+ power_measurement_data.m_min_value,
+ power_measurement_data.m_max_value,
+ power_measurement_data.m_total_number_of_samples);
+}
+
+PowerMeasurementData PowerMeasurementData::set_state(py::tuple t)
+{
+ if (PowerMeasurementData::NUM_OF_MEMBERS != t.size())
+ throw std::runtime_error("Invalid power measurement data state!");
+
+ /* Create a new C++ instance */
+ hailo_power_measurement_data_t data;
+ data.average_value = t[0].cast();
+ data.average_time_value_milliseconds = t[1].cast();
+ data.min_value = t[2].cast();
+ data.max_value = t[3].cast();
+ data.total_number_of_samples = t[4].cast();
+ return PowerMeasurementData(std::move(data));
+}
+
+bool PowerMeasurementData::equals(const PowerMeasurementData &other)
+{
+ return ((this->m_average_value == other.m_average_value) &&
+ (this->m_average_time_value_milliseconds == other.m_average_time_value_milliseconds) &&
+ (this->m_min_value == other.m_min_value) &&
+ (this->m_max_value == other.m_max_value) &&
+ (this->m_total_number_of_samples == other.m_total_number_of_samples));
+}
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/bindings/python/src/device_api.hpp b/hailort/libhailort/bindings/python/src/device_api.hpp
new file mode 100644
index 0000000..24f85e0
--- /dev/null
+++ b/hailort/libhailort/bindings/python/src/device_api.hpp
@@ -0,0 +1,132 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file device_api.hpp
+ * @brief Defines binding to hailo device
+ *
+ **/
+
+#ifndef _DEVICE_API_HPP_
+#define _DEVICE_API_HPP_
+
+#include "utils.hpp"
+#include "hailo/hailort.hpp"
+#include "common/socket.hpp"
+#include "hef_api.hpp"
+
+#include
+#include
+
+
+namespace hailort
+{
+
+
+class PowerMeasurementData
+{
+public:
+ float32_t m_average_value;
+ float32_t m_average_time_value_milliseconds;
+ float32_t m_min_value;
+ float32_t m_max_value;
+ uint32_t m_total_number_of_samples;
+ PowerMeasurementData(hailo_power_measurement_data_t &&c_power_data);
+ bool equals(const PowerMeasurementData &other);
+ static py::tuple get_state(const PowerMeasurementData &power_measurement_data);
+ static PowerMeasurementData set_state(py::tuple t);
+ const static uint32_t NUM_OF_MEMBERS = 5;
+};
+
+
+class DeviceWrapper final
+{
+public:
+
+ static DeviceWrapper create_pcie(hailo_pcie_device_info_t &device_info);
+ static DeviceWrapper create_eth(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()
+ {
+ VALIDATE_NOT_NULL(m_device);
+ return *(m_device.get());
+ }
+
+ Device& operator*() // Used for control_internals
+ {
+ return device();
+ }
+
+ /* Controls */
+ hailo_device_identity_t identify();
+ hailo_core_information_t core_identify();
+ void set_fw_logger(hailo_fw_logger_level_t level, uint32_t interface_mask);
+ void set_throttling_state(bool should_activate);
+ bool get_throttling_state();
+ void set_overcurrent_state(bool should_activate);
+ bool get_overcurrent_state();
+ py::bytes read_memory(uint32_t address, uint32_t length);
+ void write_memory(uint32_t address, py::bytes data, uint32_t length);
+ void test_chip_memories();
+ void i2c_write(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, py::bytes data,
+ uint32_t length);
+ py::bytes i2c_read(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, uint32_t length);
+ float32_t power_measurement(hailo_dvm_options_t dvm,
+ hailo_power_measurement_types_t measurement_type);
+ void start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period);
+ void set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm,
+ hailo_power_measurement_types_t measurement_type);
+ PowerMeasurementData get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear);
+ void stop_power_measurement();
+ void reset(hailo_reset_device_mode_t mode);
+ hailo_fw_user_config_information_t examine_user_config();
+ py::bytes read_user_config();
+ void write_user_config(py::bytes data);
+ void erase_user_config();
+ py::bytes read_board_config();
+ void write_board_config(py::bytes data);
+ hailo_extended_device_information_t get_extended_device_information();
+ hailo_health_info_t get_health_information();
+ void sensor_store_config(uint32_t section_index, uint32_t reset_data_size, uint32_t sensor_type,
+ const std::string &config_file_path, uint16_t config_height, uint16_t config_width, uint16_t config_fps, const std::string &config_name);
+ void store_isp_config(uint32_t reset_config_size, uint16_t config_height, uint16_t config_width, uint16_t config_fps,
+ const std::string &isp_static_config_file_path, const std::string &isp_runtime_config_file_path, const std::string &config_name);
+ py::bytes sensor_get_sections_info();
+ void sensor_set_i2c_bus_index(uint32_t sensor_type, uint32_t bus_index);
+ void sensor_load_and_start_config(uint32_t section_index);
+ void sensor_reset(uint32_t section_index);
+ void sensor_set_generic_i2c_slave(uint16_t slave_address,
+ uint8_t register_address_size, uint8_t bus_index, uint8_t should_hold_bus, uint8_t endianness);
+ void firmware_update(py::bytes fw_bin, uint32_t fw_bin_length, bool should_reset);
+ void second_stage_update(py::bytes second_stage_bin, uint32_t second_stage_bin_length);
+ py::list configure(const HefWrapper &hef,
+ const NetworkGroupsParamsMap &configure_params={});
+ void set_pause_frames(bool rx_pause_frames_enable);
+ void wd_enable(hailo_cpu_id_t cpu_id);
+ void wd_disable(hailo_cpu_id_t cpu_id);
+ void wd_config(hailo_cpu_id_t cpu_id, uint32_t wd_cycles, hailo_watchdog_mode_t wd_mode);
+ uint32_t previous_system_state(hailo_cpu_id_t cpu_id);
+ hailo_chip_temperature_info_t get_chip_temperature();
+ void set_notification_callback(const std::function &callback,
+ hailo_notification_id_t notification_id, py::object opaque);
+ void remove_notification_callback(hailo_notification_id_t notification_id);
+ 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);
+
+ static void add_to_python_module(py::module &m);
+
+private:
+ DeviceWrapper(std::unique_ptr &&device)
+ : m_device(std::move(device)) {}
+
+ std::unique_ptr m_device;
+};
+
+} /* namespace hailort */
+
+#endif /* _DEVICE_API_HPP_ */
diff --git a/hailort/libhailort/bindings/python/src/hef_api.cpp b/hailort/libhailort/bindings/python/src/hef_api.cpp
new file mode 100644
index 0000000..d31c486
--- /dev/null
+++ b/hailort/libhailort/bindings/python/src/hef_api.cpp
@@ -0,0 +1,318 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file hef_api.cpp
+ * @brief implementation of binding to an HEF class, and network_group usage over Python.
+ *
+ * TODO: doc
+ **/
+
+#include "hef_api.hpp"
+
+
+namespace hailort
+{
+
+HefWrapper::HefWrapper(const std::string &hef_path)
+{
+ auto hef_expected = Hef::create(hef_path);
+ VALIDATE_EXPECTED(hef_expected);
+
+ hef = make_unique_nothrow(hef_expected.release());
+ if (nullptr == hef) {
+ THROW_STATUS_ERROR(HAILO_OUT_OF_HOST_MEMORY);
+ }
+}
+
+HefWrapper::HefWrapper(const MemoryView &hef_buffer)
+{
+ auto hef_expected = Hef::create(hef_buffer);
+ VALIDATE_EXPECTED(hef_expected);
+
+ hef = make_unique_nothrow(hef_expected.release());
+ if (nullptr == hef) {
+ THROW_STATUS_ERROR(HAILO_OUT_OF_HOST_MEMORY);
+ }
+}
+
+HefWrapper HefWrapper::create_from_buffer(py::bytes data)
+{
+ return HefWrapper(MemoryView((uint8_t*)std::string(data).c_str(), std::string(data).size()));
+}
+
+HefWrapper HefWrapper::create_from_file(const std::string &hef_path)
+{
+ return HefWrapper(hef_path);
+}
+
+py::list HefWrapper::get_network_group_names()
+{
+ return py::cast(hef->get_network_groups_names());
+}
+
+py::list HefWrapper::get_network_groups_infos()
+{
+ auto network_group_infos = hef->get_network_groups_infos();
+ VALIDATE_EXPECTED(network_group_infos);
+ return py::cast(network_group_infos.release());
+}
+
+py::list HefWrapper::get_sorted_output_names(std::string net_group_name)
+{
+ auto names_list = hef->get_sorted_output_names(net_group_name);
+ VALIDATE_EXPECTED(names_list);
+
+ return py::cast(names_list.release());
+}
+
+float64_t HefWrapper::get_bottleneck_fps(const std::string &net_group_name)
+{
+ Expected bottleneck_fps = hef->get_bottleneck_fps(net_group_name);
+ VALIDATE_EXPECTED(bottleneck_fps);
+ return bottleneck_fps.release();
+}
+
+py::dict HefWrapper::get_udp_rates_dict(const std::string &net_group_name, uint32_t fps, uint32_t max_supported_rate_bytes)
+{
+ auto rate_calculator = NetworkUdpRateCalculator::create(hef.release(), net_group_name);
+ VALIDATE_EXPECTED(rate_calculator);
+ auto rates_per_name = rate_calculator.value().calculate_inputs_bandwith(fps, max_supported_rate_bytes);
+ VALIDATE_EXPECTED(rates_per_name);
+ return py::cast(rates_per_name.release());
+}
+
+py::list HefWrapper::get_original_names_from_vstream_name(const std::string &vstream_name, const std::string &net_group_name)
+{
+ auto results = hef->get_original_names_from_vstream_name(vstream_name, net_group_name);
+ VALIDATE_EXPECTED(results);
+ return py::cast(results.release());
+}
+
+std::string HefWrapper::get_vstream_name_from_original_name(const std::string &original_name, const std::string &net_group_name)
+{
+ auto results = hef->get_vstream_name_from_original_name(original_name, net_group_name);
+ VALIDATE_EXPECTED(results);
+ return results.release();
+}
+
+py::list HefWrapper::get_stream_names_from_vstream_name(const std::string &vstream_name, const std::string &net_group_name)
+{
+ auto results = hef->get_stream_names_from_vstream_name(vstream_name, net_group_name);
+ VALIDATE_EXPECTED(results);
+ return py::cast(results.release());
+}
+
+py::list HefWrapper::get_vstream_names_from_stream_name(const std::string &stream_name, const std::string &net_group_name)
+{
+ auto results = hef->get_vstream_names_from_stream_name(stream_name, net_group_name);
+ VALIDATE_EXPECTED(results);
+ return py::cast(results.release());
+}
+
+py::dict HefWrapper::get_input_vstreams_params(const std::string &name, bool quantized, hailo_format_type_t format_type,
+ uint32_t timeout_ms, uint32_t queue_size)
+{
+ auto result = hef->make_input_vstream_params(name, quantized, format_type, timeout_ms, queue_size);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::dict HefWrapper::get_output_vstreams_params(const std::string &name, bool quantized, hailo_format_type_t format_type,
+ uint32_t timeout_ms, uint32_t queue_size)
+{
+ auto result = hef->make_output_vstream_params(name, quantized, format_type, timeout_ms, queue_size);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_input_vstream_infos(const std::string &name)
+{
+ auto result = hef->get_input_vstream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_output_vstream_infos(const std::string &name)
+{
+ auto result = hef->get_output_vstream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_all_vstream_infos(const std::string &name)
+{
+ auto result = hef->get_all_vstream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_input_stream_infos(const std::string &name)
+{
+ auto result = hef->get_input_stream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_output_stream_infos(const std::string &name)
+{
+ auto result = hef->get_output_stream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::list HefWrapper::get_all_stream_infos(const std::string &name)
+{
+ auto result = hef->get_all_stream_infos(name);
+ VALIDATE_EXPECTED(result);
+ return py::cast(result.value());
+}
+
+py::dict HefWrapper::create_configure_params(hailo_stream_interface_t interface)
+{
+ auto configure_params = hef->create_configure_params(interface);
+ VALIDATE_EXPECTED(configure_params);
+
+ return py::cast(configure_params.release());
+}
+
+py::dict HefWrapper::create_configure_params_mipi_input(hailo_stream_interface_t output_interface,
+ const hailo_mipi_input_stream_params_t &mipi_params)
+{
+ auto configure_params = hef->create_configure_params_mipi_input(output_interface, mipi_params);
+ VALIDATE_EXPECTED(configure_params);
+
+ return py::cast(configure_params.release());
+}
+
+py::list HefWrapper::get_networks_names(const std::string &net_group_name)
+{
+ auto network_infos = hef->get_network_infos(net_group_name);
+ VALIDATE_EXPECTED(network_infos);
+
+ std::vector res;
+ for (const auto &info : network_infos.value()) {
+ res.push_back(info.name);
+ }
+
+ return py::cast(res);
+}
+
+ActivatedAppContextManagerWrapper::ActivatedAppContextManagerWrapper(ConfiguredNetworkGroup &net_group,
+ const hailo_activate_network_group_params_t &network_group_params) :
+ m_net_group(net_group), m_network_group_params(network_group_params)
+ {}
+
+const ActivatedNetworkGroup& ActivatedAppContextManagerWrapper::enter()
+{
+ auto activated = m_net_group.activate(m_network_group_params);
+ VALIDATE_EXPECTED(activated);
+
+ m_activated_net_group = activated.release();
+
+ return std::ref(*m_activated_net_group);
+}
+
+void ActivatedAppContextManagerWrapper::exit()
+{
+ m_activated_net_group.reset();
+}
+
+void ActivatedAppContextManagerWrapper::add_to_python_module(py::module &m)
+{
+ py::class_(m, "ActivatedApp")
+ .def("__enter__", &ActivatedAppContextManagerWrapper::enter, py::return_value_policy::reference)
+ .def("__exit__", [&](ActivatedAppContextManagerWrapper &self, py::args) { self.exit(); })
+ ;
+}
+
+void HefWrapper::initialize_python_module(py::module &m)
+{
+ py::class_(m, "Hef")
+ .def("create_from_buffer", &HefWrapper::create_from_buffer)
+ .def("create_from_file", &HefWrapper::create_from_file)
+ .def("get_network_group_names", &HefWrapper::get_network_group_names)
+ .def("get_network_groups_infos", &HefWrapper::get_network_groups_infos)
+ .def("get_sorted_output_names", &HefWrapper::get_sorted_output_names)
+ .def("get_bottleneck_fps", &HefWrapper::get_bottleneck_fps)
+ .def("get_stream_names_from_vstream_name", &HefWrapper::get_stream_names_from_vstream_name)
+ .def("get_vstream_names_from_stream_name", &HefWrapper::get_vstream_names_from_stream_name)
+ .def("get_vstream_name_from_original_name", &HefWrapper::get_vstream_name_from_original_name)
+ .def("get_original_names_from_vstream_name", &HefWrapper::get_original_names_from_vstream_name)
+ .def("get_udp_rates_dict", &HefWrapper::get_udp_rates_dict)
+ .def("create_configure_params", &HefWrapper::create_configure_params)
+ .def("create_configure_params_mipi_input", &HefWrapper::create_configure_params_mipi_input)
+ .def("get_input_vstreams_params", &HefWrapper::get_input_vstreams_params)
+ .def("get_output_vstreams_params", &HefWrapper::get_output_vstreams_params)
+ .def("get_input_vstream_infos", &HefWrapper::get_input_vstream_infos)
+ .def("get_output_vstream_infos", &HefWrapper::get_output_vstream_infos)
+ .def("get_all_vstream_infos", &HefWrapper::get_all_vstream_infos)
+ .def("get_input_stream_infos", &HefWrapper::get_input_stream_infos)
+ .def("get_output_stream_infos", &HefWrapper::get_output_stream_infos)
+ .def("get_all_stream_infos", &HefWrapper::get_all_stream_infos)
+ .def("get_networks_names", &HefWrapper::get_networks_names)
+ ;
+
+ py::class_(m, "ConfiguredNetworkGroup")
+ .def("get_name", [](ConfiguredNetworkGroup& self)
+ {
+ return self.get_network_group_name();
+ })
+ .def("get_default_streams_interface", [](ConfiguredNetworkGroup& self)
+ {
+ auto result = self.get_default_streams_interface();
+ VALIDATE_EXPECTED(result);
+ return result.value();
+ })
+ .def("activate", [](ConfiguredNetworkGroup& self,
+ const hailo_activate_network_group_params_t &network_group_params)
+ {
+ return ActivatedAppContextManagerWrapper(self, network_group_params);
+ })
+ .def("wait_for_activation", [](ConfiguredNetworkGroup& self, uint32_t timeout_ms)
+ {
+ auto status = self.wait_for_activation(std::chrono::milliseconds(timeout_ms));
+ VALIDATE_STATUS(status);
+ })
+ .def("InputVStreams", [](ConfiguredNetworkGroup &self, std::map &input_vstreams_params)
+ {
+ return InputVStreamsWrapper::create(self, input_vstreams_params);
+ })
+ .def("OutputVStreams", [](ConfiguredNetworkGroup &self, std::map &output_vstreams_params)
+ {
+ return OutputVStreamsWrapper::create(self, output_vstreams_params);
+ })
+ .def("get_udp_rates_dict", [](ConfiguredNetworkGroup& self, uint32_t fps, uint32_t max_supported_rate_bytes)
+ {
+ auto rate_calculator = NetworkUdpRateCalculator::create(self);
+ VALIDATE_EXPECTED(rate_calculator);
+
+ auto udp_input_streams = self.get_input_streams_by_interface(HAILO_STREAM_INTERFACE_ETH);
+ auto results = rate_calculator->get_udp_ports_rates_dict(udp_input_streams,
+ fps, max_supported_rate_bytes);
+ VALIDATE_EXPECTED(results);
+
+ return py::cast(results.value());
+ })
+ ;
+
+ ActivatedAppContextManagerWrapper::add_to_python_module(m);
+
+ py::class_(m, "ActivatedNetworkGroup")
+ .def("get_intermediate_buffer", [](ActivatedNetworkGroup& self, uint8_t src_context_index,
+ uint8_t src_stream_index)
+ {
+ auto buff = self.get_intermediate_buffer(std::make_pair(src_context_index, src_stream_index));
+ VALIDATE_EXPECTED(buff);
+
+ return py::bytes(reinterpret_cast(buff->data()), buff->size());
+ })
+ .def("get_invalid_frames_count", [](ActivatedNetworkGroup& self)
+ {
+ return self.get_invalid_frames_count();
+ })
+ ;
+}
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/bindings/python/src/hef_api.hpp b/hailort/libhailort/bindings/python/src/hef_api.hpp
index a8f7312..4de0a3c 100644
--- a/hailort/libhailort/bindings/python/src/hef_api.hpp
+++ b/hailort/libhailort/bindings/python/src/hef_api.hpp
@@ -14,8 +14,8 @@
#include "hailo/hef.hpp"
#include "hailo/network_rate_calculator.hpp"
+#include "hailo/network_group.hpp"
-#include "bindings_common.hpp"
#include "vstream_api.hpp"
#include "utils.hpp"
#include "common/logger_macros.hpp"
@@ -34,210 +34,40 @@ namespace hailort
class HefWrapper {
public:
- HefWrapper(const std::string &hef_path)
- {
- auto hef_expected = Hef::create(hef_path);
- VALIDATE_EXPECTED(hef_expected);
-
- hef = make_unique_nothrow(hef_expected.release());
- if (nullptr == hef) {
- THROW_STATUS_ERROR(HAILO_OUT_OF_HOST_MEMORY);
- }
- };
-
- HefWrapper(const MemoryView &hef_buffer)
- {
- auto hef_expected = Hef::create(hef_buffer);
- VALIDATE_EXPECTED(hef_expected);
-
- hef = make_unique_nothrow