v4.8.0
authorHailoRT-Automation <contact@hailo.ai>
Thu, 30 Jun 2022 14:21:15 +0000 (17:21 +0300)
committerHailoRT-Automation <contact@hailo.ai>
Thu, 30 Jun 2022 14:21:15 +0000 (17:21 +0300)
257 files changed:
.hailort.png [new file with mode: 0644]
.logo.svg [deleted file]
CMakeLists.txt
README.md
common/include/context_switch_defs.h
common/include/control_protocol.h
common/include/firmware_status.h
hailort/CMakeLists.txt
hailort/LICENSE-3RD-PARTY.md
hailort/common/circular_buffer.hpp
hailort/common/latency_meter.hpp
hailort/common/os/posix/filesystem.cpp
hailort/common/utils.hpp
hailort/drivers/common/hailo_ioctl_common.h
hailort/drivers/win/include/Public.h [new file with mode: 0644]
hailort/drivers/win/include/hailo_pcie_version.h [new file with mode: 0644]
hailort/hailortcli/CMakeLists.txt
hailort/hailortcli/benchmark_command.cpp
hailort/hailortcli/benchmark_command.hpp
hailort/hailortcli/command.cpp
hailort/hailortcli/command.hpp
hailort/hailortcli/download_action_list_command.cpp
hailort/hailortcli/download_action_list_command.hpp
hailort/hailortcli/example_config.json [new file with mode: 0644]
hailort/hailortcli/fw_control_command.cpp
hailort/hailortcli/fw_control_command.hpp
hailort/hailortcli/hailortcli.cpp
hailort/hailortcli/hailortcli.hpp
hailort/hailortcli/power_measurement_command.cpp
hailort/hailortcli/run_command.cpp
hailort/hailortcli/run_command.hpp
hailort/hailortcli/scan_command.cpp
hailort/libhailort/CMakeLists.txt
hailort/libhailort/bindings/CMakeLists.txt
hailort/libhailort/bindings/gstreamer/CMakeLists.txt
hailort/libhailort/bindings/gstreamer/cmake/FindHailoRT.cmake [deleted file]
hailort/libhailort/bindings/gstreamer/gst-hailo/common.hpp
hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailodevicestats.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailonet.hpp
hailort/libhailort/bindings/gstreamer/gst-hailo/gsthailorecv.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/hailo_buffer_flag_meta.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/metadata/tensor_meta.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.cpp
hailort/libhailort/bindings/gstreamer/gst-hailo/network_group_handle.hpp
hailort/libhailort/bindings/python/CMakeLists.txt
hailort/libhailort/bindings/python/examples/hef_infer_pipeline_vstream.py
hailort/libhailort/bindings/python/platform/hailo_platform/__init__.py
hailort/libhailort/bindings/python/platform/hailo_platform/common/compatibility/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/config.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/paths.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/version.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/inference_targets.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/base_utils.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/common/tools/cmd_utils/hailo_device_utils.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/config_definitions.json [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/__init__.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/control_object.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/ethernet_utils.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/hailo_control_protocol.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/i2c_slaves.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailo_controller/power_measurement.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/pyhailort.py
hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hw_object.py
hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/paths_manager/paths.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/__init__.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/control_object.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/ethernet_utils.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hailo_control_protocol.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hw_object.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/i2c_slaves.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/power_measurement.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/pyhailort.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/benchmark_command.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/__init__.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/configure_firmware.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/example_config.json [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/firmware_config.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/sensor_config.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_firmware.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/update_second_stage.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/fw_control.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/__init__.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/base_utils.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/config_definitions.json [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/example_config.json [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailo_device_utils.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailocli_commands.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/main.py [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/infer_cli.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/run_command.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_platform/tools/udp_rate_limiter.py
hailort/libhailort/bindings/python/platform/hailo_platform/tools/watchdog.py [deleted file]
hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_0_Inference_Tutorial.ipynb [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb [new file with mode: 0644]
hailort/libhailort/bindings/python/platform/requirements.txt
hailort/libhailort/bindings/python/platform/setup.py
hailort/libhailort/bindings/python/platform/tutorials/notebooks/Inference Tutorial.ipynb [deleted file]
hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb [deleted file]
hailort/libhailort/bindings/python/src/CMakeLists.txt
hailort/libhailort/bindings/python/src/bindings_common.hpp
hailort/libhailort/bindings/python/src/device_api.cpp [new file with mode: 0644]
hailort/libhailort/bindings/python/src/device_api.hpp [new file with mode: 0644]
hailort/libhailort/bindings/python/src/hef_api.cpp [new file with mode: 0644]
hailort/libhailort/bindings/python/src/hef_api.hpp
hailort/libhailort/bindings/python/src/internal/CMakeLists.txt
hailort/libhailort/bindings/python/src/internal/control_api.cpp
hailort/libhailort/bindings/python/src/internal/control_api.hpp
hailort/libhailort/bindings/python/src/internal/pyhailort_internal.cpp
hailort/libhailort/bindings/python/src/pyhailort.cpp
hailort/libhailort/bindings/python/src/vdevice_api.hpp
hailort/libhailort/bindings/python/src/vstream_api.cpp [new file with mode: 0644]
hailort/libhailort/bindings/python/src/vstream_api.hpp
hailort/libhailort/cmake/toolchains/qnx.aarch64.cmake
hailort/libhailort/cmake/toolchains/qnx.x86_64.cmake
hailort/libhailort/cmake/toolchains/toolchains.yaml
hailort/libhailort/examples/CMakeLists.txt
hailort/libhailort/examples/README.md
hailort/libhailort/examples/c/CMakeLists.txt
hailort/libhailort/examples/c/common.h
hailort/libhailort/examples/c/data_quantization_example.c
hailort/libhailort/examples/c/hailo_thread.h
hailort/libhailort/examples/c/infer_pipeline_example.c
hailort/libhailort/examples/c/multi_device_example.c
hailort/libhailort/examples/c/power_measurement_example.c [new file with mode: 0644]
hailort/libhailort/examples/c/raw_streams_example.c
hailort/libhailort/examples/c/switch_hefs_example.c [deleted file]
hailort/libhailort/examples/c/switch_network_groups_example.c [new file with mode: 0644]
hailort/libhailort/examples/c/switch_single_io_hefs_example.c [deleted file]
hailort/libhailort/examples/c/switch_single_io_network_groups_manually_example.c [new file with mode: 0644]
hailort/libhailort/examples/c/vstreams_example.c
hailort/libhailort/examples/cmake/FindHailoRT.cmake [deleted file]
hailort/libhailort/examples/cpp/CMakeLists.txt
hailort/libhailort/examples/cpp/infer_pipeline_example.cpp
hailort/libhailort/examples/cpp/multi_device_example.cpp
hailort/libhailort/examples/cpp/multi_network_vstream_example.cpp
hailort/libhailort/examples/cpp/power_measurement_example.cpp [new file with mode: 0644]
hailort/libhailort/examples/cpp/raw_streams_example.cpp
hailort/libhailort/examples/cpp/switch_hefs_example.cpp [deleted file]
hailort/libhailort/examples/cpp/switch_hefs_example_threads_reuse.cpp [deleted file]
hailort/libhailort/examples/cpp/switch_network_groups_example.cpp [new file with mode: 0644]
hailort/libhailort/examples/cpp/switch_network_groups_manually_example.cpp [new file with mode: 0644]
hailort/libhailort/examples/cpp/vstreams_example.cpp
hailort/libhailort/hef.proto
hailort/libhailort/include/hailo/device.hpp
hailort/libhailort/include/hailo/event.hpp
hailort/libhailort/include/hailo/expected.hpp
hailort/libhailort/include/hailo/hailort.h
hailort/libhailort/include/hailo/hailort_common.hpp
hailort/libhailort/include/hailo/network_group.hpp
hailort/libhailort/include/hailo/platform.h
hailort/libhailort/include/hailo/quantization.hpp
hailort/libhailort/include/hailo/stream.hpp
hailort/libhailort/include/hailo/transform.hpp
hailort/libhailort/src/CMakeLists.txt
hailort/libhailort/src/Config.cmake.in [new file with mode: 0644]
hailort/libhailort/src/config_buffer.cpp [new file with mode: 0644]
hailort/libhailort/src/config_buffer.hpp [new file with mode: 0644]
hailort/libhailort/src/context_switch/config_manager.hpp
hailort/libhailort/src/context_switch/hcp_config_activated_network_group.cpp
hailort/libhailort/src/context_switch/hcp_config_manager.cpp
hailort/libhailort/src/context_switch/hcp_config_network_group.cpp
hailort/libhailort/src/context_switch/hef_metadata.cpp
hailort/libhailort/src/context_switch/hef_metadata.hpp
hailort/libhailort/src/context_switch/multi_context/resource_manager.hpp
hailort/libhailort/src/context_switch/multi_context/vdma_config_activated_network_group.hpp
hailort/libhailort/src/context_switch/multi_context/vdma_config_manager.hpp
hailort/libhailort/src/context_switch/multi_context/vdma_config_network_group.hpp
hailort/libhailort/src/context_switch/network_group.cpp
hailort/libhailort/src/context_switch/network_group_internal.hpp
hailort/libhailort/src/context_switch/network_group_wrapper.cpp [new file with mode: 0644]
hailort/libhailort/src/context_switch/network_group_wrapper.hpp [new file with mode: 0644]
hailort/libhailort/src/context_switch/pipeline_multiplexer.cpp [new file with mode: 0644]
hailort/libhailort/src/context_switch/pipeline_multiplexer.hpp [new file with mode: 0644]
hailort/libhailort/src/context_switch/resource_manager.cpp
hailort/libhailort/src/context_switch/single_context/hcp_config_activated_network_group.hpp
hailort/libhailort/src/context_switch/single_context/hcp_config_manager.hpp
hailort/libhailort/src/context_switch/single_context/hcp_config_network_group.hpp
hailort/libhailort/src/context_switch/vdma_config_activated_network_group.cpp
hailort/libhailort/src/context_switch/vdma_config_manager.cpp
hailort/libhailort/src/context_switch/vdma_config_network_group.cpp
hailort/libhailort/src/control.cpp
hailort/libhailort/src/control.hpp
hailort/libhailort/src/control_protocol.cpp
hailort/libhailort/src/control_protocol.hpp
hailort/libhailort/src/core_stream.cpp
hailort/libhailort/src/core_stream.hpp
hailort/libhailort/src/device.cpp
hailort/libhailort/src/device_internal.cpp
hailort/libhailort/src/device_internal.hpp
hailort/libhailort/src/eth_stream.cpp
hailort/libhailort/src/eth_stream.hpp
hailort/libhailort/src/event_internal.hpp
hailort/libhailort/src/hailort.cpp
hailort/libhailort/src/hailort_common.cpp
hailort/libhailort/src/hailort_defaults.hpp
hailort/libhailort/src/hef.cpp
hailort/libhailort/src/hef_internal.hpp
hailort/libhailort/src/inference_pipeline.cpp
hailort/libhailort/src/intermediate_buffer.cpp
hailort/libhailort/src/intermediate_buffer.hpp
hailort/libhailort/src/layer_info.hpp
hailort/libhailort/src/mipi_stream.cpp
hailort/libhailort/src/mipi_stream.hpp
hailort/libhailort/src/network_group_scheduler.cpp [new file with mode: 0644]
hailort/libhailort/src/network_group_scheduler.hpp [new file with mode: 0644]
hailort/libhailort/src/os/CMakeLists.txt
hailort/libhailort/src/os/hailort_driver.hpp
hailort/libhailort/src/os/posix/hailort_driver.cpp
hailort/libhailort/src/os/posix/mmap_buffer.cpp
hailort/libhailort/src/os/posix/pcie_driver_scan.hpp [new file with mode: 0644]
hailort/libhailort/src/os/posix/pcie_driver_sysfs.cpp [deleted file]
hailort/libhailort/src/os/posix/pcie_driver_sysfs.hpp [deleted file]
hailort/libhailort/src/os/posix/qnx/event.cpp
hailort/libhailort/src/os/posix/qnx/pcie_driver_scan.cpp [new file with mode: 0644]
hailort/libhailort/src/os/posix/unix/event.cpp
hailort/libhailort/src/os/posix/unix/pcie_driver_scan.cpp [new file with mode: 0644]
hailort/libhailort/src/os/windows/event.cpp
hailort/libhailort/src/os/windows/hailort_driver.cpp
hailort/libhailort/src/pcie_stream.cpp
hailort/libhailort/src/pcie_stream.hpp
hailort/libhailort/src/pipeline.cpp
hailort/libhailort/src/stream.cpp
hailort/libhailort/src/stream_internal.cpp
hailort/libhailort/src/stream_internal.hpp
hailort/libhailort/src/transform.cpp
hailort/libhailort/src/vdevice.cpp
hailort/libhailort/src/vdevice_internal.hpp
hailort/libhailort/src/vdevice_stream.cpp
hailort/libhailort/src/vdevice_stream.hpp
hailort/libhailort/src/vdma/continuous_buffer.cpp [new file with mode: 0644]
hailort/libhailort/src/vdma/continuous_buffer.hpp [new file with mode: 0644]
hailort/libhailort/src/vdma/mapped_buffer.cpp [new file with mode: 0644]
hailort/libhailort/src/vdma/mapped_buffer.hpp [new file with mode: 0644]
hailort/libhailort/src/vdma/sg_buffer.cpp [new file with mode: 0644]
hailort/libhailort/src/vdma/sg_buffer.hpp [new file with mode: 0644]
hailort/libhailort/src/vdma/vdma_buffer.hpp [new file with mode: 0644]
hailort/libhailort/src/vdma_buffer.cpp [deleted file]
hailort/libhailort/src/vdma_buffer.hpp [deleted file]
hailort/libhailort/src/vdma_channel.cpp
hailort/libhailort/src/vdma_channel.hpp
hailort/libhailort/src/vdma_descriptor_list.cpp
hailort/libhailort/src/vdma_descriptor_list.hpp
hailort/libhailort/src/vdma_stream.cpp
hailort/libhailort/src/vdma_stream.hpp
hailort/libhailort/src/vstream.cpp
hailort/pre_build/CMakeLists.txt
hailort/pre_build/external/CMakeLists.txt
hailort/scripts/download_hefs.cmd
hailort/scripts/download_hefs.sh

diff --git a/.hailort.png b/.hailort.png
new file mode 100644 (file)
index 0000000..fdc8497
Binary files /dev/null and b/.hailort.png differ
diff --git a/.logo.svg b/.logo.svg
deleted file mode 100644 (file)
index 62315a5..0000000
--- a/.logo.svg
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   id="svg4986"
-   version="1.1"
-   inkscape:version="0.91 r13725"
-   xml:space="preserve"
-   width="454.94739"
-   height="132.55138"
-   viewBox="0 0 454.94739 132.55138"
-   sodipodi:docname="Hailo_Logo_RGB.svg"><metadata
-     id="metadata4992"><rdf:RDF><cc:Work
-         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
-     id="defs4990"><clipPath
-       clipPathUnits="userSpaceOnUse"
-       id="clipPath5014"><path
-         d="M 0,110 370,110 370,0 0,0 0,110 Z"
-         id="path5016"
-         inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="2048"
-     inkscape:window-height="1100"
-     id="namedview4988"
-     showgrid="false"
-     inkscape:zoom="2.9109866"
-     inkscape:cx="216.90465"
-     inkscape:cy="59.262279"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="g4994"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0" /><g
-     id="g4994"
-     inkscape:groupmode="layer"
-     inkscape:label="Hailo_Logo_RGB"
-     transform="matrix(1.25,0,0,-1.25,-5.127625,136.24475)"><g
-       id="g4996"
-       transform="translate(172.3149,50.2915)"><path
-         d="M 0,0 -14.161,0 -40.557,47.98 -40.674,48.181 -40.793,47.98 -67.189,0 -81.35,0 l 34.496,58.684 -0.011,0.02 0.023,0 12.334,0 0.023,0 -0.011,-0.02 L 0,0 Z"
-         style="fill:#0098c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         id="path4998"
-         inkscape:connector-curvature="0" /></g><path
-       d="m 186.287,50.291 14.16,0 0,58.704 -14.16,0 0,-58.704 z"
-       style="fill:#0098c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
-       id="path5000"
-       inkscape:connector-curvature="0" /><g
-       id="g5002"
-       transform="translate(4.2656,50.2915)"><path
-         d="m 0,0 14.298,0 0,24.747 44.268,0 0,-24.747 14.161,0 0,58.704 -14.161,0 0,-22.272 -44.268,0 0,22.272 L 0,58.704 0,0 Z"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         id="path5004"
-         inkscape:connector-curvature="0" /></g><g
-       id="g5006"
-       transform="translate(221.0957,50.2915)"><path
-         d="m 0,0 59.941,0 0,10.999 -45.643,0 0,47.705 L 0,58.704 0,0 Z"
-         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-         id="path5008"
-         inkscape:connector-curvature="0" /></g><g
-       id="g5010"><g
-         id="g5012"
-         clip-path="url(#clipPath5014)"><g
-           id="g5018"
-           transform="translate(368.06,64.1768)"><path
-             d="m 0,0 0,30.933 c 0,11.274 -3.712,13.886 -15.123,13.886 l -44.956,0 c -11.411,0 -15.123,-2.612 -15.123,-13.886 l 0,-30.933 c 0,-11.136 3.575,-13.885 15.123,-13.885 l 44.956,0 C -3.712,-13.885 0,-11.136 0,0 m -14.16,-2.612 -46.881,0 0,36.569 46.881,0 0,-36.569 z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5020"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5022"
-           transform="translate(15.4511,10.2974)"><path
-             d="m 0,0 0.106,-1.816 c -1.637,-0.106 -4.272,-0.16 -7.903,-0.16 -1.086,0 -1.945,0.289 -2.577,0.868 -0.632,0.578 -0.957,1.357 -0.975,2.337 l 0,12.068 c 0.018,0.979 0.343,1.758 0.975,2.337 0.632,0.578 1.491,0.867 2.577,0.867 3.631,0 6.266,-0.053 7.903,-0.16 L 0,14.499 l -7.396,0 c -1.069,0 -1.603,-0.587 -1.603,-1.762 l 0,-4.006 7.957,0 0,-1.896 -7.957,0 0,-5.046 C -8.999,0.596 -8.465,0 -7.396,0 L 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5024"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5026"
-           transform="translate(23.7817,21.3521)"><path
-             d="m 0,0 0.134,-2.056 c 1.833,1.584 3.604,2.376 5.313,2.376 1.816,0 2.911,-0.765 3.284,-2.296 1.763,1.531 3.507,2.296 5.234,2.296 1.121,0 1.98,-0.303 2.577,-0.907 0.596,-0.606 0.895,-1.496 0.895,-2.671 l 0,-9.746 -2.244,0 0,9.106 c -0.018,0.8 -0.182,1.383 -0.494,1.748 -0.311,0.365 -0.823,0.547 -1.535,0.547 -0.623,0 -1.224,-0.142 -1.802,-0.426 -0.579,-0.285 -1.402,-0.82 -2.47,-1.603 l 0,-9.372 -2.19,0 0,9.106 c 0,0.818 -0.164,1.405 -0.494,1.762 C 5.879,-1.78 5.367,-1.603 4.673,-1.603 4.05,-1.603 3.449,-1.745 2.871,-2.029 2.292,-2.314 1.469,-2.84 0.401,-3.605 l 0,-9.399 -2.27,0 L -1.869,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5028"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5030"
-           transform="translate(50.1899,17.6938)"><path
-             d="m 0,0 0,-6.889 c 1.815,-0.534 3.204,-0.801 4.166,-0.801 1.174,0 1.993,0.329 2.456,0.988 0.462,0.658 0.694,1.922 0.694,3.791 0,1.816 -0.218,3.089 -0.654,3.819 C 6.226,1.637 5.482,2.002 4.432,2.002 3.755,2.002 3.084,1.847 2.417,1.535 1.749,1.224 0.943,0.711 0,0 m -0.401,3.658 0.187,-2.083 c 0.694,0.748 1.531,1.335 2.51,1.762 0.979,0.428 1.94,0.642 2.884,0.642 1.549,0 2.679,-0.57 3.391,-1.709 0.712,-1.14 1.068,-2.867 1.068,-5.181 0,-2.456 -0.391,-4.196 -1.175,-5.22 -0.783,-1.024 -2.029,-1.535 -3.738,-1.535 -1.709,0 -3.311,0.445 -4.806,1.335 C -0.027,-8.937 0,-9.809 0,-10.948 l 0,-3.765 -2.27,0 0,18.371 1.869,0 z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5032"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5034"
-           transform="translate(74.581,18.7085)"><path
-             d="m 0,0 c -0.543,0.694 -1.526,1.041 -2.95,1.041 -1.425,0 -2.404,-0.347 -2.938,-1.041 -0.534,-0.694 -0.8,-1.985 -0.8,-3.872 0,-1.887 0.266,-3.177 0.8,-3.872 0.534,-0.694 1.513,-1.041 2.938,-1.041 1.424,0 2.407,0.347 2.95,1.041 0.543,0.695 0.814,1.985 0.814,3.872 C 0.814,-1.985 0.543,-0.694 0,0 m -2.95,2.964 c 2.242,0 3.822,-0.517 4.739,-1.549 0.917,-1.033 1.375,-2.795 1.375,-5.287 0,-2.492 -0.458,-4.254 -1.375,-5.287 -0.917,-1.032 -2.497,-1.549 -4.739,-1.549 -2.226,0 -3.801,0.517 -4.727,1.549 -0.926,1.033 -1.388,2.795 -1.388,5.287 0,2.492 0.462,4.254 1.388,5.287 0.926,1.032 2.501,1.549 4.727,1.549"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5036"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5038"
-           transform="translate(103.165,21.3521)"><path
-             d="m 0,0 -3.792,-12.363 c -0.106,-0.428 -0.4,-0.641 -0.881,-0.641 l -2.056,0 c -0.213,0 -0.405,0.067 -0.574,0.2 -0.169,0.134 -0.271,0.307 -0.307,0.521 l -2.136,8.838 c -0.053,0.249 -0.125,0.601 -0.213,1.055 -0.09,0.454 -0.161,0.787 -0.214,1.001 l -0.321,0 -0.454,-2.056 -2.109,-8.838 c -0.125,-0.481 -0.427,-0.721 -0.908,-0.721 l -2.029,0 c -0.481,0 -0.775,0.213 -0.881,0.641 L -20.667,0 l 2.35,0 2.697,-9.586 c 0.16,-0.552 0.302,-1.202 0.427,-1.949 l 0.347,0 0.481,1.949 2.162,8.865 c 0.089,0.48 0.374,0.721 0.855,0.721 l 2.056,0 c 0.445,0 0.729,-0.25 0.854,-0.748 l 2.137,-8.838 c 0.035,-0.196 0.106,-0.512 0.213,-0.948 0.107,-0.436 0.187,-0.77 0.24,-1.001 l 0.348,0 c 0.017,0.089 0.075,0.369 0.173,0.841 0.098,0.471 0.191,0.841 0.281,1.108 L -2.35,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5040"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5042"
-           transform="translate(110.2675,15.5044)"><path
-             d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5044"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5046"
-           transform="translate(133.9511,21.6724)"><path
-             d="m 0,0 -0.267,-2.136 -0.748,0 c -0.658,0 -1.339,-0.13 -2.042,-0.387 -0.704,-0.259 -1.642,-0.681 -2.817,-1.269 l 0,-9.532 -2.27,0 0,13.004 1.763,0 0.24,-2.056 C -4.13,-0.792 -2.279,0 -0.587,0 L 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5048"
-             inkscape:connector-curvature="0" /></g><path
-           d="m 141.801,8.348 -2.243,0 0,13.004 2.243,0 0,-13.004 z m -1.656,18.531 1.069,0 c 0.462,0 0.694,-0.232 0.694,-0.694 l 0,-1.522 c 0,-0.463 -0.232,-0.694 -0.694,-0.694 l -1.069,0 c -0.462,0 -0.694,0.231 -0.694,0.694 l 0,1.522 c 0,0.462 0.232,0.694 0.694,0.694"
-           style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-           id="path5050"
-           inkscape:connector-curvature="0" /><g
-           id="g5052"
-           transform="translate(150.6127,21.3521)"><path
-             d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5054"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5056"
-           transform="translate(169.25,15.6777)"><path
-             d="m 0,0 c 0.516,-0.365 1.415,-0.547 2.697,-0.547 1.282,0 2.18,0.182 2.697,0.547 0.516,0.365 0.774,0.983 0.774,1.856 0,0.872 -0.254,1.491 -0.761,1.855 C 4.899,4.076 3.996,4.259 2.697,4.259 1.415,4.259 0.516,4.076 0,3.711 -0.517,3.347 -0.774,2.728 -0.774,1.856 -0.774,0.983 -0.517,0.365 0,0 M 4.593,-6.715 0.16,-6.101 c -0.908,-0.694 -1.362,-1.523 -1.362,-2.483 0,-0.908 0.267,-1.504 0.801,-1.79 0.534,-0.284 1.611,-0.427 3.231,-0.427 1.585,0 2.648,0.147 3.191,0.441 0.543,0.294 0.814,0.885 0.814,1.776 0,0.64 -0.138,1.077 -0.413,1.308 -0.276,0.231 -0.886,0.418 -1.829,0.561 M 9.666,4.419 7.743,4.259 C 8.099,3.671 8.277,2.871 8.277,1.856 8.277,0.396 7.859,-0.659 7.022,-1.309 6.186,-1.958 4.744,-2.283 2.697,-2.283 1.7,-2.283 0.801,-2.194 0,-2.016 c -0.338,-0.41 -0.437,-0.859 -0.294,-1.348 0.143,-0.49 0.543,-0.788 1.202,-0.895 l 4.86,-0.774 c 1.21,-0.178 2.06,-0.557 2.549,-1.135 0.49,-0.579 0.735,-1.419 0.735,-2.523 0,-1.513 -0.45,-2.564 -1.349,-3.151 -0.899,-0.588 -2.514,-0.881 -4.846,-0.881 -2.35,0 -3.983,0.289 -4.9,0.868 -0.917,0.578 -1.375,1.606 -1.375,3.084 0,0.765 0.16,1.379 0.48,1.842 0.321,0.463 0.864,0.899 1.629,1.308 -0.658,0.517 -0.961,1.202 -0.907,2.057 0.053,0.854 0.391,1.522 1.014,2.002 -1.104,0.587 -1.655,1.718 -1.655,3.391 0,1.495 0.414,2.564 1.241,3.204 0.828,0.641 2.274,0.962 4.34,0.962 1.228,0 2.233,-0.107 3.017,-0.321 l 4.058,0 -0.133,-1.255 z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5058"
-             inkscape:connector-curvature="0" /></g><path
-           d="m 201.456,8.348 -2.35,0 0,18.424 2.35,0 0,-18.424 z"
-           style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-           id="path5060"
-           inkscape:connector-curvature="0" /><g
-           id="g5062"
-           transform="translate(210.4013,21.3521)"><path
-             d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5064"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5066"
-           transform="translate(230.08,19.563)"><path
-             d="M 0,0 0,-7.637 C 0,-8.26 0.133,-8.705 0.4,-8.972 0.667,-9.239 1.122,-9.373 1.762,-9.373 l 1.976,0 0.267,-1.735 c -0.819,-0.231 -1.798,-0.347 -2.937,-0.347 -1.086,0 -1.914,0.302 -2.483,0.908 -0.57,0.605 -0.855,1.477 -0.855,2.616 l 0,7.931 -2.35,0 0,1.655 2.35,0.107 0,3.872 2.27,0 0,-3.845 4.139,0 L 4.139,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5068"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5070"
-           transform="translate(241.455,15.5044)"><path
-             d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5072"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5074"
-           transform="translate(259.0776,27.0391)"><path
-             d="m 0,0 0,-15.113 c -0.018,-0.57 0.125,-1.001 0.427,-1.295 0.303,-0.294 0.748,-0.441 1.336,-0.441 l 1.255,0 0.267,-1.735 c -0.481,-0.231 -1.273,-0.347 -2.377,-0.347 -0.979,0 -1.754,0.289 -2.323,0.868 -0.57,0.578 -0.855,1.392 -0.855,2.443 L -2.27,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5076"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5078"
-           transform="translate(269.7314,27.0391)"><path
-             d="m 0,0 0,-15.113 c -0.018,-0.57 0.125,-1.001 0.427,-1.295 0.303,-0.294 0.748,-0.441 1.336,-0.441 l 1.255,0 0.267,-1.735 c -0.481,-0.231 -1.273,-0.347 -2.377,-0.347 -0.979,0 -1.754,0.289 -2.323,0.868 -0.57,0.578 -0.855,1.392 -0.855,2.443 L -2.27,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5080"
-             inkscape:connector-curvature="0" /></g><path
-           d="m 280.546,8.348 -2.243,0 0,13.004 2.243,0 0,-13.004 z m -1.656,18.531 1.068,0 c 0.463,0 0.694,-0.232 0.694,-0.694 l 0,-1.522 c 0,-0.463 -0.231,-0.694 -0.694,-0.694 l -1.068,0 c -0.463,0 -0.694,0.231 -0.694,0.694 l 0,1.522 c 0,0.462 0.231,0.694 0.694,0.694"
-           style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-           id="path5082"
-           inkscape:connector-curvature="0" /><g
-           id="g5084"
-           transform="translate(289.8642,15.6777)"><path
-             d="m 0,0 c 0.516,-0.365 1.415,-0.547 2.697,-0.547 1.282,0 2.18,0.182 2.697,0.547 0.516,0.365 0.774,0.983 0.774,1.856 0,0.872 -0.254,1.491 -0.761,1.855 C 4.899,4.076 3.996,4.259 2.697,4.259 1.415,4.259 0.516,4.076 0,3.711 -0.517,3.347 -0.774,2.728 -0.774,1.856 -0.774,0.983 -0.517,0.365 0,0 M 4.593,-6.715 0.16,-6.101 c -0.908,-0.694 -1.362,-1.523 -1.362,-2.483 0,-0.908 0.267,-1.504 0.801,-1.79 0.534,-0.284 1.611,-0.427 3.231,-0.427 1.585,0 2.648,0.147 3.191,0.441 0.543,0.294 0.814,0.885 0.814,1.776 0,0.64 -0.138,1.077 -0.413,1.308 -0.276,0.231 -0.886,0.418 -1.829,0.561 M 9.666,4.419 7.743,4.259 C 8.099,3.671 8.277,2.871 8.277,1.856 8.277,0.396 7.859,-0.659 7.022,-1.309 6.186,-1.958 4.744,-2.283 2.697,-2.283 1.7,-2.283 0.801,-2.194 0,-2.016 c -0.338,-0.41 -0.437,-0.859 -0.294,-1.348 0.143,-0.49 0.543,-0.788 1.202,-0.895 l 4.86,-0.774 c 1.21,-0.178 2.06,-0.557 2.549,-1.135 0.49,-0.579 0.735,-1.419 0.735,-2.523 0,-1.513 -0.45,-2.564 -1.349,-3.151 -0.899,-0.588 -2.514,-0.881 -4.846,-0.881 -2.35,0 -3.983,0.289 -4.9,0.868 -0.917,0.578 -1.375,1.606 -1.375,3.084 0,0.765 0.16,1.379 0.48,1.842 0.321,0.463 0.864,0.899 1.629,1.308 -0.658,0.517 -0.961,1.202 -0.907,2.057 0.053,0.854 0.391,1.522 1.014,2.002 -1.104,0.587 -1.655,1.718 -1.655,3.391 0,1.495 0.414,2.564 1.241,3.204 0.828,0.641 2.274,0.962 4.34,0.962 1.228,0 2.233,-0.107 3.017,-0.321 l 4.058,0 -0.133,-1.255 z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5086"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5088"
-           transform="translate(306.7929,15.5044)"><path
-             d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5090"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5092"
-           transform="translate(323.935,21.3521)"><path
-             d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5094"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5096"
-           transform="translate(349.7817,10.2173)"><path
-             d="m 0,0 0.241,-1.522 c -1.282,-0.445 -2.769,-0.667 -4.46,-0.667 -2.242,0 -3.831,0.511 -4.766,1.535 -0.934,1.023 -1.402,2.79 -1.402,5.3 0,2.51 0.468,4.272 1.402,5.287 0.935,1.015 2.532,1.522 4.793,1.522 1.709,0 3.106,-0.205 4.192,-0.614 L -0.293,9.372 c -1.175,0.107 -2.35,0.16 -3.525,0.16 -1.567,0 -2.653,-0.346 -3.258,-1.041 -0.605,-0.694 -0.907,-1.976 -0.907,-3.845 0,-1.887 0.302,-3.177 0.907,-3.872 0.605,-0.694 1.691,-1.041 3.258,-1.041 1.424,0 2.697,0.089 3.818,0.267"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5098"
-             inkscape:connector-curvature="0" /></g><g
-           id="g5100"
-           transform="translate(357.125,15.5044)"><path
-             d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
-             style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
-             id="path5102"
-             inkscape:connector-curvature="0" /></g></g></g></g></svg>
\ No newline at end of file
index 68b135bc31d0d0957d6c6c2ae83c4ebff82a1197..06f115438c56889e341af17cdb9ba78550727d70 100644 (file)
@@ -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("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
-    add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
-    add_link_options("$<$<NOT:$<CONFIG:Debug>>:/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)
index edc09bfa6f7a451757ac7955e6d486b8754e7e21..69fb8cbee5de85302794d229d53a3f7ca73b788e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 <p align="left">
-  <img src=".logo.svg" />
+  <img src=".hailort.png" />
 </p>
 
 
index b993a3be5d121716276c001ef0ce3c62e8c8dfda..ef432a45ab575bcfcd949eae5dc69bb52e769fbb 100644 (file)
@@ -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 = <last_action_executed_in_repeated>;                                |
  * |     |       |     .sub_action_type = CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT;             |
  * |     |       | }                                                                                       |
- * |     |       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
- * |     |       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
- * |     V       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
+ * |     |       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t {                                 |
+ * |     |       |     .packed_lcu_id=<some_lcu_id>;                                                       |
+ * |     |       |     .network_index=<some_network_index>                                                 |
+ * |     |       |  }                                                                                      |
+ * |     |       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t {                                 |
+ * |     |       |     .packed_lcu_id=<some_lcu_id>;                                                       |
+ * |     |       |     .network_index=<some_network_index>                                                 |
+ * |     |       |  }                                                                                      |
+ * |     |       | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t {                                 |
+ * |     |       |     .packed_lcu_id=<some_lcu_id>;                                                       |
+ * |     |       |     .network_index=<some_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 {
index 627ee041681389b7bf5f072c979b1fd6444a3520..a5d9e36b756b1427e106ab381a79fcbc914423ca 100644 (file)
@@ -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 = <some_cluster_index>;                                           |
  * |     |       |   .lcu_index = <some_lcu_index>;                                                   |
+ * |     |       |   .network_index = <some_network_index>;                                           |
  * |     |       | }                                                                                  |
  * |     |       | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t {                                    |
  * |     |       |   .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true };  |
  * |     |       |   .cluster_index = <some_cluster_index>;                                           |
  * |     |       |   .lcu_index = <some_lcu_index>;                                                   |
+ * |     |       |   .network_index = <some_network_index>;                                           |
  * |     |       | }                                                                                  |
  * |     |       | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t {                                    |
  * |     |       |   .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true };  |
  * |     |       |   .cluster_index = <some_cluster_index>;                                           |
  * |     |       |   .lcu_index = <some_lcu_index>;                                                   |
+ * |     |       |   .network_index = <some_network_index>;                                           |
  * |     V       | }                                                                                  |
  * |    ...      | (Next action control)                                                              |
  * |--------------------------------------------------------------------------------------------------|
@@ -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;
index 391213e86c81bf17875191113abea92a3db777e0..88350aa021c46d7cc79c1455ad1614b092445b45 100644 (file)
@@ -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,
index c189d11a5632d92a1a45f647595523aef23d27a3..63edd6806cfcb9c553ba642d507115656fda2099 100644 (file)
@@ -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)
-add_subdirectory(common)
-add_subdirectory(libhailort)
-add_subdirectory(hailortcli)
+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()
 
-# 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
-        $<TARGET_FILE:_pyhailort>
-    )
-    set(VENV_PYHAILORT_INTERNAL_DIR ${CMAKE_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/)
-    set(PYHAILORT_INTERNAL_FILES_TO_COPY
-        $<TARGET_FILE:_pyhailort_internal>
+# 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
     )
-    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}
+    target_compile_definitions(microprofile
+        PRIVATE
+        -DMICROPROFILE_WEBSERVER=1
+        -DMICROPROFILE_GPU_TIMERS=0
+        -DMICROPROFILE_NAME_MAX_LEN=256
+        PUBLIC
+        -DMICROPROFILE_ENABLED=1
     )
-    add_dependencies(pyhailort_venv libhailort _pyhailort)
+    target_include_directories(microprofile PUBLIC external/microprofile)
+else()
+    add_library(microprofile INTERFACE)
+    target_compile_definitions(microprofile INTERFACE -DMICROPROFILE_ENABLED=0)
+    target_include_directories(microprofile INTERFACE external/microprofile)
 endif()
 
+add_subdirectory(common)
+add_subdirectory(libhailort)
+add_subdirectory(hailortcli)
+
 if(HAILO_WIN_DRIVER)
     add_subdirectory(drivers/win)
     add_subdirectory(packaging)
index c7e45769138bcaa7e7867dcee16438f62bcab3a1..9c86db74b38eccba8cbef0dc9074e7d23386d43d 100644 (file)
@@ -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                                       |
index c50b971d5e2945aa7dd8495b2bae21b3534c6699..8df5461e2d5330d07a61a0af441ed136a7926a2b 100644 (file)
@@ -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<T> m_array;
index c839a0fc2dd59b19d7ad526524529faf5cd4fa7b..eaed098c2ede9f143331d14488c976974aad0d2d 100644 (file)
@@ -125,6 +125,7 @@ private:
 };
 
 using LatencyMeterPtr = std::shared_ptr<LatencyMeter>;
+using LatencyMetersMap = std::map<std::string, LatencyMeterPtr>;
 
 } /* namespace hailort */
 
index 00fce95e9dc3d691d2d44369b4245d0752e386db..fd96ce220844021516720183cbfcd0bb7ebf403b 100644 (file)
@@ -52,7 +52,7 @@ dirent* Filesystem::DirWalker::next_file()
     return readdir(m_dir);
 }
 
-#if defined(__unix__)
+#if defined(__linux__)
 
 Expected<std::vector<std::string>> Filesystem::get_files_in_dir_flat(const std::string &dir_path)
 {
index f4f74d7d71e28c88b8c080acc16a4475b91bf713..a93c6aa667b085614d0622440e9066ee1375e328 100644 (file)
@@ -52,6 +52,24 @@ static inline bool contains(const std::set<T> &container, T value)
     return (container.find(value) != container.end());
 }
 
+template <class T>
+class unlock_guard {
+public:
+    unlock_guard(T &lock) : m_lock(lock) {
+        m_lock.unlock();
+    }
+
+    ~unlock_guard() {
+        m_lock.lock();
+    }
+
+    unlock_guard(const unlock_guard&) = delete;
+    unlock_guard& operator=(const unlock_guard&) = delete;
+
+private:
+    T &m_lock;
+};
+
 // From https://stackoverflow.com/questions/57092289/do-stdmake-shared-and-stdmake-unique-have-a-nothrow-version
 template <class T, class... Args>
 static inline std::unique_ptr<T> make_unique_nothrow(Args&&... args)
@@ -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<class K, class V>
+static uint32_t get_max_value_of_unordered_map(const std::unordered_map<K, V> &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
index 1177130c59b4b1a2854c3cd8f08fe039d4b67a19..64603a10e604bbbcccb6907f1a8a1a3eac49c83e 100644 (file)
 #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 <linux/types.h>
 #include <linux/limits.h>
 #include <linux/kernel.h>
-#endif
+#endif // ifndef __KERNEL__
 
-#if defined(__unix__)
 #include <linux/ioctl.h>
-#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 <devctl.h>
+#include <stdint.h>
+#include <sys/types.h>
+// 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 (file)
index 0000000..96b442a
--- /dev/null
@@ -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 (file)
index 0000000..2dfaa33
--- /dev/null
@@ -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_ */
index 4fb14ec9be2c86c00d5d927cfc39a0978abeaad4..ba3dc6ac0188ff552374b66e0b627955868ed55d 100644 (file)
@@ -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
index 7b17de57af0dddb0511c34eaa34f537d0166947c..f7260f7cb331e0c0ae9ed948ea725a4763ad8742 100644 (file)
@@ -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<hailo_power_mode_t>({
+            { "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<NetworkGroupInferResult> 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<NetworkGroupInferResult> 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<NetworkGroupInferResult> 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
index bffd4016aeba78d25469ff1a6886d6f64f37a526..38178e08eb7b4f51a86749bbce78406ea4354252 100644 (file)
@@ -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;
 };
 
index 59ad8750fbb586ba2ef0896858f31aaa83064dde..49b1e048c38ceb5f58fcdd616737b3a217e70af7 100644 (file)
@@ -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)
-{
-    auto group = app->add_option_group("PCIE Device Options");
-
-    // PCIe options
-    group->add_option("-s,--bdf", m_pcie_device_params.pcie_bdf,
-        "Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command)")
-        ->default_val("");
-}
-
-hailo_status PcieDeviceCommand::execute()
+hailo_status DeviceCommand::execute_on_all_pcie_devices()
 {
-    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;
 }
index e92e999176d35c331777a932c0b1a8fd7f6be1ad..9ad9f9c6582b1910cc79e02308d740290d484947 100644 (file)
@@ -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
index 38323380c516fd15bb0e450558df396f0723fd91..6cb49ced95b158acd92b0850b6da6be95fe6ab2d 100644 (file)
@@ -13,6 +13,7 @@
 #include "md5.h"
 
 #include <iostream>
+#include <iomanip>
 
 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<std::string> 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<int>(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<int>(md5_sum[i]);
     }
 
     return hexdigest.str();
@@ -180,9 +187,9 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
             data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t *>(action);
             action_length_local = sizeof(CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t);
             break;
-        case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS:
-            data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__read_vdma_action_data_t *>(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<CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t *>(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<CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t *>(action);
@@ -200,6 +207,10 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
             data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t *>(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<CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t *>(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<CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t *>(action);
             action_length_local = sizeof(CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t);
@@ -248,6 +259,10 @@ Expected<ordered_json> 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<CONTEXT_SWITCH_DEFS__activate_cfg_channel_t *>(action);
             action_length_local = sizeof(CONTEXT_SWITCH_DEFS__activate_cfg_channel_t);
@@ -391,7 +406,7 @@ Expected<ordered_json> 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}};
 }
 
index bbbc330220e3ea22d2aab972d274f41bcd5ec89f..e669982230f08a9419e91955fc9aa3b41bfc650d 100644 (file)
@@ -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/hailortcli/example_config.json b/hailort/hailortcli/example_config.json
new file mode 100644 (file)
index 0000000..f1a08bf
--- /dev/null
@@ -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
+    }
+}
index 3be6e9a8eeed8afbea6c7ab3260c83ea8ce5ca21..5124600078977945912a393dbf3c1219ce861555 100644 (file)
@@ -230,19 +230,9 @@ FwControlCommand::FwControlCommand(CLI::App &parent_app) :
 {\r
     add_subcommand<FwControlIdentifyCommand>();\r
     add_subcommand<FwControlResetCommand>();\r
-\r
-    // TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)\r
-    //       Can also remove Command::set_description function after this, and the return value of `add_subcommand`\r
-    auto &scan = add_subcommand<ScanSubcommand>();\r
-    scan.set_description("Alias for root-level 'scan' command (i.e. 'hailortcli scan...')\n"\r
-        "Note: 'scan' as a sub-command of 'fw-control' is deprecated; use 'hailortcli scan' instead\n"\r
-        "       (or 'hailo scan' when using the 'hailo' command).");\r
-\r
     add_subcommand<FwControlTestMemoriesCommand>();\r
     // TODO: Support on windows (HRT-5919)\r
     #if defined(__GNUC__)\r
-    // TODO: Unhide (HRT-6035)\r
-    static const bool HIDDEN = true;\r
-    add_subcommand<DownloadActionListCommand>(HIDDEN);\r
+    add_subcommand<DownloadActionListCommand>();\r
     #endif\r
 }\r
index 7ffbcd410fb9b05b757d0b811b8e80c3fefe6516..d475bd3d18cde457fa18b2434a6cfae2f501c19e 100644 (file)
@@ -12,8 +12,6 @@
 \r
 #include "hailortcli.hpp"\r
 #include "command.hpp"\r
-// TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)\r
-#include "scan_command.hpp"\r
 #if defined(__GNUC__)\r
 // TODO: Support on windows (HRT-5919)\r
 #include "download_action_list_command.hpp"\r
index ceabba7df9ad082ecdbacb657688d62c53ed616a..54932227c5c96dcc337da0eaa6716be6be7af1d9 100644 (file)
@@ -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<DeviceType> 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<DeprecationActionPtr> actions{ std::make_shared<ValueDeprecation>(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 ([<domain>]:<bus>:<device>.<func>, same as in lspci command)")
+        "Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command).\n" \
+        "In order to run on all PCIe devices connected to the machine one-by-one, use '*' (instead of device id).")
         ->default_val("");
 
     // Ethernet options
@@ -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<spdlog::sinks::stderr_color_sink_mt>();
     console_sink->set_level(spdlog::level::info);
     console_sink->set_pattern("[%n] [%^%l%$] %v");
index 8edf17a10142316c7d3193426780f76470c8a7be..5c61bf67bf94b487a64b026e29d3c952c6f8c9d9 100644 (file)
@@ -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 {
index 493e475641a717a2090daaa5fb5c67a8d1150bee..72c4793c748fa9ce187a57229567d1dbbc26934f 100644 (file)
@@ -10,9 +10,6 @@
 #include "power_measurement_command.hpp"
 #include <thread>
 
-#define POWER_MEASUREMENT_DELAY_MS(__sample_period, __average_factor) \
-    (static_cast<uint32_t>((__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<LongPowerMeasurement> PowerMeasurementSubcommand::start_power_measureme
         return make_unexpected(status);
     }
 
-    status = hailo_set_power_measurement(reinterpret_cast<hailo_device>(&device), 0, dvm, measurement_type);
+    status = hailo_set_power_measurement(reinterpret_cast<hailo_device>(&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<hailo_device>(&device), measurement_delay,
+    status = hailo_start_power_measurement(reinterpret_cast<hailo_device>(&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<hailo_device>(&m_device), 0, true, &m_data);
+    status = hailo_get_power_measurement(reinterpret_cast<hailo_device>(&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;
index fc73096fb5aa5cf63734cb9d4f159564af8bf371..f623b17dc0ec79b9d6043545dcc71500443a1192 100644 (file)
@@ -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([&params]() {
+    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([&params]() {
         // 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([&params, hef_new, hef_old, power_sampling_period,
+    run_subcommand->parse_complete_callback([&params, 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<DeprecationActionPtr> actions{
-        std::make_shared<OptionDeprecation>(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<std::string, std::string> format_strings_to_key_value_pairs(const std::vector<std::string> &key_value_pairs_str) {
@@ -1030,18 +1034,34 @@ Expected<NetworkGroupInferResult> 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;
 }
 
index 7cfcae6620b14b4c90a9277e2561222776bae9c0..85f45d9208e10bbcbdb662f0e043431f5e75e2ac 100644 (file)
@@ -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 {
index 073d3ae6bf9660854415244b4be9bfae647a2240..2d9e4e252265158e96d5daa4f4487c82470524f9 100644 (file)
@@ -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> 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<DeprecationActionPtr> actions{
-        std::make_shared<ValueDeprecation>(device_type_option, "udp", "eth"),
-        std::make_shared<OptionDeprecation>(ip_option, "--interface-ip")
-    };
-    hailo_deprecate_options(m_app, actions, false);
 }
 
 hailo_status ScanSubcommand::execute()
index 393ad62b940b5ee57ae301f8f9eea406d13027fe..aff9879b9a205287bef8ebda484f67ed6dbed798 100644 (file)
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
 # set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
 
 set(HAILORT_MAJOR_VERSION    4)
-set(HAILORT_MINOR_VERSION    6)
+set(HAILORT_MINOR_VERSION    8)
 set(HAILORT_REVISION_VERSION 0)
 
 # Add the cmake folder so the modules there are found
index 3388d7f0d4140c7e3d43f186e5b1bf4437bd7772..c8037279eb020bcc691af04262a932d7d7682282 100644 (file)
@@ -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)
index 7094c839f5c30d0d6f76a03192f5c8ef120f3edf..c9fe743b66e503e2a654fc9b7e96bbb2fbcb20de 100644 (file)
@@ -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 (file)
index 85906ac..0000000
+++ /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()
index 1ee88a3eafc0f0fb0836dedbeb1e92fc6b3266b2..8e8759ef73663f6c808dc756b5c344dd24107dca 100644 (file)
@@ -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)) {                  \
index 1049a16416a4cbba892579ff164daf8260101a04..f4a2f31fcc85df655ceba2c59ffcbefb851971bc 100644 (file)
@@ -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<uint32_t>(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) {
index cd1fa982b5dbedb70893be61e42913ec17052659..b39e4e2ddd109ec112e0f9b0b351144944048e9f 100644 (file)
 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<uint32_t>::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<uint32_t>::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<hailo_scheduling_algorithm_t>(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();
index 810e37db9a83c918f874e843467bb56b3a7c392b..7ff211d773b55889077c127485f87cc2019c8ba5 100644 (file)
@@ -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<gchar*> m_device_id;
@@ -62,6 +63,9 @@ public:
     HailoElemProperty<gboolean> m_is_active;
     HailoElemProperty<guint16> m_device_count;
     HailoElemProperty<guint32> m_vdevice_key;
+    HailoElemProperty<hailo_scheduling_algorithm_t> m_scheduling_algorithm;
+    HailoElemProperty<guint32> m_scheduler_timeout_ms;
+    HailoElemProperty<guint32> 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<std::string> 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;
index 34496e985c7787307d6098583c8c223233b6261c..9c6835c55cb19a60ffe2f2fabbd916447e591c18 100644 (file)
@@ -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;
index a500f17468f513b1e7748aa818dd6300c6df21b9..e436de892fb52fe089a39a485ef2438a3383e7de 100644 (file)
@@ -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)) {
index 060ad6d228d72cf5d46ecc077bc06a44fdc5d647..302a96d87c7164028ed5bb0dca69b59db8952737 100644 (file)
@@ -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)) {
index eec733b61a0e5872da047f62f9cbc9071387a4e4..3453ebe5cca0db82606a4211607675dde7dc5dc0 100644 (file)
@@ -26,14 +26,16 @@ VDeviceManager NetworkGroupHandle::m_vdevice_manager;
 NetworkGroupConfigManager NetworkGroupHandle::m_net_group_config_manager;
 NetworkGroupActivationManager NetworkGroupHandle::m_net_group_activation_manager;
 
-Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key)
+Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
+    hailo_scheduling_algorithm_t scheduling_algorithm)
 {
-    auto expected_device = m_vdevice_manager.create_vdevice(m_element, device_id, device_count, vdevice_key);
+    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::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> NetworkGroupHandle::create_vstreams(const char *network_name,
     const std::vector<hailo_format_with_name_t> &output_formats)
 {
     GST_CHECK(nullptr != network_name, make_unexpected(HAILO_INVALID_ARGUMENT), m_element, RESOURCE, "Got nullptr in network name!");
 
     m_network_name = network_name;
-    hailo_status status = m_net_group_config_manager.add_network(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<bool> NetworkGroupHandle::remove_network_group()
 
 
 Expected<std::shared_ptr<VDevice>> 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<std::mutex> 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<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id)
+Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id,
+    hailo_scheduling_algorithm_t scheduling_algorithm)
 {
     // If passing device_id, than device_count must be 1
     const auto device_count = 1;
 
     // If vdevice already exist, use it
-    auto found_vdevice = get_vdevice(device_id);
-    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<std::shared_ptr<VDevice>> 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> vdevice_ptr = std::move(vdevice.release());
 
     m_shared_vdevices[device_id] = vdevice_ptr;
+    m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
     return vdevice_ptr;
 }
 
-Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key)
+Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
+    hailo_scheduling_algorithm_t scheduling_algorithm)
 {
     auto device_id = std::to_string(device_count) + "-" + std::to_string(vdevice_key);
 
     // If vdevice already exist, use it
-    auto found_vdevice = get_vdevice(device_id);
-    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> vdevice_ptr = std::move(vdevice.release());
 
     m_shared_vdevices[device_id] = vdevice_ptr;
+    m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
     return vdevice_ptr;
 }
 
-Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count)
+Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count,
+    hailo_scheduling_algorithm_t scheduling_algorithm)
 {
     hailo_vdevice_params_t params = {};
     params.device_count = device_count;
     params.device_infos = nullptr;
+    params.scheduling_algorithm = scheduling_algorithm;
     auto vdevice = VDevice::create(params);
     GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
 
@@ -270,12 +293,23 @@ Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const v
     return vdevice_ptr;
 }
 
-Expected<std::shared_ptr<VDevice>> VDeviceManager::get_vdevice(const std::string &device_id)
+Expected<std::shared_ptr<VDevice>> VDeviceManager::get_vdevice(const std::string &device_id,
+    hailo_scheduling_algorithm_t scheduling_algorithm)
 {
     auto found = m_shared_vdevices.find(device_id);
     if (found == m_shared_vdevices.end()) {
         return make_unexpected(HAILO_NOT_FOUND);
     }
+
+    // shared_vdevice is found, verify the requested scheduling_algorithm
+    assert(m_shared_vdevices_scheduling_algorithm.end() != m_shared_vdevices_scheduling_algorithm.find(device_id));
+    if (scheduling_algorithm != m_shared_vdevices_scheduling_algorithm[device_id]) {
+        auto status = HAILO_INVALID_OPERATION;
+        g_warning("Shared vdevice with the same credentials is already exists (%s) but with a different scheduling-algorithm (requested: %d, exists: %d), status = %d",
+            device_id.c_str(), scheduling_algorithm, m_shared_vdevices_scheduling_algorithm[device_id], status);
+        return make_unexpected(HAILO_INVALID_OPERATION);
+    }
+
     auto vdevice_cpy = found->second;
     return vdevice_cpy;
 }
@@ -300,15 +334,24 @@ Expected<std::shared_ptr<ConfiguredNetworkGroup>> 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<std::mutex> 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;
+    }
+
+    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[network_name] = GST_ELEMENT_NAME(owner_element);
+    m_configured_networks[shared_device_id][network_name] = GST_ELEMENT_NAME(owner_element);
     return HAILO_SUCCESS;
 }
 
index b83dd24e0bd24973c4d0e7f15112af8f45e4c85b..f402678abb957187d1afd2e539947862de6c05e4 100644 (file)
 class VDeviceManager final
 {
 public:
-    VDeviceManager() : m_shared_vdevices(), m_unique_vdevices() {}
+    VDeviceManager() : m_shared_vdevices(), m_shared_vdevices_scheduling_algorithm(), m_unique_vdevices() {}
 
-    Expected<std::shared_ptr<VDevice>> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
+    Expected<std::shared_ptr<VDevice>> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
+        hailo_scheduling_algorithm_t scheduling_algorithm);
 
 private:
-    Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id);
-    Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key);
-    Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count);
-    Expected<std::shared_ptr<VDevice>> get_vdevice(const std::string &device_id);
+    Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id,
+        hailo_scheduling_algorithm_t scheduling_algorithm);
+    Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
+        hailo_scheduling_algorithm_t scheduling_algorithm);
+    Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count,
+        hailo_scheduling_algorithm_t scheduling_algorithm);
+    Expected<std::shared_ptr<VDevice>> get_vdevice(const std::string &device_id, hailo_scheduling_algorithm_t scheduling_algorithm);
 
     /* Contains only the shared vdevices (either created by bdf, or with device-count && vdevice-key)
        Keys are either "<BDF>" or "<device_count>-<vdevice_key>" */
     std::unordered_map<std::string, std::shared_ptr<VDevice>> m_shared_vdevices;
+    std::unordered_map<std::string, hailo_scheduling_algorithm_t> m_shared_vdevices_scheduling_algorithm; // Used to check that 2 shared vdevices gets the same scheduling-algorithm
     std::vector<std::shared_ptr<VDevice>> m_unique_vdevices;
     std::mutex m_mutex;
 };
 
+using device_id_t = std::string;
 using network_name_t = std::string;
 using hailonet_name_t = std::string;
 
@@ -58,7 +64,8 @@ public:
     Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(const void *element, const std::string &device_id,
         const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
         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<std::string, std::shared_ptr<ConfiguredNetworkGroup>> m_configured_net_groups;
-    std::unordered_map<network_name_t, hailonet_name_t> m_configured_networks;
+    std::unordered_map<device_id_t, std::unordered_map<network_name_t, hailonet_name_t>> 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::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> create_vstreams(const char *network_name,
         const std::vector<hailo_format_with_name_t> &output_formats);
@@ -104,6 +112,10 @@ public:
     hailo_status abort_streams();
     Expected<bool> 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> hef()
     {
         return m_hef;
@@ -111,13 +123,14 @@ public:
 
 private:
     Expected<NetworkGroupsParamsMap> get_configure_params(Hef &hef, const char *net_group_name, uint16_t batch_size);
-    Expected<std::shared_ptr<VDevice>> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
+    Expected<std::shared_ptr<VDevice>> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
+        hailo_scheduling_algorithm_t scheduling_algorithm);
 
     static VDeviceManager m_vdevice_manager;
     static 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;
index febd4f0ab6f826fc669a9047b2c86fd7dc8c351d..d38c6e821a70f6e3bcaceb82b7e3b1f3b2b77c21 100644 (file)
@@ -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 $<TARGET_FILE:_pyhailort> ${CMAKE_CURRENT_LIST_DIR}/platform/hailo_platform/pyhailort/
+    )
+    add_dependencies(pyhailort_venv _pyhailort)
+endif()
\ No newline at end of file
index b01c038e90f0d40f337cf10ca9bf574ae8b14fae..c1896df94e7cd003480419b18ba1da9b3c0f01c1 100644 (file)
@@ -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
index 1c6ca2e1deb9f5bd5eac8a8a18d2765d2a5bba80..610f8781f2dea18677044ee5ac18c9c9518192da 100644 (file)
@@ -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 (file)
index 3dd945d..0000000
+++ /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/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/paths_manager/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
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 (file)
index 5e1d7fc..0000000
+++ /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 (file)
index 3dada52..0000000
+++ /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 (file)
index 04d40ee..0000000
+++ /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/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/common/targets/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
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 (file)
index 80335b4..0000000
+++ /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 <hailo_sdk_common.targets.inference_targets.InferenceTargets>`.
-        """
-        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 (file)
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 (file)
index e69de29..0000000
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/common/tools/cmd_utils/base_utils.py
deleted file mode 100644 (file)
index 911ae3d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-from builtins import object
-import subprocess
-
-from hailo_platform.common.logger.logger import default_logger
-
-
-class CmdUtilsBaseUtilError(Exception):
-    pass
-
-
-class HailortCliUtilError(CmdUtilsBaseUtilError):
-    pass
-
-
-# Note: CmdUtilsBaseUtil and CmdUtilsBaseUtilError are external dependencies in phase2-sdk/demos repo; don't change!
-class CmdUtilsBaseUtil(object):
-    def __init__(self, args_parser):
-        pass
-
-
-class Helper(CmdUtilsBaseUtil):
-    def __init__(self, commands):
-        self._commands = commands
-
-    def __call__(self, parser):
-        parser.set_defaults(func=self.run)
-
-    def run(self, args):
-        for command_name, (help_, _) in self._commands.items():
-            print("{} - {}".format(command_name, help_))
-
-
-class HailortCliUtil(CmdUtilsBaseUtil):
-    def __init__(self, args_parser, command):
-        self._command = command
-        self._logger = default_logger()
-
-    @classmethod
-    def _run_hailortcli(cls, binary_path, command, command_args):
-        cmd_args = [binary_path, command] + command_args
-
-        process = subprocess.Popen(cmd_args)
-        try:
-            _ = process.communicate()
-            return process.returncode
-        except KeyboardInterrupt:
-            process.terminate()
-            raise HailortCliUtilError('hailo has been interrupted by the user')
-
-    def run(self, argv):
-        hailortcli_cmd = 'hailortcli'
-        self._logger.info('(hailo) Running command \'{}\' with \'hailortcli\''.format(self._command))
-        return self._run_hailortcli(hailortcli_cmd, self._command, argv)
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/common/tools/cmd_utils/hailo_device_utils.py
deleted file mode 100644 (file)
index fd33bb1..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/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.common.logger.logger import default_logger
-from hailo_platform.drivers.hailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
-
-logger = default_logger()
-
-class HailoCLITargets(Enum):
-    udp = 'udp'
-    pcie = 'pcie'
-
-
-class HailoDeviceCmdUtil(CmdUtilsBaseUtil):
-    """
-    Base class for any cmd utility that use a specific hailo device
-    """
-    def __init__(self, args_parser, set_target_args=True):
-        super().__init__(args_parser)
-        self._parser = args_parser
-        if set_target_args:
-            self.add_target_args(args_parser)
-
-    def get_target(self, args):
-        self.validate_args(args)
-        target_type = self.get_target_type(args)
-        if target_type == HailoCLITargets.udp.value:
-            return EthernetDevice(args.ip)
-        else:
-            try:
-                return PcieDevice(device_info=args.board_location)
-            except Exception as e:
-                logger.error('Internal PCIe error (No PCIe device connected?)')
-                logger.error('Error code: {}'.format(e))
-                raise
-
-    def get_target_type(self, args):
-        if args.target is not None:
-            return args.target
-
-        if args.ip is not None:
-            # If IP is given, we assume that the target is udp
-            return HailoCLITargets.udp.value
-
-        # Otherwise the default target is pcie
-        return HailoCLITargets.pcie.value
-
-
-    def validate_args(self, args):
-        if args.target == HailoCLITargets.udp.value:
-            if not args.ip:
-                self._parser.error('When using --target udp, you must supply --ip')
-            if args.board_location:
-                self._parser.error("When using --target udp, you must not supply --board-location")
-
-        if args.board_location:
-            all_devices = InternalPcieDevice.scan_devices()
-            if args.board_location not in all_devices:
-                self._parser.error('Device {} does not appear on your host, please run `hailo scan -d pcie` to see all available devices'
-                    .format(args.board_location))
-
-    def add_target_args(self, args_parser):
-        args_parser.add_argument('--target', type=str, choices=[t.value for t in HailoCLITargets],
-                                 default=None, help='Device type to use')
-        args_parser.add_argument('--ip', type=str, default=None, help='IP address of the target (udp)')
-        args_parser.add_argument('-s', '--board-location', help=PcieDeviceInfo.BOARD_LOCATION_HELP_STRING,
-                                 type=PcieDeviceInfo.argument_type)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/config_definitions.json b/hailort/libhailort/bindings/python/platform/hailo_platform/config_definitions.json
deleted file mode 100644 (file)
index f1efdca..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-{
-    "_comment": 
-        [
-        "This file defines the available fields of the firmwares config. It is not used to serialize any data.",
-        "WARNING! DO NOT CHANGE THE ORDER OF THE DEFINITIONS AS IT WILL CHANGE THEIR GENERATED VALUES!"
-        ],
-    "version": 0,
-    "categories": 
-    {
-        "network": 
-        {
-            "entries":
-            {
-                "should_use_dhcp": {"size": 1, "deserialize_as": "bool"},
-                "mac_address": {"size": 1, "length": 6, "deserialize_as": "mac_address"},
-                "static_ip_address": {"size": 4, "deserialize_as": "ipv4"},
-                "static_gw_address": {"size": 4, "deserialize_as": "ipv4"},
-                "static_netmask": {"size": 4, "deserialize_as": "ipv4"},
-                "rx_pause_frames_enable": {"size": 1, "deserialize_as": "bool"}
-            }
-        },
-        "system":
-        {
-            "entries":
-            {
-                "name": {"size": 1, "length": 32, "deserialize_as": "str"},
-                "app_watchdog_enable": {"size": 1, "deserialize_as": "bool"},
-                "app_watchdog_cycles": {"size": 4, "deserialize_as": "int"},
-                "core_watchdog_enable": {"size": 1, "deserialize_as": "bool"},
-                "core_watchdog_cycles": {"size": 4, "deserialize_as": "int"},
-                "watchdog_mode" : {"size": 1, "deserialize_as": "watchdog_mode"},
-                "max_neural_network_core_clock_rate": {"size": 4, "deserialize_as": "clock_frequency"},
-                "supported_aspm_states": {"size": 1, "deserialize_as": "supported_aspm_states"},
-                "bus_0_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
-                "bus_1_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
-                "bus_2_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
-                "bus_3_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
-                "supported_aspm_l1_substates": {"size": 1, "deserialize_as": "supported_aspm_l1_substates"},
-                "overcurrent_parameters_source": {"size": 1, "deserialize_as": "overcurrent_parameters_source"},
-                "overcurrent_monitoring_red_threshold": {"size": 4, "deserialize_as": "int"},
-                "overcurrent_conversion_time_microseconds": {"size": 4, "deserialize_as": "conversion_time"},
-                "temperature_parameters_source": {"size": 1, "deserialize_as": "temperature_parameters_source"},
-                "temperature_red_threshold": {"size": 1, "deserialize_as": "int"},
-                "temperature_red_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
-                "temperature_orange_threshold": {"size": 1, "deserialize_as": "int"},
-                "temperature_orange_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
-                "temperature_throttling_enable": {"size": 1, "deserialize_as": "bool"},
-                "overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"}
-            }
-        },
-        "control":
-        {
-            "entries":
-            {
-                "udp_port": {"size": 2, "deserialize_as": "int"}
-            }
-        },
-        "d2h_event":
-        {
-            "entries":
-            {
-                "host_udp_port": {"size": 2, "deserialize_as": "int"},
-                "src_udp_port": {"size": 2, "deserialize_as": "int"},
-                "host_ip_address": {"size": 4, "deserialize_as": "ipv4"},
-                "connection_type": {"size": 1, "deserialize_as": "bool"}
-            }
-        },
-        "logger":
-        {
-            "entries":
-            {
-                "send_via_pci": {"size": 1, "deserialize_as": "bool"},
-                "send_via_uart": {"size": 1, "deserialize_as": "bool"},
-                "logger_level": {"size": 4, "deserialize_as": "logger_level"}
-            }
-        }
-    }
-}
-
index 22a799fbf0a458d5f6cbfaabb9956eadb550568d..e7a12fb42742db9a01576acbc0d5bc69915984b2 100644 (file)
@@ -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
index 0e7d4f31d6611c01866abebda8ee9519e603dda1..ddf2de4b29ca81114b64aa21f7fbb33127e512e7 100644 (file)
@@ -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
index 0b0bb84e1c7a447d30f86fbac977991743f89480..785a6422c7f64878050d50ad06a9c4e47b193b8b 100644 (file)
@@ -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
index bdfc8cf454719d06df1ea4802a7d17e7a736aa9e..af38579779354e6a0088a408bb51830decbc57de 100644 (file)
@@ -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 <Not Configured> if the string field is empty
-        return string_field.rstrip('\x00') or "<Not Configured>"
-
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return 'Control Protocol Version: {}\n' \
-               'Firmware Version: {}\n' \
-               'Logger Version: {}\n' \
-               'Board Name: {}\n' \
-               'Device Architecture: {}\n' \
-               'Serial Number: {}\n' \
-               'Part Number: {}\n' \
-               'Product Name: {}\n'.format(
-            self.protocol_version,
-            self.firmware_version,
-            self.logger_version,
-            self.board_name.rstrip('\x00'),
-            str(self.device_architecture),
-            self._string_field_str(self.serial_number),
-            self._string_field_str(self.part_number),
-            self._string_field_str(self.product_name))
-       
-    def __repr__(self):
-        """Returns:
-            str: Human readable string.
-        """ 
-        return self.__str__()
-
-    @staticmethod
-    def get_hw_arch_str(device_arch):
-        if device_arch == DeviceArchitectureTypes.HAILO8_B0:
-            return 'hailo8'
-        elif device_arch == DeviceArchitectureTypes.MERCURY_CA:
-            return 'mercury'
-        else:
-            raise HailoControlProtocolException("Unsupported device architecture.")
-
-class CoreInformation(object):
-    def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release):
-        self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.CORE)
-        self.is_release = is_release
-    
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return 'Core Firmware Version: {}'.format(
-            self.firmware_version)
-
-    def __repr__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return self.__str__()
-
-class TemperatureThrottlingLevel(object):
-    def __init__(self, level_number, temperature_threshold, hysteresis_temperature_threshold, throttling_nn_clock_freq):
-        self.level_number = level_number
-        self.temperature_threshold = temperature_threshold
-        self.hysteresis_temperature_threshold = hysteresis_temperature_threshold
-        self.throttling_nn_clock_freq = throttling_nn_clock_freq
-
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return 'Temperature Throttling Level {}: \n' \
-               'Temperature Threshold: {}\n' \
-               'Hysteresis Temperature Threshold: {}\n' \
-               'Throttling NN Clock Frequency: {}\n' \
-               .format(self.level_number, self.temperature_threshold, self.hysteresis_temperature_threshold, self.throttling_nn_clock_freq)
-        
-    def __repr__(self):
-        return self.__str__()
-
-class HealthInformation(object):
-    def __init__(self, overcurrent_protection_active, current_overcurrent_zone, red_overcurrent_threshold, orange_overcurrent_threshold, 
-                       temperature_throttling_active, current_temperature_zone, current_temperature_throttling_level,
-                       temperature_throttling_levels, orange_temperature_threshold, orange_hysteresis_temperature_threshold, 
-                       red_temperature_threshold, red_hysteresis_temperature_threshold):
-        self.overcurrent_protection_active = overcurrent_protection_active
-        self.current_overcurrent_zone = current_overcurrent_zone
-        self.red_overcurrent_threshold = red_overcurrent_threshold
-        self.orange_overcurrent_threshold = orange_overcurrent_threshold
-        self.temperature_throttling_active = temperature_throttling_active
-        self.current_temperature_zone = current_temperature_zone
-        self.current_temperature_throttling_level = current_temperature_throttling_level
-        self.orange_temperature_threshold = orange_temperature_threshold
-        self.orange_hysteresis_temperature_threshold = orange_hysteresis_temperature_threshold
-        self.red_temperature_threshold = red_temperature_threshold
-        self.red_hysteresis_temperature_threshold = red_hysteresis_temperature_threshold
-        
-        # Add TemperatureThrottlingLevel in case it has new throttling_nn_clock_freq. level_number can be used as only last
-        # levels can be with the same freq
-        self.temperature_throttling_levels = []
-        if self.temperature_throttling_active:
-            throttling_nn_clock_frequencies = []
-            for level_number, temperature_throttling_level in enumerate(temperature_throttling_levels):
-                if temperature_throttling_level.throttling_nn_clock_freq not in throttling_nn_clock_frequencies:
-                    throttling_nn_clock_frequencies.append(temperature_throttling_level.throttling_nn_clock_freq)
-                    self.temperature_throttling_levels.append(TemperatureThrottlingLevel(level_number,
-                                                                                        temperature_throttling_level.temperature_threshold, 
-                                                                                        temperature_throttling_level.hysteresis_temperature_threshold, 
-                                                                                        temperature_throttling_level.throttling_nn_clock_freq))
-    def __repr__(self):
-        return self.__str__()
-
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        temperature_throttling_levels_str = "\n".join(["\n\n{}\n".format(str(temperature_throttling_level)) for temperature_throttling_level in self.temperature_throttling_levels]) \
-                                            if self.temperature_throttling_active else "<Temperature throttling is disabled>"
-        return 'Overcurrent Protection Active: {}\n' \
-               'Overcurrent Protection Current Overcurrent Zone: {}\n' \
-               'Overcurrent Protection Red Threshold: {}\n' \
-               'Overcurrent Protection Orange Threshold: {}\n' \
-               'Temperature Protection Red Threshold: {}\n' \
-               'Temperature Protection Red Hysteresis Threshold: {}\n' \
-               'Temperature Protection Orange Threshold: {}\n' \
-               'Temperature Protection Orange Hysteresis Threshold: {}\n' \
-               'Temperature Protection Throttling State: {}\n' \
-               'Temperature Protection Current Zone: {}\n' \
-               'Temperature Protection Current Throttling Level: {}\n' \
-               'Temperature Protection Throttling Levels: {}' \
-               .format(self.overcurrent_protection_active, self.current_overcurrent_zone, self.red_overcurrent_threshold, 
-                       self.orange_overcurrent_threshold, self.red_temperature_threshold, 
-                       self.red_hysteresis_temperature_threshold, self.orange_temperature_threshold, 
-                       self.orange_hysteresis_temperature_threshold, self.temperature_throttling_active,
-                       self.current_temperature_zone, self.current_temperature_throttling_level, temperature_throttling_levels_str)
-
-class ExtendedDeviceInformation(object):
-    def __init__(self, neural_network_core_clock_rate, supported_features, boot_source, lcs, soc_id, eth_mac_address, unit_level_tracking_id, soc_pm_values):
-        self.neural_network_core_clock_rate = neural_network_core_clock_rate
-        self.supported_features = SupportedFeatures(supported_features)
-        self.boot_source = boot_source
-        self.lcs = lcs
-        self.soc_id = soc_id
-        self.eth_mac_address = eth_mac_address
-        self.unit_level_tracking_id = unit_level_tracking_id
-        self.soc_pm_values = soc_pm_values
-
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        string = 'Neural Network Core Clock Rate: {}MHz\n' \
-                 '{}' \
-                 'Boot source: {}\n' \
-                 'LCS: {}\n'.format(
-            self.neural_network_core_clock_rate / MEGA_MULTIPLIER,
-            str(self.supported_features),
-            str(self.boot_source.name),
-            str(self.lcs))
-        if any(self.soc_id):
-            string += 'SoC ID: ' + (self.soc_id.hex())
-
-        if any(self.eth_mac_address):
-            string += '\nMAC Address: ' + (":".join("{:02X}".format(i) for i in self.eth_mac_address))
-        
-        if any(self.unit_level_tracking_id):
-            string += '\nULT ID: ' + (self.unit_level_tracking_id.hex())
-        
-        if any(self.soc_pm_values):
-            string += '\nPM Values: ' + (self.soc_pm_values.hex())
-
-
-        return string
-
-    def __repr__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return self.__str__()
-
-class HailoFirmwareMode(Enum):
-    """Indication that firmware version is stable and official  """
-    DEVELOP = 'develop'
-    RELEASE = 'release'
-
-
-class HailoFirmwareType(Enum):
-    """Indication the firmware type """
-    CORE = 'core'
-    APP = 'app'
-
-
-class 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 = '<III'
-
-    def __init__(self, firmware_version_buffer, is_release, fw_type):
-        """Initialize a new Hailo Firmware Version object.
-
-        Args:
-            firmware_version_buffer (str): A buffer containing the firmware version struct.
-            is_release (bool, optional): Flag indicating if firmware is at develop/release mode.
-                                        None indicates unknown
-        """
-        self.major, self.minor, self.revision = struct.unpack(
-            self.FW_VERSION_FORMAT,
-            firmware_version_buffer)
-        
-        self.fw_type = fw_type
-        self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
-        
-        self.revision &= ~(self.CORE_BIT | self.DEV_BIT)
-
-    def __str__(self):
-        """Returns:
-            str: Firmware version in a human readable format.
-        """
-        return '{}.{}.{} ({},{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value)
-
-    @classmethod
-    def construct_from_params(cls, major, minor, revision, is_release, fw_type):
-        """Returns:
-            class HailoFirmwareVersion : with the given Firmware version.
-        """
-        return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release, fw_type)
-
-    @property
-    def comparable_value(self):
-        """A value that could be compared to other firmware versions."""
-        return (self.major << 64) + (self.minor << 32) + (self.revision)
-
-    def __hash__(self):
-        return self.comparable_value
-
-    def __eq__(self, other):
-        return self.comparable_value == other.comparable_value
-
-    # TODO: Required for Python2 BW compatibility (SDK-10038)
-    # This impl' comes by default in Python3
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __lt__(self, other):
-        return self.comparable_value < other.comparable_value
-
-    def check_protocol_compatibility(self, other):
-        return ((self.major == other.major) and (self.minor == other.minor))
-
-class SupportedFeatures(object):
-    def __init__(self, supported_features):
-        self.ethernet = supported_features.ethernet
-        self.mipi = supported_features.mipi
-        self.pcie = supported_features.pcie
-        self.current_monitoring = supported_features.current_monitoring
-        self.mdio = supported_features.mdio
-    
-    def _feature_str(self, feature_name, is_feature_enabled):
-        return '{}: {}\n'.format(feature_name, 'Enabled' if is_feature_enabled else 'Disabled')
-
-    def __str__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return 'Device supported features: \n' + \
-            self._feature_str('Ethernet', self.ethernet) + \
-            self._feature_str('MIPI', self.mipi) + \
-            self._feature_str('PCIE', self.pcie) + \
-            self._feature_str('Current Monitoring', self.current_monitoring) + \
-            self._feature_str('MDIO', self.mdio)
-
-    def __repr__(self):
-        """Returns:
-            str: Human readable string.
-        """
-        return self.__str__()
-
-    def _is_feature_enabled(self, feature):
-        return (self.supported_features & feature) != 0
+from hailo_platform.pyhailort.hailo_control_protocol import * # noqa F401
\ No newline at end of file
index b76cd5c8f3fcc952f22ed23ff54ff6fa1ad6fab5..f4dd7292c827af6a0191bb892dac2521e7c808b1 100644 (file)
@@ -1,191 +1,2 @@
 #!/usr/bin/env python
-from builtins import object
-import struct
-
-from hailo_platform.common.logger.logger import default_logger
-from hailo_platform.drivers.hailort.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.drivers.hailort.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.drivers.hailort.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.drivers.hailort.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.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
index b9da00203b539b5a60692de292a101bb555615e0..1732ad7efa2dcd2656bd385a5baa4e7e88cfe48b 100644 (file)
@@ -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
index ca2461ed4b56629f3d44e8afd35852cba1443753..a29dd9578872c7e83bf84719894b399407aa22c5 100644 (file)
@@ -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" ([<domain>]:<bus>:<device>.<func>). 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 [<domain>]:<bus>:<device>.<func>"""
-        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 [<domain>]:<bus>:<device>.<func>')
-
-
-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
index c285cafd9f7ad2592755f449a7da1f4de1c70ced..c70c01919d59430c07ed58df49c32921cc59846f 100644 (file)
@@ -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 <hailo_platform.drivers.control_object.HailoControl>`: Returns
-        the control object of this device, which implements the control API of the Hailo device.
-
-        .. attention:: Use the low level control API with care.
-        """
-        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 (file)
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 (file)
index 6855145..0000000
+++ /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/pyhailort/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
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 (file)
index 0000000..f4b3e20
--- /dev/null
@@ -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 (file)
index 0000000..0b0bb84
--- /dev/null
@@ -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 (file)
index 0000000..2754cc8
--- /dev/null
@@ -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 <Not Configured> if the string field is empty
+        return string_field.rstrip('\x00') or "<Not Configured>"
+
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return 'Control Protocol Version: {}\n' \
+               'Firmware Version: {}\n' \
+               'Logger Version: {}\n' \
+               'Board Name: {}\n' \
+               'Device Architecture: {}\n' \
+               'Serial Number: {}\n' \
+               'Part Number: {}\n' \
+               'Product Name: {}\n'.format(
+            self.protocol_version,
+            self.firmware_version,
+            self.logger_version,
+            self.board_name.rstrip('\x00'),
+            str(self.device_architecture),
+            self._string_field_str(self.serial_number),
+            self._string_field_str(self.part_number),
+            self._string_field_str(self.product_name))
+       
+    def __repr__(self):
+        """Returns:
+            str: Human readable string.
+        """ 
+        return self.__str__()
+
+    @staticmethod
+    def get_hw_arch_str(device_arch):
+        if device_arch == DeviceArchitectureTypes.HAILO8_B0:
+            return 'hailo8'
+        elif device_arch == DeviceArchitectureTypes.MERCURY_CA:
+            return 'mercury'
+        else:
+            raise HailoControlProtocolException("Unsupported device architecture.")
+
+class CoreInformation(object):
+    def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release):
+        self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.CORE)
+        self.is_release = is_release
+    
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return 'Core Firmware Version: {}'.format(
+            self.firmware_version)
+
+    def __repr__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return self.__str__()
+
+class TemperatureThrottlingLevel(object):
+    def __init__(self, level_number, temperature_threshold, hysteresis_temperature_threshold, throttling_nn_clock_freq):
+        self.level_number = level_number
+        self.temperature_threshold = temperature_threshold
+        self.hysteresis_temperature_threshold = hysteresis_temperature_threshold
+        self.throttling_nn_clock_freq = throttling_nn_clock_freq
+
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return 'Temperature Throttling Level {}: \n' \
+               'Temperature Threshold: {}\n' \
+               'Hysteresis Temperature Threshold: {}\n' \
+               'Throttling NN Clock Frequency: {}\n' \
+               .format(self.level_number, self.temperature_threshold, self.hysteresis_temperature_threshold, self.throttling_nn_clock_freq)
+        
+    def __repr__(self):
+        return self.__str__()
+
+class HealthInformation(object):
+    def __init__(self, overcurrent_protection_active, current_overcurrent_zone, red_overcurrent_threshold, orange_overcurrent_threshold, 
+                       temperature_throttling_active, current_temperature_zone, current_temperature_throttling_level,
+                       temperature_throttling_levels, orange_temperature_threshold, orange_hysteresis_temperature_threshold, 
+                       red_temperature_threshold, red_hysteresis_temperature_threshold):
+        self.overcurrent_protection_active = overcurrent_protection_active
+        self.current_overcurrent_zone = current_overcurrent_zone
+        self.red_overcurrent_threshold = red_overcurrent_threshold
+        self.orange_overcurrent_threshold = orange_overcurrent_threshold
+        self.temperature_throttling_active = temperature_throttling_active
+        self.current_temperature_zone = current_temperature_zone
+        self.current_temperature_throttling_level = current_temperature_throttling_level
+        self.orange_temperature_threshold = orange_temperature_threshold
+        self.orange_hysteresis_temperature_threshold = orange_hysteresis_temperature_threshold
+        self.red_temperature_threshold = red_temperature_threshold
+        self.red_hysteresis_temperature_threshold = red_hysteresis_temperature_threshold
+        
+        # Add TemperatureThrottlingLevel in case it has new throttling_nn_clock_freq. level_number can be used as only last
+        # levels can be with the same freq
+        self.temperature_throttling_levels = []
+        if self.temperature_throttling_active:
+            throttling_nn_clock_frequencies = []
+            for level_number, temperature_throttling_level in enumerate(temperature_throttling_levels):
+                if temperature_throttling_level.throttling_nn_clock_freq not in throttling_nn_clock_frequencies:
+                    throttling_nn_clock_frequencies.append(temperature_throttling_level.throttling_nn_clock_freq)
+                    self.temperature_throttling_levels.append(TemperatureThrottlingLevel(level_number,
+                                                                                        temperature_throttling_level.temperature_threshold, 
+                                                                                        temperature_throttling_level.hysteresis_temperature_threshold, 
+                                                                                        temperature_throttling_level.throttling_nn_clock_freq))
+    def __repr__(self):
+        return self.__str__()
+
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        temperature_throttling_levels_str = "\n".join(["\n\n{}\n".format(str(temperature_throttling_level)) for temperature_throttling_level in self.temperature_throttling_levels]) \
+                                            if self.temperature_throttling_active else "<Temperature throttling is disabled>"
+        return 'Overcurrent Protection Active: {}\n' \
+               'Overcurrent Protection Current Overcurrent Zone: {}\n' \
+               'Overcurrent Protection Red Threshold: {}\n' \
+               'Overcurrent Protection Orange Threshold: {}\n' \
+               'Temperature Protection Red Threshold: {}\n' \
+               'Temperature Protection Red Hysteresis Threshold: {}\n' \
+               'Temperature Protection Orange Threshold: {}\n' \
+               'Temperature Protection Orange Hysteresis Threshold: {}\n' \
+               'Temperature Protection Throttling State: {}\n' \
+               'Temperature Protection Current Zone: {}\n' \
+               'Temperature Protection Current Throttling Level: {}\n' \
+               'Temperature Protection Throttling Levels: {}' \
+               .format(self.overcurrent_protection_active, self.current_overcurrent_zone, self.red_overcurrent_threshold, 
+                       self.orange_overcurrent_threshold, self.red_temperature_threshold, 
+                       self.red_hysteresis_temperature_threshold, self.orange_temperature_threshold, 
+                       self.orange_hysteresis_temperature_threshold, self.temperature_throttling_active,
+                       self.current_temperature_zone, self.current_temperature_throttling_level, temperature_throttling_levels_str)
+
+class ExtendedDeviceInformation(object):
+    def __init__(self, neural_network_core_clock_rate, supported_features, boot_source, lcs, soc_id, eth_mac_address, unit_level_tracking_id, soc_pm_values):
+        self.neural_network_core_clock_rate = neural_network_core_clock_rate
+        self.supported_features = SupportedFeatures(supported_features)
+        self.boot_source = boot_source
+        self.lcs = lcs
+        self.soc_id = soc_id
+        self.eth_mac_address = eth_mac_address
+        self.unit_level_tracking_id = unit_level_tracking_id
+        self.soc_pm_values = soc_pm_values
+
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        string = 'Neural Network Core Clock Rate: {}MHz\n' \
+                 '{}' \
+                 'Boot source: {}\n' \
+                 'LCS: {}\n'.format(
+            self.neural_network_core_clock_rate / MEGA_MULTIPLIER,
+            str(self.supported_features),
+            str(self.boot_source.name),
+            str(self.lcs))
+        if any(self.soc_id):
+            string += 'SoC ID: ' + (self.soc_id.hex())
+
+        if any(self.eth_mac_address):
+            string += '\nMAC Address: ' + (":".join("{:02X}".format(i) for i in self.eth_mac_address))
+        
+        if any(self.unit_level_tracking_id):
+            string += '\nULT ID: ' + (self.unit_level_tracking_id.hex())
+        
+        if any(self.soc_pm_values):
+            string += '\nPM Values: ' + (self.soc_pm_values.hex())
+
+
+        return string
+
+    def __repr__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return self.__str__()
+
+class HailoFirmwareMode(Enum):
+    """Indication that firmware version is stable and official  """
+    DEVELOP = 'develop'
+    RELEASE = 'release'
+
+
+class HailoFirmwareType(Enum):
+    """Indication the firmware type """
+    CORE = 'core'
+    APP = 'app'
+
+
+class HailoFirmwareVersion(object):
+    """Represents a Hailo chip firmware version."""
+    DEV_BIT  = 0x80000000
+    CORE_BIT = 0x08000000
+    FW_VERSION_FORMAT = '<III'
+
+    def __init__(self, firmware_version_buffer, is_release, fw_type):
+        """Initialize a new Hailo Firmware Version object.
+
+        Args:
+            firmware_version_buffer (str): A buffer containing the firmware version struct.
+            is_release (bool, optional): Flag indicating if firmware is at develop/release mode.
+                                        None indicates unknown
+        """
+        self.major, self.minor, self.revision = struct.unpack(
+            self.FW_VERSION_FORMAT,
+            firmware_version_buffer)
+        
+        self.fw_type = fw_type
+        self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
+        
+        self.revision &= ~(self.CORE_BIT | self.DEV_BIT)
+
+    def __str__(self):
+        """Returns:
+            str: Firmware version in a human readable format.
+        """
+        return '{}.{}.{} ({},{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value)
+
+    @classmethod
+    def construct_from_params(cls, major, minor, revision, is_release, fw_type):
+        """Returns:
+            class HailoFirmwareVersion : with the given Firmware version.
+        """
+        return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release, fw_type)
+
+    @property
+    def comparable_value(self):
+        """A value that could be compared to other firmware versions."""
+        return (self.major << 64) + (self.minor << 32) + (self.revision)
+
+    def __hash__(self):
+        return self.comparable_value
+
+    def __eq__(self, other):
+        return self.comparable_value == other.comparable_value
+
+    # TODO: Required for Python2 BW compatibility (SDK-10038)
+    # This impl' comes by default in Python3
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __lt__(self, other):
+        return self.comparable_value < other.comparable_value
+
+    def check_protocol_compatibility(self, other):
+        return ((self.major == other.major) and (self.minor == other.minor))
+
+class SupportedFeatures(object):
+    def __init__(self, supported_features):
+        self.ethernet = supported_features.ethernet
+        self.mipi = supported_features.mipi
+        self.pcie = supported_features.pcie
+        self.current_monitoring = supported_features.current_monitoring
+        self.mdio = supported_features.mdio
+    
+    def _feature_str(self, feature_name, is_feature_enabled):
+        return '{}: {}\n'.format(feature_name, 'Enabled' if is_feature_enabled else 'Disabled')
+
+    def __str__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return 'Device supported features: \n' + \
+            self._feature_str('Ethernet', self.ethernet) + \
+            self._feature_str('MIPI', self.mipi) + \
+            self._feature_str('PCIE', self.pcie) + \
+            self._feature_str('Current Monitoring', self.current_monitoring) + \
+            self._feature_str('MDIO', self.mdio)
+
+    def __repr__(self):
+        """Returns:
+            str: Human readable string.
+        """
+        return self.__str__()
+
+    def _is_feature_enabled(self, feature):
+        return (self.supported_features & feature) != 0
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hw_object.py b/hailort/libhailort/bindings/python/platform/hailo_platform/pyhailort/hw_object.py
new file mode 100644 (file)
index 0000000..cd2cc86
--- /dev/null
@@ -0,0 +1,478 @@
+#!/usr/bin/env python
+
+"""Hailo hardware API"""
+from __future__ import division
+
+import gc
+import os
+
+from contextlib import contextmanager
+
+from hailo_platform.pyhailort.control_object import UdpHcpControl, PcieHcpControl
+from hailo_platform.common.logger.logger import default_logger
+from hailo_platform.pyhailort.hailo_control_protocol import BoardInformation
+
+from hailo_platform.pyhailort.pyhailort import ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice, HailoRTTransformUtils, HailoUdpScan, HailoRTException
+
+
+class InferenceTargets(object):
+    """Enum-like class with all inference targets supported by the HailoRT."""
+    UNINITIALIZED = 'uninitialized'
+    UDP_CONTROLLER = 'udp'
+    PCIE_CONTROLLER = 'pcie'
+
+class HailoHWObjectException(Exception):
+    """Raised in any error related to Hailo hardware."""
+    pass
+
+
+class HailoHWObject(object):
+    """Abstract Hailo hardware device representation."""
+
+    NAME = InferenceTargets.UNINITIALIZED
+    IS_HARDWARE = True
+
+    def __init__(self):
+        """Create the Hailo hardware object."""
+        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
+
+    # TODO: HRT-6310 Remove this.
+    def __eq__(self, other):
+        return type(self).NAME == other
+
+    @property
+    def name(self):
+        """str: The name of this target. Valid values are defined by :class:`~hailo_platform.pyhailort.hw_object.InferenceTargets`"""
+        return type(self).NAME
+
+    @property
+    def is_hardware(self):
+        """bool: Indicates this target runs on a physical hardware device."""
+        return type(self).IS_HARDWARE
+
+    @property
+    def device_id(self):
+        """Getter for the device_id.
+
+        Returns:
+            str: A string ID of the device. BDF for PCIe devices, IP address for Ethernet devices, "Core" for core devices.
+        """
+        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"""
+
+    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 <hailo_platform.pyhailort.control_object.HailoControl>`: Returns
+        the control object of this device, which implements the control API of the Hailo device.
+
+        .. attention:: Use the low level control API with care.
+        """
+        if self._control_object is None:
+            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 (file)
index 0000000..b70dde8
--- /dev/null
@@ -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 (file)
index 0000000..b0612af
--- /dev/null
@@ -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 (file)
index 0000000..8351041
--- /dev/null
@@ -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" ([<domain>]:<bus>:<device>.<func>). 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 [<domain>]:<bus>:<device>.<func>"""
+        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 [<domain>]:<bus>:<device>.<func>')
+
+
+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 (file)
index cc5eb6a..0000000
+++ /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 (file)
index e69de29..0000000
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/cmd_utils/main.py
deleted file mode 100644 (file)
index 8133f35..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-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
-
-
-# Note: PlatformCommands are external dependencies in phase2-sdk/demos repo; don't change!
-class PlatformCommands:
-    INVALID_COMMAND_EXIT_CODE = 1
-
-    PLATFORM_COMMANDS = {
-        'fw-update': ('Firmware update tool', FWUpdaterCLI),
-        'ssb-update': ('Second stage boot update tool', SSBUpdaterCLI),
-        'fw-config': ('Firmware configuration tool', FWConfigCommandCLI),
-        'udp-limiter': ('UDP rate limitation tool', UDPRateLimiterCLI),
-        'udp': ('Alias to udp-limiter', UDPRateLimiterCLI),
-        '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),
-    }
-
-    def __init__(self):
-        self.parser = argparse.ArgumentParser(description=self._get_description())
-        self.subparsers = self.parser.add_subparsers(help='Hailo utilities aimed to help with everything you need')
-        self.COMMANDS = {}
-        self.COMMANDS.update(type(self).PLATFORM_COMMANDS)
-
-        try:
-            # If sdk_client is importable - add its commands to this tool
-            from hailo_sdk_client.tools.cmd_utils.main import ClientCommands
-            self.COMMANDS.update(ClientCommands.SDK_COMMANDS)
-        except ImportError:
-            pass
-
-    @staticmethod
-    def _get_description():
-        return 'Hailo Platform SW v{} command line utilities'.format(hailo_platform.__version__)
-
-    def run(self):
-        argv = sys.argv[1:]
-        return self._run(argv)
-
-    # Dependency injection for testing
-    def _run(self, argv):
-        self.COMMANDS['help'] = ('show the list of commands', Helper(self.COMMANDS))
-        # Create the commands and let them set the arguments
-        commands = {}
-        for command_name, (help_, command_class) in self.COMMANDS.items():
-            commands[command_name] = command_class(self.subparsers.add_parser(command_name, help=help_))
-
-        argcomplete.autocomplete(self.parser)
-        # HailortCliUtil commands are parsed by hailortcli:
-        # * argv from after the command name are forwarded to hailortcli.
-        # * E.g. calling `hailo udp-limiter arg1 arg2` will result in the call `commands['udp-limiter'].run(['arg1', 'arg2'])`.
-        #   Inturn, this will create the process `hailortcli udp-rate-limiter arg1 arg2` (via the UDPRateLimiterCLI class).
-        # In order to support this, we first check if the first argument in argv is the name of a HailortCliUtil class.
-        # If so, we'll pass the arguments to the HailortCliUtil, otherwise we parse with argparse as usual.
-        if len(argv) == 0:
-            self.parser.print_help()
-            return self.INVALID_COMMAND_EXIT_CODE
-
-        command_name = argv[0]
-        if (command_name in commands) and isinstance(commands[command_name], HailortCliUtil):
-            # HailortCliUtil just passes the rest of the argv to hailortcli
-            try :
-                return commands[command_name].run(argv[1:])
-            except HailortCliUtilError as e:
-                print('\n'+ str(e))
-                return
-
-        # This isn't a HailortCliUtil commnad, parse with argparse
-        args = self.parser.parse_args(argv)
-        # Due to a bug in Python's handling of subparsers, we cannot require a sub-command using argparse. A manual
-        # check is performed here so we can print out a proper message. (https://bugs.python.org/issue9253)
-        if not vars(args):
-            self.parser.print_help()
-            return self.INVALID_COMMAND_EXIT_CODE
-
-        # The commands themself, set the default func.
-        return args.func(args)
-
-
-def main():
-    a = PlatformCommands()
-    return a.run()
-
-
-if __name__ == '__main__':
-    main()
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 (file)
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 (file)
index d1e6bf8..0000000
+++ /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/example_config.json b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/example_config.json
deleted file mode 100644 (file)
index f1a08bf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "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/tools/firmware/firmware_config.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/firmware/firmware_config.py
deleted file mode 100644 (file)
index 7b5738a..0000000
+++ /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 (file)
index 3588e28..0000000
+++ /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 (file)
index a15d218..0000000
+++ /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 (file)
index 653d0d0..0000000
+++ /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 (file)
index d169039..0000000
+++ /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/tools/hailocli/__init__.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/base_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/base_utils.py
new file mode 100644 (file)
index 0000000..911ae3d
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+from __future__ import print_function
+from builtins import object
+import subprocess
+
+from hailo_platform.common.logger.logger import default_logger
+
+
+class CmdUtilsBaseUtilError(Exception):
+    pass
+
+
+class HailortCliUtilError(CmdUtilsBaseUtilError):
+    pass
+
+
+# Note: CmdUtilsBaseUtil and CmdUtilsBaseUtilError are external dependencies in phase2-sdk/demos repo; don't change!
+class CmdUtilsBaseUtil(object):
+    def __init__(self, args_parser):
+        pass
+
+
+class Helper(CmdUtilsBaseUtil):
+    def __init__(self, commands):
+        self._commands = commands
+
+    def __call__(self, parser):
+        parser.set_defaults(func=self.run)
+
+    def run(self, args):
+        for command_name, (help_, _) in self._commands.items():
+            print("{} - {}".format(command_name, help_))
+
+
+class HailortCliUtil(CmdUtilsBaseUtil):
+    def __init__(self, args_parser, command):
+        self._command = command
+        self._logger = default_logger()
+
+    @classmethod
+    def _run_hailortcli(cls, binary_path, command, command_args):
+        cmd_args = [binary_path, command] + command_args
+
+        process = subprocess.Popen(cmd_args)
+        try:
+            _ = process.communicate()
+            return process.returncode
+        except KeyboardInterrupt:
+            process.terminate()
+            raise HailortCliUtilError('hailo has been interrupted by the user')
+
+    def run(self, argv):
+        hailortcli_cmd = 'hailortcli'
+        self._logger.info('(hailo) Running command \'{}\' with \'hailortcli\''.format(self._command))
+        return self._run_hailortcli(hailortcli_cmd, self._command, argv)
diff --git a/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/config_definitions.json b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/config_definitions.json
new file mode 100644 (file)
index 0000000..f1efdca
--- /dev/null
@@ -0,0 +1,79 @@
+{
+    "_comment": 
+        [
+        "This file defines the available fields of the firmwares config. It is not used to serialize any data.",
+        "WARNING! DO NOT CHANGE THE ORDER OF THE DEFINITIONS AS IT WILL CHANGE THEIR GENERATED VALUES!"
+        ],
+    "version": 0,
+    "categories": 
+    {
+        "network": 
+        {
+            "entries":
+            {
+                "should_use_dhcp": {"size": 1, "deserialize_as": "bool"},
+                "mac_address": {"size": 1, "length": 6, "deserialize_as": "mac_address"},
+                "static_ip_address": {"size": 4, "deserialize_as": "ipv4"},
+                "static_gw_address": {"size": 4, "deserialize_as": "ipv4"},
+                "static_netmask": {"size": 4, "deserialize_as": "ipv4"},
+                "rx_pause_frames_enable": {"size": 1, "deserialize_as": "bool"}
+            }
+        },
+        "system":
+        {
+            "entries":
+            {
+                "name": {"size": 1, "length": 32, "deserialize_as": "str"},
+                "app_watchdog_enable": {"size": 1, "deserialize_as": "bool"},
+                "app_watchdog_cycles": {"size": 4, "deserialize_as": "int"},
+                "core_watchdog_enable": {"size": 1, "deserialize_as": "bool"},
+                "core_watchdog_cycles": {"size": 4, "deserialize_as": "int"},
+                "watchdog_mode" : {"size": 1, "deserialize_as": "watchdog_mode"},
+                "max_neural_network_core_clock_rate": {"size": 4, "deserialize_as": "clock_frequency"},
+                "supported_aspm_states": {"size": 1, "deserialize_as": "supported_aspm_states"},
+                "bus_0_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
+                "bus_1_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
+                "bus_2_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
+                "bus_3_i2c_speed": {"size": 1, "deserialize_as": "i2c_speed"},
+                "supported_aspm_l1_substates": {"size": 1, "deserialize_as": "supported_aspm_l1_substates"},
+                "overcurrent_parameters_source": {"size": 1, "deserialize_as": "overcurrent_parameters_source"},
+                "overcurrent_monitoring_red_threshold": {"size": 4, "deserialize_as": "int"},
+                "overcurrent_conversion_time_microseconds": {"size": 4, "deserialize_as": "conversion_time"},
+                "temperature_parameters_source": {"size": 1, "deserialize_as": "temperature_parameters_source"},
+                "temperature_red_threshold": {"size": 1, "deserialize_as": "int"},
+                "temperature_red_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
+                "temperature_orange_threshold": {"size": 1, "deserialize_as": "int"},
+                "temperature_orange_hysteresis_threshold": {"size": 1, "deserialize_as": "int"},
+                "temperature_throttling_enable": {"size": 1, "deserialize_as": "bool"},
+                "overcurrent_monitoring_orange_threshold_enable": {"size": 1, "deserialize_as": "bool"}
+            }
+        },
+        "control":
+        {
+            "entries":
+            {
+                "udp_port": {"size": 2, "deserialize_as": "int"}
+            }
+        },
+        "d2h_event":
+        {
+            "entries":
+            {
+                "host_udp_port": {"size": 2, "deserialize_as": "int"},
+                "src_udp_port": {"size": 2, "deserialize_as": "int"},
+                "host_ip_address": {"size": 4, "deserialize_as": "ipv4"},
+                "connection_type": {"size": 1, "deserialize_as": "bool"}
+            }
+        },
+        "logger":
+        {
+            "entries":
+            {
+                "send_via_pci": {"size": 1, "deserialize_as": "bool"},
+                "send_via_uart": {"size": 1, "deserialize_as": "bool"},
+                "logger_level": {"size": 4, "deserialize_as": "logger_level"}
+            }
+        }
+    }
+}
+
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 (file)
index 0000000..f1a08bf
--- /dev/null
@@ -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/tools/hailocli/hailo_device_utils.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/hailo_device_utils.py
new file mode 100644 (file)
index 0000000..99be958
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+from enum import Enum
+
+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.pyhailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
+
+logger = default_logger()
+
+class HailoCLITargets(Enum):
+    udp = 'udp'
+    pcie = 'pcie'
+
+
+class HailoDeviceCmdUtil(CmdUtilsBaseUtil):
+    """
+    Base class for any cmd utility that use a specific hailo device
+    """
+    def __init__(self, args_parser, set_target_args=True):
+        super().__init__(args_parser)
+        self._parser = args_parser
+        if set_target_args:
+            self.add_target_args(args_parser)
+
+    def get_target(self, args):
+        self.validate_args(args)
+        target_type = self.get_target_type(args)
+        if target_type == HailoCLITargets.udp.value:
+            return EthernetDevice(args.ip)
+        else:
+            try:
+                return PcieDevice(device_info=args.board_location)
+            except Exception as e:
+                logger.error('Internal PCIe error (No PCIe device connected?)')
+                logger.error('Error code: {}'.format(e))
+                raise
+
+    def get_target_type(self, args):
+        if args.target is not None:
+            return args.target
+
+        if args.ip is not None:
+            # If IP is given, we assume that the target is udp
+            return HailoCLITargets.udp.value
+
+        # Otherwise the default target is pcie
+        return HailoCLITargets.pcie.value
+
+
+    def validate_args(self, args):
+        if args.target == HailoCLITargets.udp.value:
+            if not args.ip:
+                self._parser.error('When using --target udp, you must supply --ip')
+            if args.board_location:
+                self._parser.error("When using --target udp, you must not supply --board-location")
+
+        if args.board_location:
+            all_devices = InternalPcieDevice.scan_devices()
+            if args.board_location not in all_devices:
+                self._parser.error('Device {} does not appear on your host, please run `hailo scan -d pcie` to see all available devices'
+                    .format(args.board_location))
+
+    def add_target_args(self, args_parser):
+        args_parser.add_argument('--target', type=str, choices=[t.value for t in HailoCLITargets],
+                                 default=None, help='Device type to use')
+        args_parser.add_argument('--ip', type=str, default=None, help='IP address of the target (udp)')
+        args_parser.add_argument('-s', '--board-location', help=PcieDeviceInfo.BOARD_LOCATION_HELP_STRING,
+                                 type=PcieDeviceInfo.argument_type)
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 (file)
index 0000000..d3a62fd
--- /dev/null
@@ -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/hailocli/main.py b/hailort/libhailort/bindings/python/platform/hailo_platform/tools/hailocli/main.py
new file mode 100644 (file)
index 0000000..0e329c4
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import argparse
+import argcomplete
+import sys
+
+import hailo_platform
+from hailo_platform.tools.hailocli.base_utils import HailortCliUtil, Helper, HailortCliUtilError
+from hailo_platform.tools.hailocli.hailocli_commands import (FWUpdaterCLI, SSBUpdaterCLI, ControlCommandCLI, ScanCommandCLI,
+                                                            LoggerCommandCLI, MeasurePowerCommandCLI, RunCommandCLI, SensorConfigCommandCLI,
+                                                            FWConfigCommandCLI, BenchmarkCommandCLI, UDPRateLimiterCLI)
+
+# Note: PlatformCommands are external dependencies in phase2-sdk/demos repo; don't change!
+class PlatformCommands:
+    INVALID_COMMAND_EXIT_CODE = 1
+
+    PLATFORM_COMMANDS = {
+        'fw-update': ('Firmware update tool', FWUpdaterCLI),
+        'ssb-update': ('Second stage boot update tool', SSBUpdaterCLI),
+        'fw-config': ('Firmware configuration tool', FWConfigCommandCLI),
+        'udp-limiter': ('UDP rate limitation tool', UDPRateLimiterCLI),
+        'udp': ('Alias to udp-limiter', UDPRateLimiterCLI),
+        'fw-control': ('Useful firmware control operations', ControlCommandCLI),
+        'fw-logger': ('Download fw logs to a file', LoggerCommandCLI),
+        'scan': ('Scans for devices (Ethernet or PCIE)', ScanCommandCLI),
+        'sensor-config': ('Sensor configuration tool', SensorConfigCommandCLI),
+        'run': ('Run a compiled network', RunCommandCLI),
+        'benchmark': ('Measure basic performance on compiled network', BenchmarkCommandCLI),
+        'measure-power': ('Measures power consumption', MeasurePowerCommandCLI),
+    }
+
+    def __init__(self):
+        self.parser = argparse.ArgumentParser(description=self._get_description())
+        self.subparsers = self.parser.add_subparsers(help='Hailo utilities aimed to help with everything you need')
+        self.COMMANDS = {}
+        self.COMMANDS.update(type(self).PLATFORM_COMMANDS)
+
+        try:
+            # If sdk_client is importable - add its commands to this tool
+            from hailo_sdk_client.tools.cmd_utils.main import ClientCommands
+            self.COMMANDS.update(ClientCommands.SDK_COMMANDS)
+        except ImportError:
+            pass
+
+    @staticmethod
+    def _get_description():
+        return 'Hailo Platform SW v{} command line utilities'.format(hailo_platform.__version__)
+
+    def run(self):
+        argv = sys.argv[1:]
+        return self._run(argv)
+
+    # Dependency injection for testing
+    def _run(self, argv):
+        self.COMMANDS['help'] = ('show the list of commands', Helper(self.COMMANDS))
+        # Create the commands and let them set the arguments
+        commands = {}
+        for command_name, (help_, command_class) in self.COMMANDS.items():
+            commands[command_name] = command_class(self.subparsers.add_parser(command_name, help=help_))
+
+        argcomplete.autocomplete(self.parser)
+        # HailortCliUtil commands are parsed by hailortcli:
+        # * argv from after the command name are forwarded to hailortcli.
+        # * E.g. calling `hailo udp-limiter arg1 arg2` will result in the call `commands['udp-limiter'].run(['arg1', 'arg2'])`.
+        #   Inturn, this will create the process `hailortcli udp-rate-limiter arg1 arg2` (via the UDPRateLimiterCLI class).
+        # In order to support this, we first check if the first argument in argv is the name of a HailortCliUtil class.
+        # If so, we'll pass the arguments to the HailortCliUtil, otherwise we parse with argparse as usual.
+        if len(argv) == 0:
+            self.parser.print_help()
+            return self.INVALID_COMMAND_EXIT_CODE
+
+        command_name = argv[0]
+        if (command_name in commands) and isinstance(commands[command_name], HailortCliUtil):
+            # HailortCliUtil just passes the rest of the argv to hailortcli
+            try :
+                return commands[command_name].run(argv[1:])
+            except HailortCliUtilError as e:
+                print('\n'+ str(e))
+                return
+
+        # This isn't a HailortCliUtil commnad, parse with argparse
+        args = self.parser.parse_args(argv)
+        # Due to a bug in Python's handling of subparsers, we cannot require a sub-command using argparse. A manual
+        # check is performed here so we can print out a proper message. (https://bugs.python.org/issue9253)
+        if not vars(args):
+            self.parser.print_help()
+            return self.INVALID_COMMAND_EXIT_CODE
+
+        # The commands themself, set the default func.
+        return args.func(args)
+
+
+def main():
+    a = PlatformCommands()
+    return a.run()
+
+
+if __name__ == '__main__':
+    main()
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 (file)
index 153ea8d..0000000
+++ /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 (file)
index 1b16bbc..0000000
+++ /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')
index 658edacda18b8b0c3fa3d6b0c11385ad3222080a..75967ef8cccd6811176ea27763a6471cef0a57b9 100644 (file)
@@ -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 (file)
index acc485e..0000000
+++ /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/hailo_tutorials/notebooks/HRT_0_Inference_Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_0_Inference_Tutorial.ipynb
new file mode 100644 (file)
index 0000000..2f7d477
--- /dev/null
@@ -0,0 +1,202 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "\n",
+    "# Python inference tutorial\n",
+    "\n",
+    "This tutorial will walk you through the inference process.\n",
+    "\n",
+    "**Requirements:**\n",
+    "\n",
+    "* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Standalone hardware deployment\n",
+    "\n",
+    "The standalone flow allows direct access to the HW, developing applications directly on top of Hailo\n",
+    "core HW, using HailoRT. This way we can use the Hailo hardware without Tensorflow, and\n",
+    "even without the Hailo SDK (after the HEF is built).\n",
+    "\n",
+    "An HEF is Hailo’s binary format for neural networks. The HEF files contain:\n",
+    "\n",
+    "* Target HW configuration\n",
+    "* Weights\n",
+    "* Metadata for HailoRT (e.g. input/output scaling)\n",
+    "\n",
+    "First create the desired target object. In our example we use the Hailo-8 PCIe interface:\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np\n",
+    "from multiprocessing import Process\n",
+    "from hailo_platform import (HEF, PcieDevice, HailoStreamInterface, InferVStreams, ConfigureParams,\n",
+    "    InputVStreamParams, OutputVStreamParams, InputVStreams, OutputVStreams, FormatType)\n",
+    "\n",
+    "# The target can be used as a context manager (\"with\" statement) to ensure it's released on time.\n",
+    "# Here it's avoided for the sake of simplicity\n",
+    "target = PcieDevice()\n",
+    "\n",
+    "# Loading compiled HEFs to device:\n",
+    "model_name = 'resnet_v1_18'\n",
+    "hef_path = '../hefs/{}.hef'.format(model_name) \n",
+    "hef = HEF(hef_path)\n",
+    "    \n",
+    "# Configure network groups\n",
+    "configure_params = ConfigureParams.create_from_hef(hef=hef, interface=HailoStreamInterface.PCIe)\n",
+    "network_groups = target.configure(hef, configure_params)\n",
+    "network_group = network_groups[0]\n",
+    "network_group_params = network_group.create_params()\n",
+    "\n",
+    "# Create input and output virtual streams params\n",
+    "# Quantized argument signifies whether or not the incoming data is already quantized.\n",
+    "# Data is quantized by HailoRT if and only if quantized == False .\n",
+    "input_vstreams_params = InputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)\n",
+    "output_vstreams_params = OutputVStreamParams.make(network_group, quantized=True, format_type=FormatType.UINT8)\n",
+    "\n",
+    "# Define dataset params\n",
+    "input_vstream_info = hef.get_input_vstream_infos()[0]\n",
+    "output_vstream_info = hef.get_output_vstream_infos()[0]\n",
+    "image_height, image_width, channels = input_vstream_info.shape\n",
+    "num_of_images = 10\n",
+    "low, high = 2, 20\n",
+    "\n",
+    "# Generate random dataset\n",
+    "dataset = np.random.randint(low, high, (num_of_images, image_height, image_width, channels)).astype(np.float32)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Running hardware inference\n",
+    "Infer the model and then display the output shape:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Infer \n",
+    "with InferVStreams(network_group, input_vstreams_params, output_vstreams_params) as infer_pipeline:\n",
+    "    input_data = {input_vstream_info.name: dataset}\n",
+    "    with network_group.activate(network_group_params):\n",
+    "        infer_results = infer_pipeline.infer(input_data)\n",
+    "        print('Stream output shape is {}'.format(infer_results[output_vstream_info.name].shape))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Streaming inference\n",
+    "\n",
+    "This section shows how to run streaming inference using multiple processes in Python.\n",
+    "\n",
+    "We will not use infer. Instead we will use a send and receive model.\n",
+    "The send function and the receive function will run in different processes."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Define the send and receive functions:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def send(configured_network, num_frames):\n",
+    "    vstreams_params = InputVStreamParams.make(configured_network)\n",
+    "    configured_network.wait_for_activation(1000)\n",
+    "    with InputVStreams(configured_network, vstreams_params) as vstreams:\n",
+    "        vstream_to_buffer = {vstream: np.ndarray([1] + list(vstream.shape), dtype=vstream.dtype) for vstream in vstreams}\n",
+    "        for _ in range(num_frames):\n",
+    "            for vstream, buff in vstream_to_buffer.items():\n",
+    "                vstream.send(buff)\n",
+    "\n",
+    "def recv(configured_network, vstreams_params, num_frames):\n",
+    "    configured_network.wait_for_activation(1000)\n",
+    "    with OutputVStreams(configured_network, vstreams_params) as vstreams:\n",
+    "        for _ in range(num_frames):\n",
+    "            for vstream in vstreams:\n",
+    "                data = vstream.recv()\n",
+    "\n",
+    "def recv_all(configured_network, num_frames):\n",
+    "    vstreams_params_groups = OutputVStreamParams.make_groups(configured_network)\n",
+    "    recv_procs = []\n",
+    "    for vstreams_params in vstreams_params_groups:\n",
+    "        proc = Process(target=recv, args=(configured_network, vstreams_params, num_frames))\n",
+    "        proc.start()\n",
+    "        recv_procs.append(proc)\n",
+    "    for proc in recv_procs:\n",
+    "        proc.join()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Define the amount of frames to stream, define the processes, create the target and run processes:\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Define the amount of frames to stream\n",
+    "num_of_frames = 1000\n",
+    "\n",
+    "send_process = Process(target=send, args=(network_group, num_of_frames))\n",
+    "recv_process = Process(target=recv_all, args=(network_group, num_of_frames))\n",
+    "recv_process.start()\n",
+    "send_process.start()\n",
+    "print('Starting streaming (hef=\\'{}\\', num_of_frames={})'.format(model_name, num_of_frames))\n",
+    "with network_group.activate(network_group_params):\n",
+    "    send_process.join()\n",
+    "    recv_process.join()\n",
+    "print('Done')"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/hailo_tutorials/notebooks/HRT_1_Power_Measurement_Tutorial.ipynb
new file mode 100644 (file)
index 0000000..c55f7b1
--- /dev/null
@@ -0,0 +1,184 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Python power measurement tutorial\n",
+    "\n",
+    "This tutorial will show how to perform a power measurement on the chip.\n",
+    "\n",
+    "The Hailo chip supports power measurement which is done via the control protocol.\n",
+    "\n",
+    "**Requirements:**\n",
+    "\n",
+    "* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```\n",
+    "\n",
+    "**Attention:**\n",
+    "\n",
+    "* These examples should run in a different process than the one that performs the actual inference.\n"
+   ]
+  },
+  {
+   "source": [
+    "## Single power measurement"
+   ],
+   "cell_type": "markdown",
+   "metadata": {}
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "%matplotlib inline\n",
+    "import time\n",
+    "\n",
+    "from hailo_platform import PcieDevice, DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex # noqa F401\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Initialize the hardware object:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "target = PcieDevice()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "When using the ``power_measurement()`` function with no parameters, the function tries to detect which board is connected (evaluation board, M.2 or mPCIe) and determine the DVM accordingly (at the moment only the mentioned boards are supported). \n",
+    "\n",
+    "The parameter ``dvm`` (of type ``DvmTypes``) defines which DVM will be measured. The user can choose a specific DVM or choose the default DVM. The meaning of the default DVM changes according to the board or module in use. \n",
+    "\n",
+    "The default for the evaluation board is the sum of three DVMs: ``DvmTypes.VDD_CORE``, ``DvmTypes.MIPI_AVDD`` and ``DvmTypes.AVDD_H``. The sum of these three DVMs approximates of the total power consumption of the chip in PCIe setups. Only power can be measured using this default option, as voltage and current can't be summed up this way. \n",
+    "\n",
+    "The default for platforms supporting current monitoring, such as M.2 and mPCIe modules, is ``DvmTypes.OVERCURRENT_PROTECTION``, which measures the power consumption of the whole module. \n",
+    "\n",
+    "See the API documentation for further details about the supported DVMs and measurement types.\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "single_power_measurement = target.control.power_measurement()\n",
+    "print('Power from single measurement: {} W'.format(single_power_measurement))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Periodic power measurement\n",
+    "\n",
+    "In the following example, a periodic power measurement is taken.\n",
+    "\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"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "buffer_index = MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0\n",
+    "target.control.set_power_measurement(buffer_index=buffer_index)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The following call to ``start_power_measurement()`` allows to configure the power sampling frequency. In this case we keep the default configuration. The API documentation provides more details. \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "target.control.start_power_measurement()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Clear old samples and statistics (min, max, average) each time the measurement is taken from the chip."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "should_clear = True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The power measurement is read every second, for 10 seconds.\n",
+    "\n",
+    "The firmware calculates the min, max, and average of all the values from the sensor. Note that the average calculated by the firmware is the \"average of averages\". This is the average of all values that have already been averaged by the sensor. The host then requests these values from the firmware every second by calling the ``get_power_measurement()`` function. The host can also read the average time interval between new sensor values."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [],
+   "source": [
+    "for _ in range(10):\n",
+    "    time.sleep(1)\n",
+    "    # Get saved power measurement values from the firmware.\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",
+    "target.control.stop_power_measurement()"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
\ No newline at end of file
index 10782be4997e67313820c6190ec15edbacbe65ce..08c3adbadd99ca9be9e64029e8a1628f0cbfebfd 100644 (file)
@@ -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
index d269c63cb75ec0b498550b1298d27b6acf4d8484..04502e9182de3556f91e237fc3008d1c97590e78 100644 (file)
@@ -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/platform/tutorials/notebooks/Inference Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Inference Tutorial.ipynb
deleted file mode 100644 (file)
index 2f7d477..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "\n",
-    "# Python inference tutorial\n",
-    "\n",
-    "This tutorial will walk you through the inference process.\n",
-    "\n",
-    "**Requirements:**\n",
-    "\n",
-    "* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Standalone hardware deployment\n",
-    "\n",
-    "The standalone flow allows direct access to the HW, developing applications directly on top of Hailo\n",
-    "core HW, using HailoRT. This way we can use the Hailo hardware without Tensorflow, and\n",
-    "even without the Hailo SDK (after the HEF is built).\n",
-    "\n",
-    "An HEF is Hailo’s binary format for neural networks. The HEF files contain:\n",
-    "\n",
-    "* Target HW configuration\n",
-    "* Weights\n",
-    "* Metadata for HailoRT (e.g. input/output scaling)\n",
-    "\n",
-    "First create the desired target object. In our example we use the Hailo-8 PCIe interface:\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import numpy as np\n",
-    "from multiprocessing import Process\n",
-    "from hailo_platform import (HEF, PcieDevice, HailoStreamInterface, InferVStreams, ConfigureParams,\n",
-    "    InputVStreamParams, OutputVStreamParams, InputVStreams, OutputVStreams, FormatType)\n",
-    "\n",
-    "# The target can be used as a context manager (\"with\" statement) to ensure it's released on time.\n",
-    "# Here it's avoided for the sake of simplicity\n",
-    "target = PcieDevice()\n",
-    "\n",
-    "# Loading compiled HEFs to device:\n",
-    "model_name = 'resnet_v1_18'\n",
-    "hef_path = '../hefs/{}.hef'.format(model_name) \n",
-    "hef = HEF(hef_path)\n",
-    "    \n",
-    "# Configure network groups\n",
-    "configure_params = ConfigureParams.create_from_hef(hef=hef, interface=HailoStreamInterface.PCIe)\n",
-    "network_groups = target.configure(hef, configure_params)\n",
-    "network_group = network_groups[0]\n",
-    "network_group_params = network_group.create_params()\n",
-    "\n",
-    "# Create input and output virtual streams params\n",
-    "# Quantized argument signifies whether or not the incoming data is already quantized.\n",
-    "# Data is quantized by HailoRT if and only if quantized == False .\n",
-    "input_vstreams_params = InputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)\n",
-    "output_vstreams_params = OutputVStreamParams.make(network_group, quantized=True, format_type=FormatType.UINT8)\n",
-    "\n",
-    "# Define dataset params\n",
-    "input_vstream_info = hef.get_input_vstream_infos()[0]\n",
-    "output_vstream_info = hef.get_output_vstream_infos()[0]\n",
-    "image_height, image_width, channels = input_vstream_info.shape\n",
-    "num_of_images = 10\n",
-    "low, high = 2, 20\n",
-    "\n",
-    "# Generate random dataset\n",
-    "dataset = np.random.randint(low, high, (num_of_images, image_height, image_width, channels)).astype(np.float32)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "#### Running hardware inference\n",
-    "Infer the model and then display the output shape:"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# Infer \n",
-    "with InferVStreams(network_group, input_vstreams_params, output_vstreams_params) as infer_pipeline:\n",
-    "    input_data = {input_vstream_info.name: dataset}\n",
-    "    with network_group.activate(network_group_params):\n",
-    "        infer_results = infer_pipeline.infer(input_data)\n",
-    "        print('Stream output shape is {}'.format(infer_results[output_vstream_info.name].shape))"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Streaming inference\n",
-    "\n",
-    "This section shows how to run streaming inference using multiple processes in Python.\n",
-    "\n",
-    "We will not use infer. Instead we will use a send and receive model.\n",
-    "The send function and the receive function will run in different processes."
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Define the send and receive functions:"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "def send(configured_network, num_frames):\n",
-    "    vstreams_params = InputVStreamParams.make(configured_network)\n",
-    "    configured_network.wait_for_activation(1000)\n",
-    "    with InputVStreams(configured_network, vstreams_params) as vstreams:\n",
-    "        vstream_to_buffer = {vstream: np.ndarray([1] + list(vstream.shape), dtype=vstream.dtype) for vstream in vstreams}\n",
-    "        for _ in range(num_frames):\n",
-    "            for vstream, buff in vstream_to_buffer.items():\n",
-    "                vstream.send(buff)\n",
-    "\n",
-    "def recv(configured_network, vstreams_params, num_frames):\n",
-    "    configured_network.wait_for_activation(1000)\n",
-    "    with OutputVStreams(configured_network, vstreams_params) as vstreams:\n",
-    "        for _ in range(num_frames):\n",
-    "            for vstream in vstreams:\n",
-    "                data = vstream.recv()\n",
-    "\n",
-    "def recv_all(configured_network, num_frames):\n",
-    "    vstreams_params_groups = OutputVStreamParams.make_groups(configured_network)\n",
-    "    recv_procs = []\n",
-    "    for vstreams_params in vstreams_params_groups:\n",
-    "        proc = Process(target=recv, args=(configured_network, vstreams_params, num_frames))\n",
-    "        proc.start()\n",
-    "        recv_procs.append(proc)\n",
-    "    for proc in recv_procs:\n",
-    "        proc.join()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Define the amount of frames to stream, define the processes, create the target and run processes:\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# Define the amount of frames to stream\n",
-    "num_of_frames = 1000\n",
-    "\n",
-    "send_process = Process(target=send, args=(network_group, num_of_frames))\n",
-    "recv_process = Process(target=recv_all, args=(network_group, num_of_frames))\n",
-    "recv_process.start()\n",
-    "send_process.start()\n",
-    "print('Starting streaming (hef=\\'{}\\', num_of_frames={})'.format(model_name, num_of_frames))\n",
-    "with network_group.activate(network_group_params):\n",
-    "    send_process.join()\n",
-    "    recv_process.join()\n",
-    "print('Done')"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.6.9"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb b/hailort/libhailort/bindings/python/platform/tutorials/notebooks/Power Measurement Tutorial.ipynb
deleted file mode 100644 (file)
index a180861..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "# Python power measurement tutorial\n",
-    "\n",
-    "This tutorial will show how to perform a power measurement on the chip.\n",
-    "\n",
-    "The Hailo chip supports power measurement which is done via the control protocol.\n",
-    "\n",
-    "**Requirements:**\n",
-    "\n",
-    "* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```\n",
-    "\n",
-    "**Attention:**\n",
-    "\n",
-    "* These examples should run in a different process than the one that performs the actual inference.\n"
-   ]
-  },
-  {
-   "source": [
-    "## Single power measurement"
-   ],
-   "cell_type": "markdown",
-   "metadata": {}
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "%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"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Initialize the hardware object:"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "target = PcieDevice()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "When using the ``power_measurement()`` function with no parameters, the function tries to detect which board is connected (evaluation board, M.2 or mPCIe) and determine the DVM accordingly (at the moment only the mentioned boards are supported). \n",
-    "\n",
-    "The parameter ``dvm`` (of type ``DvmTypes``) defines which DVM will be measured. The user can choose a specific DVM or choose the default DVM. The meaning of the default DVM changes according to the board or module in use. \n",
-    "\n",
-    "The default for the evaluation board is the sum of three DVMs: ``DvmTypes.VDD_CORE``, ``DvmTypes.MIPI_AVDD`` and ``DvmTypes.AVDD_H``. The sum of these three DVMs approximates of the total power consumption of the chip in PCIe setups. Only power can be measured using this default option, as voltage and current can't be summed up this way. \n",
-    "\n",
-    "The default for platforms supporting current monitoring, such as M.2 and mPCIe modules, is ``DvmTypes.OVERCURRENT_PROTECTION``, which measures the power consumption of the whole module. \n",
-    "\n",
-    "See the API documentation for further details about the supported DVMs and measurement types.\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "single_power_measurement = target.control.power_measurement()\n",
-    "print('Power from single measurement: {} W'.format(single_power_measurement))"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Periodic power measurement\n",
-    "\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"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "index = 0\n",
-    "target.control.set_power_measurement(index)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "The following call to ``start_power_measurement()`` allows to configure the power sampling frequency. In this case we keep the default configuration. The API documentation provides more details. \n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "target.control.start_power_measurement()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "Clear old samples and statistics (min, max, average) each time the measurement is taken from the chip."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "should_clear = True"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "The power measurement is read every second, for 10 seconds.\n",
-    "\n",
-    "The firmware calculates the min, max, and average of all the values from the sensor. Note that the average calculated by the firmware is the \"average of averages\". This is the average of all values that have already been averaged by the sensor. The host then requests these values from the firmware every second by calling the ``get_power_measurement()`` function. The host can also read the average time interval between new sensor values."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "scrolled": true
-   },
-   "outputs": [],
-   "source": [
-    "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",
-    "    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",
-    "target.control.stop_power_measurement()"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.6.9"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
index 0df9525b39703dbd991bf3f7a9248258c4d85130..e1147b401f81b714f98dab94175b58ab0859e35c 100644 (file)
@@ -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
     $<BUILD_INTERFACE:${HAILORT_INC_DIR}>
@@ -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 $<TARGET_FILE:_pyhailort_internal> ${PROJECT_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/
+        )
+        add_dependencies(pyhailort_internal_venv _pyhailort_internal)
+    endif()
+endif()
index ea3118715f7e9ea49dabce452e594d6736947497..95b60a95397f8227ccf7b2e0a13ad99cc029f646 100644 (file)
 
 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.");
+public:
+    static 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::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.");
+    static std::vector<size_t> 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};
+        }
     }
-}
 
-std::vector<size_t> 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)
+    static py::dtype get_dtype(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};
+        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 (file)
index 0000000..d363ed4
--- /dev/null
@@ -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<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
+    VALIDATE_NOT_NULL(response);
+
+    MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(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<uint8_t*>(reinterpret_cast<const uint8_t*>(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<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
+    VALIDATE_NOT_NULL(response);
+
+    MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(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<std::string> response = make_unique_nothrow<std::string>(
+        const_cast<char*>(reinterpret_cast<const char*>(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<std::string> response = make_unique_nothrow<std::string>(
+        const_cast<char*>(reinterpret_cast<const char*>(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<hailo_sensor_types_t>(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<std::string> response = make_unique_nothrow<std::string>(
+        const_cast<char*>(reinterpret_cast<const char*>(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<hailo_sensor_types_t>(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<void(uintptr_t, const hailo_notification_t&, py::object)> &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 &notification, 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<std::string>(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_<DeviceWrapper>(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<float32_t>();
+    data.average_time_value_milliseconds = t[1].cast<float32_t>();
+    data.min_value = t[2].cast<float32_t>();
+    data.max_value = t[3].cast<float32_t>();
+    data.total_number_of_samples = t[4].cast<uint32_t>();
+    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 (file)
index 0000000..24f85e0
--- /dev/null
@@ -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 <pybind11/pybind11.h>
+#include <pybind11/pybind11.h>
+
+
+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<void(uintptr_t, const hailo_notification_t&, py::object)> &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> &&device)
+        : m_device(std::move(device)) {}
+
+    std::unique_ptr<Device> 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 (file)
index 0000000..d31c486
--- /dev/null
@@ -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>(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>(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<float64_t> 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<std::string> 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_<ActivatedAppContextManagerWrapper>(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_<HefWrapper>(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_<ConfiguredNetworkGroup>(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<std::string, hailo_vstream_params_t> &input_vstreams_params)
+            {
+                return InputVStreamsWrapper::create(self, input_vstreams_params);
+            })
+        .def("OutputVStreams", [](ConfiguredNetworkGroup &self, std::map<std::string, hailo_vstream_params_t> &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_<ActivatedNetworkGroup>(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<char*>(buff->data()), buff->size());
+        })
+        .def("get_invalid_frames_count", [](ActivatedNetworkGroup& self)
+        {
+            return self.get_invalid_frames_count();
+        })
+        ;
+}
+
+} /* namespace hailort */
index a8f731283cfc3817c51ad0e976c82d1a5b6c79c9..4de0a3c7722438f59ad8db25e2361d7271149a54 100644 (file)
@@ -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>(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<Hef>(hef_expected.release());
-        if (nullptr == hef) {
-            THROW_STATUS_ERROR(HAILO_OUT_OF_HOST_MEMORY);
-        }
-    };
-
-    static HefWrapper create_from_buffer(py::bytes data)
-    {
-        return HefWrapper(MemoryView((uint8_t*)std::string(data).c_str(), std::string(data).size()));
-    }
-
-    static HefWrapper create_from_file(const std::string &hef_path)
-    {
-        return HefWrapper(hef_path);
-    }
-
-    const std::unique_ptr<Hef>& hef_ptr() const
-    {
-        return hef;
-    }
-
-    py::list get_network_group_names()
-    {
-        return py::cast(hef->get_network_groups_names());
-    }
-
-    py::list 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 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 get_bottleneck_fps(const std::string &net_group_name)
-    {
-        Expected<float64_t> bottleneck_fps = hef->get_bottleneck_fps(net_group_name);
-        VALIDATE_EXPECTED(bottleneck_fps);
-        return bottleneck_fps.release();
-    };
-
-    py::dict 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 get_original_names_from_stream_name(const std::string &stream_name, const std::string &net_group_name)
-    {
-        LOGGER__WARNING("'get_original_names_from_stream_name()' is deprecated. One should use get_original_names_from_vstream_name()");
-        auto results = hef->get_vstream_names_from_stream_name(stream_name, net_group_name);
-        VALIDATE_EXPECTED(results);
-        return py::cast(results.release());
-    };
-
-    std::string get_stream_name_from_original_name(const std::string &original_name, const std::string &net_group_name)
-    {
-        LOGGER__WARNING("'get_stream_name_from_original_name()' is deprecated. One should use get_vstream_name_from_original_name()");
-        auto results = hef->get_stream_names_from_vstream_name(original_name, net_group_name);
-        VALIDATE_EXPECTED(results);
-        return results.release()[0];
-    };
-
-    py::list 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 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 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 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());
-    };
-
+    HefWrapper(const std::string &hef_path);
+    HefWrapper(const MemoryView &hef_buffer);
+    static HefWrapper create_from_buffer(py::bytes data);
+    static HefWrapper create_from_file(const std::string &hef_path);
+    py::list get_network_group_names();
+    py::list get_network_groups_infos();
+    py::list get_sorted_output_names(std::string net_group_name);
+    float64_t get_bottleneck_fps(const std::string &net_group_name);
+    py::dict get_udp_rates_dict(const std::string &net_group_name, uint32_t fps, uint32_t max_supported_rate_bytes);
+    py::list get_original_names_from_vstream_name(const std::string &vstream_name, const std::string &net_group_name);
+    std::string get_vstream_name_from_original_name(const std::string &original_name, const std::string &net_group_name);
+    py::list get_stream_names_from_vstream_name(const std::string &vstream_name, const std::string &net_group_name);
+    py::list get_vstream_names_from_stream_name(const std::string &stream_name, const std::string &net_group_name);
     py::dict 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());
-    };
-
+        uint32_t timeout_ms, uint32_t queue_size);
     py::dict 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());
-    };
+        uint32_t timeout_ms, uint32_t queue_size);
+    py::list get_input_vstream_infos(const std::string &name);
+    py::list get_output_vstream_infos(const std::string &name);
+    py::list get_all_vstream_infos(const std::string &name);
+    py::list get_input_stream_infos(const std::string &name);
+    py::list get_output_stream_infos(const std::string &name);
+    py::list get_all_stream_infos(const std::string &name);
+    py::dict create_configure_params(hailo_stream_interface_t interface);
 
-    py::list 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 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 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 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 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 get_all_stream_infos(const std::string &name)
+    const std::unique_ptr<Hef>& hef_ptr() const
     {
-        auto result = hef->get_all_stream_infos(name);
-        VALIDATE_EXPECTED(result);
-        return py::cast(result.value());
+        return hef;
     }
 
-    py::dict 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 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 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<std::string> res;
-        for (const auto &info : network_infos.value()) {
-            res.push_back(info.name);
-        }
-
-        return py::cast(res);
-    };
+        const hailo_mipi_input_stream_params_t &mipi_params);
+    py::list get_networks_names(const std::string &net_group_name);
+    static void initialize_python_module(py::module &m);
 
 private:
     std::unique_ptr<Hef> hef;
@@ -247,129 +77,17 @@ class ActivatedAppContextManagerWrapper final
 {
 public:
     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& 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 exit()
-    {
-        m_activated_net_group.reset();
-    }
-
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<ActivatedAppContextManagerWrapper>(m, "ActivatedApp")
-        .def("__enter__", &ActivatedAppContextManagerWrapper::enter, py::return_value_policy::reference)
-        .def("__exit__",  [&](ActivatedAppContextManagerWrapper &self, py::args) { self.exit(); })
-        ;
-    }
-
+        const hailo_activate_network_group_params_t &network_group_params);
+    
+    const ActivatedNetworkGroup& enter();
+    void exit();
+    static void add_to_python_module(py::module &m);
 private:
     std::unique_ptr<ActivatedNetworkGroup> m_activated_net_group;
     ConfiguredNetworkGroup &m_net_group;
     hailo_activate_network_group_params_t m_network_group_params;
 };
 
-void HEF_API_initialize_python_module(py::module &m)
-{
-    py::class_<HefWrapper>(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_name_from_original_name", &HefWrapper::get_stream_name_from_original_name) // deprecated
-        .def("get_original_names_from_stream_name", &HefWrapper::get_original_names_from_stream_name) // deprecated
-        .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_<ConfiguredNetworkGroup>(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<std::string, hailo_vstream_params_t> &input_vstreams_params)
-            {
-                return InputVStreamsWrapper::create(self, input_vstreams_params);
-            })
-        .def("OutputVStreams", [](ConfiguredNetworkGroup &self, std::map<std::string, hailo_vstream_params_t> &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_<ActivatedNetworkGroup>(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<char*>(buff->data()), buff->size());
-        })
-        .def("get_invalid_frames_count", [](ActivatedNetworkGroup& self)
-        {
-            return self.get_invalid_frames_count();
-        })
-        ;
-}
-
 } /* namespace hailort */
 
 #endif /* HEF_API_HPP_ */
index e011653d627399c1001cc50c5772f5fa1a94c108..c36310bd3fb39648d425bbe6a29ab83d511c341c 100644 (file)
@@ -6,6 +6,11 @@ pybind11_add_module(_pyhailort_internal SHARED
     ${HAILORT_SRCS_ABS}
 )
 
+set_target_properties(_pyhailort_internal PROPERTIES
+    CXX_STANDARD              14
+    CXX_STANDARD_REQUIRED     YES
+)
+
 target_include_directories(_pyhailort_internal
     PRIVATE
     $<BUILD_INTERFACE:${PYHAILORT_DIR}>
@@ -16,10 +21,10 @@ target_include_directories(_pyhailort_internal
     $<BUILD_INTERFACE:${DRIVER_INC_DIR}>
 )
 
-target_link_libraries(_pyhailort_internal PRIVATE libhailort hef_proto spdlog::spdlog readerwriterqueue)
+target_link_libraries(_pyhailort_internal PRIVATE libhailort hef_proto spdlog::spdlog readerwriterqueue microprofile)
 if(WIN32)
     target_link_libraries(_pyhailort_internal PRIVATE Ws2_32 Iphlpapi Shlwapi)
 endif()
 
 target_compile_options(_pyhailort_internal PRIVATE ${HAILORT_COMPILE_OPTIONS})
-exclude_archive_libs_symbols(_pyhailort_internal)
\ No newline at end of file
+exclude_archive_libs_symbols(_pyhailort_internal)
index 75a4f2647fc827add10d0d697cef4f5fbf0cf3fc..b53f4ccb084e13f60d11522bf2a5d3599357cdcf 100644 (file)
 namespace hailort
 {
 
-
-void ControlWrapper::set_clock_freq(uintptr_t device, uint32_t clock_freq)
+void ControlWrapper::set_clock_freq(DeviceWrapper &device, uint32_t clock_freq)
 {
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-    auto status = Control::set_clock_freq(*reinterpret_cast<Device*>(device), clock_freq);
+    auto status = Control::set_clock_freq(*device, clock_freq);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::close_all_streams(uintptr_t device)
+void ControlWrapper::close_all_streams(DeviceWrapper &device)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::close_all_streams(*reinterpret_cast<Device *>(device));
+    auto status = Control::close_all_streams(*device);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::config_ahb_to_axi(uintptr_t device, bool use_64bit_data_only)
+void ControlWrapper::config_ahb_to_axi(DeviceWrapper &device, bool use_64bit_data_only)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__config_core_top_type_t config_type = CONTROL_PROTOCOL__CONFIG_CORE_TOP_TYPE_AHB_TO_AXI;
     CONTROL_PROTOCOL__config_core_top_params_t params = {0};
     params.ahb_to_axi.enable_use_64bit_data_only = use_64bit_data_only;
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::config_core_top(*reinterpret_cast<Device *>(device), config_type, &params);
+    auto status = Control::config_core_top(*device, config_type, &params);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-void ControlWrapper::phy_operation(uintptr_t device, CONTROL_PROTOCOL__phy_operation_t operation_type)
+void ControlWrapper::phy_operation(DeviceWrapper &device, CONTROL_PROTOCOL__phy_operation_t operation_type)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::phy_operation(*reinterpret_cast<Device *>(device), operation_type);
+    auto status = Control::phy_operation(*device, operation_type);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-uint32_t ControlWrapper::latency_measurement_read(uintptr_t device)
+uint32_t ControlWrapper::latency_measurement_read(DeviceWrapper &device)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     uint32_t inbound_to_outbound_latency_nsec = 0;
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::latency_measurement_read(*reinterpret_cast<Device *>(device), &inbound_to_outbound_latency_nsec);
+    auto status = Control::latency_measurement_read(*device, &inbound_to_outbound_latency_nsec);
     VALIDATE_STATUS(status);
 
     return inbound_to_outbound_latency_nsec;
 }
 
-void ControlWrapper::latency_measurement_config(uintptr_t device, uint8_t latency_measurement_en,
+void ControlWrapper::latency_measurement_config(DeviceWrapper &device, uint8_t latency_measurement_en,
     uint32_t inbound_start_buffer_number, uint32_t outbound_stop_buffer_number, uint32_t inbound_stream_index,
     uint32_t outbound_stream_index)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::latency_measurement_config(*reinterpret_cast<Device *>(device), latency_measurement_en, inbound_start_buffer_number,
+    auto status = Control::latency_measurement_config(*device, latency_measurement_en, inbound_start_buffer_number,
             outbound_stop_buffer_number, inbound_stream_index, outbound_stream_index);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-void ControlWrapper::start_firmware_update(uintptr_t device)
+void ControlWrapper::start_firmware_update(DeviceWrapper &device)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::start_firmware_update(*reinterpret_cast<Device *>(device));
+    auto status = Control::start_firmware_update(*device);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-void ControlWrapper::finish_firmware_update(uintptr_t device)
+void ControlWrapper::finish_firmware_update(DeviceWrapper &device)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::finish_firmware_update(*reinterpret_cast<Device *>(device));
+    auto status = Control::finish_firmware_update(*device);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-void ControlWrapper::write_firmware_update(uintptr_t device, uint32_t offset, py::bytes data, uint32_t length)
+void ControlWrapper::write_firmware_update(DeviceWrapper &device, uint32_t offset, py::bytes data, uint32_t length)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::write_firmware_update(*reinterpret_cast<Device *>(device), offset, (uint8_t*)std::string(data).c_str(), length);
+    auto status = Control::write_firmware_update(*device, offset, (uint8_t*)std::string(data).c_str(), length);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-void ControlWrapper::validate_firmware_update(uintptr_t device, py::bytes md5_raw_data, uint32_t firmware_size)
+void ControlWrapper::validate_firmware_update(DeviceWrapper &device, py::bytes md5_raw_data, uint32_t firmware_size)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     MD5_SUM_t expected_md5 = {0};
-
     memcpy(&expected_md5, (uint8_t*)std::string(md5_raw_data).c_str(), sizeof(expected_md5));
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::validate_firmware_update(*reinterpret_cast<Device *>(device), &expected_md5, firmware_size);
+    auto status = Control::validate_firmware_update(*device, &expected_md5, firmware_size);
     VALIDATE_STATUS(status);
-
-    return;
 }
 
-py::bytes ControlWrapper::sensor_get_config(uintptr_t device, uint32_t section_index, uint32_t offset, uint32_t data_length)
+py::bytes ControlWrapper::sensor_get_config(DeviceWrapper &device, uint32_t section_index, uint32_t offset, uint32_t data_length)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(data_length, '\x00');
     VALIDATE_NOT_NULL(response);
     
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::sensor_get_config(*reinterpret_cast<Device *>(device), section_index, offset, data_length,
-        (uint8_t*)(response->data()));
-   
+    auto status = Control::sensor_get_config(*device, section_index, offset, data_length, (uint8_t*)(response->data()));
     VALIDATE_STATUS(status);
 
      return *response;
 }
 
-void ControlWrapper::idle_time_set_measurement(uintptr_t device, bool measurement_enable)
+void ControlWrapper::idle_time_set_measurement(DeviceWrapper &device, bool measurement_enable)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::idle_time_set_measurement(*reinterpret_cast<Device *>(device), measurement_enable);
+    auto status = Control::idle_time_set_measurement(*device, measurement_enable);
     VALIDATE_STATUS(status);
 }
 
-uint64_t ControlWrapper::idle_time_get_measurement(uintptr_t device)
+uint64_t ControlWrapper::idle_time_get_measurement(DeviceWrapper &device)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     uint64_t measurement = 0;
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::idle_time_get_measurement(*reinterpret_cast<Device *>(device), &measurement);
+    auto status = Control::idle_time_get_measurement(*device, &measurement);
     VALIDATE_STATUS(status);
 
     return measurement;
 }
 
-void ControlWrapper::d2h_notification_manager_set_host_info(uintptr_t device, uint16_t host_port, uint32_t host_ip_address)
+void ControlWrapper::d2h_notification_manager_set_host_info(DeviceWrapper &device, uint16_t host_port, uint32_t host_ip_address)
 {
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = Control::d2h_notification_manager_set_host_info(*reinterpret_cast<Device *>(device), host_port, host_ip_address);
+    auto status = Control::d2h_notification_manager_set_host_info(*device, host_port, host_ip_address);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::d2h_notification_manager_send_host_info_notification(uintptr_t device, uint8_t notification_priority)
+void ControlWrapper::d2h_notification_manager_send_host_info_notification(DeviceWrapper &device, uint8_t notification_priority)
 {
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = Control::d2h_notification_manager_send_host_info_notification(*reinterpret_cast<Device *>(device), notification_priority);
+    auto status = Control::d2h_notification_manager_send_host_info_notification(*device, notification_priority);
     VALIDATE_STATUS(status);
 }
 
 /* Context switch */
-void ControlWrapper::set_context_switch_breakpoint(uintptr_t device, 
+void ControlWrapper::set_context_switch_breakpoint(DeviceWrapper &device, 
         uint8_t breakpoint_id,
         bool break_at_any_network_group_index, uint8_t network_group_index, 
         bool break_at_any_batch_index, uint16_t batch_index, 
         bool break_at_any_context_index,uint8_t context_index, 
         bool break_at_any_action_index, uint16_t action_index) 
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__context_switch_breakpoint_control_t breakpoint_control = 
         CONTROL_PROTOCOL__CONTEXT_SWITCH_BREAKPOINT_CONTROL_SET;
     CONTROL_PROTOCOL__context_switch_breakpoint_data_t breakpoint_data = {
@@ -202,72 +149,59 @@ void ControlWrapper::set_context_switch_breakpoint(uintptr_t device,
         break_at_any_action_index,
         action_index};
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::config_context_switch_breakpoint(*reinterpret_cast<Device *>(device), breakpoint_id,
-            breakpoint_control, &breakpoint_data);
+    auto status = Control::config_context_switch_breakpoint(*device, breakpoint_id, breakpoint_control, &breakpoint_data);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::continue_context_switch_breakpoint(uintptr_t device, uint8_t breakpoint_id) 
+void ControlWrapper::continue_context_switch_breakpoint(DeviceWrapper &device, uint8_t breakpoint_id) 
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__context_switch_breakpoint_control_t breakpoint_control = 
         CONTROL_PROTOCOL__CONTEXT_SWITCH_BREAKPOINT_CONTROL_CONTINUE;
     CONTROL_PROTOCOL__context_switch_breakpoint_data_t breakpoint_data = {false,0,false,0,false,0,false,0};
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::config_context_switch_breakpoint(*reinterpret_cast<Device *>(device), breakpoint_id, 
+    auto status = Control::config_context_switch_breakpoint(*device, breakpoint_id, 
             breakpoint_control, &breakpoint_data);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::clear_context_switch_breakpoint(uintptr_t device, uint8_t breakpoint_id) 
+void ControlWrapper::clear_context_switch_breakpoint(DeviceWrapper &device, uint8_t breakpoint_id) 
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__context_switch_breakpoint_control_t breakpoint_control = 
         CONTROL_PROTOCOL__CONTEXT_SWITCH_BREAKPOINT_CONTROL_CLEAR;
     CONTROL_PROTOCOL__context_switch_breakpoint_data_t breakpoint_data = {false,0,false,0,false,0,false,0};
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::config_context_switch_breakpoint(*reinterpret_cast<Device *>(device), breakpoint_id,
+    auto status = Control::config_context_switch_breakpoint(*device, breakpoint_id,
             breakpoint_control, &breakpoint_data);
     VALIDATE_STATUS(status);
 }
 
-uint8_t ControlWrapper::get_context_switch_breakpoint_status(uintptr_t device, uint8_t breakpoint_id) 
+uint8_t ControlWrapper::get_context_switch_breakpoint_status(DeviceWrapper &device, uint8_t breakpoint_id) 
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__context_switch_debug_sys_status_t breakpoint_status = 
         CONTROL_PROTOCOL__CONTEXT_SWITCH_DEBUG_SYS_STATUS_COUNT;
 
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::get_context_switch_breakpoint_status(*reinterpret_cast<Device *>(device), breakpoint_id,
+    auto status = Control::get_context_switch_breakpoint_status(*device, breakpoint_id,
             &breakpoint_status);
     VALIDATE_STATUS(status);
 
     return static_cast<uint8_t>(breakpoint_status);
 }
 
-void ControlWrapper::config_context_switch_timestamp(uintptr_t device, uint16_t batch_index) 
+void ControlWrapper::config_context_switch_timestamp(DeviceWrapper &device, uint16_t batch_index) 
 {
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = Control::config_context_switch_timestamp(*reinterpret_cast<Device *>(device), batch_index, true);
+    auto status = Control::config_context_switch_timestamp(*device, batch_index, true);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::remove_context_switch_timestamp_configuration(uintptr_t device) 
+void ControlWrapper::remove_context_switch_timestamp_configuration(DeviceWrapper &device) 
 {
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = Control::config_context_switch_timestamp(*reinterpret_cast<Device *>(device), 0, false);
+    auto status = Control::config_context_switch_timestamp(*device, 0, false);
     VALIDATE_STATUS(status);
 }
 
-void ControlWrapper::enable_debugging(uintptr_t device, bool is_rma)
+void ControlWrapper::enable_debugging(DeviceWrapper &device, bool is_rma)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    status = Control::enable_debugging(*reinterpret_cast<Device *>(device), is_rma);
+    auto status = Control::enable_debugging(*device, is_rma);
     VALIDATE_STATUS(status);
 }
 
index 47dce8358d6795a8b8df2adbfed53705425dfc39..8106f342cdda77cda7884d468c6dbeb71bc9a750 100644 (file)
@@ -14,6 +14,8 @@
 #include "control.hpp"
 #include "utils.hpp"
 
+#include "device_api.hpp"
+
 #include <pybind11/pybind11.h>
 #include <pybind11/pybind11.h>
 #include <pybind11/numpy.h>
@@ -29,36 +31,36 @@ class ControlWrapper {
 public:
     static void add_to_python_module(py::module &m);
 
-    static void set_clock_freq(uintptr_t device, uint32_t clock_freq);
-    static void close_all_streams(uintptr_t device);
-    static void config_ahb_to_axi(uintptr_t device, bool use_64bit_data_only);
-    static void phy_operation(uintptr_t device, CONTROL_PROTOCOL__phy_operation_t operation_type);
-    static uint32_t latency_measurement_read(uintptr_t device);
-    static void latency_measurement_config(uintptr_t device, uint8_t latency_measurement_en,
+    static void set_clock_freq(DeviceWrapper &device, uint32_t clock_freq);
+    static void close_all_streams(DeviceWrapper &device);
+    static void config_ahb_to_axi(DeviceWrapper &device, bool use_64bit_data_only);
+    static void phy_operation(DeviceWrapper &device, CONTROL_PROTOCOL__phy_operation_t operation_type);
+    static uint32_t latency_measurement_read(DeviceWrapper &device);
+    static void latency_measurement_config(DeviceWrapper &device, uint8_t latency_measurement_en,
         uint32_t inbound_start_buffer_number, uint32_t outbound_stop_buffer_number, uint32_t inbound_stream_index,
         uint32_t outbound_stream_index);
-    static void start_firmware_update(uintptr_t device);
-    static void finish_firmware_update(uintptr_t device);
-    static void write_firmware_update(uintptr_t device, uint32_t offset, py::bytes data, uint32_t length);
-    static void validate_firmware_update(uintptr_t device, py::bytes md5_raw_data, uint32_t firmware_size);
-    static py::bytes sensor_get_config(uintptr_t device, uint32_t section_index, uint32_t offset, uint32_t data_length);
-    static void idle_time_set_measurement(uintptr_t device, bool measurement_enable);
-    static uint64_t idle_time_get_measurement(uintptr_t device);
-    static void d2h_notification_manager_set_host_info(uintptr_t device, uint16_t host_port, uint32_t host_ip_address);
-    static void d2h_notification_manager_send_host_info_notification(uintptr_t device, uint8_t notification_priority);
-    static void enable_debugging(uintptr_t device, bool is_rma);
+    static void start_firmware_update(DeviceWrapper &device);
+    static void finish_firmware_update(DeviceWrapper &device);
+    static void write_firmware_update(DeviceWrapper &device, uint32_t offset, py::bytes data, uint32_t length);
+    static void validate_firmware_update(DeviceWrapper &device, py::bytes md5_raw_data, uint32_t firmware_size);
+    static py::bytes sensor_get_config(DeviceWrapper &device, uint32_t section_index, uint32_t offset, uint32_t data_length);
+    static void idle_time_set_measurement(DeviceWrapper &device, bool measurement_enable);
+    static uint64_t idle_time_get_measurement(DeviceWrapper &device);
+    static void d2h_notification_manager_set_host_info(DeviceWrapper &device, uint16_t host_port, uint32_t host_ip_address);
+    static void d2h_notification_manager_send_host_info_notification(DeviceWrapper &device, uint8_t notification_priority);
+    static void enable_debugging(DeviceWrapper &device, bool is_rma);
 
     /* Context switch */
-    static void set_context_switch_breakpoint(uintptr_t device, uint8_t breakpoint_id,
+    static void set_context_switch_breakpoint(DeviceWrapper &device, uint8_t breakpoint_id,
         bool break_at_any_network_group_index, uint8_t network_group_index, 
         bool break_at_any_batch_index, uint16_t batch_index, 
         bool break_at_any_context_index,uint8_t context_index, 
         bool break_at_any_action_index, uint16_t action_index);
-    static void continue_context_switch_breakpoint(uintptr_t device, uint8_t breakpoint_id);
-    static void clear_context_switch_breakpoint(uintptr_t device, uint8_t breakpoint_id);
-    static uint8_t get_context_switch_breakpoint_status(uintptr_t device, uint8_t breakpoint_id);
-    static void config_context_switch_timestamp(uintptr_t device, uint16_t batch_index);
-    static void remove_context_switch_timestamp_configuration(uintptr_t device);
+    static void continue_context_switch_breakpoint(DeviceWrapper &device, uint8_t breakpoint_id);
+    static void clear_context_switch_breakpoint(DeviceWrapper &device, uint8_t breakpoint_id);
+    static uint8_t get_context_switch_breakpoint_status(DeviceWrapper &device, uint8_t breakpoint_id);
+    static void config_context_switch_timestamp(DeviceWrapper &device, uint16_t batch_index);
+    static void remove_context_switch_timestamp_configuration(DeviceWrapper &device);
 };
 
 } /* namespace hailort */
index 0f4c36055f71644c5b3ad75211e8a86e3c6b44ad..620a89c7fe1cde99cf427c196f3a8edfd263fb85 100644 (file)
@@ -209,7 +209,7 @@ PYBIND11_MODULE(_pyhailort_internal, m) {
         .def_readonly("buffer_indices", &LayerInfo::buffer_indices)
         .def_readonly("core_bytes_per_buffer", &LayerInfo::core_bytes_per_buffer)
         .def_readonly("core_buffers_per_frame", &LayerInfo::core_buffers_per_frame)
-        .def_readonly("network_name", &LayerInfo::partial_network_name)
+        .def_readonly("network_name", &LayerInfo::network_name)
         ;
 }
 
index 20d15c1bf641d8c3704727ac8bf2a0237df35234..b6798305d979a5df445d9f504bc5110d7619825f 100644 (file)
@@ -5,22 +5,21 @@
 #include <pybind11/complex.h>
 #include <pybind11/functional.h>
 #include <vector>
+#include <exception>
 using namespace std;
 
-#include "hailo/hailort.h"
-#include "hailo/device.hpp"
-#include "hailo/transform.hpp"
-#include "hailo/hef.hpp"
-#include "hailo/hailort_common.hpp"
-#include "hailo/quantization.hpp"
+#include "hailo/hailort.hpp"
 
 #include "hef_api.hpp"
 #include "vstream_api.hpp"
 #include "vdevice_api.hpp"
+#include "device_api.hpp"
+
 #include "utils.hpp"
 #include "utils.h"
 
-#include "common/socket.hpp"
+#include "bindings_common.hpp"
+
 #include "sensor_config_exports.h"
 #include "hailort_defaults.hpp"
 #if defined(__GNUC__)
@@ -32,62 +31,6 @@ namespace hailort
 
 #define MAX_HAILO_PACKET_SIZE (4*1024)
 
-
-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;
-};
-
-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<float32_t>();
-    data.average_time_value_milliseconds = t[1].cast<float32_t>();
-    data.min_value = t[2].cast<float32_t>();
-    data.max_value = t[3].cast<float32_t>();
-    data.total_number_of_samples = t[4].cast<uint32_t>();
-    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));
-}
-
 bool temperature_info_equals(hailo_chip_temperature_info_t &first, hailo_chip_temperature_info_t &second){
     return ((first.ts0_temperature == second.ts0_temperature) &&
         (first.ts1_temperature == second.ts1_temperature) &&
@@ -101,45 +44,33 @@ bool hailo_format_equals(hailo_format_t &first, hailo_format_t &second){
 }
 class UdpScan {
     public:
-        UdpScan();
+        UdpScan() = default;
         std::list<std::string> scan_devices(char *interface_name, uint32_t timeout_milliseconds);
     private:
         static const size_t m_max_number_of_devices = 100;
         hailo_eth_device_info_t m_eth_device_infos[m_max_number_of_devices] = {};
 };
 
-/* Device */
-// TODO HRT-5285: Change Python bindings of device class to use CPP API and move functionality to a new device module.
-uintptr_t create_eth_device(char *device_address, size_t device_address_length, uint16_t port,
-    uint32_t timeout_milliseconds, uint8_t max_number_of_attempts)
+std::list<std::string> UdpScan::scan_devices(char* interface_name, uint32_t timeout_milliseconds)
 {
     hailo_status status = HAILO_UNINITIALIZED;
-    hailo_device device = NULL;
-    hailo_eth_device_info_t device_info = {};
-
-    /* Validate address length */
-    if (INET_ADDRSTRLEN < device_address_length) {
-        EXIT_WITH_ERROR("device_address_length is invalid")
-    }
-
-    device_info.host_address.sin_family = AF_INET;
-    device_info.host_address.sin_port = HAILO_ETH_PORT_ANY;
-    status = Socket::pton(AF_INET, HAILO_ETH_ADDRESS_ANY, &(device_info.host_address.sin_addr));
-    VALIDATE_STATUS(status);
+    size_t number_of_devices = 0;
+    std::list<std::string> device_addresses;
+    char textual_ip_address[INET_ADDRSTRLEN] = {0};
+    const char *inet_ntop_rc = NULL;
 
-    device_info.device_address.sin_family = AF_INET;
-    device_info.device_address.sin_port = port;
-    status = Socket::pton(AF_INET, device_address, &(device_info.device_address.sin_addr));
+    status = hailo_scan_ethernet_devices(interface_name, m_eth_device_infos, 1, &number_of_devices, timeout_milliseconds);
     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;
-    
-    status = hailo_create_ethernet_device(&device_info, &device);
-    VALIDATE_STATUS(status);
+    for(size_t i = 0; i<number_of_devices; ++i) {
+        inet_ntop_rc = inet_ntop(AF_INET, &(m_eth_device_infos[i].device_address.sin_addr), textual_ip_address, INET_ADDRSTRLEN);
+        if (NULL == inet_ntop_rc) {
+            EXIT_WITH_ERROR("Could not convert ip address to textual format (inet_ntop has failed)");
+        }
+        device_addresses.push_back(textual_ip_address);
+    }
 
-    return (uintptr_t)device;
+    return device_addresses;
 }
 
 std::vector<hailo_pcie_device_info_t> scan_pcie_devices(void)
@@ -150,422 +81,6 @@ std::vector<hailo_pcie_device_info_t> scan_pcie_devices(void)
     return scan_result.release();
 }
 
-uintptr_t create_pcie_device(hailo_pcie_device_info_t *device_info)
-{
-    hailo_device device = NULL;
-    hailo_status status = hailo_create_pcie_device(device_info, &device);
-    VALIDATE_STATUS(status);
-
-    return (uintptr_t)device;
-}
-
-void release_device(uintptr_t device)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    status = hailo_release_device((hailo_device)device);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-uintptr_t get_hlpcie_device(uintptr_t hailort_device)
-{
-    return hailort_device;
-}
-
-/* Controls */
-hailo_device_identity_t identify(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto board_info = reinterpret_cast<Device *>(device)->identify();
-    VALIDATE_EXPECTED(board_info);
-
-    return board_info.release();
-}
-
-hailo_core_information_t core_identify(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto core_info = reinterpret_cast<Device *>(device)->core_identify();
-    VALIDATE_EXPECTED(core_info);
-
-    return core_info.release();
-}
-
-void set_fw_logger(uintptr_t device, hailo_fw_logger_level_t level, uint32_t interface_mask)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->set_fw_logger(level, interface_mask);
-    VALIDATE_STATUS(status);
-}
-
-void set_throttling_state(uintptr_t device, bool should_activate)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->set_throttling_state(should_activate);
-    VALIDATE_STATUS(status);
-}
-
-bool get_throttling_state(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto is_active_expected = reinterpret_cast<Device *>(device)->get_throttling_state();
-    VALIDATE_EXPECTED(is_active_expected);
-
-    return is_active_expected.release();
-}
-
-void set_overcurrent_state(uintptr_t device, bool should_activate)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto status = reinterpret_cast<Device*>(device)->set_overcurrent_state(should_activate);
-    VALIDATE_STATUS(status);
-}
-
-bool get_overcurrent_state(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto is_required_expected = reinterpret_cast<Device*>(device)->get_overcurrent_state();
-    VALIDATE_EXPECTED(is_required_expected);
-
-    return is_required_expected.release();
-}
-
-py::bytes read_memory(uintptr_t device, uint32_t address, uint32_t length)
-{
-    std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
-    VALIDATE_NOT_NULL(response);
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(response->data())), length);
-    auto status = (reinterpret_cast<Device*>(device))->read_memory(address, data_view);
-    VALIDATE_STATUS(status);
-
-    return *response;
-}
-
-void write_memory(uintptr_t device, uint32_t address, py::bytes data, uint32_t length)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-
-    auto status = (reinterpret_cast<Device*>(device))->write_memory(address, MemoryView(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(std::string(data).c_str())), length));
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void test_chip_memories(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    hailo_status status = reinterpret_cast<Device *>(device)->test_chip_memories();
-    VALIDATE_STATUS(status);
-}
-
-void i2c_write(uintptr_t device, hailo_i2c_slave_config_t *slave_config, uint32_t register_address, py::bytes data,
-    uint32_t length)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    VALIDATE_NOT_NULL(slave_config);
-
-    std::string data_str(data);
-    MemoryView data_view = MemoryView::create_const(data_str.c_str(), length);
-    auto status = reinterpret_cast<Device *>(device)->i2c_write(*slave_config, register_address, data_view);
-    VALIDATE_STATUS(status);
-}
-
-py::bytes i2c_read(uintptr_t device, hailo_i2c_slave_config_t *slave_config, uint32_t register_address, uint32_t length)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    VALIDATE_NOT_NULL(slave_config);
-
-    std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
-    VALIDATE_NOT_NULL(response);
-
-    MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(response->data())), length);
-    auto status = reinterpret_cast<Device *>(device)->i2c_read(*slave_config, register_address, data_view);
-    VALIDATE_STATUS(status);
-
-    return *response;
-}
-
-float32_t power_measurement(uintptr_t device, hailo_dvm_options_t dvm,
-    hailo_power_measurement_types_t measurement_type)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto measurement = reinterpret_cast<Device *>(device)->power_measurement(dvm, measurement_type);
-    VALIDATE_EXPECTED(measurement);
-    
-    return measurement.release();
-}
-
-void start_power_measurement(uintptr_t device, uint32_t delay_milliseconds,
-    hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->start_power_measurement(delay_milliseconds, averaging_factor,
-        sampling_period);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void set_power_measurement(uintptr_t device, uint32_t index, hailo_dvm_options_t dvm,
-    hailo_power_measurement_types_t measurement_type)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->set_power_measurement(index, dvm, measurement_type);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-PowerMeasurementData get_power_measurement(uintptr_t device, uint32_t index, bool should_clear)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto measurement_data = reinterpret_cast<Device *>(device)->get_power_measurement(index, should_clear);
-    VALIDATE_EXPECTED(measurement_data);
-
-    return PowerMeasurementData(measurement_data.release());
-}
-
-void stop_power_measurement(uintptr_t device)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    status = hailo_stop_power_measurement((hailo_device)device);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void reset(uintptr_t device, hailo_reset_device_mode_t mode)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-
-    status = hailo_reset_device((hailo_device)device, mode);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-hailo_fw_user_config_information_t examine_user_config(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto user_config_info = reinterpret_cast<Device *>(device)->examine_user_config();
-    VALIDATE_EXPECTED(user_config_info);
-
-    return user_config_info.release();
-}
-
-py::bytes read_user_config(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto config_buffer = reinterpret_cast<Device *>(device)->read_user_config();
-    VALIDATE_EXPECTED(config_buffer);
-
-    std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
-        const_cast<char*>(reinterpret_cast<const char*>(config_buffer->data())), config_buffer->size());
-    VALIDATE_NOT_NULL(response);
-
-    return *response;
-}
-
-void write_user_config(uintptr_t device, py::bytes data)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    std::string data_str(data); 
-    MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
-    auto status = reinterpret_cast<Device *>(device)->write_user_config(data_view);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void erase_user_config(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->erase_user_config();
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-py::bytes read_board_config(uintptr_t device)
-{
-    auto config_buffer = reinterpret_cast<Device *>(device)->read_board_config();
-    VALIDATE_EXPECTED(config_buffer);
-
-    std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
-        const_cast<char*>(reinterpret_cast<const char*>(config_buffer->data())), config_buffer->size());
-    VALIDATE_NOT_NULL(response);
-    
-    return *response;
-}
-
-void write_board_config(uintptr_t device, py::bytes data)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    std::string data_str(data); 
-    MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
-    auto status = reinterpret_cast<Device *>(device)->write_board_config(data_view);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-hailo_extended_device_information_t get_extended_device_information(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto extended_device_info = reinterpret_cast<Device *>(device)->get_extended_device_information();
-    VALIDATE_EXPECTED(extended_device_info);
-       
-    return extended_device_info.release();
-}
-
-hailo_health_info_t get_health_information(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    auto health_info = reinterpret_cast<Device *>(device)->get_health_information();
-    VALIDATE_EXPECTED(health_info);
-       
-    return health_info.release();
-}
-
-void sensor_store_config(uintptr_t device, 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)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-    status = (reinterpret_cast<Device*>(device))->store_sensor_config(section_index, static_cast<hailo_sensor_types_t>(sensor_type), reset_data_size, config_height, config_width,
-        config_fps, config_file_path, config_name);
-
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void store_isp_config(uintptr_t device, 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)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    VALIDATE_NOT_NULL(reinterpret_cast<Device*>(device));
-    status = (reinterpret_cast<Device*>(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);
-
-    return;
-}
-
-py::bytes sensor_get_sections_info(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto buffer = (reinterpret_cast<Device*>(device))->sensor_get_sections_info();
-    VALIDATE_EXPECTED(buffer);
-    
-    std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
-        const_cast<char*>(reinterpret_cast<const char*>(buffer->data())), buffer->size());
-    VALIDATE_NOT_NULL(response);
-
-    return *response;
-}
-
-void sensor_set_i2c_bus_index(uintptr_t device, uint32_t sensor_type, uint32_t bus_index)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    hailo_status status = (reinterpret_cast<Device*>(device))->sensor_set_i2c_bus_index(
-        static_cast<hailo_sensor_types_t>(sensor_type), bus_index);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void sensor_load_and_start_config(uintptr_t device, uint32_t section_index)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = (reinterpret_cast<Device*>(device))->sensor_load_and_start_config(section_index);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void sensor_reset(uintptr_t device, uint32_t section_index)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = (reinterpret_cast<Device*>(device))->sensor_reset(section_index);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void sensor_set_generic_i2c_slave(uintptr_t device, uint16_t slave_address,
-    uint8_t register_address_size, uint8_t bus_index, uint8_t should_hold_bus, uint8_t endianness)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = (reinterpret_cast<Device*>(device))->sensor_set_generic_i2c_slave(slave_address, register_address_size,
-        bus_index, should_hold_bus, endianness);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void firmware_update(uintptr_t device, py::bytes fw_bin, uint32_t fw_bin_length, bool should_reset)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = reinterpret_cast<Device *>(device)->firmware_update(MemoryView::create_const(std::string(fw_bin).c_str(), fw_bin_length),
-        should_reset);
-    VALIDATE_STATUS(status);
-}
-
-void second_stage_update(uintptr_t device, py::bytes second_stage_bin, uint32_t second_stage_bin_length)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    hailo_status status = reinterpret_cast<Device *>(device)->second_stage_update((uint8_t *)std::string(second_stage_bin).c_str(), 
-        second_stage_bin_length);
-    VALIDATE_STATUS(status);
-}
-
-py::list configure_device_from_hef(uintptr_t device, const HefWrapper &hef,
-    const NetworkGroupsParamsMap &configure_params={})
-{
-    if (nullptr == (void*)device) {
-        EXIT_WITH_ERROR("Got NULL in parameter 'device'!");
-    }
-
-    auto network_groups = (reinterpret_cast<Device*>(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;
-}
-
 // Quantization
 void dequantize_output_buffer_from_uint8(py::array src_buffer, py::array dst_buffer, const hailo_format_type_t &dst_dtype,
     uint32_t shape_size, const hailo_quant_info_t &quant_info)
@@ -585,7 +100,7 @@ void dequantize_output_buffer_from_uint8(py::array src_buffer, py::array dst_buf
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -605,7 +120,7 @@ void dequantize_output_buffer_from_uint16(py::array src_buffer, py::array dst_bu
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -621,7 +136,7 @@ void dequantize_output_buffer_from_float32(py::array src_buffer, py::array dst_b
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -645,7 +160,7 @@ void dequantize_output_buffer_from_uint8_in_place(py::array dst_buffer, const ha
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src format type uint8 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -665,7 +180,7 @@ void dequantize_output_buffer_from_uint16_in_place(py::array dst_buffer, const h
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src dormat type uint16 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -681,7 +196,7 @@ void dequantize_output_buffer_from_float32_in_place(py::array dst_buffer, const
             break;
         default:
             LOGGER__ERROR("Output quantization isn't supported from src format type float32 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -701,7 +216,7 @@ void dequantize_output_buffer_in_place(py::array dst_buffer, const hailo_format_
             dequantize_output_buffer_from_float32_in_place(dst_buffer, dst_dtype, shape_size, quant_info);
             break;
         default:
-            LOGGER__ERROR("Unsupported src format type = {}", convert_format_type_to_string(dst_dtype));
+            LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -721,7 +236,7 @@ void dequantize_output_buffer(py::array src_buffer, py::array dst_buffer, const
             dequantize_output_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
             break;
         default:
-            LOGGER__ERROR("Unsupported src format type = {}", convert_format_type_to_string(dst_dtype));
+            LOGGER__ERROR("Unsupported src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -736,7 +251,7 @@ void quantize_input_buffer_from_uint8(py::array src_buffer, py::array dst_buffer
                 static_cast<uint8_t*>(dst_buffer.mutable_data()), shape_size, quant_info);
             break;
         default:
-            LOGGER__ERROR("Input quantization isn't supported from src format type uint8 to dst format type = {}", convert_format_type_to_string(dst_dtype));
+            LOGGER__ERROR("Input quantization isn't supported from src format type uint8 to dst format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -756,7 +271,7 @@ void quantize_input_buffer_from_uint16(py::array src_buffer, py::array dst_buffe
             break;
         default:
             LOGGER__ERROR("Input quantization isn't supported from src format type uint16 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -776,7 +291,7 @@ void quantize_input_buffer_from_float32(py::array src_buffer, py::array dst_buff
             break;
         default:
             LOGGER__ERROR("Input quantization isn't supported from src format type float32 to dst format type = {}",
-                convert_format_type_to_string(dst_dtype));
+                HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
@@ -796,163 +311,12 @@ void quantize_input_buffer(py::array src_buffer, py::array dst_buffer, const hai
             quantize_input_buffer_from_float32(src_buffer, dst_buffer, dst_dtype, shape_size, quant_info);
             break;
         default:
-            LOGGER__ERROR("Input quantization isn't supported for src format type = {}", convert_format_type_to_string(dst_dtype));
+            LOGGER__ERROR("Input quantization isn't supported for src format type = {}", HailoRTBindingsCommon::convert_format_type_to_string(dst_dtype));
             THROW_STATUS_ERROR(HAILO_INVALID_ARGUMENT);
             break;
     }
 }
 
-void set_pause_frames(uintptr_t device, bool rx_pause_frames_enable)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto status = reinterpret_cast<Device *>(device)->set_pause_frames(rx_pause_frames_enable);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void wd_enable(uintptr_t device, hailo_cpu_id_t cpu_id)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    hailo_status status = reinterpret_cast<Device *>(device)->wd_enable(cpu_id);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void wd_disable(uintptr_t device, hailo_cpu_id_t cpu_id)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    hailo_status status = reinterpret_cast<Device *>(device)->wd_disable(cpu_id);
-    VALIDATE_STATUS(status);
-
-    return;
-}
-
-void wd_config(uintptr_t device, hailo_cpu_id_t cpu_id, uint32_t wd_cycles, hailo_watchdog_mode_t wd_mode)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    auto status = reinterpret_cast<Device *>(device)->wd_config(cpu_id, wd_cycles, wd_mode);
-    VALIDATE_STATUS(status);
-}
-
-uint32_t previous_system_state(uintptr_t device, hailo_cpu_id_t cpu_id)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-
-    auto system_state = reinterpret_cast<Device *>(device)->previous_system_state(cpu_id);
-    VALIDATE_EXPECTED(system_state);
-
-    return system_state.release();
-}
-
-hailo_chip_temperature_info_t get_chip_temperature(uintptr_t device)
-{
-    VALIDATE_NOT_NULL(reinterpret_cast<Device *>(device));
-    
-    auto temp_info = reinterpret_cast<Device *>(device)->get_chip_temperature();
-    VALIDATE_EXPECTED(temp_info);
-
-    return temp_info.release();
-}
-
-void set_input_stream_timeout(uintptr_t input_stream, uint32_t timeout_milis)
-{
-    hailo_status status = hailo_set_input_stream_timeout((hailo_input_stream)input_stream, timeout_milis);
-    VALIDATE_STATUS(status);
-}
-
-void set_output_stream_timeout(uintptr_t output_stream, uint32_t timeout_milis)
-{
-    hailo_status status = hailo_set_output_stream_timeout((hailo_output_stream)output_stream, timeout_milis);
-    VALIDATE_STATUS(status);
-}
-
-void set_notification_callback(uintptr_t device, const std::function<void(uintptr_t, const hailo_notification_t&, py::object)> &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*)device)->set_notification_callback(
-        [callback, op = std::move(opaque)] (Device &device, const hailo_notification_t &notification, void* opaque) {
-            (void)opaque;
-            callback((uintptr_t)&device, notification, op);
-        }, notification_id, nullptr);
-    VALIDATE_STATUS(status);
-}
-
-void remove_notification_callback(uintptr_t device, hailo_notification_id_t notification_id)
-{
-    hailo_status status = hailo_remove_notification_callback(reinterpret_cast<hailo_device>(device), notification_id);
-    VALIDATE_STATUS(status);
-}
-
-UdpScan::UdpScan()
-{
-}
-
-std::list<std::string> UdpScan::scan_devices(char* interface_name, uint32_t timeout_milliseconds)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    size_t number_of_devices = 0;
-    std::list<std::string> device_addresses;
-    char textual_ip_address[INET_ADDRSTRLEN] = {0};
-    const char *inet_ntop_rc = NULL;
-
-    status = hailo_scan_ethernet_devices(interface_name, m_eth_device_infos, 1, &number_of_devices, timeout_milliseconds);
-    VALIDATE_STATUS(status);
-
-    for(size_t i = 0; i<number_of_devices; ++i) {
-        inet_ntop_rc = inet_ntop(AF_INET, &(m_eth_device_infos[i].device_address.sin_addr), textual_ip_address, INET_ADDRSTRLEN);
-        if (NULL == inet_ntop_rc) {
-            EXIT_WITH_ERROR("Could not convert ip address to textual format (inet_ntop has failed)");
-        }
-        device_addresses.push_back(textual_ip_address);
-    }
-
-    return device_addresses;
-}
-
-py::bytes read_log(uintptr_t device, 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*)device)->read_log(response_view, cpu_id);
-    VALIDATE_EXPECTED(response_size_expected);
-
-    response.resize(response_size_expected.release());
-    return py::bytes(response);
-}
-
-void direct_write_memory(uintptr_t device, uint32_t address, py::bytes buffer)
-{
-    const auto buffer_str = static_cast<std::string>(buffer);
-    hailo_status status = ((Device*)device)->direct_write_memory(address, buffer_str.c_str(),
-        (uint32_t) (buffer_str.length()));
-    VALIDATE_STATUS(status);
-}
-
-py::bytes direct_read_memory(uintptr_t device, uint32_t address, uint32_t size)
-{
-    std::string buffer_str;
-
-    buffer_str.reserve(size);
-    buffer_str.resize(size);
-
-    hailo_status status = ((Device*)device)->direct_read_memory(address, (char*)buffer_str.c_str(), size);
-    VALIDATE_STATUS(status);
-
-    buffer_str.resize(size);
-    return py::bytes(buffer_str);
-}
-
 std::string get_status_message(uint32_t status_in)
 {
     auto status_str = hailo_get_status_message((hailo_status)status_in);
@@ -1008,8 +372,7 @@ public:
         .def("reset_rate_limit", &TrafficControlUtilWrapper::reset_rate_limit)
         .def_static("get_interface_name", [](const std::string &ip) {
             return TrafficControlUtilWrapper::get_interface_name(ip);
-        });
-        ;
+        })
         ;
     }
 
@@ -1025,67 +388,39 @@ private:
 
 // End of temp hack for hlpcie
 
+static void validate_versions_match()
+{
+    hailo_version_t libhailort_version = {};
+    auto status = hailo_get_library_version(&libhailort_version);
+    if (HAILO_SUCCESS != status) {
+        throw std::logic_error("Failed to get libhailort version");
+    }
+
+    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::stringstream message;
+        message << "libhailort version (" <<
+            libhailort_version.major << "." << libhailort_version.minor << "." << libhailort_version.revision <<
+            ") does not match pyhailort version (" <<
+            HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << ")";
+        throw std::logic_error(message.str());
+    }
+}
+
 PYBIND11_MODULE(_pyhailort, m) {
+    validate_versions_match();
+
     m.def("get_status_message", &get_status_message);
-    // Device
-    m.def("create_eth_device", &create_eth_device);
-    m.def("create_pcie_device", &create_pcie_device);
     m.def("scan_pcie_devices", &scan_pcie_devices);
-    m.def("release_device", &release_device);
-    m.def("get_hlpcie_device", &get_hlpcie_device);
-    // Controls
-    m.def("identify", &identify);
-    m.def("core_identify", &core_identify);
-    m.def("set_fw_logger", &set_fw_logger);
-    m.def("read_memory", &read_memory);
-    m.def("write_memory", &write_memory);
-    m.def("power_measurement", &power_measurement);
-    m.def("start_power_measurement", &start_power_measurement);
-    m.def("stop_power_measurement", &stop_power_measurement);
-    m.def("set_power_measurement", &set_power_measurement);
-    m.def("get_power_measurement", &get_power_measurement);
-    m.def("firmware_update", &firmware_update);
-    m.def("second_stage_update", &second_stage_update);
-    m.def("examine_user_config", &examine_user_config);
-    m.def("read_user_config", &read_user_config);
-    m.def("write_user_config", &write_user_config);
-    m.def("erase_user_config", &erase_user_config);
-    m.def("read_board_config", &read_board_config);
-    m.def("write_board_config", &write_board_config);
-    m.def("i2c_write", &i2c_write);
-    m.def("i2c_read", &i2c_read);
-    m.def("sensor_store_config", &sensor_store_config);
-    m.def("store_isp_config", &store_isp_config);
-    m.def("sensor_set_i2c_bus_index", &sensor_set_i2c_bus_index);
-    m.def("sensor_load_and_start_config", &sensor_load_and_start_config);
-    m.def("sensor_reset", &sensor_reset);
-    m.def("sensor_set_generic_i2c_slave", &sensor_set_generic_i2c_slave);
-    m.def("sensor_get_sections_info", &sensor_get_sections_info);
-    m.def("reset", &reset);
-    m.def("wd_enable", &wd_enable);
-    m.def("wd_disable", &wd_disable);
-    m.def("wd_config", &wd_config);
-    m.def("previous_system_state", &previous_system_state);
-    m.def("get_chip_temperature", &get_chip_temperature);
-    m.def("get_extended_device_information", &get_extended_device_information);
-    m.def("set_pause_frames", &set_pause_frames);
-    m.def("test_chip_memories", &test_chip_memories);
-    m.def("_get_health_information", &get_health_information);
-    m.def("set_throttling_state", &set_throttling_state);
-    m.def("get_throttling_state", &get_throttling_state);
-    m.def("_set_overcurrent_state", &set_overcurrent_state);
-    m.def("_get_overcurrent_state", &get_overcurrent_state);
-    //HEF
-    m.def("configure_device_from_hef", &configure_device_from_hef);
-    //Stream related
-    m.def("set_input_stream_timeout", &set_input_stream_timeout);
-    m.def("set_output_stream_timeout", &set_output_stream_timeout);
-    m.def("set_notification_callback", &set_notification_callback);
-    m.def("remove_notification_callback", &remove_notification_callback);
     m.def("dequantize_output_buffer_in_place", &dequantize_output_buffer_in_place);
     m.def("dequantize_output_buffer", &dequantize_output_buffer);
     m.def("quantize_input_buffer", &quantize_input_buffer);
 
+    m.def("get_format_data_bytes", &HailoRTCommon::get_format_data_bytes);
+    m.def("get_dtype", &HailoRTBindingsCommon::get_dtype);
+
     py::class_<hailo_pcie_device_info_t>(m, "PcieDeviceInfo")
         .def(py::init<>())
         .def_static("_parse", [](const std::string &device_info_str) {
@@ -1170,6 +505,13 @@ PYBIND11_MODULE(_pyhailort, m) {
         .value("AVERAGE_1024", HAILO_AVERAGE_FACTOR_1024, "Each sample reflects a value of 1024 sub-samples.")
         ;
 
+    py::enum_<hailo_measurement_buffer_index_t>(m, "MeasurementBufferIndex", "Enum-like class representing all FW buffers for power measurements storing.")
+        .value("MEASUREMENT_BUFFER_INDEX_0", HAILO_MEASUREMENT_BUFFER_INDEX_0)
+        .value("MEASUREMENT_BUFFER_INDEX_1", HAILO_MEASUREMENT_BUFFER_INDEX_1)
+        .value("MEASUREMENT_BUFFER_INDEX_2", HAILO_MEASUREMENT_BUFFER_INDEX_2)
+        .value("MEASUREMENT_BUFFER_INDEX_3", HAILO_MEASUREMENT_BUFFER_INDEX_3)
+        ;
+
     py::class_<hailo_notification_t>(m, "Notification")
         .def_readonly("notification_id", &hailo_notification_t::id)
         .def_readonly("sequence", &hailo_notification_t::sequence)
@@ -1353,12 +695,40 @@ PYBIND11_MODULE(_pyhailort, m) {
         .def_readwrite("height", &hailo_3d_image_shape_t::height)
         .def_readwrite("width", &hailo_3d_image_shape_t::width)
         .def_readwrite("features", &hailo_3d_image_shape_t::features)
+        .def(py::pickle(
+            [](const hailo_3d_image_shape_t &shape) { // __getstate__
+                return py::make_tuple(
+                    shape.height,
+                    shape.width,
+                    shape.features);
+            },
+            [](py::tuple t) { // __setstate__
+                hailo_3d_image_shape_t shape;
+                shape.height = t[0].cast<uint32_t>();
+                shape.width = t[1].cast<uint32_t>();
+                shape.features = t[2].cast<uint32_t>();
+                return shape;
+            }
+        ))
         ;
 
     py::class_<hailo_nms_shape_t>(m, "NmsShape")
         .def(py::init<>())
         .def_readonly("number_of_classes", &hailo_nms_shape_t::number_of_classes)
         .def_readonly("max_bboxes_per_class", &hailo_nms_shape_t::max_bboxes_per_class)
+        .def(py::pickle(
+            [](const hailo_nms_shape_t &nms_shape) { // __getstate__
+                return py::make_tuple(
+                    nms_shape.number_of_classes,
+                    nms_shape.max_bboxes_per_class);
+            },
+            [](py::tuple t) { // __setstate__
+                hailo_nms_shape_t nms_shape;
+                nms_shape.number_of_classes = t[0].cast<uint32_t>();
+                nms_shape.max_bboxes_per_class = t[1].cast<uint32_t>();
+                return nms_shape;
+            }
+        ))
         ;
 
     py::class_<hailo_nms_info_t>(m, "NmsInfo")
@@ -1434,6 +804,23 @@ PYBIND11_MODULE(_pyhailort, m) {
         .def_readwrite("qp_scale", &hailo_quant_info_t::qp_scale)
         .def_readwrite("limvals_min", &hailo_quant_info_t::limvals_min)
         .def_readwrite("limvals_max", &hailo_quant_info_t::limvals_max)
+        .def(py::pickle(
+            [](const hailo_quant_info_t &quant_info) { // __getstate__
+                return py::make_tuple(
+                    quant_info.qp_zp,
+                    quant_info.qp_scale,
+                    quant_info.limvals_min,
+                    quant_info.limvals_max);
+            },
+            [](py::tuple t) { // __setstate__
+                hailo_quant_info_t quant_info;
+                quant_info.qp_zp = t[0].cast<float32_t>();
+                quant_info.qp_scale = t[1].cast<float32_t>();
+                quant_info.limvals_min = t[2].cast<float32_t>();
+                quant_info.limvals_max = t[3].cast<float32_t>();
+                return quant_info;
+            }
+        ))
         ;
 
     py::enum_<hailo_mipi_pixels_per_clock_t>(m, "MipiPixelsPerClock")
@@ -1807,6 +1194,43 @@ PYBIND11_MODULE(_pyhailort, m) {
         .def("__repr__", [](const hailo_vstream_info_t &self) {
             return std::string("VStreamInfo(\"") + std::string(self.name) + std::string("\")");
         })
+        .def(py::pickle(
+            [](const hailo_vstream_info_t &vstream_info) { // __getstate__
+                if (HAILO_FORMAT_ORDER_HAILO_NMS == vstream_info.format.order) {
+                    return py::make_tuple(
+                        vstream_info.name,
+                        vstream_info.network_name,
+                        vstream_info.direction,
+                        vstream_info.format,
+                        vstream_info.nms_shape,
+                        vstream_info.quant_info);
+                }
+                else {
+                    return py::make_tuple(
+                        vstream_info.name,
+                        vstream_info.network_name,
+                        vstream_info.direction,
+                        vstream_info.format,
+                        vstream_info.shape,
+                        vstream_info.quant_info);
+                }
+            },
+            [](py::tuple t) { // __setstate__
+                hailo_vstream_info_t vstream_info;
+                strcpy(vstream_info.name, t[0].cast<std::string>().c_str());
+                strcpy(vstream_info.network_name, t[1].cast<std::string>().c_str());
+                vstream_info.direction = t[2].cast<hailo_stream_direction_t>();
+                vstream_info.format = t[3].cast<hailo_format_t>();
+                if (HAILO_FORMAT_ORDER_HAILO_NMS == vstream_info.format.order) {
+                    vstream_info.nms_shape = t[4].cast<hailo_nms_shape_t>();
+                }
+                else {
+                    vstream_info.shape = t[4].cast<hailo_3d_image_shape_t>();
+                }
+                vstream_info.quant_info = t[5].cast<hailo_quant_info_t>();
+                return vstream_info;
+            }
+        ))
         ;
 
     py::class_<hailo_stream_info_t>(m, "StreamInfo", py::module_local())
@@ -1847,23 +1271,18 @@ PYBIND11_MODULE(_pyhailort, m) {
         .def_static("MAX_ALIGNED_UDP_PAYLOAD_SIZE_RTP", []() { return 1472;} )
         ;
 
-    m.def("read_log", &read_log, py::return_value_policy::move);
-    m.def("direct_write_memory", &direct_write_memory);
-    m.def("direct_read_memory", &direct_read_memory);
-    m.def("get_format_data_bytes", &HailoRTCommon::get_format_data_bytes);
-
-    HEF_API_initialize_python_module(m);
+    HefWrapper::initialize_python_module(m);
     VStream_api_initialize_python_module(m);
     VDevice_api_initialize_python_module(m);
+    DeviceWrapper::add_to_python_module(m);
+
     #if defined(__GNUC__)
     TrafficControlUtilWrapper::add_to_python_module(m);
     #endif
 
-#ifdef VERSION_INFO
-    m.attr("__version__") = VERSION_INFO;
-#else
-    m.attr("__version__") = "dev";
-#endif
+    std::stringstream version;
+    version << HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION;
+    m.attr("__version__") = version.str();
 }
 
 } /* namespace hailort */
index 857cfad4c427c1524cbf5b69abde0dac1d8b1b81..48e7d7a2285c47542a23501b901fb4cfaf8d60a1 100644 (file)
@@ -15,7 +15,6 @@
 #include "hailo/hef.hpp"
 #include "hailo/vdevice.hpp"
 
-#include "bindings_common.hpp"
 #include "utils.hpp"
 #include "common/logger_macros.hpp"
 
diff --git a/hailort/libhailort/bindings/python/src/vstream_api.cpp b/hailort/libhailort/bindings/python/src/vstream_api.cpp
new file mode 100644 (file)
index 0000000..2ae7a98
--- /dev/null
@@ -0,0 +1,335 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file vstream_api.cpp
+ * @brief Implementation of binding to virtual stream usage over Python.
+ **/
+
+#include "common/logger_macros.hpp"
+#include "common/utils.hpp"
+
+#include "vstream_api.hpp"
+#include "bindings_common.hpp"
+#include "utils.hpp"
+
+
+namespace hailort
+{
+
+void InputVStreamWrapper::add_to_python_module(py::module &m)
+{
+    py::class_<InputVStream, std::shared_ptr<InputVStream>>(m, "InputVStream")
+    .def("send", [](InputVStream &self, py::array data)
+    {
+        hailo_status status = self.write(
+            MemoryView(const_cast<void*>(reinterpret_cast<const void*>(data.data())), data.nbytes()));
+        VALIDATE_STATUS(status);
+    })
+    .def("flush", [](InputVStream &self)
+    {
+        hailo_status status = self.flush();
+        VALIDATE_STATUS(status);
+    })
+    .def_property_readonly("info", [](InputVStream &self)
+    {
+        return self.get_info();
+    })
+    .def_property_readonly("dtype", [](InputVStream &self)
+    {
+        const auto format_type = self.get_user_buffer_format().type;
+        return HailoRTBindingsCommon::get_dtype(format_type);
+    })
+    .def_property_readonly("shape", [](InputVStream &self)
+    {
+        return *py::array::ShapeContainer(HailoRTBindingsCommon::get_pybind_shape(self.get_info(), self.get_user_buffer_format()));
+    })
+    ;
+}
+
+InputVStreamsWrapper InputVStreamsWrapper::create(ConfiguredNetworkGroup &net_group,
+    const std::map<std::string, hailo_vstream_params_t> &input_vstreams_params)
+{
+    auto input_vstreams_expected = VStreamsBuilder::create_input_vstreams(net_group, input_vstreams_params);
+    VALIDATE_STATUS(input_vstreams_expected.status());
+
+    std::unordered_map<std::string, std::shared_ptr<InputVStream>> input_vstreams;
+    for (auto &input : input_vstreams_expected.value()) {
+        input_vstreams.emplace(input.name(), make_shared_nothrow<InputVStream>(std::move(input)));
+    }
+    return InputVStreamsWrapper(input_vstreams);
+}
+
+const InputVStreamsWrapper &InputVStreamsWrapper::enter()
+{
+    return std::ref(*this);
+}
+
+void InputVStreamsWrapper::exit()
+{
+    m_input_vstreams.clear();
+}
+
+std::shared_ptr<InputVStream> InputVStreamsWrapper::get_input_by_name(const std::string &name) 
+{
+    auto input = m_input_vstreams.find(name);
+    if (m_input_vstreams.end() == input) {
+        LOGGER__ERROR("Input virtual stream for name={} not found", name);
+        THROW_STATUS_ERROR(HAILO_NOT_FOUND);
+    }
+
+    return input->second;
+}
+
+py::dict InputVStreamsWrapper::get_all_inputs()
+{
+    return py::cast(m_input_vstreams);
+}
+
+void InputVStreamsWrapper::clear()
+{
+    std::vector<std::reference_wrapper<InputVStream>> inputs;
+    inputs.reserve(m_input_vstreams.size());
+    for (auto &name_vstream_pair : m_input_vstreams) {
+        inputs.emplace_back(std::ref(*name_vstream_pair.second));
+    }
+    
+    auto status = InputVStream::clear(inputs);
+    VALIDATE_STATUS(status);
+}
+
+void InputVStreamsWrapper::add_to_python_module(py::module &m)
+{
+    py::class_<InputVStreamsWrapper>(m, "InputVStreams")
+    .def(py::init(&InputVStreamsWrapper::create))
+    .def("get_input_by_name", &InputVStreamsWrapper::get_input_by_name)
+    .def("get_all_inputs", &InputVStreamsWrapper::get_all_inputs)
+    .def("clear", &InputVStreamsWrapper::clear)
+    .def("__enter__", &InputVStreamsWrapper::enter, py::return_value_policy::reference)
+    .def("__exit__",  [&](InputVStreamsWrapper &self, py::args) { self.exit(); })
+    ;
+}
+
+InputVStreamsWrapper::InputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<InputVStream>> &input_vstreams)
+    : m_input_vstreams(std::move(input_vstreams))
+{}
+
+py::dtype OutputVStreamWrapper::get_dtype(OutputVStream &self)
+{
+    const auto format_type = self.get_user_buffer_format().type;
+    return HailoRTBindingsCommon::get_dtype(format_type);
+}
+
+hailo_format_t OutputVStreamWrapper::get_user_buffer_format(OutputVStream &self)
+{
+    const auto format = self.get_user_buffer_format();
+    return format;
+}
+
+auto OutputVStreamWrapper::get_shape(OutputVStream &self)
+{
+    return *py::array::ShapeContainer(HailoRTBindingsCommon::get_pybind_shape(self.get_info(), self.get_user_buffer_format()));
+}
+
+void OutputVStreamWrapper::add_to_python_module(py::module &m)
+{
+    py::class_<OutputVStream, std::shared_ptr<OutputVStream>>(m, "OutputVStream")
+    .def("recv", [](OutputVStream &self)
+    {
+        auto buffer = Buffer::create(self.get_frame_size());
+        VALIDATE_STATUS(buffer.status());
+
+        hailo_status status = self.read(MemoryView(buffer->data(), buffer->size()));
+        VALIDATE_STATUS(status);
+
+        // Note: The ownership of the buffer is transferred to Python wrapped as a py::array.
+        //       When the py::array isn't referenced anymore in Python and is destructed, the py::capsule's dtor
+        //       is called too (and it deletes the raw buffer)
+        const auto unmanaged_addr = buffer.release().release();
+        return py::array(get_dtype(self), get_shape(self), unmanaged_addr,
+            py::capsule(unmanaged_addr, [](void *p) { delete reinterpret_cast<uint8_t*>(p); }));
+    })
+    .def_property_readonly("info", [](OutputVStream &self)
+    {
+        return self.get_info();
+    })
+    .def_property_readonly("dtype", &OutputVStreamWrapper::get_dtype)
+    .def_property_readonly("shape", &OutputVStreamWrapper::get_shape)
+    .def("get_user_buffer_format", &OutputVStreamWrapper::get_user_buffer_format)
+    ;
+}
+
+OutputVStreamsWrapper OutputVStreamsWrapper::create(ConfiguredNetworkGroup &net_group,
+        const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params)
+{
+    auto output_vstreams_expected = VStreamsBuilder::create_output_vstreams(net_group, output_vstreams_params);
+    VALIDATE_STATUS(output_vstreams_expected.status());
+
+    std::unordered_map<std::string, std::shared_ptr<OutputVStream>> output_vstreams;
+    for (auto &output : output_vstreams_expected.value()) {
+        output_vstreams.emplace(output.name(), make_shared_nothrow<OutputVStream>(std::move(output)));
+    }
+    return OutputVStreamsWrapper(output_vstreams);
+}
+
+std::shared_ptr<OutputVStream> OutputVStreamsWrapper::get_output_by_name(const std::string &name)
+{
+    auto output = m_output_vstreams.find(name);
+    if (m_output_vstreams.end() == output) {
+        LOGGER__ERROR("Output virtual stream for name={} not found", name);
+        THROW_STATUS_ERROR(HAILO_NOT_FOUND);
+    }
+
+    return output->second;
+}
+
+const OutputVStreamsWrapper &OutputVStreamsWrapper::enter()
+{
+    return std::ref(*this);
+}
+
+void OutputVStreamsWrapper::exit()
+{
+    m_output_vstreams.clear();
+}
+
+py::dict OutputVStreamsWrapper::get_all_outputs()
+{
+    return py::cast(m_output_vstreams);
+}
+
+void OutputVStreamsWrapper::clear()
+{
+    std::vector<std::reference_wrapper<OutputVStream>> outputs;
+    outputs.reserve(m_output_vstreams.size());
+    for (auto &name_vstream_pair : m_output_vstreams) {
+        outputs.emplace_back(std::ref(*name_vstream_pair.second));
+    }
+    
+    auto status = OutputVStream::clear(outputs);
+    VALIDATE_STATUS(status);
+}
+
+void OutputVStreamsWrapper::add_to_python_module(py::module &m)
+{
+    py::class_<OutputVStreamsWrapper>(m, "OutputVStreams")
+    .def(py::init(&OutputVStreamsWrapper::create))
+    .def("get_output_by_name", &OutputVStreamsWrapper::get_output_by_name)
+    .def("get_all_outputs", &OutputVStreamsWrapper::get_all_outputs)
+    .def("clear", &OutputVStreamsWrapper::clear)
+    .def("__enter__", &OutputVStreamsWrapper::enter, py::return_value_policy::reference)
+    .def("__exit__",  [&](OutputVStreamsWrapper &self, py::args) { self.exit(); })
+    ;
+}
+
+OutputVStreamsWrapper::OutputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<OutputVStream>> &output_vstreams)
+    : m_output_vstreams(std::move(output_vstreams))
+{}
+
+InferVStreamsWrapper InferVStreamsWrapper::create(ConfiguredNetworkGroup &network_group,
+    const std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
+    const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params)
+{
+    auto infer_pipeline = InferVStreams::create(network_group, input_vstreams_params, output_vstreams_params);
+    VALIDATE_EXPECTED(infer_pipeline);
+    auto infer_vstream_ptr = make_shared_nothrow<InferVStreams>(std::move(infer_pipeline.value()));
+
+    return InferVStreamsWrapper(infer_vstream_ptr);
+}
+
+void InferVStreamsWrapper::infer(std::map<std::string, py::array> input_data, std::map<std::string, py::array> output_data,
+    size_t batch_size)
+{
+    std::map<std::string, MemoryView> input_data_c;
+    std::map<std::string, MemoryView> output_data_c;
+
+    for (auto& name_pair : input_data) {
+        input_data_c.emplace(name_pair.first, MemoryView(name_pair.second.mutable_data(),
+            static_cast<size_t>(name_pair.second.nbytes())));
+    }
+
+    for (auto& name_pair : output_data) {
+        output_data_c.emplace(name_pair.first, MemoryView(name_pair.second.mutable_data(),
+            static_cast<size_t>(name_pair.second.nbytes())));
+    }
+
+    hailo_status status = m_infer_pipeline->infer(input_data_c, output_data_c, batch_size);
+    VALIDATE_STATUS(status);
+}
+
+py::dtype InferVStreamsWrapper::get_host_dtype(const std::string &stream_name)
+{
+    auto input = m_infer_pipeline->get_input_by_name(stream_name);
+    if (HAILO_SUCCESS == input.status()) {
+        return HailoRTBindingsCommon::get_dtype(input->get().get_user_buffer_format().type);
+    } else if (HAILO_NOT_FOUND != input.status()) {
+        THROW_STATUS_ERROR(input.status());
+    }
+    auto output = m_infer_pipeline->get_output_by_name(stream_name);
+    VALIDATE_EXPECTED(output);
+
+    return HailoRTBindingsCommon::get_dtype(output->get().get_user_buffer_format().type);
+}
+
+hailo_format_t InferVStreamsWrapper::get_user_buffer_format(const std::string &stream_name)
+{
+    auto input = m_infer_pipeline->get_input_by_name(stream_name);
+    if (HAILO_SUCCESS == input.status()) {
+        return input->get().get_user_buffer_format();
+    } else if (HAILO_NOT_FOUND != input.status()) {
+        THROW_STATUS_ERROR(input.status());
+    }
+    auto output = m_infer_pipeline->get_output_by_name(stream_name);
+    VALIDATE_EXPECTED(output);
+
+    return output->get().get_user_buffer_format();
+}
+
+std::vector<size_t> InferVStreamsWrapper::get_shape(const std::string &stream_name)
+{
+    auto input = m_infer_pipeline->get_input_by_name(stream_name);
+    if (HAILO_SUCCESS == input.status()) {
+        return HailoRTBindingsCommon::get_pybind_shape(input->get().get_info(), input->get().get_user_buffer_format());
+    }
+
+    auto output = m_infer_pipeline->get_output_by_name(stream_name);
+    if (HAILO_SUCCESS == output.status()) {
+        return HailoRTBindingsCommon::get_pybind_shape(output->get().get_info(), output->get().get_user_buffer_format());
+    }
+
+    LOGGER__ERROR("Stream {} not found", stream_name);
+    THROW_STATUS_ERROR(HAILO_NOT_FOUND);
+}
+
+void InferVStreamsWrapper::release()
+{
+    m_infer_pipeline.reset();
+}
+
+void InferVStreamsWrapper::add_to_python_module(py::module &m)
+{
+    py::class_<InferVStreamsWrapper>(m, "InferVStreams")
+    .def(py::init(&InferVStreamsWrapper::create))
+    .def("get_host_dtype", &InferVStreamsWrapper::get_host_dtype)
+    .def("get_shape", &InferVStreamsWrapper::get_shape)
+    .def("get_user_buffer_format", &InferVStreamsWrapper::get_user_buffer_format)
+    .def("infer", &InferVStreamsWrapper::infer)
+    .def("release",  [](InferVStreamsWrapper &self, py::args) { self.release(); })
+    ;
+}
+
+InferVStreamsWrapper::InferVStreamsWrapper(std::shared_ptr<InferVStreams> &infer_pipeline)
+    : m_infer_pipeline(std::move(infer_pipeline))
+{}
+
+void VStream_api_initialize_python_module(py::module &m)
+{
+    InputVStreamWrapper::add_to_python_module(m);
+    InputVStreamsWrapper::add_to_python_module(m);
+    OutputVStreamWrapper::add_to_python_module(m);
+    OutputVStreamsWrapper::add_to_python_module(m);
+    InferVStreamsWrapper::add_to_python_module(m);
+}
+
+} /* namespace hailort */
index 1c7625631c3abb5f7b34fbe9971be2a300f461c4..2f384054cd4e1db0f457f49688b187ad36c37a19 100644 (file)
@@ -14,7 +14,6 @@
 #include "common/utils.hpp"
 #include "hailo/vstream.hpp"
 #include "hailo/inference_pipeline.hpp"
-#include "bindings_common.hpp"
 #include "utils.hpp"
 
 #include <pybind11/pybind11.h>
@@ -29,234 +28,49 @@ namespace hailort
 class InputVStreamWrapper final
 {
 public:
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<InputVStream, std::shared_ptr<InputVStream>>(m, "InputVStream")
-        .def("send", [](InputVStream &self, py::array data)
-        {
-            hailo_status status = self.write(
-                MemoryView(const_cast<void*>(reinterpret_cast<const void*>(data.data())), data.nbytes()));
-            VALIDATE_STATUS(status);
-        })
-        .def("flush", [](InputVStream &self)
-        {
-            hailo_status status = self.flush();
-            VALIDATE_STATUS(status);
-        })
-        .def_property_readonly("info", [](InputVStream &self)
-        {
-            return self.get_info();
-        })
-        .def_property_readonly("dtype", [](InputVStream &self)
-        {
-            const auto format_type = self.get_user_buffer_format().type;
-            return py::dtype(convert_format_type_to_string(format_type));
-        })
-        .def_property_readonly("shape", [](InputVStream &self)
-        {
-            return *py::array::ShapeContainer(get_pybind_shape(self.get_info(), self.get_user_buffer_format()));
-        })
-        ;
-    }
+    static void add_to_python_module(py::module &m);
 };
 
 class InputVStreamsWrapper final 
 {
 public:
-
     static InputVStreamsWrapper create(ConfiguredNetworkGroup &net_group,
-        const std::map<std::string, hailo_vstream_params_t> &input_vstreams_params)
-    {
-        auto input_vstreams_expected = VStreamsBuilder::create_input_vstreams(net_group, input_vstreams_params);
-        VALIDATE_STATUS(input_vstreams_expected.status());
-
-        std::unordered_map<std::string, std::shared_ptr<InputVStream>> input_vstreams;
-        for (auto &input : input_vstreams_expected.value()) {
-            input_vstreams.emplace(input.name(), make_shared_nothrow<InputVStream>(std::move(input)));
-        }
-        return InputVStreamsWrapper(input_vstreams);
-    }
-
-    const InputVStreamsWrapper &enter()
-    {
-        return std::ref(*this);
-    }
-
-    void exit()
-    {
-        m_input_vstreams.clear();
-    }
-
-    std::shared_ptr<InputVStream> get_input_by_name(const std::string &name) 
-    {
-        auto input = m_input_vstreams.find(name);
-        if (m_input_vstreams.end() == input) {
-            LOGGER__ERROR("Input virtual stream for name={} not found", name);
-            THROW_STATUS_ERROR(HAILO_NOT_FOUND);
-        }
-
-        return input->second;
-    }
-
-    py::dict get_all_inputs()
-    {
-        return py::cast(m_input_vstreams);
-    }
-
-    void clear()
-    {
-        std::vector<std::reference_wrapper<InputVStream>> inputs;
-        inputs.reserve(m_input_vstreams.size());
-        for (auto &name_vstream_pair : m_input_vstreams) {
-            inputs.emplace_back(std::ref(*name_vstream_pair.second));
-        }
-        
-        auto status = InputVStream::clear(inputs);
-        VALIDATE_STATUS(status);
-    }
-
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<InputVStreamsWrapper>(m, "InputVStreams")
-        .def(py::init(&InputVStreamsWrapper::create))
-        .def("get_input_by_name", &InputVStreamsWrapper::get_input_by_name)
-        .def("get_all_inputs", &InputVStreamsWrapper::get_all_inputs)
-        .def("clear", &InputVStreamsWrapper::clear)
-        .def("__enter__", &InputVStreamsWrapper::enter, py::return_value_policy::reference)
-        .def("__exit__",  [&](InputVStreamsWrapper &self, py::args) { self.exit(); })
-        ;
-    }
+        const std::map<std::string, hailo_vstream_params_t> &input_vstreams_params);
+    const InputVStreamsWrapper &enter();
+    void exit();
+    std::shared_ptr<InputVStream> get_input_by_name(const std::string &name);
+    py::dict get_all_inputs();
+    void clear();
+    static void add_to_python_module(py::module &m);
 
 private:
-    InputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<InputVStream>> &input_vstreams) :
-        m_input_vstreams(std::move(input_vstreams))
-    {}
-
+    InputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<InputVStream>> &input_vstreams);
     std::unordered_map<std::string, std::shared_ptr<InputVStream>> m_input_vstreams;
 };
 
 class OutputVStreamWrapper final
 {
 public:
-
-    static py::dtype get_dtype(OutputVStream &self)
-    {
-        const auto format_type = self.get_user_buffer_format().type;
-        return py::dtype(convert_format_type_to_string(format_type));
-    }
-
-    static hailo_format_t get_user_buffer_format(OutputVStream &self)
-    {
-        const auto format = self.get_user_buffer_format();
-        return format;
-    }
-    
-    static auto get_shape(OutputVStream &self)
-    {
-        return *py::array::ShapeContainer(get_pybind_shape(self.get_info(), self.get_user_buffer_format()));
-    }
-
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<OutputVStream, std::shared_ptr<OutputVStream>>(m, "OutputVStream")
-        .def("recv", [](OutputVStream &self)
-        {
-            auto buffer = Buffer::create(self.get_frame_size());
-            VALIDATE_STATUS(buffer.status());
-
-            hailo_status status = self.read(MemoryView(buffer->data(), buffer->size()));
-            VALIDATE_STATUS(status);
-
-            // Note: The ownership of the buffer is transferred to Python wrapped as a py::array.
-            //       When the py::array isn't referenced anymore in Python and is destructed, the py::capsule's dtor
-            //       is called too (and it deletes the raw buffer)
-            const auto unmanaged_addr = buffer.release().release();
-            return py::array(get_dtype(self), get_shape(self), unmanaged_addr,
-                py::capsule(unmanaged_addr, [](void *p) { delete reinterpret_cast<uint8_t*>(p); }));
-        })
-        .def_property_readonly("info", [](OutputVStream &self)
-        {
-            return self.get_info();
-        })
-        .def_property_readonly("dtype", &OutputVStreamWrapper::get_dtype)
-        .def_property_readonly("shape", &OutputVStreamWrapper::get_shape)
-        .def("get_user_buffer_format", &OutputVStreamWrapper::get_user_buffer_format)
-        ;
-    }
+    static py::dtype get_dtype(OutputVStream &self);
+    static hailo_format_t get_user_buffer_format(OutputVStream &self);
+    static auto get_shape(OutputVStream &self);
+    static void add_to_python_module(py::module &m);
 };
 
 class OutputVStreamsWrapper final
 {
 public:
-
     static OutputVStreamsWrapper create(ConfiguredNetworkGroup &net_group,
-        const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params)
-    {
-        auto output_vstreams_expected = VStreamsBuilder::create_output_vstreams(net_group, output_vstreams_params);
-        VALIDATE_STATUS(output_vstreams_expected.status());
-
-        std::unordered_map<std::string, std::shared_ptr<OutputVStream>> output_vstreams;
-        for (auto &output : output_vstreams_expected.value()) {
-            output_vstreams.emplace(output.name(), make_shared_nothrow<OutputVStream>(std::move(output)));
-        }
-        return OutputVStreamsWrapper(output_vstreams);
-    }
-
-    std::shared_ptr<OutputVStream> get_output_by_name(const std::string &name)
-    {
-        auto output = m_output_vstreams.find(name);
-        if (m_output_vstreams.end() == output) {
-            LOGGER__ERROR("Output virtual stream for name={} not found", name);
-            THROW_STATUS_ERROR(HAILO_NOT_FOUND);
-        }
-
-        return output->second;
-    }
-
-    const OutputVStreamsWrapper &enter()
-    {
-        return std::ref(*this);
-    }
-
-    void exit()
-    {
-        m_output_vstreams.clear();
-    }
-
-    py::dict get_all_outputs()
-    {
-        return py::cast(m_output_vstreams);
-    }
-
-    void clear()
-    {
-        std::vector<std::reference_wrapper<OutputVStream>> outputs;
-        outputs.reserve(m_output_vstreams.size());
-        for (auto &name_vstream_pair : m_output_vstreams) {
-            outputs.emplace_back(std::ref(*name_vstream_pair.second));
-        }
-        
-        auto status = OutputVStream::clear(outputs);
-        VALIDATE_STATUS(status);
-    }
-
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<OutputVStreamsWrapper>(m, "OutputVStreams")
-        .def(py::init(&OutputVStreamsWrapper::create))
-        .def("get_output_by_name", &OutputVStreamsWrapper::get_output_by_name)
-        .def("get_all_outputs", &OutputVStreamsWrapper::get_all_outputs)
-        .def("clear", &OutputVStreamsWrapper::clear)
-        .def("__enter__", &OutputVStreamsWrapper::enter, py::return_value_policy::reference)
-        .def("__exit__",  [&](OutputVStreamsWrapper &self, py::args) { self.exit(); })
-        ;
-    }
+        const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params);
+    std::shared_ptr<OutputVStream> get_output_by_name(const std::string &name);
+    const OutputVStreamsWrapper &enter();
+    void exit();
+    py::dict get_all_outputs();
+    void clear();
+    static void add_to_python_module(py::module &m);
 
 private:
-    OutputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<OutputVStream>> &output_vstreams) :
-        m_output_vstreams(std::move(output_vstreams))
-    {}
-
+    OutputVStreamsWrapper(std::unordered_map<std::string, std::shared_ptr<OutputVStream>> &output_vstreams);
     std::unordered_map<std::string, std::shared_ptr<OutputVStream>> m_output_vstreams;
 };
 
@@ -265,113 +79,22 @@ class InferVStreamsWrapper final
 public:
     static InferVStreamsWrapper create(ConfiguredNetworkGroup &network_group,
         const std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
-        const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params)
-    {
-        auto infer_pipeline = InferVStreams::create(network_group, input_vstreams_params, output_vstreams_params);
-        VALIDATE_EXPECTED(infer_pipeline);
-        auto infer_vstream_ptr = make_shared_nothrow<InferVStreams>(std::move(infer_pipeline.value()));
-
-        return InferVStreamsWrapper(infer_vstream_ptr);
-    }
-
+        const std::map<std::string, hailo_vstream_params_t> &output_vstreams_params);
     void infer(std::map<std::string, py::array> input_data, std::map<std::string, py::array> output_data,
-        size_t batch_size)
-    {
-        std::map<std::string, MemoryView> input_data_c;
-        std::map<std::string, MemoryView> output_data_c;
-
-        for (auto& name_pair : input_data) {
-            input_data_c.emplace(name_pair.first, MemoryView(name_pair.second.mutable_data(),
-                static_cast<size_t>(name_pair.second.nbytes())));
-        }
-
-        for (auto& name_pair : output_data) {
-            output_data_c.emplace(name_pair.first, MemoryView(name_pair.second.mutable_data(),
-                static_cast<size_t>(name_pair.second.nbytes())));
-        }
-
-        hailo_status status = m_infer_pipeline->infer(input_data_c, output_data_c, batch_size);
-        VALIDATE_STATUS(status);
-    }
-
-    py::dtype get_host_dtype(const std::string &stream_name)
-    {
-        auto input = m_infer_pipeline->get_input_by_name(stream_name);
-        if (HAILO_SUCCESS == input.status()) {
-            return py::dtype(convert_format_type_to_string(input->get().get_user_buffer_format().type));
-        } else if (HAILO_NOT_FOUND != input.status()) {
-            THROW_STATUS_ERROR(input.status());
-        }
-        auto output = m_infer_pipeline->get_output_by_name(stream_name);
-        VALIDATE_EXPECTED(output);
-
-        return py::dtype(convert_format_type_to_string(output->get().get_user_buffer_format().type));
-    }
-
-    hailo_format_t get_user_buffer_format(const std::string &stream_name)
-    {
-        auto input = m_infer_pipeline->get_input_by_name(stream_name);
-        if (HAILO_SUCCESS == input.status()) {
-            return input->get().get_user_buffer_format();
-        } else if (HAILO_NOT_FOUND != input.status()) {
-            THROW_STATUS_ERROR(input.status());
-        }
-        auto output = m_infer_pipeline->get_output_by_name(stream_name);
-        VALIDATE_EXPECTED(output);
-
-        return output->get().get_user_buffer_format();
-    }
-
-    std::vector<size_t> get_shape(const std::string &stream_name)
-    {
-        auto input = m_infer_pipeline->get_input_by_name(stream_name);
-        if (HAILO_SUCCESS == input.status()) {
-            return get_pybind_shape(input->get().get_info(), input->get().get_user_buffer_format());
-        }
-
-        auto output = m_infer_pipeline->get_output_by_name(stream_name);
-        if (HAILO_SUCCESS == output.status()) {
-            return get_pybind_shape(output->get().get_info(), output->get().get_user_buffer_format());
-        }
-
-        LOGGER__ERROR("Stream {} not found", stream_name);
-        THROW_STATUS_ERROR(HAILO_NOT_FOUND);
-    }
-
-    void release()
-    {
-        m_infer_pipeline.reset();
-    }
-
-    static void add_to_python_module(py::module &m)
-    {
-        py::class_<InferVStreamsWrapper>(m, "InferVStreams")
-        .def(py::init(&InferVStreamsWrapper::create))
-        .def("get_host_dtype", &InferVStreamsWrapper::get_host_dtype)
-        .def("get_shape", &InferVStreamsWrapper::get_shape)
-        .def("get_user_buffer_format", &InferVStreamsWrapper::get_user_buffer_format)
-        .def("infer", &InferVStreamsWrapper::infer)
-        .def("release",  [](InferVStreamsWrapper &self, py::args) { self.release(); })
-        ;
-    }
+        size_t batch_size);
+    py::dtype get_host_dtype(const std::string &stream_name);
+    hailo_format_t get_user_buffer_format(const std::string &stream_name);
+    std::vector<size_t> get_shape(const std::string &stream_name);
+    void release();
+    static void add_to_python_module(py::module &m);
 
 private:
-    InferVStreamsWrapper(std::shared_ptr<InferVStreams> &infer_pipeline) :
-        m_infer_pipeline(std::move(infer_pipeline))
-    {}
-
-     std::shared_ptr<InferVStreams> m_infer_pipeline;
+    InferVStreamsWrapper(std::shared_ptr<InferVStreams> &infer_pipeline);
+    
+    std::shared_ptr<InferVStreams> m_infer_pipeline;
 };
 
-void VStream_api_initialize_python_module(py::module &m)
-{
-    InputVStreamWrapper::add_to_python_module(m);
-    InputVStreamsWrapper::add_to_python_module(m);
-    OutputVStreamWrapper::add_to_python_module(m);
-    OutputVStreamsWrapper::add_to_python_module(m);
-    InferVStreamsWrapper::add_to_python_module(m);
-}
-
+void VStream_api_initialize_python_module(py::module &m);
 } /* namespace hailort */
 
 #endif // _VSTREAM_API_HPP_
index c476c20203dd5f1f58a5274cddf9b25ae7be3fd4..721da10f5b04e78bda5f0e66a5e4044e0940692d 100644 (file)
@@ -1,22 +1,50 @@
-set(CMAKE_SYSTEM_NAME QNX)
-set(arch ntoaarch64)
-set(QNX_PROCESSOR aarch64)
+# CMake added fix for QCC compiler in this version - will not compile in older versions
+cmake_minimum_required(VERSION 3.14.0)
 
-set(CMAKE_C_COMPILER $ENV{QNX_HOST}/usr/bin/${arch}-gcc)
-set(CMAKE_C_COMPILER_TARGET ${arch})
+set(CMAKE_SYSTEM_NAME QNX)
+set(QNX_PROCESSOR aarch64le)
+SET(CMAKE_SYSTEM_PROCESSOR aarch64)
 
-set(CMAKE_CXX_COMPILER $ENV{QNX_HOST}/usr/bin/${arch}-g++)
-set(CMAKE_CXX_COMPILER_TARGET ${arch})
+SET(CMAKE_MAKE_PROGRAM "$ENV{QNX_HOST}/usr/bin/make"                                  CACHE PATH "QNX Make Program")
+SET(CMAKE_SH           "$ENV{QNX_HOST}/usr/bin/sh "                                   CACHE PATH "QNX shell Program")
+SET(CMAKE_AR           "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ar"       CACHE PATH "QNX ar Program")
+SET(CMAKE_RANLIB       "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ranlib"   CACHE PATH "QNX ranlib Program")
+SET(CMAKE_NM           "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-nm"       CACHE PATH "QNX nm Program")
+SET(CMAKE_OBJCOPY      "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-objcopy"  CACHE PATH "QNX objcopy Program")
+SET(CMAKE_OBJDUMP      "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-objdump"  CACHE PATH "QNX objdump Program")
+SET(CMAKE_LINKER       "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ld"       CACHE PATH "QNX Linker Program")
+SET(CMAKE_STRIP        "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-strip"    CACHE PATH "QNX Strip Program")
 
 add_definitions("-D_QNX_SOURCE")
 
-file(GLOB_RECURSE libgcc_a 
-  "$ENV{QNX_HOST}/usr/lib/gcc/${QNX_PROCESSOR}*/*/pic/libgcc.a")
+SET(CMAKE_SHARED_LIBRARY_PREFIX "lib")
+SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
+SET(CMAKE_STATIC_LIBRARY_PREFIX "lib")
+SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
+
+SET(CMAKE_C_COMPILER $ENV{QNX_HOST}/usr/bin/qcc)
+SET(CMAKE_C_FLAGS_DEBUG "-g")
+SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
+SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
+
+SET(CMAKE_CXX_COMPILER $ENV{QNX_HOST}/usr/bin/q++)
+SET(CMAKE_CXX_FLAGS_DEBUG "-g")
+SET(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
+
+LIST(APPEND CMAKE_FIND_ROOT_PATH $ENV{QNX_TARGET})
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+SET(CMAKE_C_FLAGS "-Vgcc_nto${QNX_PROCESSOR}" CACHE STRING "qcc c flags" FORCE)
+SET(CMAKE_CXX_FLAGS "-Vgcc_nto${QNX_PROCESSOR} -lang-c++ -Y_cxx" CACHE STRING "qcc cxx flags" FORCE)
 
-set(CMAKE_C_STANDARD_LIBRARIES_INIT
-  "${libgcc_a} -lc -lsocket -Bstatic -lcS")
-set(CMAKE_CXX_STANDARD_LIBRARIES_INIT
-  "-lc++ -lstdc++ -lm ${CMAKE_C_STANDARD_LIBRARIES_INIT}")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "exe_linker_flags")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "so_linker_flags")
 
 # pybind is not supported in this platform
 set(HAILO_BUILD_PYBIND 0)
index 2108b4f264da37bd5f87c26fb00ab519aaf96e82..1b885dea50ecb4dc2474ca5b56478532f561d88f 100644 (file)
@@ -1,22 +1,50 @@
+# CMake added fix for QCC compiler in this version - will not compile in older versions
+cmake_minimum_required(VERSION 3.14.0)
+
 set(CMAKE_SYSTEM_NAME QNX)
-set(arch ntox86_64)
 set(QNX_PROCESSOR x86_64)
+SET(CMAKE_SYSTEM_PROCESSOR x86_64)
 
-set(CMAKE_C_COMPILER $ENV{QNX_HOST}/usr/bin/${arch}-gcc)
-set(CMAKE_C_COMPILER_TARGET ${arch})
-
-set(CMAKE_CXX_COMPILER $ENV{QNX_HOST}/usr/bin/${arch}-g++)
-set(CMAKE_CXX_COMPILER_TARGET ${arch})
+SET(CMAKE_MAKE_PROGRAM "$ENV{QNX_HOST}/usr/bin/make"                                  CACHE PATH "QNX Make Program")
+SET(CMAKE_SH           "$ENV{QNX_HOST}/usr/bin/sh "                                   CACHE PATH "QNX shell Program")
+SET(CMAKE_AR           "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ar"       CACHE PATH "QNX ar Program")
+SET(CMAKE_RANLIB       "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ranlib"   CACHE PATH "QNX ranlib Program")
+SET(CMAKE_NM           "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-nm"       CACHE PATH "QNX nm Program")
+SET(CMAKE_OBJCOPY      "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-objcopy"  CACHE PATH "QNX objcopy Program")
+SET(CMAKE_OBJDUMP      "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-objdump"  CACHE PATH "QNX objdump Program")
+SET(CMAKE_LINKER       "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-ld"       CACHE PATH "QNX Linker Program")
+SET(CMAKE_STRIP        "$ENV{QNX_HOST}/usr/bin/nto${CMAKE_SYSTEM_PROCESSOR}-strip"    CACHE PATH "QNX Strip Program")
 
 add_definitions("-D_QNX_SOURCE")
 
-file(GLOB_RECURSE libgcc_a 
-  "$ENV{QNX_HOST}/usr/lib/gcc/${QNX_PROCESSOR}*/*/pic/libgcc.a")
+SET(CMAKE_SHARED_LIBRARY_PREFIX "lib")
+SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
+SET(CMAKE_STATIC_LIBRARY_PREFIX "lib")
+SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
+
+SET(CMAKE_C_COMPILER $ENV{QNX_HOST}/usr/bin/qcc)
+SET(CMAKE_C_FLAGS_DEBUG "-g")
+SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
+SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
+
+SET(CMAKE_CXX_COMPILER $ENV{QNX_HOST}/usr/bin/q++)
+SET(CMAKE_CXX_FLAGS_DEBUG "-g")
+SET(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
+
+LIST(APPEND CMAKE_FIND_ROOT_PATH $ENV{QNX_TARGET})
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+SET(CMAKE_C_FLAGS "-Vgcc_nto${QNX_PROCESSOR}" CACHE STRING "qcc c flags" FORCE)
+SET(CMAKE_CXX_FLAGS "-Vgcc_nto${QNX_PROCESSOR} -lang-c++ -Y_cxx" CACHE STRING "qcc cxx flags" FORCE)
 
-set(CMAKE_C_STANDARD_LIBRARIES_INIT
-  "${libgcc_a} -lc -lsocket -Bstatic -lcS")
-set(CMAKE_CXX_STANDARD_LIBRARIES_INIT
-  "-lc++ -lstdc++ -lm ${CMAKE_C_STANDARD_LIBRARIES_INIT}")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "exe_linker_flags")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--build-id=md5 -lang-c++ -lsocket ${EXTRA_CMAKE_LINKER_FLAGS}" CACHE STRING "so_linker_flags")
 
 # pybind is not supported in this platform
 set(HAILO_BUILD_PYBIND 0)
index 460fa139697662d665b99baa52b2d0cc4e15c8b4..3c5abf64a0ada59a05d2aea5a05031e54f0f4d6a 100644 (file)
@@ -12,6 +12,9 @@
     -   version: '3.8'
         installation: deb
         package_name: python3.8-dev
+    -   version: '3.9'
+        installation: deb
+        package_name: python3.9-dev
 -   name: linux.aarch64
     required_packages:
     -   gcc-aarch64-linux-gnu
         installation: manual
         package_name: https://launchpad.net/ubuntu/+source/python3.8/3.8.2-1ubuntu1/+build/18834117/+files/libpython3.8-dev_3.8.2-1ubuntu1_arm64.deb        
         package_dest: /usr/include/aarch64-linux-gnu
+    -   version: '3.9'
+        installation: manual
+        package_name: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa/+build/23779329/+files/libpython3.9-dev_3.9.13-1+bionic1_arm64.deb
+        package_dest: /usr/include/aarch64-linux-gnu
 -   name: linux.armv7l
     required_packages:
     -   gcc-arm-linux-gnueabi
index 401e511e0e50dfa05b8b4b712b04eafcfe47b406..06bc93bd02acb9590e2cd8093644bd935ae5d015 100644 (file)
@@ -2,11 +2,11 @@ cmake_minimum_required(VERSION 3.0.0)
 
 project(hailort-examples)
 
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/")
-find_package(HailoRT)
 find_package(Threads REQUIRED)
 set(THREADS_PREFER_PTHREAD_FLAG ON)
 
+find_package(HailoRT 4.8.0 EXACT REQUIRED)
+
 add_library(example_base INTERFACE)
 target_link_libraries(example_base INTERFACE HailoRT::libhailort Threads::Threads)
 
@@ -19,4 +19,6 @@ endif()
 add_subdirectory(cpp)
 add_subdirectory(c)
 
+set_target_properties(${EXAMPLES_CPP_TARGETS} PROPERTIES CXX_STANDARD 14)
+
 add_custom_target(hailort_examples DEPENDS ${EXAMPLES_C_TARGETS} ${EXAMPLES_CPP_TARGETS})
\ No newline at end of file
index 21f481353797133be49f63bbc16b386cfc0e999d..fd429244ad958449e3fdf37c1cbbc638e1209f12 100644 (file)
@@ -5,28 +5,38 @@ The following examples are provided, demonstrating the HailoRT API:
     - Configure and activate network group and virtual streams.
     - The data is sent to the device via input vstreams and received via output vstreams.
     - The data is transformed before sent and after receiving in a different thread using the virtual stream pipeline.
-  - `raw_streams_example` - Basic inference of a shortcut network using raw stream api.
-    - The data is transformed before sent and after received in the same thread sending/receiving using the transformation api.
-  - `data_quantization_example` - Demonstrates how to set input/output stream params so as to allow for custom quantization:
-    - Input streams may be marked as quantized, so that input data will not to be automatically quantized by the HailoRT library.
-    - Output streams may be marked as quantized, so that output data will remain quantized (as it is after exiting the device by default), and won't be 'de-quantized' by the HailoRT library.
-    - This example uses pcie devices.
-  - `switch_hefs_example` - Demonstrates how to work with multiple HEFs using virtual streams.
-    - This example uses pcie devices.
-  - `switch_single_io_hefs_example` - Demonstrates how to work with multiple single input single output HEFs using virtual streams.
-    - This example uses pcie devices.
+  - `multi_device_example` - Basic inference of a shortcut network (inputs are sent through the device and right back out, without any changes made to the data), using VDevice over multiple pcie devices:
+    - Configure and activate network group and virtual streams.
+    - The data is sent to the device via input vstreams and received via output vstreams.
+    - The data is transformed before sent and after receiving in a different thread using the virtual stream pipeline.
   - `multi_network_vstream_example` - Demonstrates how to work with multiple networks in a network group, using virtual streams.
     - The example works with an HEF that contains one network group, and two networks in the network group.
     - Configure the network group and set the batch size for each network.
     - Get the networks information to create the vstreams for each network.
     - The data is sent to the device via input vstreams and received via output vstreams.
     - The data is transformed before sent and after receiving in a different thread using the virtual stream pipeline.
+  - `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT scheduler for automatic network group switching.
+    - This example uses pcie devices.
+  - `switch_single_io_network_groups_manually_example` - Demonstrates how to work with multiple single input single output HEFs, switching the created network groups manually, using virtual streams.
+  - `data_quantization_example` - Demonstrates how to set input/output stream params so as to allow for custom quantization:
+    - Input streams may be marked as quantized, so that input data will not to be automatically quantized by the HailoRT library.
+    - Output streams may be marked as quantized, so that output data will remain quantized (as it is after exiting the device by default), and won't be 'de-quantized' by the HailoRT library.
+    - This example uses pcie devices.
+  - `infer_pipeline_example` - Basic inference of a shortcut network using inference pipeline (blocking) api.
+    - this example uses udp device.
+  - `raw_streams_example` - Basic inference of a shortcut network using raw stream api.
+    - The data is transformed before sent and after received in the same thread sending/receiving using the transformation api.
+
 - C++ examples:
   - `vstreams_example` - Basic inference of a shortcut network, same as `vstreams_example` C example, uses HailoRT C++ api.
-  - `raw_streams_example` - Basic inference of a shortcut network, same as `raw_streams_example` C example, uses HailoRT C++ api.
+  - `multi_device_example` - Basic inference of a shortcut network over multiple devices, same as `multi_device_example` C example, uses HailoRT C++ api.
   - `multi_network_vstream_example` - Demonstrates how to work with multiple networks in a network group, same as `multi_network_vstream_example ` C example, uses HailoRT C++ api.
-  - `switch_hefs_example` - Demonstrates how to work with multiple HEFs using virtual streams, same as `switch_hefs_example ` C example, uses HailoRT C++ api.
-  - `switch_hefs_example_threads_reuse` - Same as `switch_hefs_example` CPP example, with performance optimizations for I/O threads re-usage instead of re-creation at each network group activation.
+  - `switch_network_groups_example` - Demonstrates how to work with multiple HEFs using virtual streams and HailoRT scheduler, same as `switch_network_groups_example ` C example, uses HailoRT C++ api.
+  - `switch_network_groups_manually_example` -Demonstrates how to work with multiple HEFs, switching the running network_groups manually, with performance optimizations for I/O threads re-usage instead of re-creation at each network group activation. Uses C++ api.
+  - `infer_streams_example` - Basic inference of a shortcut network, same as `raw_streams_example` C example, uses HailoRT C++ api.
+  - `infer_pipeline_example` - Basic inference of a shortcut network using inference pipeline (blocking) api.
+    - same as `infer_pipeline_example` C example, uses HailoRT C++ api.
+  - `raw_streams_example` - Basic inference of a shortcut network, same as `raw_streams_example` C example, uses HailoRT C++ api.
 
 ## Compiling with CMake
 Examples are configured and compiled using the following commands:
index e001b9e90574d029904f120d0d1d541422160b8f..ec29225a848aa345ddffff534adbfc7e770a9acf 100644 (file)
@@ -18,14 +18,17 @@ target_link_libraries(c_infer_pipeline_example PRIVATE example_base)
 add_executable(c_multi_network_vstream_example multi_network_vstream_example.c)
 target_link_libraries(c_multi_network_vstream_example PRIVATE example_base)
 
-add_executable(c_switch_hefs_example switch_hefs_example.c)
-target_link_libraries(c_switch_hefs_example PRIVATE example_base)
+add_executable(c_switch_network_groups_example switch_network_groups_example.c)
+target_link_libraries(c_switch_network_groups_example PRIVATE example_base)
 
-add_executable(c_switch_single_io_hefs_example switch_single_io_hefs_example.c)
-target_link_libraries(c_switch_single_io_hefs_example PRIVATE example_base)
+add_executable(c_switch_single_io_network_groups_manually_example switch_single_io_network_groups_manually_example.c)
+target_link_libraries(c_switch_single_io_network_groups_manually_example PRIVATE example_base)
 
-add_executable(multi_device_example_c multi_device_example.c)
-target_link_libraries(multi_device_example_c PRIVATE example_base)
+add_executable(c_multi_device_example multi_device_example.c)
+target_link_libraries(c_multi_device_example PRIVATE example_base)
+
+add_executable(c_power_measurement_example power_measurement_example.c)
+target_link_libraries(c_power_measurement_example PRIVATE example_base)
 
 set(EXAMPLES_C_TARGETS
     c_data_quantization_example
@@ -33,7 +36,8 @@ set(EXAMPLES_C_TARGETS
     c_vstreams_example
     c_infer_pipeline_example
     c_multi_network_vstream_example
-    c_switch_hefs_example
-    c_switch_single_io_hefs_example
-    multi_device_example_c
+    c_switch_network_groups_example
+    c_switch_single_io_network_groups_manually_example
+    c_multi_device_example
+    c_power_measurement_example
     PARENT_SCOPE)
index 85e6e890559dbdde4a4eba17838657d624791bef..aafb298c0ed1030d8e3a3dd8bcc75314922bb08d 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file example_common.h
+ * @file example_common.h
  * Common macros and defines used by Hailort Examples
  **/
 
index 831d3c182577eab8e076b1f7d8ce76f0b3fcdd8e..4275bfee56c644cdcebe947afc33ede75fe2185a 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file data_quantization_example.c
+ * @file data_quantization_example.c
  * This example demonstrates using quantization on an HEF network with multiple inputs and multiple outputs
  **/
 
index 8bd6778a2fe595294138e3a0a7bd1d75ebe6816f..2c0d3be1b3ccb6867c7ac82423dc5a05ec47586f 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file hailo_thread.h
+ * @file hailo_thread.h
  * Common threads related functions, for linux and windows
  **/
 
index fc8f7fa3569dfa31e1f470f4b82b1f70804dd13b..b5d16be0f826532ea5c4714506cf2ccf50b712e7 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file infer_pipeline_example.c
+ * @file infer_pipeline_example.c
  * This example demonstrates the basic data-path on HailoRT using the high level API - Virtual Stream Pipeline.
  * The program scans for Hailo-8 devices connected to a provided Ethernet interface, generates a random dataset,
  * and runs it through the device with virtual streams pipeline.
index 6dbfa273483f88a152a65d8fb148d7cee3af4c7b..a631e5f128908dbecbb592d4d5e5caec41266283 100644 (file)
@@ -11,7 +11,7 @@
  * You shall not reproduce, modify or distribute this software without prior written permission.
  **/
 /**
- * @ file multi_device_example.c
+ * @file multi_device_example.c
  * This example demonstrates how to work with multiple devices using virtual device.
  * The program scans for Hailo-8 devices connected to a provided PCIe interface, generates random dataset,
  * and runs it through the virtual device with virtual streams.
diff --git a/hailort/libhailort/examples/c/power_measurement_example.c b/hailort/libhailort/examples/c/power_measurement_example.c
new file mode 100644 (file)
index 0000000..b4c75ea
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file power_measurement_example.c
+ * This example demonstrates power and current measurements.
+ **/
+
+#include "common.h"
+#include "hailo/hailort.h"
+
+#include <string.h>
+
+#define SAMPLING_PERIOD (HAILO_SAMPLING_PERIOD_1100US)
+#define AVERAGE_FACTOR (HAILO_AVERAGE_FACTOR_256)
+#define DVM_OPTION (HAILO_DVM_OPTIONS_AUTO) // For current measurement over EVB - pass DVM explicitly (see hailo_dvm_options_t)
+#define MEASUREMENT_BUFFER_INDEX (HAILO_MEASUREMENT_BUFFER_INDEX_0)
+
+#define MEASUREMENTS_DURATION_SECS (5)
+#define MAX_PCIE_DEVICES (16)
+
+#define MEASUREMENT_UNITS(__type) \
+    ((HAILO_POWER_MEASUREMENT_TYPES__POWER == __type) ? ("W") : ("mA"))
+
+#define USAGE_ERROR_MSG ("Args parsing error.\nUsage: power_measurement_example [power / current]\n" \
+    "* power   - measure power consumption in W\n" \
+    "* current - measure current in mA\n")
+
+#define POWER_ARG "power"
+#define CURRENT_ARG "current"
+
+
+void sleep_seconds(uint32_t duration_seconds)
+{
+#if defined(__unix__) || defined(__QNX__)
+    sleep(duration_seconds);
+#else
+    Sleep(duration_seconds);
+#endif
+}
+
+void parse_arguments(int argc, char **argv, hailo_power_measurement_types_t *measurement_type)
+{
+    if (2 != argc) {
+        printf(USAGE_ERROR_MSG);
+        exit(1);
+    }
+
+    if (0 == strncmp(POWER_ARG, argv[1], ARRAY_LENGTH(POWER_ARG))) {
+        *measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
+    } else if (0 == strncmp(CURRENT_ARG, argv[1], ARRAY_LENGTH(CURRENT_ARG))) {
+        *measurement_type = HAILO_POWER_MEASUREMENT_TYPES__CURRENT;
+    } else {
+        printf(USAGE_ERROR_MSG);
+        exit(1);
+    }
+}
+
+hailo_status print_measurements_results(hailo_device device, hailo_power_measurement_data_t *result, hailo_power_measurement_types_t type)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_device_id_t id = {0};
+    status = hailo_get_device_id(device, &id);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to get device id");
+    const char* type_str = (type == HAILO_POWER_MEASUREMENT_TYPES__POWER) ? "Power measurement" :
+        "Current measurement";
+
+    printf("Device %s:\n", id.id);
+    printf("  %s\n", type_str);
+    printf("    Minimum value: %f %s\n", result->min_value, MEASUREMENT_UNITS(type));
+    printf("    Average value: %f %s\n", result->average_value, MEASUREMENT_UNITS(type));
+    printf("    Maximum value: %f %s\n", result->max_value, MEASUREMENT_UNITS(type));
+
+l_exit:
+    return status;
+}
+
+int main(int argc, char **argv)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_vdevice vdevice = NULL;
+    hailo_pcie_device_info_t device_infos[MAX_PCIE_DEVICES];
+    size_t actual_device_count = 0;
+    hailo_vdevice_params_t params = {0};
+    hailo_device physical_devices[MAX_PCIE_DEVICES];
+    hailo_power_measurement_data_t measurement_result[MAX_PCIE_DEVICES] = {0};
+    hailo_power_measurement_types_t measurement_type = {0};
+
+    parse_arguments(argc, argv, &measurement_type);
+
+    status = hailo_scan_pcie_devices(device_infos, MAX_PCIE_DEVICES, &actual_device_count);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to scan pcie_device");
+
+    status = hailo_init_vdevice_params(&params);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to init vdevice_params");
+
+    params.device_count = (uint32_t)actual_device_count;
+    status = hailo_create_vdevice(&params, &vdevice);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
+
+    status = hailo_get_physical_devices(vdevice, physical_devices, &actual_device_count);
+    REQUIRE_SUCCESS(status, l_release_vdevice, "Failed to get physical devices");
+
+    for (size_t i = 0; i < actual_device_count; i++) {
+        status = hailo_stop_power_measurement(physical_devices[i]);
+        REQUIRE_SUCCESS(status, l_exit, "Failed stopping former measurements");
+
+        status = hailo_set_power_measurement(physical_devices[i], MEASUREMENT_BUFFER_INDEX, DVM_OPTION, measurement_type);
+        REQUIRE_SUCCESS(status, l_exit, "Failed setting measurement params");
+
+        status = hailo_start_power_measurement(physical_devices[i], AVERAGE_FACTOR, SAMPLING_PERIOD);
+        REQUIRE_SUCCESS(status, l_exit, "Failed to start measurement");
+    }
+
+    sleep_seconds(MEASUREMENTS_DURATION_SECS);
+
+    for (size_t i = 0; i < actual_device_count; i++) {
+        status = hailo_stop_power_measurement(physical_devices[i]);
+        REQUIRE_SUCCESS(status, l_exit, "Failed to stop measurement");
+
+        status = hailo_get_power_measurement(physical_devices[i], MEASUREMENT_BUFFER_INDEX, true, &(measurement_result[i]));
+        REQUIRE_SUCCESS(status, l_exit, "Failed to get measurement results");
+
+        status = print_measurements_results(physical_devices[i], &(measurement_result[i]), measurement_type);
+        REQUIRE_SUCCESS(status, l_release_vdevice, "Failed to print measurement results");
+    }
+
+    status = HAILO_SUCCESS;
+
+l_release_vdevice:
+    (void) hailo_release_vdevice(vdevice);
+l_exit:
+    return status;
+}
\ No newline at end of file
index 84f48b6abbe00c0abf77a37bbe8988aba7c04b98..33592bf0a30d763708995a29da51a157ad777e76 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file raw_streams_example.c
+ * @file raw_streams_example.c
  * This example demonstrates basic usage of HailoRT streaming api.
  * It loads an HEF network with multiple inputs and multiple outputs into a Hailo PCIe device and performs a
  * short inference.
@@ -185,8 +185,13 @@ int main()
     size_t index = 0;
 
     status = hailo_create_pcie_device(NULL, &device);
+    /*
+    For simplicity, passing NULL as `device_info` - This function will fail in case more than one PCIe device is present.
+    See `hailo_scan_pcie_devices` and `hailo_create_pcie_device` functions documentation.
+    */
     REQUIRE_SUCCESS(status, l_exit, "Failed to create pcie_device");
 
+
     status = hailo_create_hef_file(&hef, HEF_FILE);
     REQUIRE_SUCCESS(status, l_release_device, "Failed creating hef file %s", HEF_FILE);
 
diff --git a/hailort/libhailort/examples/c/switch_hefs_example.c b/hailort/libhailort/examples/c/switch_hefs_example.c
deleted file mode 100644 (file)
index 336d3a3..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @ file switch_hefs_example.c
- * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using vstreams.
- * It loads several HEF networks with single/multiple inputs and single/multiple outputs into a Hailo PCIe VDevice and performs a
- * short inference on each one. 
- * After inference is finished, the example switches to the next HEF and start inference again.
- **/
-
-#include "common.h"
-#include "hailo_thread.h"
-#include "hailo/hailort.h"
-#include <time.h>
-
-#define MAX_HEF_PATH_LEN (255)
-#define MAX_EDGE_LAYERS (16)
-
-#define INFER_FRAME_COUNT (100)
-#define HEF_COUNT (2)
-#define RUN_COUNT (10)
-#define DEVICE_COUNT (1)
-
-typedef struct write_thread_args_t {
-    hailo_input_vstream input_vstream;
-    uint8_t *src_data;
-    size_t src_frame_size;
-} write_thread_args_t;
-
-typedef struct read_thread_args_t {
-    hailo_output_vstream output_vstream;
-    uint8_t *dst_data;
-    size_t dst_frame_size;
-} read_thread_args_t;
-
-thread_return_type write_to_device(void *args)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    write_thread_args_t *write_args = (write_thread_args_t*)args;
-
-    for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
-        // Write data
-        status = hailo_vstream_write_raw_buffer(write_args->input_vstream, write_args->src_data, write_args->src_frame_size);
-        REQUIRE_SUCCESS(status, l_exit, "Failed writing input frame to device");
-    }
-
-    status = HAILO_SUCCESS;
-l_exit:
-    return (thread_return_type)status;
-}
-
-thread_return_type read_from_device(void *args)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    read_thread_args_t *read_args = (read_thread_args_t*)args;
-
-    for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
-        // Read data
-        status = hailo_vstream_read_raw_buffer(read_args->output_vstream, read_args->dst_data, read_args->dst_frame_size);
-        REQUIRE_SUCCESS(status, l_exit, "Failed reading output frame from device");
-
-        // Process data here
-    }
-
-    status = HAILO_SUCCESS;
-l_exit:
-    return (thread_return_type)status;
-}
-
-hailo_status create_input_vstream_thread(hailo_input_vstream input_vstream, uint8_t *src_data, size_t src_frame_size,
-    hailo_thread *input_thread, write_thread_args_t *write_args)
-{
-    write_args->src_data = src_data;
-    write_args->src_frame_size = src_frame_size;
-    write_args->input_vstream = input_vstream;
-
-    // Run write
-    return hailo_create_thread(write_to_device, write_args, input_thread);
-}
-
-hailo_status create_output_vstream_thread(hailo_output_vstream output_vstream, uint8_t *dst_data, size_t dst_frame_size,
-    hailo_thread *output_thread, read_thread_args_t *read_args)
-{
-    read_args->dst_data = dst_data;
-    read_args->dst_frame_size = dst_frame_size;
-    read_args->output_vstream = output_vstream;
-
-    // Run read
-    return hailo_create_thread(read_from_device, read_args, output_thread);
-}
-
-hailo_status build_vstreams(hailo_configured_network_group network_group,
-    hailo_input_vstream *input_vstreams, size_t *input_frame_sizes, uint8_t **src_data,
-    hailo_output_vstream *output_vstreams, size_t *output_frame_sizes, uint8_t **dst_data,
-    size_t *num_input_vstreams, size_t *num_output_vstreams)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    hailo_input_vstream_params_by_name_t input_vstream_params[MAX_EDGE_LAYERS];
-    hailo_output_vstream_params_by_name_t output_vstream_params[MAX_EDGE_LAYERS];
-
-    // Make sure it can hold amount of vstreams for hailo_make_input/output_vstream_params
-    size_t input_vstream_size = MAX_EDGE_LAYERS;
-    size_t output_vstream_size = MAX_EDGE_LAYERS;
-
-    status = hailo_make_input_vstream_params(network_group, true, HAILO_FORMAT_TYPE_AUTO,
-        input_vstream_params, &input_vstream_size);
-    REQUIRE_SUCCESS(status, l_exit, "Failed making input virtual stream params");
-    *num_input_vstreams = input_vstream_size;
-
-    status = hailo_make_output_vstream_params(network_group, true, HAILO_FORMAT_TYPE_AUTO,
-        output_vstream_params, &output_vstream_size);
-    REQUIRE_SUCCESS(status, l_exit, "Failed making output virtual stream params");
-    *num_output_vstreams = output_vstream_size;
-
-    REQUIRE_ACTION((*num_input_vstreams <= MAX_EDGE_LAYERS || *num_output_vstreams <= MAX_EDGE_LAYERS),
-        status = HAILO_INVALID_OPERATION, l_exit, "Trying to infer network with too many input/output virtual streams, "
-        "Maximum amount is %d, (either change HEF or change the definition of MAX_EDGE_LAYERS)\n", MAX_EDGE_LAYERS);
-
-    status = hailo_create_input_vstreams(network_group, input_vstream_params, input_vstream_size, input_vstreams);
-    REQUIRE_SUCCESS(status, l_exit, "Failed creating virtual stream");
-
-    status = hailo_create_output_vstreams(network_group, output_vstream_params, output_vstream_size, output_vstreams);
-    REQUIRE_SUCCESS(status, l_release_input_vstream, "Failed creating virtual stream");
-
-    for (size_t i = 0; i < input_vstream_size; i++) {
-        status = hailo_get_input_vstream_frame_size(input_vstreams[i], &input_frame_sizes[i]);
-        REQUIRE_SUCCESS(status, l_clear_buffers, "Failed getting input virtual stream frame size");
-
-        src_data[i] = (uint8_t*)malloc(input_frame_sizes[i]);
-        REQUIRE_ACTION(NULL != src_data[i], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_buffers, "Out of memory");
-
-        // Prepare data here
-        for (size_t frame_index = 0; frame_index < input_frame_sizes[i]; frame_index++) {
-            src_data[i][frame_index] = (uint8_t)(rand() % 256);
-        }
-    }  
-
-    for (size_t i = 0; i < output_vstream_size; i++) {
-        status = hailo_get_output_vstream_frame_size(output_vstreams[i], &output_frame_sizes[i]);
-        REQUIRE_SUCCESS(status, l_clear_buffers, "Failed getting input virtual stream frame size");
-
-        dst_data[i] = (uint8_t*)malloc(output_frame_sizes[i]);
-        REQUIRE_ACTION(NULL != dst_data[i], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_buffers, "Out of memory");
-    }
-
-    status = HAILO_SUCCESS;
-    goto l_exit;
-
-l_clear_buffers:
-    for (size_t i = 0; i < input_vstream_size; i++) {
-        FREE(src_data[i]);
-    }
-    for (size_t i = 0; i < output_vstream_size; i++) {
-        FREE(dst_data[i]);
-    }
-
-    (void)hailo_release_output_vstreams(output_vstreams, output_vstream_size);
-l_release_input_vstream:
-    (void)hailo_release_input_vstreams(input_vstreams, input_vstream_size);
-l_exit:
-    return status;
-}
-
-int main()
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    hailo_vdevice vdevice = NULL;
-    hailo_vdevice_params_t params = {0};
-    hailo_hef hef[HEF_COUNT] = {NULL};
-    hailo_configure_params_t configure_params = {0};
-    hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
-    size_t network_groups_size = 1;
-    hailo_activated_network_group activated_network_group = NULL;
-    hailo_input_vstream input_vstreams[HEF_COUNT][MAX_EDGE_LAYERS];
-    hailo_output_vstream output_vstreams[HEF_COUNT][MAX_EDGE_LAYERS];
-    size_t input_frame_size[HEF_COUNT][MAX_EDGE_LAYERS];
-    size_t output_frame_size[HEF_COUNT][MAX_EDGE_LAYERS];
-    // Initialize 2d array to all NULL
-    uint8_t *src_data[HEF_COUNT][MAX_EDGE_LAYERS];
-    uint8_t *dst_data[HEF_COUNT][MAX_EDGE_LAYERS];
-    size_t num_input_vstreams[HEF_COUNT];
-    size_t num_output_vstreams[HEF_COUNT];
-    uint8_t hef_index = 0;
-    uint8_t run_index = 0;
-
-    hailo_thread input_vstream_threads[MAX_EDGE_LAYERS];
-    hailo_thread output_vstream_threads[MAX_EDGE_LAYERS];
-    write_thread_args_t write_args[MAX_EDGE_LAYERS];
-    read_thread_args_t read_args[MAX_EDGE_LAYERS];
-
-    bool break_main_loop = false;
-
-    char HEF_FILES[HEF_COUNT][MAX_HEF_PATH_LEN] = {"hefs/shortcut_net.hef", "hefs/shortcut_net.hef"};
-
-    status = hailo_init_vdevice_params(&params);
-    REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
-
-    params.device_count = DEVICE_COUNT;
-    status = hailo_create_vdevice(&params, &vdevice);
-    REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
-
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        /* Select user HEFs here. In this example it's the same HEF for all networks */
-        status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
-
-        status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
-
-        status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
-        REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
-            "Unexpected network group size");
-
-        status = build_vstreams(network_groups[hef_index],
-            input_vstreams[hef_index], input_frame_size[hef_index], src_data[hef_index],
-            output_vstreams[hef_index], output_frame_size[hef_index], dst_data[hef_index],
-            &num_input_vstreams[hef_index], &num_output_vstreams[hef_index]);
-        REQUIRE_SUCCESS(status, l_release_vstreams, "Failed building streams");
-    }
-
-    // Inference part
-    for (run_index = 0; run_index < RUN_COUNT; run_index++) {
-        for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-            status = hailo_activate_network_group(network_groups[hef_index], NULL, &activated_network_group);
-            REQUIRE_SUCCESS(status, l_release_vstreams, "Failed activate network group");
-
-            for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
-                status = create_input_vstream_thread(input_vstreams[hef_index][i], src_data[hef_index][i],
-                    input_frame_size[hef_index][i], &input_vstream_threads[i], &write_args[i]);
-            }
-
-            for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
-                status = create_output_vstream_thread(output_vstreams[hef_index][i], dst_data[hef_index][i],
-                    output_frame_size[hef_index][i], &output_vstream_threads[i], &read_args[i]);
-            }
-
-            for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
-                status = hailo_join_thread(&input_vstream_threads[i]);
-                if (HAILO_SUCCESS != status) {
-                    printf("write_thread failed \n");
-                    break_main_loop = true;
-                }
-            }
-
-            for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
-                status = hailo_join_thread(&output_vstream_threads[i]);
-                if (HAILO_SUCCESS != status) {
-                    printf("write_thread failed \n");
-                    break_main_loop = true;
-                }
-            }
-
-            status = hailo_deactivate_network_group(activated_network_group);
-            REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed to de-activate network group");
-
-            if(break_main_loop) {
-                goto l_release_vstreams;
-            }
-        }
-    }
-
-    printf("Inference ran successfully\n");
-    status = HAILO_SUCCESS;
-    goto l_release_vstreams;
-
-l_deactivate_network_group:
-    (void)hailo_deactivate_network_group(activated_network_group);
-l_release_vstreams:
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        (void)hailo_release_output_vstreams(output_vstreams[hef_index], num_output_vstreams[hef_index]);
-        (void)hailo_release_input_vstreams(input_vstreams[hef_index], num_input_vstreams[hef_index]);
-    }
-
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
-            if (NULL != src_data[hef_index] && NULL != src_data[hef_index][i]) {
-                FREE(src_data[hef_index][i]);
-            }
-        }
-        for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
-            if (NULL != dst_data[hef_index] && NULL != dst_data[hef_index][i]) {
-                FREE(dst_data[hef_index][i]);
-            }
-        }
-    }
-l_release_hef:
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        if (NULL != hef[hef_index]) {
-            (void)hailo_release_hef(hef[hef_index]);            
-        }
-    }
-    (void)hailo_release_vdevice(vdevice);
-l_exit:
-    return status;
-}
\ No newline at end of file
diff --git a/hailort/libhailort/examples/c/switch_network_groups_example.c b/hailort/libhailort/examples/c/switch_network_groups_example.c
new file mode 100644 (file)
index 0000000..e3f258c
--- /dev/null
@@ -0,0 +1,280 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file switch_network_groups_example.c
+ * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using VStreams.
+ * It loads several network_groups (via several HEFs) into a Hailo PCIe VDevice and performs a inferences on all of them in parallel.
+ * The network_groups switching is performed automatically by the HailoRT scheduler.
+ **/
+
+#include "common.h"
+#include "hailo_thread.h"
+#include "hailo/hailort.h"
+#include <time.h>
+
+#define MAX_HEF_PATH_LEN (255)
+#define MAX_EDGE_LAYERS (16)
+
+#define INFER_FRAME_COUNT (100)
+#define HEF_COUNT (2)
+#define DEVICE_COUNT (1)
+
+typedef struct write_thread_args_t {
+    hailo_input_vstream input_vstream;
+    uint8_t *src_data;
+    size_t src_frame_size;
+} write_thread_args_t;
+
+typedef struct read_thread_args_t {
+    hailo_output_vstream output_vstream;
+    uint8_t *dst_data;
+    size_t dst_frame_size;
+} read_thread_args_t;
+
+thread_return_type write_to_device(void *args)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    write_thread_args_t *write_args = (write_thread_args_t*)args;
+
+    for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
+        // Write data
+        status = hailo_vstream_write_raw_buffer(write_args->input_vstream, write_args->src_data, write_args->src_frame_size);
+        REQUIRE_SUCCESS(status, l_exit, "Failed writing input frame to device");
+    }
+
+    status = HAILO_SUCCESS;
+l_exit:
+    return (thread_return_type)status;
+}
+
+thread_return_type read_from_device(void *args)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    read_thread_args_t *read_args = (read_thread_args_t*)args;
+
+    for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
+        // Read data
+        status = hailo_vstream_read_raw_buffer(read_args->output_vstream, read_args->dst_data, read_args->dst_frame_size);
+        REQUIRE_SUCCESS(status, l_exit, "Failed reading output frame from device");
+
+        // Process data here
+    }
+
+    status = HAILO_SUCCESS;
+l_exit:
+    return (thread_return_type)status;
+}
+
+hailo_status create_input_vstream_thread(hailo_input_vstream input_vstream, uint8_t *src_data, size_t src_frame_size,
+    hailo_thread *input_thread, write_thread_args_t *write_args)
+{
+    write_args->src_data = src_data;
+    write_args->src_frame_size = src_frame_size;
+    write_args->input_vstream = input_vstream;
+
+    // Run write
+    return hailo_create_thread(write_to_device, write_args, input_thread);
+}
+
+hailo_status create_output_vstream_thread(hailo_output_vstream output_vstream, uint8_t *dst_data, size_t dst_frame_size,
+    hailo_thread *output_thread, read_thread_args_t *read_args)
+{
+    read_args->dst_data = dst_data;
+    read_args->dst_frame_size = dst_frame_size;
+    read_args->output_vstream = output_vstream;
+
+    // Run read
+    return hailo_create_thread(read_from_device, read_args, output_thread);
+}
+
+hailo_status build_vstreams(hailo_configured_network_group network_group,
+    hailo_input_vstream *input_vstreams, size_t *input_frame_sizes, uint8_t **src_data,
+    hailo_output_vstream *output_vstreams, size_t *output_frame_sizes, uint8_t **dst_data,
+    size_t *num_input_vstreams, size_t *num_output_vstreams)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_input_vstream_params_by_name_t input_vstream_params[MAX_EDGE_LAYERS];
+    hailo_output_vstream_params_by_name_t output_vstream_params[MAX_EDGE_LAYERS];
+
+    // Make sure it can hold amount of vstreams for hailo_make_input/output_vstream_params
+    size_t input_vstream_size = MAX_EDGE_LAYERS;
+    size_t output_vstream_size = MAX_EDGE_LAYERS;
+
+    status = hailo_make_input_vstream_params(network_group, true, HAILO_FORMAT_TYPE_AUTO,
+        input_vstream_params, &input_vstream_size);
+    REQUIRE_SUCCESS(status, l_exit, "Failed making input virtual stream params");
+    *num_input_vstreams = input_vstream_size;
+
+    status = hailo_make_output_vstream_params(network_group, true, HAILO_FORMAT_TYPE_AUTO,
+        output_vstream_params, &output_vstream_size);
+    REQUIRE_SUCCESS(status, l_exit, "Failed making output virtual stream params");
+    *num_output_vstreams = output_vstream_size;
+
+    REQUIRE_ACTION((*num_input_vstreams <= MAX_EDGE_LAYERS || *num_output_vstreams <= MAX_EDGE_LAYERS),
+        status = HAILO_INVALID_OPERATION, l_exit, "Trying to infer network with too many input/output virtual streams, "
+        "Maximum amount is %d, (either change HEF or change the definition of MAX_EDGE_LAYERS)\n", MAX_EDGE_LAYERS);
+
+    status = hailo_create_input_vstreams(network_group, input_vstream_params, input_vstream_size, input_vstreams);
+    REQUIRE_SUCCESS(status, l_exit, "Failed creating virtual stream");
+
+    status = hailo_create_output_vstreams(network_group, output_vstream_params, output_vstream_size, output_vstreams);
+    REQUIRE_SUCCESS(status, l_release_input_vstream, "Failed creating virtual stream");
+
+    for (size_t i = 0; i < input_vstream_size; i++) {
+        status = hailo_get_input_vstream_frame_size(input_vstreams[i], &input_frame_sizes[i]);
+        REQUIRE_SUCCESS(status, l_clear_buffers, "Failed getting input virtual stream frame size");
+
+        src_data[i] = (uint8_t*)malloc(input_frame_sizes[i]);
+        REQUIRE_ACTION(NULL != src_data[i], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_buffers, "Out of memory");
+
+        // Prepare data here
+        for (size_t frame_index = 0; frame_index < input_frame_sizes[i]; frame_index++) {
+            src_data[i][frame_index] = (uint8_t)(rand() % 256);
+        }
+    }  
+
+    for (size_t i = 0; i < output_vstream_size; i++) {
+        status = hailo_get_output_vstream_frame_size(output_vstreams[i], &output_frame_sizes[i]);
+        REQUIRE_SUCCESS(status, l_clear_buffers, "Failed getting input virtual stream frame size");
+
+        dst_data[i] = (uint8_t*)malloc(output_frame_sizes[i]);
+        REQUIRE_ACTION(NULL != dst_data[i], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_buffers, "Out of memory");
+    }
+
+    status = HAILO_SUCCESS;
+    goto l_exit;
+
+l_clear_buffers:
+    for (size_t i = 0; i < input_vstream_size; i++) {
+        FREE(src_data[i]);
+    }
+    for (size_t i = 0; i < output_vstream_size; i++) {
+        FREE(dst_data[i]);
+    }
+
+    (void)hailo_release_output_vstreams(output_vstreams, output_vstream_size);
+l_release_input_vstream:
+    (void)hailo_release_input_vstreams(input_vstreams, input_vstream_size);
+l_exit:
+    return status;
+}
+
+int main()
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_vdevice vdevice = NULL;
+    hailo_vdevice_params_t params = {0};
+    hailo_hef hef[HEF_COUNT] = {NULL};
+    hailo_configure_params_t configure_params = {0};
+    hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
+    size_t network_groups_size = 1;
+    hailo_input_vstream input_vstreams[HEF_COUNT][MAX_EDGE_LAYERS];
+    hailo_output_vstream output_vstreams[HEF_COUNT][MAX_EDGE_LAYERS];
+    size_t input_frame_size[HEF_COUNT][MAX_EDGE_LAYERS];
+    size_t output_frame_size[HEF_COUNT][MAX_EDGE_LAYERS];
+    // Initialize 2d array to all NULL
+    uint8_t *src_data[HEF_COUNT][MAX_EDGE_LAYERS];
+    uint8_t *dst_data[HEF_COUNT][MAX_EDGE_LAYERS];
+    size_t num_input_vstreams[HEF_COUNT];
+    size_t num_output_vstreams[HEF_COUNT];
+    uint8_t hef_index = 0;
+
+    hailo_thread input_vstream_threads[HEF_COUNT][MAX_EDGE_LAYERS];
+    hailo_thread output_vstream_threads[HEF_COUNT][MAX_EDGE_LAYERS];
+    write_thread_args_t write_args[HEF_COUNT][MAX_EDGE_LAYERS];
+    read_thread_args_t read_args[HEF_COUNT][MAX_EDGE_LAYERS];
+
+    char HEF_FILES[HEF_COUNT][MAX_HEF_PATH_LEN] = {"hefs/multi_network_shortcut_net.hef", "hefs/shortcut_net.hef"};
+
+    status = hailo_init_vdevice_params(&params);
+    REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
+
+    params.device_count = DEVICE_COUNT;
+    params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN;
+    status = hailo_create_vdevice(&params, &vdevice);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
+
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        /* Select user HEFs here. In this example it's the same HEF for all networks */
+        status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
+
+        status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
+
+        status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
+        REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
+            "Unexpected network group size");
+
+        status = build_vstreams(network_groups[hef_index],
+            input_vstreams[hef_index], input_frame_size[hef_index], src_data[hef_index],
+            output_vstreams[hef_index], output_frame_size[hef_index], dst_data[hef_index],
+            &num_input_vstreams[hef_index], &num_output_vstreams[hef_index]);
+        REQUIRE_SUCCESS(status, l_release_vstreams, "Failed building streams");
+    }
+
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
+            status = create_input_vstream_thread(input_vstreams[hef_index][i], src_data[hef_index][i],
+                input_frame_size[hef_index][i], &input_vstream_threads[hef_index][i], &write_args[hef_index][i]);
+        }
+        REQUIRE_SUCCESS(status, l_release_vstreams, "Failed creating write threads");
+
+        for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
+            status = create_output_vstream_thread(output_vstreams[hef_index][i], dst_data[hef_index][i],
+                output_frame_size[hef_index][i], &output_vstream_threads[hef_index][i], &read_args[hef_index][i]);
+        }
+        REQUIRE_SUCCESS(status, l_release_vstreams, "Failed creating read threads");
+    }
+
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
+            status = hailo_join_thread(&input_vstream_threads[hef_index][i]);
+            if (HAILO_SUCCESS != status) {
+                printf("write_thread failed \n");
+            }
+        }
+
+        for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
+            status = hailo_join_thread(&output_vstream_threads[hef_index][i]);
+            if (HAILO_SUCCESS != status) {
+                printf("read_thread failed \n");
+            }
+        }
+    }
+
+    printf("Inference ran successfully\n");
+    status = HAILO_SUCCESS;
+    goto l_release_vstreams;
+
+l_release_vstreams:
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        (void)hailo_release_output_vstreams(output_vstreams[hef_index], num_output_vstreams[hef_index]);
+        (void)hailo_release_input_vstreams(input_vstreams[hef_index], num_input_vstreams[hef_index]);
+    }
+
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        for (size_t i = 0; i < num_input_vstreams[hef_index]; i++) {
+            if (NULL != src_data[hef_index] && NULL != src_data[hef_index][i]) {
+                FREE(src_data[hef_index][i]);
+            }
+        }
+        for (size_t i = 0; i < num_output_vstreams[hef_index]; i++) {
+            if (NULL != dst_data[hef_index] && NULL != dst_data[hef_index][i]) {
+                FREE(dst_data[hef_index][i]);
+            }
+        }
+    }
+l_release_hef:
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        if (NULL != hef[hef_index]) {
+            (void)hailo_release_hef(hef[hef_index]);            
+        }
+    }
+    (void)hailo_release_vdevice(vdevice);
+l_exit:
+    return status;
+}
\ No newline at end of file
diff --git a/hailort/libhailort/examples/c/switch_single_io_hefs_example.c b/hailort/libhailort/examples/c/switch_single_io_hefs_example.c
deleted file mode 100644 (file)
index bb3c4d2..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @ file switch_single_io_hefs_example.c
- * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using vstreams.
- * It loads several HEF networks with a single input and a single output into a Hailo PCIe VDevice and performs a inference on each one. 
- * After inference is finished, the example switches to the next HEF and start inference again.
- **/
-
-#include "common.h"
-#include "hailo_thread.h"
-#include "hailo/hailort.h"
-#include <time.h>
-
-#define MAX_HEF_PATH_LEN (255)
-#define MAX_EDGE_LAYERS (16)
-
-#define INFER_FRAME_COUNT (100)
-#define HEF_COUNT (2)
-#define RUN_COUNT (10)
-#define DEVICE_COUNT (1)
-
-typedef struct input_vstream_thread_args_t {
-    hailo_configured_network_group *configured_networks;
-    hailo_input_vstream_params_by_name_t *input_vstream_params;
-} input_vstream_thread_args_t;
-
-typedef struct output_vstream_thread_args_t {
-    hailo_configured_network_group *configured_networks;
-    hailo_activated_network_group *activated_network_group;
-    hailo_output_vstream_params_by_name_t *output_vstream_params;
-} output_vstream_thread_args_t;
-
-thread_return_type input_vstream_thread_func(void *args)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    hailo_input_vstream input_vstreams[HEF_COUNT];
-    size_t input_frame_size[HEF_COUNT];
-    uint8_t *src_data[HEF_COUNT];
-    input_vstream_thread_args_t *input_vstream_args = (input_vstream_thread_args_t*)args;
-
-    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        // Input vstream size has to be one in this example- otherwise would haveve returned error
-        status = hailo_create_input_vstreams(input_vstream_args->configured_networks[hef_index],
-            &input_vstream_args->input_vstream_params[hef_index], 1, &input_vstreams[hef_index]);
-        REQUIRE_SUCCESS(status, l_clear_src, "Failed creating virtual stream");
-
-        status = hailo_get_input_vstream_frame_size(input_vstreams[hef_index], &input_frame_size[hef_index]);
-        REQUIRE_SUCCESS(status, l_clear_src, "Failed getting input virtual stream frame size");
-
-        src_data[hef_index] = (uint8_t*)malloc(input_frame_size[hef_index]);
-        REQUIRE_ACTION(NULL != src_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_src, "Out of memory");
-    }
-
-    for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
-        for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
-            // Wait for hef to be activated to send data
-            hailo_wait_for_network_group_activation(input_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
-
-            // Send data on relevant Hef
-            for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
-                // Prepare data here
-                for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
-                    src_data[hef_index][i] = (uint8_t)(rand() % 256);
-                }
-
-                status = hailo_vstream_write_raw_buffer(input_vstreams[hef_index], src_data[hef_index], input_frame_size[hef_index]);
-                REQUIRE_SUCCESS(status, l_clear_src, "Failed writing input frame to device");
-            }
-        }
-    }
-
-    status = HAILO_SUCCESS;
-
-l_clear_src:
-    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        FREE(src_data[hef_index]);
-    }
-
-    (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
-    return (thread_return_type)status;
-}
-
-thread_return_type output_vstream_thread_func(void *args)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    hailo_output_vstream output_vstreams[HEF_COUNT];
-    size_t output_frame_size[HEF_COUNT];
-    uint8_t *dst_data[HEF_COUNT];
-    output_vstream_thread_args_t *output_vstream_args = (output_vstream_thread_args_t*)args;
-
-    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        // Output vstream size has to be one in this example- otherwise would haveve returned error
-        status = hailo_create_output_vstreams(output_vstream_args->configured_networks[hef_index],
-            &output_vstream_args->output_vstream_params[hef_index], 1, &output_vstreams[hef_index]);
-        REQUIRE_SUCCESS(status, l_clear_dst, "Failed creating virtual stream");
-
-        status = hailo_get_output_vstream_frame_size(output_vstreams[hef_index], &output_frame_size[hef_index]);
-        REQUIRE_SUCCESS(status, l_clear_dst, "Failed getting input virtual stream frame size");
-
-        dst_data[hef_index] = (uint8_t*)malloc(output_frame_size[hef_index]);
-        REQUIRE_ACTION(NULL != dst_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_dst, "Out of memory");
-    }
-
-    for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
-        for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
-            // Wait for hef to be activated to send data
-            hailo_wait_for_network_group_activation(output_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
-    
-            for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
-                // Read data
-                status = hailo_vstream_read_raw_buffer(output_vstreams[hef_index],
-                    dst_data[hef_index], output_frame_size[hef_index]);
-                REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed reading output frame from device");
-    
-                // Process data here
-            }
-    
-            // Deavticate network after finishing inference
-            status = hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
-            REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed Deactivating network");
-    
-            // Dont activate on last iteration
-            if (hef_index < HEF_COUNT - 1) {
-                // Activate next network so input thread can start sending again
-                status = hailo_activate_network_group(output_vstream_args->configured_networks[hef_index + 1],
-                    NULL, output_vstream_args->activated_network_group);
-                REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
-            }
-            else {
-                // Meaning we finished a run and now need to activate the first network again for the next run
-                if (run_index < RUN_COUNT - 1) {
-                    status = hailo_activate_network_group(output_vstream_args->configured_networks[0],
-                        NULL, output_vstream_args->activated_network_group);
-                    REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
-                }
-            }
-        }
-    }
-
-    status = HAILO_SUCCESS;
-    goto l_clear_dst;
-
-l_deactivate_network_group:
-    (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
-l_clear_dst:
-    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        FREE(dst_data[hef_index]);
-    }
-
-    (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
-    return (thread_return_type)status;
-}
-
-int main()
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    hailo_vdevice vdevice = NULL;
-    hailo_vdevice_params_t params = {0};
-    hailo_hef hef[HEF_COUNT] = {NULL};
-    hailo_configure_params_t configure_params = {0};
-    hailo_activated_network_group activated_network;
-    hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
-    size_t network_groups_size = 1;
-    uint8_t hef_index = 0;
-    hailo_input_vstream_params_by_name_t input_vstream_params[HEF_COUNT];
-    hailo_output_vstream_params_by_name_t output_vstream_params[HEF_COUNT];
-    size_t input_vstream_size = 1;
-    size_t output_vstream_size = 1;
-
-    hailo_thread input_vstream_thread = {0};
-    hailo_thread output_vstream_thread = {0};
-    input_vstream_thread_args_t input_args = {0};
-    output_vstream_thread_args_t output_args = {0};
-
-    char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
-
-    status = hailo_init_vdevice_params(&params);
-    REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
-
-    params.device_count = DEVICE_COUNT;
-    status = hailo_create_vdevice(&params, &vdevice);
-    REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
-
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        /* Select user HEFs here. In this example it's the same HEF for all networks */
-        status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
-
-        status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
-
-        status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
-        REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
-            "Unexpected network group size");
-
-        // Mae sure each hef is single input single output
-        status = hailo_make_input_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
-            &input_vstream_params[hef_index], &input_vstream_size);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed making input virtual stream params");
-        REQUIRE_ACTION(input_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
-            "INVALID HEF - Only hefs with single input vstream are allowed");
-
-        status = hailo_make_output_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
-            &output_vstream_params[hef_index], &output_vstream_size);
-        REQUIRE_SUCCESS(status, l_release_hef, "Failed making output virtual stream params");
-        REQUIRE_ACTION(output_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
-            "INVALID HEF - Only hefs with single output vstream are allowed");
-    }
-
-    input_args.configured_networks      = network_groups;
-    input_args.input_vstream_params     = input_vstream_params;
-
-    // Open input vstream and output vstream threads
-    status = hailo_create_thread(input_vstream_thread_func, &input_args, &input_vstream_thread);
-    REQUIRE_SUCCESS(status, l_release_hef, "Failed creating thread");
-
-    output_args.configured_networks         = network_groups;
-    output_args.activated_network_group     = &activated_network;
-    output_args.output_vstream_params       = output_vstream_params;
-
-    // Open output vstream and output vstream threads
-    status = hailo_create_thread(output_vstream_thread_func, &output_args, &output_vstream_thread);
-    REQUIRE_SUCCESS(status, l_join_input_thread, "Failed creating thread");
-
-    // Activate first network so input thread can start
-    status = hailo_activate_network_group(network_groups[0], NULL, &activated_network);
-    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed Activating network");
-
-
-    status = hailo_join_thread(&input_vstream_thread);
-    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
-
-    status = hailo_join_thread(&output_vstream_thread);
-    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
-
-    printf("Inference ran successfully\n");
-    status = HAILO_SUCCESS;
-    goto l_release_hef;
-
-l_join_output_thread:
-    (void)hailo_join_thread(&output_vstream_thread);
-l_join_input_thread:
-    (void)hailo_join_thread(&input_vstream_thread);
-l_release_hef:
-    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
-        if (NULL != hef[hef_index]) {
-            (void)hailo_release_hef(hef[hef_index]);            
-        }
-    }
-    (void)hailo_release_vdevice(vdevice);
-l_exit:
-    return status;
-}
diff --git a/hailort/libhailort/examples/c/switch_single_io_network_groups_manually_example.c b/hailort/libhailort/examples/c/switch_single_io_network_groups_manually_example.c
new file mode 100644 (file)
index 0000000..3d09f95
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file switch_single_io_network_groups_manually_example.c
+ * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using vstreams.
+ * It loads several HEF networks with a single input and a single output into a Hailo PCIe VDevice and performs a inference on each one. 
+ * After inference is finished, the example switches to the next HEF and start inference again.
+ **/
+
+#include "common.h"
+#include "hailo_thread.h"
+#include "hailo/hailort.h"
+#include <time.h>
+
+#define MAX_HEF_PATH_LEN (255)
+#define MAX_EDGE_LAYERS (16)
+
+#define INFER_FRAME_COUNT (100)
+#define HEF_COUNT (2)
+#define RUN_COUNT (10)
+#define DEVICE_COUNT (1)
+
+typedef struct input_vstream_thread_args_t {
+    hailo_configured_network_group *configured_networks;
+    hailo_input_vstream_params_by_name_t *input_vstream_params;
+} input_vstream_thread_args_t;
+
+typedef struct output_vstream_thread_args_t {
+    hailo_configured_network_group *configured_networks;
+    hailo_activated_network_group *activated_network_group;
+    hailo_output_vstream_params_by_name_t *output_vstream_params;
+} output_vstream_thread_args_t;
+
+thread_return_type input_vstream_thread_func(void *args)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_input_vstream input_vstreams[HEF_COUNT];
+    size_t input_frame_size[HEF_COUNT];
+    uint8_t *src_data[HEF_COUNT];
+    input_vstream_thread_args_t *input_vstream_args = (input_vstream_thread_args_t*)args;
+
+    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        // Input vstream size has to be one in this example- otherwise would haveve returned error
+        status = hailo_create_input_vstreams(input_vstream_args->configured_networks[hef_index],
+            &input_vstream_args->input_vstream_params[hef_index], 1, &input_vstreams[hef_index]);
+        REQUIRE_SUCCESS(status, l_clear_src, "Failed creating virtual stream");
+
+        status = hailo_get_input_vstream_frame_size(input_vstreams[hef_index], &input_frame_size[hef_index]);
+        REQUIRE_SUCCESS(status, l_clear_src, "Failed getting input virtual stream frame size");
+
+        src_data[hef_index] = (uint8_t*)malloc(input_frame_size[hef_index]);
+        REQUIRE_ACTION(NULL != src_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_src, "Out of memory");
+    }
+
+    for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
+        for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
+            // Wait for hef to be activated to send data
+            hailo_wait_for_network_group_activation(input_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
+
+            // Send data on relevant Hef
+            for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
+                // Prepare data here
+                for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
+                    src_data[hef_index][i] = (uint8_t)(rand() % 256);
+                }
+
+                status = hailo_vstream_write_raw_buffer(input_vstreams[hef_index], src_data[hef_index], input_frame_size[hef_index]);
+                REQUIRE_SUCCESS(status, l_clear_src, "Failed writing input frame to device");
+            }
+        }
+    }
+
+    status = HAILO_SUCCESS;
+
+l_clear_src:
+    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        FREE(src_data[hef_index]);
+    }
+
+    (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
+    return (thread_return_type)status;
+}
+
+thread_return_type output_vstream_thread_func(void *args)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_output_vstream output_vstreams[HEF_COUNT];
+    size_t output_frame_size[HEF_COUNT];
+    uint8_t *dst_data[HEF_COUNT];
+    output_vstream_thread_args_t *output_vstream_args = (output_vstream_thread_args_t*)args;
+
+    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        // Output vstream size has to be one in this example- otherwise would haveve returned error
+        status = hailo_create_output_vstreams(output_vstream_args->configured_networks[hef_index],
+            &output_vstream_args->output_vstream_params[hef_index], 1, &output_vstreams[hef_index]);
+        REQUIRE_SUCCESS(status, l_clear_dst, "Failed creating virtual stream");
+
+        status = hailo_get_output_vstream_frame_size(output_vstreams[hef_index], &output_frame_size[hef_index]);
+        REQUIRE_SUCCESS(status, l_clear_dst, "Failed getting input virtual stream frame size");
+
+        dst_data[hef_index] = (uint8_t*)malloc(output_frame_size[hef_index]);
+        REQUIRE_ACTION(NULL != dst_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_dst, "Out of memory");
+    }
+
+    for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
+        for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
+            // Wait for hef to be activated to send data
+            hailo_wait_for_network_group_activation(output_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
+    
+            for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
+                // Read data
+                status = hailo_vstream_read_raw_buffer(output_vstreams[hef_index],
+                    dst_data[hef_index], output_frame_size[hef_index]);
+                REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed reading output frame from device");
+    
+                // Process data here
+            }
+    
+            // Deavticate network after finishing inference
+            status = hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
+            REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed Deactivating network");
+    
+            // Dont activate on last iteration
+            if (hef_index < HEF_COUNT - 1) {
+                // Activate next network so input thread can start sending again
+                status = hailo_activate_network_group(output_vstream_args->configured_networks[hef_index + 1],
+                    NULL, output_vstream_args->activated_network_group);
+                REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
+            }
+            else {
+                // Meaning we finished a run and now need to activate the first network again for the next run
+                if (run_index < RUN_COUNT - 1) {
+                    status = hailo_activate_network_group(output_vstream_args->configured_networks[0],
+                        NULL, output_vstream_args->activated_network_group);
+                    REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
+                }
+            }
+        }
+    }
+
+    status = HAILO_SUCCESS;
+    goto l_clear_dst;
+
+l_deactivate_network_group:
+    (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
+l_clear_dst:
+    for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        FREE(dst_data[hef_index]);
+    }
+
+    (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
+    return (thread_return_type)status;
+}
+
+int main()
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    hailo_vdevice vdevice = NULL;
+    hailo_vdevice_params_t params = {0};
+    hailo_hef hef[HEF_COUNT] = {NULL};
+    hailo_configure_params_t configure_params = {0};
+    hailo_activated_network_group activated_network;
+    hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
+    size_t network_groups_size = 1;
+    uint8_t hef_index = 0;
+    hailo_input_vstream_params_by_name_t input_vstream_params[HEF_COUNT];
+    hailo_output_vstream_params_by_name_t output_vstream_params[HEF_COUNT];
+    size_t input_vstream_size = 1;
+    size_t output_vstream_size = 1;
+
+    hailo_thread input_vstream_thread = {0};
+    hailo_thread output_vstream_thread = {0};
+    input_vstream_thread_args_t input_args = {0};
+    output_vstream_thread_args_t output_args = {0};
+
+    char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
+
+    status = hailo_init_vdevice_params(&params);
+    REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
+
+    params.device_count = DEVICE_COUNT;
+    status = hailo_create_vdevice(&params, &vdevice);
+    REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
+
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        /* Select user HEFs here. In this example it's the same HEF for all networks */
+        status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
+
+        status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
+
+        status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
+        REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
+            "Unexpected network group size");
+
+        // Mae sure each hef is single input single output
+        status = hailo_make_input_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
+            &input_vstream_params[hef_index], &input_vstream_size);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed making input virtual stream params");
+        REQUIRE_ACTION(input_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
+            "INVALID HEF - Only hefs with single input vstream are allowed");
+
+        status = hailo_make_output_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
+            &output_vstream_params[hef_index], &output_vstream_size);
+        REQUIRE_SUCCESS(status, l_release_hef, "Failed making output virtual stream params");
+        REQUIRE_ACTION(output_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef, 
+            "INVALID HEF - Only hefs with single output vstream are allowed");
+    }
+
+    input_args.configured_networks      = network_groups;
+    input_args.input_vstream_params     = input_vstream_params;
+
+    // Open input vstream and output vstream threads
+    status = hailo_create_thread(input_vstream_thread_func, &input_args, &input_vstream_thread);
+    REQUIRE_SUCCESS(status, l_release_hef, "Failed creating thread");
+
+    output_args.configured_networks         = network_groups;
+    output_args.activated_network_group     = &activated_network;
+    output_args.output_vstream_params       = output_vstream_params;
+
+    // Open output vstream and output vstream threads
+    status = hailo_create_thread(output_vstream_thread_func, &output_args, &output_vstream_thread);
+    REQUIRE_SUCCESS(status, l_join_input_thread, "Failed creating thread");
+
+    // Activate first network so input thread can start
+    status = hailo_activate_network_group(network_groups[0], NULL, &activated_network);
+    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed Activating network");
+
+
+    status = hailo_join_thread(&input_vstream_thread);
+    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
+
+    status = hailo_join_thread(&output_vstream_thread);
+    REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
+
+    printf("Inference ran successfully\n");
+    status = HAILO_SUCCESS;
+    goto l_release_hef;
+
+l_join_output_thread:
+    (void)hailo_join_thread(&output_vstream_thread);
+l_join_input_thread:
+    (void)hailo_join_thread(&input_vstream_thread);
+l_release_hef:
+    for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
+        if (NULL != hef[hef_index]) {
+            (void)hailo_release_hef(hef[hef_index]);            
+        }
+    }
+    (void)hailo_release_vdevice(vdevice);
+l_exit:
+    return status;
+}
index 31854d41026aebc7069cd5c76dad369b94dc295f..e75ef410a612ce3990d8329618423a661d058b22 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file vstreams_example.c
+ * @file vstreams_example.c
  * This example demonstrates the basic data-path on HailoRT using the high level API - Virtual Stream Pipeline.
  * The program scans for Hailo-8 devices connected to a provided PCIe interface, generates random dataset,
  * and runs it through the VDevice with virtual streams.
diff --git a/hailort/libhailort/examples/cmake/FindHailoRT.cmake b/hailort/libhailort/examples/cmake/FindHailoRT.cmake
deleted file mode 100644 (file)
index 173726c..0000000
+++ /dev/null
@@ -1,35 +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
-    if(WIN32)
-        find_library(HAILORT_LIB "libhailort.lib" PATH_SUFFIXES "HailoRT/lib/")
-        find_path(HAILORT_INCLUDE_DIR "hailo/" PATH_SUFFIXES "HailoRT/include/")
-
-    else()
-        find_library(HAILORT_LIB "libhailort.so.4.6.0" PATH_SUFFIXES "lib/")
-        find_path(HAILORT_INCLUDE_DIR "hailo/" PATH_SUFFIXES "include/")
-    endif()
-
-    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}"
-        IMPORTED_IMPLIB "${HAILORT_LIB}"
-        INTERFACE_INCLUDE_DIRECTORIES "${HAILORT_INCLUDE_DIR}"
-    )
-
-else()
-    add_library(HailoRT::libhailort ALIAS libhailort)
-endif()
index e3f17b4b04717796e8861fdac7280c1f5cbe962f..47d29137ad5f8898c33ea4397947c4a23b32f7a0 100644 (file)
@@ -12,21 +12,25 @@ target_link_libraries(cpp_raw_streams_example PRIVATE example_base)
 add_executable(cpp_multi_network_vstream_example multi_network_vstream_example.cpp)
 target_link_libraries(cpp_multi_network_vstream_example PRIVATE example_base)
 
-add_executable(cpp_switch_hefs_example switch_hefs_example.cpp)
-target_link_libraries(cpp_switch_hefs_example PRIVATE example_base)
+add_executable(cpp_switch_network_groups_example switch_network_groups_example.cpp)
+target_link_libraries(cpp_switch_network_groups_example PRIVATE example_base)
 
-add_executable(cpp_switch_hefs_example_threads_reuse switch_hefs_example_threads_reuse.cpp)
-target_link_libraries(cpp_switch_hefs_example_threads_reuse PRIVATE example_base)
+add_executable(cpp_switch_network_groups_manually_example switch_network_groups_manually_example.cpp)
+target_link_libraries(cpp_switch_network_groups_manually_example PRIVATE example_base)
 
-add_executable(multi_device_example_cpp multi_device_example.cpp)
-target_link_libraries(multi_device_example_cpp PRIVATE example_base)
+add_executable(cpp_multi_device_example multi_device_example.cpp)
+target_link_libraries(cpp_multi_device_example PRIVATE example_base)
+
+add_executable(cpp_power_measurement_example power_measurement_example.cpp)
+target_link_libraries(cpp_power_measurement_example PRIVATE example_base)
 
 set(EXAMPLES_CPP_TARGETS
     cpp_vstreams_example
     cpp_infer_pipeline_example
     cpp_raw_streams_example
     cpp_multi_network_vstream_example
-    cpp_switch_hefs_example
-    cpp_switch_hefs_example_threads_reuse
-    multi_device_example_cpp
+    cpp_switch_network_groups_example
+    cpp_switch_network_groups_manually_example
+    cpp_multi_device_example
+    cpp_power_measurement_example
     PARENT_SCOPE)
index 10113aa90034934bb5283134a27a8f68328e312c..0b0379000c8906ff8edfd29d86987890a7156de4 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file vstreams_example
+ * @file vstreams_example
  * This example demonstrates the basic data-path on HailoRT using the high level API - Virtual Stream Pipeline.
  * The program creates a device according to the provdied IP address, generates a random dataset,
  * and runs it through the device with virtual streams pipeline.
@@ -19,15 +19,7 @@ constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
 
 #define USAGE_ERROR_MSG ("Args parsing error.\nUsage: infer_pipeline_example <ip_address>\n")
 
-
-using hailort::Device;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::MemoryView;
-using hailort::InferVStreams;
-
+using namespace hailort;
 
 Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(Device &device)
 {
index 2d55c212c254b1bd256c539dc838a005ccad32d3..2b1e2df44402ab96707b5869e58b969c5360d933 100644 (file)
@@ -11,7 +11,7 @@
  * You shall not reproduce, modify or distribute this software without prior written permission.
  **/
 /**
- * @ file multi_device_example.cpp
+ * @file multi_device_example.cpp
  * This example demonstrates how to work with multiple devices using virtual device.
  **/
 
@@ -25,17 +25,7 @@ constexpr bool QUANTIZED = true;
 constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
 constexpr size_t MAX_LAYER_EDGES = 16;
 
-
-using hailort::VDevice;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputVStream;
-using hailort::OutputVStream;
-using hailort::MemoryView;
-
+using namespace hailort;
 
 Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(VDevice &vdevice)
 {
index 1deed9405115e9a7f2f2b20ee2a9869c2de72503..ac6aa1245c2fa0f270b7dbc4cc39634f065cbfd8 100644 (file)
@@ -22,18 +22,9 @@ constexpr size_t FIRST_NET_BATCH_SIZE = 1;
 constexpr size_t SECOND_NET_BATCH_SIZE = 2;
 constexpr uint32_t DEVICE_COUNT = 1;
 
-using hailort::VDevice;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputVStream;
-using hailort::OutputVStream;
-using hailort::MemoryView;
+using namespace hailort;
 using InOutVStreams = std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>;
 
-
 Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(VDevice &vdevice, Hef &hef, uint16_t batch_size[NET_COUNT])
 {
     auto configure_params = hef.create_configure_params(HAILO_STREAM_INTERFACE_PCIE);
@@ -225,7 +216,7 @@ int main()
     auto network_infos = get_network_infos(*network_group.value());
     if (!network_infos) {
         std::cerr << "Failed to get network infos, status = " << network_infos.status() << std::endl;
-        return network_group.status();
+        return network_infos.status();
     }
 
     auto vstreams = create_vstreams_per_network(*network_group.value(), network_infos.value());
diff --git a/hailort/libhailort/examples/cpp/power_measurement_example.cpp b/hailort/libhailort/examples/cpp/power_measurement_example.cpp
new file mode 100644 (file)
index 0000000..21c5ce2
--- /dev/null
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file power_measurement_example.cpp
+ * This example demonstrates power and current measurements.
+ **/
+
+#include "hailo/hailort.hpp"
+
+#include <iostream>
+#include <chrono>
+#include <thread>
+
+#define SAMPLING_PERIOD (HAILO_SAMPLING_PERIOD_1100US)
+#define AVERAGE_FACTOR (HAILO_AVERAGE_FACTOR_256)
+#define DVM_OPTION (HAILO_DVM_OPTIONS_AUTO) // For current measurement over EVB - pass DVM explicitly (see hailo_dvm_options_t)
+#define MEASUREMENT_BUFFER_INDEX (HAILO_MEASUREMENT_BUFFER_INDEX_0)
+
+#define MEASUREMENT_UNITS(__type) \
+    ((HAILO_POWER_MEASUREMENT_TYPES__POWER == __type) ? ("W") : ("mA"))
+
+#define USAGE_ERROR_MSG ("Args parsing error.\nUsage: power_measurement_example [power / current]\n" \
+    "* power   - measure power consumption in W\n" \
+    "* current - measure current in mA\n")
+
+const std::string POWER_ARG = "power";
+const std::string CURRENT_ARG = "current";
+
+const std::chrono::seconds MEASUREMENTS_DURATION_SECS(5);
+
+using namespace hailort;
+
+Expected<hailo_power_measurement_types_t> parse_arguments(int argc, char **argv)
+{
+    if (2 != argc) {
+        std::cerr << USAGE_ERROR_MSG << std::endl;
+        return make_unexpected(HAILO_INVALID_ARGUMENT);
+    }
+
+    if (POWER_ARG == std::string(argv[1])) {
+        return HAILO_POWER_MEASUREMENT_TYPES__POWER;
+    } else if (CURRENT_ARG == std::string(argv[1]))  {
+        return HAILO_POWER_MEASUREMENT_TYPES__CURRENT;
+    } else {
+        std::cerr << USAGE_ERROR_MSG << std::endl;
+        return make_unexpected(HAILO_INVALID_ARGUMENT);
+    }
+}
+
+void print_measurements_results(Device &device, const hailo_power_measurement_data_t &result, hailo_power_measurement_types_t type)
+{
+    auto id = device.get_dev_id();
+
+    auto type_str = (type == HAILO_POWER_MEASUREMENT_TYPES__POWER) ? "Power measurement" :
+        "Current measurement";
+
+    std::cout << "Device" << std::string(id) << ":" << std::endl;
+    std::cout << "  " << type_str << std::endl;
+    std::cout << "    Minimum value: " << result.min_value << MEASUREMENT_UNITS(type) << std::endl;
+    std::cout << "    Average value: " << result.average_value << MEASUREMENT_UNITS(type) << std::endl;
+    std::cout << "    Maximum value: " << result.max_value << MEASUREMENT_UNITS(type) << std::endl;
+}
+
+int main(int argc, char **argv)
+{
+    auto measurement_type = parse_arguments(argc, argv);
+    if (!measurement_type) {
+        return measurement_type.status();
+    }
+
+    auto scan_res = Device::scan_pcie();
+    if (!scan_res) {
+        std::cerr << "Failed to scan pcie_device" << std::endl;
+        return scan_res.status();
+    }
+
+    hailo_vdevice_params_t params;
+    auto status = hailo_init_vdevice_params(&params);
+    if (HAILO_SUCCESS != status) {
+        std::cerr << "Failed init vdevice_params, status = " << status << std::endl;
+        return status;
+    }
+
+    params.device_count = static_cast<uint32_t>(scan_res->size());
+    auto vdevice = VDevice::create(params);
+    if (!vdevice) {
+        std::cerr << "Failed create vdevice, status = " << vdevice.status() << std::endl;
+        return vdevice.status();
+    }
+
+    auto physical_devices = vdevice.value()->get_physical_devices();
+    if (!physical_devices) {
+        std::cerr << "Failed to get physical devices" << std::endl;
+        return physical_devices.status();
+    }
+
+    for (auto &physical_device : physical_devices.value()) {
+        status = physical_device.get().stop_power_measurement();
+        if (HAILO_SUCCESS != status) {
+            std::cerr << "Failed stopping former measurements" << std::endl;
+            return status;
+        }
+
+        status = physical_device.get().set_power_measurement(MEASUREMENT_BUFFER_INDEX, DVM_OPTION, measurement_type.value());
+        if (HAILO_SUCCESS != status) {
+            std::cerr << "Failed setting measurement params" << std::endl;
+            return status;
+        }
+
+        status = physical_device.get().start_power_measurement(AVERAGE_FACTOR, SAMPLING_PERIOD);
+        if (HAILO_SUCCESS != status) {
+            std::cerr << "Failed to start measurement" << std::endl;
+            return status;
+        }
+    }
+
+    std::this_thread::sleep_for(MEASUREMENTS_DURATION_SECS);
+
+    for (auto &physical_device : physical_devices.value()) {
+        status = physical_device.get().stop_power_measurement();
+        if (HAILO_SUCCESS != status) {
+            std::cerr << "Failed to stop measurement" << std::endl;
+            return status;
+        }
+
+        auto measurement_result = physical_device.get().get_power_measurement(MEASUREMENT_BUFFER_INDEX, true);
+        if (!measurement_result) {
+            std::cerr << "Failed to get measurement results" << std::endl;
+            return measurement_result.status();
+        }
+
+        print_measurements_results(physical_device.get(), measurement_result.value(), measurement_type.value());
+    }
+
+    return HAILO_SUCCESS;
+}
\ No newline at end of file
index c336bf3705a01ee3bd57ba22a4cc6fde3dad98bf..df2c37eb5f2a86e992802043cdf1e12aecfe1de9 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file raw_streams_example
+ * @file raw_streams_example
  * This example demonstrates using low level streams over c++
  **/
 
@@ -17,20 +17,7 @@ constexpr bool QUANTIZED = true;
 constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
 constexpr size_t MAX_LAYER_EDGES = 16;
 
-using hailort::Device;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputStream;
-using hailort::InputTransformContext;
-using hailort::OutputTransformContext;
-using hailort::OutputStream;
-using hailort::MemoryView;
-using hailort::InputStreamRefVector;
-using hailort::OutputStreamRefVector;
-
+using namespace hailort;
 
 Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(Device &device)
 {
@@ -157,6 +144,10 @@ hailo_status infer(InputStreamRefVector &input_streams, OutputStreamRefVector &o
 int main()
 {
     auto device = Device::create_pcie();
+    /*
+    For simplicity, not passing `device_info` - This function will fail in case more than one PCIe device is present.
+    See `hailort::Device::scan_pcie` and `hailort::Device::create_pcie` functions documentation.
+    */
     if (!device) {
         std::cerr << "Failed create_pcie " << device.status() << std::endl;
         return device.status();
diff --git a/hailort/libhailort/examples/cpp/switch_hefs_example.cpp b/hailort/libhailort/examples/cpp/switch_hefs_example.cpp
deleted file mode 100644 (file)
index aab82c8..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @ file switch_hefs_example.cpp
- * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using vstreams.
- * It loads several HEF networks with single/multiple inputs and single/multiple outputs into a Hailo PCIe VDevice and performs a
- * short inference on each one. 
- * After inference is finished, the example switches to the next HEF and start inference again.
- **/
-
-#include "hailo/hailort.hpp"
-
-#include <iostream>
-#include <chrono>
-
-constexpr bool QUANTIZED = true;
-constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
-constexpr size_t INFER_FRAME_COUNT = 100;
-constexpr size_t RUN_COUNT = 10;
-constexpr uint32_t DEVICE_COUNT = 1;
-
-
-using hailort::VDevice;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputVStream;
-using hailort::OutputVStream;
-using hailort::MemoryView;
-
-
-void write_all(InputVStream &input_vstream, hailo_status &status_out)
-{
-    std::vector<uint8_t> buff(input_vstream.get_frame_size());
-
-    for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
-        auto status = input_vstream.write(MemoryView(buff.data(), buff.size()));
-        if (HAILO_SUCCESS != status) {
-            status_out = status;
-            return;
-        }
-    }
-    return;
-}
-
-void read_all(OutputVStream &output_vstream, hailo_status &status_out)
-{
-    std::vector<uint8_t> buff(output_vstream.get_frame_size());
-
-    for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
-        auto status = output_vstream.read(MemoryView(buff.data(), buff.size()));
-        if (HAILO_SUCCESS != status) {
-            status_out = status;
-            return;
-        }
-    }
-    return;
-}
-
-Expected<std::vector<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>>> build_vstreams(
-    const std::vector<std::shared_ptr<ConfiguredNetworkGroup>> &configured_network_groups)
-{
-    std::vector<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> vstreams_per_network_group;
-
-    for (auto &network_group : configured_network_groups) {
-        auto vstreams_exp = VStreamsBuilder::create_vstreams(*network_group, QUANTIZED, FORMAT_TYPE);
-        if (!vstreams_exp) {
-            return make_unexpected(vstreams_exp.status());
-        }
-        vstreams_per_network_group.emplace_back(vstreams_exp.release());
-    }
-    return vstreams_per_network_group;
-}
-
-std::vector<std::unique_ptr<std::thread>> create_read_threads(std::vector<OutputVStream> &vstreams,
-    std::vector<hailo_status> &read_results)
-{
-    std::vector<std::unique_ptr<std::thread>> read_threads;
-
-    read_results.reserve(vstreams.size());
-    for (auto &vstream : vstreams) {
-        read_results.push_back(HAILO_SUCCESS); // Success oriented
-        read_threads.emplace_back(std::make_unique<std::thread>(read_all,
-            std::ref(vstream), std::ref(read_results.back())));
-    }
-    return read_threads;
-}
-
-std::vector<std::unique_ptr<std::thread>> create_write_threads(std::vector<InputVStream> &vstreams,
-    std::vector<hailo_status> &write_results)
-{
-    std::vector<std::unique_ptr<std::thread>> write_threads;
-
-    write_results.reserve(vstreams.size());
-    for (auto &vstream : vstreams) {
-        write_results.push_back(HAILO_SUCCESS); // Success oriented
-        write_threads.emplace_back(std::make_unique<std::thread>(write_all,
-            std::ref(vstream), std::ref(write_results.back())));
-    }
-    return write_threads;
-}
-
-int main()
-{
-    hailo_vdevice_params_t params;
-    auto status = hailo_init_vdevice_params(&params);
-    if (HAILO_SUCCESS != status) {
-        std::cerr << "Failed init vdevice_params, status = " << status << std::endl;
-        return status;
-    }
-
-    params.device_count = DEVICE_COUNT;
-    auto vdevice_exp = VDevice::create(params);
-    if (!vdevice_exp) {
-        std::cerr << "Failed create vdevice, status = " << vdevice_exp.status() << std::endl;
-        return vdevice_exp.status();
-    }
-    auto vdevice = vdevice_exp.release();
-
-    std::vector<std::string> hef_paths = {"hefs/shortcut_net.hef", "hefs/shortcut_net.hef"};
-    std::vector<std::shared_ptr<ConfiguredNetworkGroup>> configured_network_groups;
-
-    for (const auto &path : hef_paths) {
-        auto hef_exp = Hef::create(path);
-        if (!hef_exp) {
-            std::cerr << "Failed to create hef: " << path  << ", status = " << hef_exp.status() << std::endl;
-            return hef_exp.status();
-        }
-        auto hef = hef_exp.release();
-
-        auto added_network_groups = vdevice->configure(hef);
-        if (!added_network_groups) {
-            std::cerr << "Failed to configure vdevice, status = " << added_network_groups.status() << std::endl;
-            return added_network_groups.status();
-        }
-        configured_network_groups.insert(configured_network_groups.end(), added_network_groups->begin(),
-            added_network_groups->end());
-    }
-
-    auto vstreams_per_network_group_exp = build_vstreams(configured_network_groups);
-    if (!vstreams_per_network_group_exp) {
-        std::cerr << "Failed to create vstreams, status = " << vstreams_per_network_group_exp.status() << std::endl;
-        return vstreams_per_network_group_exp.status();
-    }
-    auto vstreams_per_network_group = vstreams_per_network_group_exp.release();
-
-    for (size_t i = 0; i < RUN_COUNT; i++) {
-        for (size_t network_group_idx = 0; network_group_idx < configured_network_groups.size(); network_group_idx++) {
-            auto activated_network_group_exp = configured_network_groups[network_group_idx]->activate();
-
-            if (!activated_network_group_exp) {
-                std::cerr << "Failed to activate network group, status = "  << activated_network_group_exp.status() << std::endl;
-                return activated_network_group_exp.status();
-            }
-
-            // Create send/recv threads
-            std::vector<hailo_status> read_results;
-            auto read_threads = create_read_threads(vstreams_per_network_group[network_group_idx].second, read_results);
-
-            std::vector<hailo_status> write_results;
-            auto write_threads = create_write_threads(vstreams_per_network_group[network_group_idx].first, write_results);
-
-            // Join threads and validate results
-            for (auto &th : write_threads) {
-                if (th->joinable()) {
-                    th->join();
-                }
-            }
-            for (auto &th : read_threads) {
-                if (th->joinable()) {
-                    th->join();
-                }
-            }
-
-            for (auto &thread_status : write_results) {
-                if (HAILO_SUCCESS != thread_status) {
-                    std::cerr << "Inference failed, status = "  << thread_status << std::endl;
-                    return thread_status;
-                }
-            }
-            for (auto &thread_status : read_results) {
-                if (HAILO_SUCCESS != thread_status) {
-                    std::cerr << "Inference failed, status = "  << thread_status << std::endl;
-                    return thread_status;
-                }
-            }
-        }
-    }
-
-    std::cout << "Inference finished successfully" << std::endl;
-    return HAILO_SUCCESS;
-}
\ No newline at end of file
diff --git a/hailort/libhailort/examples/cpp/switch_hefs_example_threads_reuse.cpp b/hailort/libhailort/examples/cpp/switch_hefs_example_threads_reuse.cpp
deleted file mode 100644 (file)
index 735a5f8..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**git checkout HRT-4862-change-switch_hefs_example-to-r
- * @ file switch_hefs_example_threads_reuse.cpp
- * This example demonstrates basic usage of HailoRT streaming api over multiple networks, using vstreams.
- * It loads several HEF networks with single/multiple inputs and single/multiple outputs into a Hailo PCIe VDevice and performs a
- * short inference on each one. 
- * After inference is finished, the example switches to the next HEF and start inference again.
- **/
-
-#include "hailo/hailort.hpp"
-
-#include <iostream>
-#include <chrono>
-
-constexpr bool QUANTIZED = true;
-constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
-
-constexpr size_t INFER_FRAME_COUNT = 100;
-constexpr size_t RUN_COUNT = 10;
-constexpr std::chrono::milliseconds WAIT_FOR_ACTIVATION_TIMEOUT_MS(10);
-constexpr uint32_t DEVICE_COUNT = 1;
-
-using hailort::VDevice;
-using hailort::Hef;
-using hailort::ConfiguredNetworkGroup;
-using hailort::ActivatedNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputVStream;
-using hailort::OutputVStream;
-using hailort::MemoryView;
-
-
-#include <mutex>
-#include <condition_variable>
-
-class SyncObject final {
-/* Synchronization class used to make sure I/O threads are blocking while their network_group is not activated  */
-public:
-    explicit SyncObject(size_t count) : m_original_count(count), m_count(count), m_all_arrived(false), m_mutex(), m_cv(), m_is_active(true)
-        {};
-
-    /* In main thread we wait until I/O threads are done (0 == m_count),
-       signaling the I/O threads only after deactivating their network_group and resetting m_count to m_original_count */
-    void wait_all(std::unique_ptr<ActivatedNetworkGroup> &&activated_network_group)
-    {
-        if (!m_is_active.load()) {
-            return;
-        }
-        std::unique_lock<std::mutex> lock(m_mutex);
-        m_cv.wait(lock, [this] { return ((0 == m_count) || !m_is_active); });
-        activated_network_group.reset();
-        m_count = m_original_count;
-        m_all_arrived = true;
-        m_cv.notify_all();
-    }
-
-    /* In I/O threads we wait until signaled by main thread (true == m_all_arrived),
-       resetting m_all_arrived to false to make sure it was setted by 'wait_all' call */
-    void notify_and_wait()
-    {
-        if (!m_is_active.load()) {
-            return;
-        }
-        std::unique_lock<std::mutex> lock(m_mutex);
-        m_all_arrived = false;
-        --m_count;
-        m_cv.notify_all();
-        m_cv.wait(lock, [this] { return ((m_all_arrived) || !m_is_active); });
-    }
-
-    void terminate()
-    {
-        {
-            std::unique_lock<std::mutex> lock(m_mutex);
-            m_is_active.store(false);
-        }
-        m_cv.notify_all();
-    }
-
-private:
-    const size_t m_original_count;
-    std::atomic_size_t m_count;
-    std::atomic_bool m_all_arrived;
-
-    std::mutex m_mutex;
-    std::condition_variable m_cv;
-    std::atomic_bool m_is_active;
-};
-
-
-void write_all(std::shared_ptr<ConfiguredNetworkGroup> network_group, InputVStream &input_vstream,
-    std::shared_ptr<SyncObject> sync_object, std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
-{
-    std::vector<uint8_t> buff(input_vstream.get_frame_size());
-
-    auto status = HAILO_UNINITIALIZED;
-    while (true) {
-        if (!(*should_threads_run)) {
-            break;
-        }
-        status = network_group->wait_for_activation(WAIT_FOR_ACTIVATION_TIMEOUT_MS);
-        if (HAILO_TIMEOUT == status) {
-            continue;
-        } else if (HAILO_SUCCESS != status) {
-            std::cerr << "Wait for network group activation failed. status = " << status << std::endl;
-            status_out = status;
-            return;
-        }
-
-        for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
-            status = input_vstream.write(MemoryView(buff.data(), buff.size()));
-            if (HAILO_SUCCESS != status) {
-                status_out = status;
-                return;
-            }
-        }
-        sync_object->notify_and_wait();
-    }
-    return;
-}
-
-void read_all(std::shared_ptr<ConfiguredNetworkGroup> network_group, OutputVStream &output_vstream,
-    std::shared_ptr<SyncObject> sync_object, std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
-{
-    std::vector<uint8_t> buff(output_vstream.get_frame_size());
-
-    auto status = HAILO_UNINITIALIZED;
-    while (true) {
-        if (!(*should_threads_run)) {
-            break;
-        }
-        status = network_group->wait_for_activation(WAIT_FOR_ACTIVATION_TIMEOUT_MS);
-        if (HAILO_TIMEOUT == status) {
-            continue;
-        } else if (HAILO_SUCCESS != status) {
-            std::cerr << "Wait for network group activation failed. status = " << status << std::endl;
-            status_out = status;
-            return;
-        }
-
-        for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
-            status = output_vstream.read(MemoryView(buff.data(), buff.size()));
-            if (HAILO_SUCCESS != status) {
-                status_out = status;
-                return;
-            }
-        }
-        sync_object->notify_and_wait();
-    }
-    return;
-}
-
-void network_group_thread_main(std::shared_ptr<ConfiguredNetworkGroup> network_group, std::shared_ptr<SyncObject> sync_object,
-    std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
-{
-    // Create VStreams
-    auto vstreams_exp = VStreamsBuilder::create_vstreams(*network_group, QUANTIZED, FORMAT_TYPE);
-    if (!vstreams_exp) {
-        std::cerr << "Failed to create vstreams, status = " << vstreams_exp.status() << std::endl;
-        status_out = vstreams_exp.status();
-        return;
-    }
-
-    // Create send/recv loops
-    std::vector<std::unique_ptr<std::thread>> recv_ths;
-    std::vector<hailo_status> read_results;
-    read_results.reserve(vstreams_exp->second.size());
-    for (auto &vstream : vstreams_exp->second) {
-        read_results.push_back(HAILO_SUCCESS); // Success oriented
-        recv_ths.emplace_back(std::make_unique<std::thread>(read_all,
-            network_group, std::ref(vstream), sync_object, should_threads_run, std::ref(read_results.back())));
-    }
-
-    std::vector<std::unique_ptr<std::thread>> send_ths;
-    std::vector<hailo_status> write_results;
-    write_results.reserve(vstreams_exp->first.size());
-    for (auto &vstream : vstreams_exp->first) {
-        write_results.push_back(HAILO_SUCCESS); // Success oriented
-        send_ths.emplace_back(std::make_unique<std::thread>(write_all,
-            network_group, std::ref(vstream), std::ref(sync_object), should_threads_run, std::ref(write_results.back())));
-    }
-
-    for (auto &send_th : send_ths) {
-        if (send_th->joinable()) {
-            send_th->join();
-        }
-    }
-    for (auto &recv_th : recv_ths) {
-        if (recv_th->joinable()) {
-            recv_th->join();
-        }
-    }
-
-    for (auto &status : read_results) {
-        if (HAILO_SUCCESS != status) {
-            status_out = status;
-            return;
-        }
-    }
-    for (auto &status : write_results) {
-        if (HAILO_SUCCESS != status) {
-            status_out = status;
-            return;
-        }
-    }
-    status_out = HAILO_SUCCESS;
-    return;
-}
-
-int main()
-{
-    hailo_vdevice_params_t params;
-    auto status = hailo_init_vdevice_params(&params);
-    if (HAILO_SUCCESS != status) {
-        std::cerr << "Failed init vdevice_params, status = " << status << std::endl;
-        return status;
-    }
-
-    params.device_count = DEVICE_COUNT;
-    auto vdevice_exp = VDevice::create(params);
-    if (!vdevice_exp) {
-        std::cerr << "Failed create vdevice, status = " << vdevice_exp.status() << std::endl;
-        return vdevice_exp.status();
-    }
-    auto vdevice = vdevice_exp.release();
-
-    std::vector<std::string> hef_paths = {"hefs/shortcut_net.hef", "hefs/shortcut_net.hef"};
-    std::vector<std::shared_ptr<ConfiguredNetworkGroup>> configured_network_groups;
-
-    for (const auto &path : hef_paths) {
-        auto hef_exp = Hef::create(path);
-        if (!hef_exp) {
-            std::cerr << "Failed to create hef: " << path  << ", status = " << hef_exp.status() << std::endl;
-            return hef_exp.status();
-        }
-        auto hef = hef_exp.release();
-
-        auto added_network_groups = vdevice->configure(hef);
-        if (!added_network_groups) {
-            std::cerr << "Failed to configure vdevice, status = " << added_network_groups.status() << std::endl;
-            return added_network_groups.status();
-        }
-        configured_network_groups.insert(configured_network_groups.end(), added_network_groups->begin(), added_network_groups->end());
-    }
-
-    auto should_threads_run = std::make_shared<std::atomic_bool>(true);
-
-    std::vector<std::shared_ptr<SyncObject>> sync_objects;
-    sync_objects.reserve(configured_network_groups.size());
-    std::vector<hailo_status> threads_results;
-    threads_results.reserve(configured_network_groups.size());
-    std::vector<std::unique_ptr<std::thread>> network_group_threads;
-    network_group_threads.reserve(configured_network_groups.size());
-
-    for (auto network_group : configured_network_groups) {
-        threads_results.push_back(HAILO_UNINITIALIZED);
-        auto vstream_infos = network_group->get_all_vstream_infos();
-        if (!vstream_infos) {
-            std::cerr << "Failed to get vstream infos, status = " << vstream_infos.status() << std::endl;
-            return vstream_infos.status();
-        }
-        sync_objects.emplace_back((std::make_shared<SyncObject>(vstream_infos->size())));
-        network_group_threads.emplace_back(std::make_unique<std::thread>(network_group_thread_main,
-            network_group, sync_objects.back(), should_threads_run, std::ref(threads_results.back())));
-    }
-
-    for (size_t i = 0; i < RUN_COUNT; i++) {
-        for (size_t network_group_idx = 0; network_group_idx < configured_network_groups.size(); network_group_idx++) {
-            auto activated_network_group_exp = configured_network_groups[network_group_idx]->activate();
-            if (!activated_network_group_exp) {
-                std::cerr << "Failed to activate network group, status = "  << activated_network_group_exp.status() << std::endl;
-                return activated_network_group_exp.status();
-            }
-            sync_objects[network_group_idx]->wait_all(activated_network_group_exp.release());
-        }
-    }
-
-    *should_threads_run = false;
-    for (auto &sync_object : sync_objects) {
-        sync_object->terminate();
-    }
-
-    for (auto &th : network_group_threads) {
-        if (th->joinable()) {
-            th->join();
-        }
-    }
-
-    for (auto &thread_status : threads_results) {
-        if (HAILO_SUCCESS != thread_status) {
-            std::cerr << "Inference failed, status = "  << thread_status << std::endl;
-            return thread_status;
-        }
-    }
-
-    std::cout << "Inference finished successfully" << std::endl;
-    return HAILO_SUCCESS;
-}
\ No newline at end of file
diff --git a/hailort/libhailort/examples/cpp/switch_network_groups_example.cpp b/hailort/libhailort/examples/cpp/switch_network_groups_example.cpp
new file mode 100644 (file)
index 0000000..a0a067d
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file switch_network_groups_example.cpp
+ * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using VStreams.
+ * It loads several network_groups (via several HEFs) into a Hailo PCIe VDevice and performs a inferences on all of them in parallel.
+ * The network_groups switching is performed automatically by the HailoRT scheduler.
+ **/
+
+#include "hailo/hailort.hpp"
+
+#include <iostream>
+#include <chrono>
+
+constexpr bool QUANTIZED = true;
+constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
+constexpr size_t INFER_FRAME_COUNT = 100;
+constexpr uint32_t DEVICE_COUNT = 1;
+
+using namespace hailort;
+using ThreadsVector = std::vector<std::unique_ptr<std::thread>>;
+using StatusVector = std::vector<std::shared_ptr<hailo_status>>;
+
+void write_all(InputVStream &input_vstream, std::shared_ptr<hailo_status> status_out)
+{
+    std::vector<uint8_t> buff(input_vstream.get_frame_size());
+
+    for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
+        auto status = input_vstream.write(MemoryView(buff.data(), buff.size()));
+        if (HAILO_SUCCESS != status) {
+            *status_out = status;
+            return;
+        }
+    }
+    *status_out = HAILO_SUCCESS;
+    return;
+}
+
+void read_all(OutputVStream &output_vstream, std::shared_ptr<hailo_status> status_out)
+{
+    std::vector<uint8_t> buff(output_vstream.get_frame_size());
+
+    for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
+        auto status = output_vstream.read(MemoryView(buff.data(), buff.size()));
+        if (HAILO_SUCCESS != status) {
+            *status_out = status;
+            return;
+        }
+    }
+    *status_out = HAILO_SUCCESS;
+    return;
+}
+
+Expected<std::vector<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>>> build_vstreams(
+    const std::vector<std::shared_ptr<ConfiguredNetworkGroup>> &configured_network_groups)
+{
+    std::vector<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> vstreams_per_network_group;
+
+    for (auto &network_group : configured_network_groups) {
+        auto vstreams_exp = VStreamsBuilder::create_vstreams(*network_group, QUANTIZED, FORMAT_TYPE);
+        if (!vstreams_exp) {
+            return make_unexpected(vstreams_exp.status());
+        }
+        vstreams_per_network_group.emplace_back(vstreams_exp.release());
+    }
+    return vstreams_per_network_group;
+}
+
+void create_read_threads(std::vector<OutputVStream> &vstreams, StatusVector &read_results, ThreadsVector &threads_vector)
+{
+    for (auto &vstream : vstreams) {
+        read_results.push_back(std::make_shared<hailo_status>(HAILO_UNINITIALIZED));
+        threads_vector.emplace_back(std::make_unique<std::thread>(read_all, std::ref(vstream), read_results.back()));
+    }
+}
+
+void create_write_threads(std::vector<InputVStream> &vstreams, StatusVector &write_results, ThreadsVector &threads_vector)
+{
+    for (auto &vstream : vstreams) {
+        write_results.push_back(std::make_shared<hailo_status>(HAILO_UNINITIALIZED));
+        threads_vector.emplace_back(std::make_unique<std::thread>(write_all, std::ref(vstream), write_results.back()));
+    }
+}
+
+Expected<std::unique_ptr<VDevice>> create_vdevice()
+{
+    hailo_vdevice_params_t params;
+    auto status = hailo_init_vdevice_params(&params);
+    if (HAILO_SUCCESS != status) {
+        std::cerr << "Failed init vdevice_params, status = " << status << std::endl;
+        return make_unexpected(status);
+    }
+    params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN;
+    params.device_count = DEVICE_COUNT;
+
+    return VDevice::create(params);
+}
+
+Expected<std::vector<std::shared_ptr<ConfiguredNetworkGroup>>> configure_hefs(VDevice &vdevice, std::vector<std::string> &hef_paths)
+{
+    std::vector<std::shared_ptr<ConfiguredNetworkGroup>> results;
+
+    for (const auto &path : hef_paths) {
+        auto hef_exp = Hef::create(path);
+        if (!hef_exp) {
+            return make_unexpected(hef_exp.status());
+        }
+        auto hef = hef_exp.release();
+
+        auto added_network_groups = vdevice.configure(hef);
+        if (!added_network_groups) {
+            return make_unexpected(added_network_groups.status());
+        }
+        results.insert(results.end(), added_network_groups->begin(),
+            added_network_groups->end());
+    }
+    return results;
+}
+
+int main()
+{
+    auto vdevice_exp = create_vdevice();
+    if (!vdevice_exp) {
+        std::cerr << "Failed create vdevice, status = " << vdevice_exp.status() << std::endl;
+        return vdevice_exp.status();
+    }
+    auto vdevice = vdevice_exp.release();
+
+    std::vector<std::string> hef_paths = {"hefs/multi_network_shortcut_net.hef", "hefs/shortcut_net.hef"};
+    auto configured_network_groups_exp = configure_hefs(*vdevice, hef_paths);
+    if (!configured_network_groups_exp) {
+        std::cerr << "Failed to configure HEFs, status = " << configured_network_groups_exp.status() << std::endl;
+        return configured_network_groups_exp.status();
+    }
+    auto configured_network_groups = configured_network_groups_exp.release();
+
+    auto vstreams_per_network_group_exp = build_vstreams(configured_network_groups);
+    if (!vstreams_per_network_group_exp) {
+        std::cerr << "Failed to create vstreams, status = " << vstreams_per_network_group_exp.status() << std::endl;
+        return vstreams_per_network_group_exp.status();
+    }
+    auto vstreams_per_network_group = vstreams_per_network_group_exp.release();
+
+    ThreadsVector threads;
+    StatusVector results;
+
+    for (auto &vstreams_pair : vstreams_per_network_group) {
+        // Create send/recv threads
+        create_read_threads(vstreams_pair.second, results, threads);
+        create_write_threads(vstreams_pair.first, results, threads);
+    }
+
+    // Join threads and validate results
+    for (auto &thread : threads) {
+        if (thread->joinable()) {
+            thread->join();
+        }
+    }
+    for (auto &status : results) {
+        if (HAILO_SUCCESS != *status) {
+            std::cerr << "Inference failed, status = "  << *status << std::endl;
+            return *status;
+        }
+    }
+
+    std::cout << "Inference finished successfully" << std::endl;
+    return HAILO_SUCCESS;
+}
\ No newline at end of file
diff --git a/hailort/libhailort/examples/cpp/switch_network_groups_manually_example.cpp b/hailort/libhailort/examples/cpp/switch_network_groups_manually_example.cpp
new file mode 100644 (file)
index 0000000..aabfe67
--- /dev/null
@@ -0,0 +1,293 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file switch_network_groups_manually_example.cpp
+ * This example demonstrates basic usage of HailoRT streaming api over multiple networks, using vstreams.
+ * It loads several HEF networks with single/multiple inputs and single/multiple outputs into a Hailo PCIe VDevice and performs a
+ * short inference on each one.
+ * After inference is finished, the example switches to the next HEF and start inference again.
+ **/
+
+#include "hailo/hailort.hpp"
+
+#include <iostream>
+#include <chrono>
+
+constexpr bool QUANTIZED = true;
+constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
+
+constexpr size_t INFER_FRAME_COUNT = 100;
+constexpr size_t RUN_COUNT = 10;
+constexpr std::chrono::milliseconds WAIT_FOR_ACTIVATION_TIMEOUT_MS(10);
+constexpr uint32_t DEVICE_COUNT = 1;
+
+using namespace hailort;
+
+#include <mutex>
+#include <condition_variable>
+
+class SyncObject final {
+/* Synchronization class used to make sure I/O threads are blocking while their network_group is not activated  */
+public:
+    explicit SyncObject(size_t count) : m_original_count(count), m_count(count), m_all_arrived(false), m_mutex(), m_cv(), m_is_active(true)
+        {};
+
+    /* In main thread we wait until I/O threads are done (0 == m_count),
+       signaling the I/O threads only after deactivating their network_group and resetting m_count to m_original_count */
+    void wait_all(std::unique_ptr<ActivatedNetworkGroup> &&activated_network_group)
+    {
+        if (!m_is_active.load()) {
+            return;
+        }
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_cv.wait(lock, [this] { return ((0 == m_count) || !m_is_active); });
+        activated_network_group.reset();
+        m_count = m_original_count;
+        m_all_arrived = true;
+        m_cv.notify_all();
+    }
+
+    /* In I/O threads we wait until signaled by main thread (true == m_all_arrived),
+       resetting m_all_arrived to false to make sure it was setted by 'wait_all' call */
+    void notify_and_wait()
+    {
+        if (!m_is_active.load()) {
+            return;
+        }
+        std::unique_lock<std::mutex> lock(m_mutex);
+        m_all_arrived = false;
+        --m_count;
+        m_cv.notify_all();
+        m_cv.wait(lock, [this] { return ((m_all_arrived) || !m_is_active); });
+    }
+
+    void terminate()
+    {
+        {
+            std::unique_lock<std::mutex> lock(m_mutex);
+            m_is_active.store(false);
+        }
+        m_cv.notify_all();
+    }
+
+private:
+    const size_t m_original_count;
+    std::atomic_size_t m_count;
+    std::atomic_bool m_all_arrived;
+
+    std::mutex m_mutex;
+    std::condition_variable m_cv;
+    std::atomic_bool m_is_active;
+};
+
+
+void write_all(std::shared_ptr<ConfiguredNetworkGroup> network_group, InputVStream &input_vstream,
+    std::shared_ptr<SyncObject> sync_object, std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
+{
+    std::vector<uint8_t> buff(input_vstream.get_frame_size());
+
+    auto status = HAILO_UNINITIALIZED;
+    while (true) {
+        if (!(*should_threads_run)) {
+            break;
+        }
+        status = network_group->wait_for_activation(WAIT_FOR_ACTIVATION_TIMEOUT_MS);
+        if (HAILO_TIMEOUT == status) {
+            continue;
+        } else if (HAILO_SUCCESS != status) {
+            std::cerr << "Wait for network group activation failed. status = " << status << std::endl;
+            status_out = status;
+            return;
+        }
+
+        for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
+            status = input_vstream.write(MemoryView(buff.data(), buff.size()));
+            if (HAILO_SUCCESS != status) {
+                status_out = status;
+                return;
+            }
+        }
+        sync_object->notify_and_wait();
+    }
+    return;
+}
+
+void read_all(std::shared_ptr<ConfiguredNetworkGroup> network_group, OutputVStream &output_vstream,
+    std::shared_ptr<SyncObject> sync_object, std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
+{
+    std::vector<uint8_t> buff(output_vstream.get_frame_size());
+
+    auto status = HAILO_UNINITIALIZED;
+    while (true) {
+        if (!(*should_threads_run)) {
+            break;
+        }
+        status = network_group->wait_for_activation(WAIT_FOR_ACTIVATION_TIMEOUT_MS);
+        if (HAILO_TIMEOUT == status) {
+            continue;
+        } else if (HAILO_SUCCESS != status) {
+            std::cerr << "Wait for network group activation failed. status = " << status << std::endl;
+            status_out = status;
+            return;
+        }
+
+        for (size_t i = 0; i < INFER_FRAME_COUNT; i++) {
+            status = output_vstream.read(MemoryView(buff.data(), buff.size()));
+            if (HAILO_SUCCESS != status) {
+                status_out = status;
+                return;
+            }
+        }
+        sync_object->notify_and_wait();
+    }
+    return;
+}
+
+void network_group_thread_main(std::shared_ptr<ConfiguredNetworkGroup> network_group, std::shared_ptr<SyncObject> sync_object,
+    std::shared_ptr<std::atomic_bool> should_threads_run, hailo_status &status_out)
+{
+    // Create VStreams
+    auto vstreams_exp = VStreamsBuilder::create_vstreams(*network_group, QUANTIZED, FORMAT_TYPE);
+    if (!vstreams_exp) {
+        std::cerr << "Failed to create vstreams, status = " << vstreams_exp.status() << std::endl;
+        status_out = vstreams_exp.status();
+        return;
+    }
+
+    // Create send/recv loops
+    std::vector<std::unique_ptr<std::thread>> recv_ths;
+    std::vector<hailo_status> read_results;
+    read_results.reserve(vstreams_exp->second.size());
+    for (auto &vstream : vstreams_exp->second) {
+        read_results.push_back(HAILO_SUCCESS); // Success oriented
+        recv_ths.emplace_back(std::make_unique<std::thread>(read_all,
+            network_group, std::ref(vstream), sync_object, should_threads_run, std::ref(read_results.back())));
+    }
+
+    std::vector<std::unique_ptr<std::thread>> send_ths;
+    std::vector<hailo_status> write_results;
+    write_results.reserve(vstreams_exp->first.size());
+    for (auto &vstream : vstreams_exp->first) {
+        write_results.push_back(HAILO_SUCCESS); // Success oriented
+        send_ths.emplace_back(std::make_unique<std::thread>(write_all,
+            network_group, std::ref(vstream), std::ref(sync_object), should_threads_run, std::ref(write_results.back())));
+    }
+
+    for (auto &send_th : send_ths) {
+        if (send_th->joinable()) {
+            send_th->join();
+        }
+    }
+    for (auto &recv_th : recv_ths) {
+        if (recv_th->joinable()) {
+            recv_th->join();
+        }
+    }
+
+    for (auto &status : read_results) {
+        if (HAILO_SUCCESS != status) {
+            status_out = status;
+            return;
+        }
+    }
+    for (auto &status : write_results) {
+        if (HAILO_SUCCESS != status) {
+            status_out = status;
+            return;
+        }
+    }
+    status_out = HAILO_SUCCESS;
+    return;
+}
+
+int main()
+{
+    hailo_vdevice_params_t params;
+    auto status = hailo_init_vdevice_params(&params);
+    if (HAILO_SUCCESS != status) {
+        std::cerr << "Failed init vdevice_params, status = " << status << std::endl;
+        return status;
+    }
+
+    params.device_count = DEVICE_COUNT;
+    auto vdevice_exp = VDevice::create(params);
+    if (!vdevice_exp) {
+        std::cerr << "Failed create vdevice, status = " << vdevice_exp.status() << std::endl;
+        return vdevice_exp.status();
+    }
+    auto vdevice = vdevice_exp.release();
+
+    std::vector<std::string> hef_paths = {"hefs/shortcut_net.hef", "hefs/shortcut_net.hef"};
+    std::vector<std::shared_ptr<ConfiguredNetworkGroup>> configured_network_groups;
+
+    for (const auto &path : hef_paths) {
+        auto hef_exp = Hef::create(path);
+        if (!hef_exp) {
+            std::cerr << "Failed to create hef: " << path  << ", status = " << hef_exp.status() << std::endl;
+            return hef_exp.status();
+        }
+        auto hef = hef_exp.release();
+
+        auto added_network_groups = vdevice->configure(hef);
+        if (!added_network_groups) {
+            std::cerr << "Failed to configure vdevice, status = " << added_network_groups.status() << std::endl;
+            return added_network_groups.status();
+        }
+        configured_network_groups.insert(configured_network_groups.end(), added_network_groups->begin(), added_network_groups->end());
+    }
+
+    auto should_threads_run = std::make_shared<std::atomic_bool>(true);
+
+    std::vector<std::shared_ptr<SyncObject>> sync_objects;
+    sync_objects.reserve(configured_network_groups.size());
+    std::vector<hailo_status> threads_results;
+    threads_results.reserve(configured_network_groups.size());
+    std::vector<std::unique_ptr<std::thread>> network_group_threads;
+    network_group_threads.reserve(configured_network_groups.size());
+
+    for (auto network_group : configured_network_groups) {
+        threads_results.push_back(HAILO_UNINITIALIZED);
+        auto vstream_infos = network_group->get_all_vstream_infos();
+        if (!vstream_infos) {
+            std::cerr << "Failed to get vstream infos, status = " << vstream_infos.status() << std::endl;
+            return vstream_infos.status();
+        }
+        sync_objects.emplace_back((std::make_shared<SyncObject>(vstream_infos->size())));
+        network_group_threads.emplace_back(std::make_unique<std::thread>(network_group_thread_main,
+            network_group, sync_objects.back(), should_threads_run, std::ref(threads_results.back())));
+    }
+
+    for (size_t i = 0; i < RUN_COUNT; i++) {
+        for (size_t network_group_idx = 0; network_group_idx < configured_network_groups.size(); network_group_idx++) {
+            auto activated_network_group_exp = configured_network_groups[network_group_idx]->activate();
+            if (!activated_network_group_exp) {
+                std::cerr << "Failed to activate network group, status = "  << activated_network_group_exp.status() << std::endl;
+                return activated_network_group_exp.status();
+            }
+            sync_objects[network_group_idx]->wait_all(activated_network_group_exp.release());
+        }
+    }
+
+    *should_threads_run = false;
+    for (auto &sync_object : sync_objects) {
+        sync_object->terminate();
+    }
+
+    for (auto &th : network_group_threads) {
+        if (th->joinable()) {
+            th->join();
+        }
+    }
+
+    for (auto &thread_status : threads_results) {
+        if (HAILO_SUCCESS != thread_status) {
+            std::cerr << "Inference failed, status = "  << thread_status << std::endl;
+            return thread_status;
+        }
+    }
+
+    std::cout << "Inference finished successfully" << std::endl;
+    return HAILO_SUCCESS;
+}
\ No newline at end of file
index d87f800b177625a9b1b25713a1212580919a9bbe..5488e140d9538e00e08ab2d7ed6a5a9dc169dfaa 100644 (file)
@@ -3,7 +3,7 @@
  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
  **/
 /**
- * @ file vstreams_example
+ * @file vstreams_example
  * This example demonstrates using virtual streams over c++
  **/
 
@@ -17,17 +17,7 @@ constexpr bool QUANTIZED = true;
 constexpr hailo_format_type_t FORMAT_TYPE = HAILO_FORMAT_TYPE_AUTO;
 constexpr size_t MAX_LAYER_EDGES = 16;
 
-
-using hailort::VDevice;
-using hailort::Hef;
-using hailort::Expected;
-using hailort::make_unexpected;
-using hailort::ConfiguredNetworkGroup;
-using hailort::VStreamsBuilder;
-using hailort::InputVStream;
-using hailort::OutputVStream;
-using hailort::MemoryView;
-
+using namespace hailort;
 
 Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(VDevice &vdevice)
 {
index d8d5cdf23ca9f438672da02328019e6f3e210c07..f629ed793a1afada3e37126493d6c90eb3912b30 100644 (file)
@@ -32,6 +32,8 @@ enum ProtoHEFExtensionType {
     MULTI_NETWORK_VARIABLE_BATCH_SIZE = 8;
     IS_NMS_MULTI_CONTEXT = 9;
     OFFLOAD_ARGMAX = 10;
+    HW_PADDING = 11;
+    PRELIMINARY_RUN_ASAP = 12;
     UNUSED = 0XFFFF;
 }
 
@@ -461,6 +463,7 @@ message ProtoHEFEdgeLayerBase {
 
     repeated ProtoHEFResourceIndices buffer_indices = 13;
     bool host_argmax = 14;
+    uint32 max_shmifo_size = 15;
 }
 
 // Additional information for specific layer types
index 9527df3faf2f792f62286e1984de434cdde6df11..90eba66428539bd9f2eca7d2531a57787573b84c 100644 (file)
@@ -312,7 +312,7 @@ public:
     /**
      * Start performing a long power measurement.
      * 
-     * @param[in]   delay_milliseconds   Amount of time between each measurement interval.
+     * @param[in]   unused               Unused parameter.
      *                                   This time period is sleep time of the core.
      * @param[in]   averaging_factor     Number of samples per time period, sensor configuration value.
      * @param[in]   sampling_period      Related conversion time, sensor configuration value.
@@ -323,8 +323,9 @@ public:
      *                                   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 Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     * @note This function is deprecated. One should use 'Device::start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)'
      */
-    hailo_status start_power_measurement(uint32_t delay_milliseconds, hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period);
+    hailo_status start_power_measurement(uint32_t unused, hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period);
 
     /**
      * Set parameters for long power measurement.
@@ -338,6 +339,7 @@ public:
      * @param[in]   measurement_type   The type of the measurement. Choosing ::HAILO_POWER_MEASUREMENT_TYPES__AUTO
      *                                 will select the default value according to the supported features.
      * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     * @note This function is deprecated. One should use 'Device::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)'
      */
     hailo_status set_power_measurement(uint32_t index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type);
 
@@ -347,10 +349,54 @@ public:
      * @param[in]   index                 Index of the buffer on the firmware the data would be saved at.
      * @param[in]   should_clear          Flag indicating if the results saved at the firmware will be deleted after reading.
      * @return Upon success, returns @a hailo_power_measurement_data_t. Measured units are determined due to ::hailo_power_measurement_types_t
-     *         passed to ::hailo_set_power_measurement. Otherwise, returns a ::hailo_status error.
+     *         passed to 'Device::set_power_measurement'. Otherwise, returns a ::hailo_status error.
+     * @note This function is deprecated. One should use "Device::get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear)'
      */
     Expected<hailo_power_measurement_data_t> get_power_measurement(uint32_t index, bool should_clear);
 
+    /**
+     * Start performing a long power measurement.
+     * 
+     * @param[in]   averaging_factor     Number of samples per time period, sensor configuration value.
+     * @param[in]   sampling_period      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 interval_milliseconds {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 Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     */
+    hailo_status start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period);
+
+
+    /**
+     * Set parameters for long power measurement.
+     * 
+     * @param[in]   buffer_index       A ::hailo_measurement_buffer_index_t represents the buffer on the firmware the data would be saved at.
+     *                                 Should match the one passed to 'Device::get_power_measurement'.
+     * @param[in]   dvm                Which DVM will be measured. Default (::HAILO_DVM_OPTIONS_AUTO) will be different according to the board: <br>
+     *                                 - Default (::HAILO_DVM_OPTIONS_AUTO) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
+     *                                 It sums ::HAILO_DVM_OPTIONS_VDD_CORE, ::HAILO_DVM_OPTIONS_MIPI_AVDD and ::HAILO_DVM_OPTIONS_AVDD_H.
+     *                                 Only ::HAILO_POWER_MEASUREMENT_TYPES__POWER can measured with this option.
+     *                                 - Default (::HAILO_DVM_OPTIONS_AUTO) for platforms supporting current monitoring (such as M.2 and mPCIe): OVERCURRENT_PROTECTION.
+     * @param[in]   measurement_type   The type of the measurement. Choosing ::HAILO_POWER_MEASUREMENT_TYPES__AUTO
+     *                                 will select the default value according to the supported features.
+     * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     */
+    hailo_status set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type);
+
+    /**
+     * Read measured power from a long power measurement
+     * 
+     * @param[in]   buffer_index          A ::hailo_measurement_buffer_index_t represents the buffer on the firmware the data would be saved at.
+     *                                    Should match the one passed to 'Device::set_power_measurement'.
+     * @param[in]   should_clear          Flag indicating if the results saved at the firmware will be deleted after reading.
+     * @return Upon success, returns @a hailo_power_measurement_data_t. Measured units are determined due to ::hailo_power_measurement_types_t
+     *         passed to 'Device::set_power_measurement'. Otherwise, returns a ::hailo_status error.
+     */
+    Expected<hailo_power_measurement_data_t> get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear);
+
     /**
      * Stop performing a long power measurement.
      * 
@@ -387,7 +433,7 @@ public:
      * @param[in] opaque                User specific data.
      * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
      */
-    virtual hailo_status set_notification_callback(NotificationCallback func, hailo_notification_id_t notification_id,
+    virtual hailo_status set_notification_callback(const NotificationCallback &func, hailo_notification_id_t notification_id,
         void *opaque) = 0;
 
     /**
@@ -614,6 +660,8 @@ public:
     Expected<std::vector<uint8_t>> get_number_of_contexts_per_network_group();
     Expected<Buffer> download_context_action_list(uint8_t context_index, uint32_t *base_address,
         uint32_t *batch_counter, uint16_t max_size = 10000);
+    // The batch configured is reset between network groups
+    hailo_status set_context_action_list_timestamp_batch(uint16_t batch_index);
 
     virtual ~Device() = default;
     Device(const Device &) = delete;
index d3da128883699cbe8f60baf25bd5150c2090c346..81190d312d0337ba86364da94ca7e05be776da81 100644 (file)
 #include <poll.h>
 #endif
 
+#if defined(__QNX__)
+#include <atomic>
+#include <mutex>
+
+// Forward declare neosmart::neosmart_event_t_
+namespace neosmart {
+    struct neosmart_event_t_;
+}
+#endif // defined (__QNX__)
+
 namespace hailort
 {
 
+// underlying_waitable_handle_t
+#if defined(_MSC_VER) || defined(__linux__)
+    typedef underlying_handle_t underlying_waitable_handle_t; 
+#elif defined(__QNX__)
+    typedef neosmart::neosmart_event_t_* underlying_waitable_handle_t;
+#else
+    #error "Unsupported Platform"
+#endif
+
+
 class Waitable;
 using WaitablePtr = std::shared_ptr<Waitable>;
 using WaitablePtrList = std::vector<WaitablePtr>;
@@ -31,7 +51,7 @@ using WaitablePtrList = std::vector<WaitablePtr>;
 class HAILORTAPI Waitable
 {
 public:    
-    explicit Waitable(underlying_handle_t handle);
+    explicit Waitable(underlying_waitable_handle_t handle);
     virtual ~Waitable();
     Waitable(Waitable&& other);
 
@@ -45,22 +65,25 @@ public:
     virtual hailo_status wait(std::chrono::milliseconds timeout) = 0;
     virtual hailo_status signal() = 0;
     virtual bool is_auto_reset() = 0;
-    underlying_handle_t get_underlying_handle();
+    underlying_waitable_handle_t get_underlying_handle();
+#if defined(__QNX__)
+    virtual void post_wait() = 0;
+#endif // defined (__QNX__)
 
     static constexpr auto INIFINITE_TIMEOUT() { return std::chrono::milliseconds(HAILO_INFINITE); }
 
 protected:
-    #if defined(_MSC_VER)
-    static hailo_status wait_for_single_object(underlying_handle_t handle, std::chrono::milliseconds timeout);
+    #if defined(_MSC_VER) || defined(__QNX__)
+    static hailo_status wait_for_single_object(underlying_waitable_handle_t handle, std::chrono::milliseconds timeout);
     #else
     // Waits on the fd until the waitable is signaled
-    static hailo_status eventfd_poll(underlying_handle_t fd, std::chrono::milliseconds timeout);
+    static hailo_status eventfd_poll(underlying_waitable_handle_t fd, std::chrono::milliseconds timeout);
     // Expected to be called after eventfd_poll returns HAILO_SUCCESS
-    static hailo_status eventfd_read(underlying_handle_t fd);
-    static hailo_status eventfd_write(underlying_handle_t fd);
+    static hailo_status eventfd_read(underlying_waitable_handle_t fd);
+    static hailo_status eventfd_write(underlying_waitable_handle_t fd);
     #endif
 
-    underlying_handle_t m_handle;
+    underlying_waitable_handle_t m_handle;
 };
 
 class Event;
@@ -86,9 +109,12 @@ public:
     virtual hailo_status signal() override;
     virtual bool is_auto_reset() override;
     hailo_status reset();
+#if defined(__QNX__)
+    virtual void post_wait() override;
+#endif // defined (__QNX__)
 
 private:
-    static underlying_handle_t open_event_handle(const State& initial_state);
+    static underlying_waitable_handle_t open_event_handle(const State& initial_state);
 };
 
 class Semaphore;
@@ -106,9 +132,19 @@ public:
     virtual hailo_status wait(std::chrono::milliseconds timeout) override;
     virtual hailo_status signal() override;
     virtual bool is_auto_reset() override;
+#if defined(__QNX__)
+    Semaphore(underlying_waitable_handle_t handle, uint32_t initial_count);
+    Semaphore(Semaphore&& other);
+
+    virtual void post_wait() override;
+#endif // defined (__QNX__)
 
 private:
-    static underlying_handle_t open_semaphore_handle(uint32_t initial_count);
+    static underlying_waitable_handle_t open_semaphore_handle(uint32_t initial_count);
+#if defined (__QNX__)
+    std::atomic<unsigned int> m_count;
+    std::mutex m_sem_mutex;
+#endif // defined(__QNX__)
 };
 
 } /* namespace hailort */
index d6b8c3c384fae0ec2a58a4c8c46235b6ae0fdd89..cae0ea98ea488c1506cd81511a70dab895504e12 100644 (file)
@@ -209,7 +209,7 @@ class Expected final
 {
 public:
     /**
-     * Expected<T> can access Expected<U>'s private members (needed for implicit upcasting)
+     * Expected<T> can access Expected\<U\>'s private members (needed for implicit upcasting)
      */
     template<class U>
     friend class Expected;
@@ -231,30 +231,42 @@ public:
      * Copy constructor
      */
     explicit Expected(const Expected<T> &other) :
-        m_value(other.m_value),
         m_status(other.m_status)
-    {}
+    {
+        if (other.has_value()) {
+            construct(&m_value, other.m_value);
+        }
+    }
 
     /**
      * Copy constructor for implicit upcasting
      */
     template <typename U>
     Expected(const Expected<U>& other) :
-        m_value(other.m_value),
         m_status(other.m_status)
-    {}
+    {
+        if (other.has_value()) {
+            construct(&m_value, other.m_value);
+        }
+    }
 
     /**
      * Move constructor
      * 
      * Construct a new Expected<T> where:
-     *  - other.m_value moved to this.m_value.
-     *  - other.m_status moved to this.m_status, and other.m_status is set to HAILO_UNINITIALIZED.
+     *  - other.m_status moved to this.m_status.
+     *  - other.m_value moved to this.m_value if other.m_value exists.
+     *
+     * If other had value before the move, it will still have the value that was moved (so the value object is valid but
+     * in an unspecified state).
      */
     Expected(Expected<T> &&other) :
-        m_value(std::move(other.m_value)),
-        m_status(std::exchange(other.m_status, HAILO_UNINITIALIZED))
-    {}
+        m_status(other.m_status)
+    {
+        if (other.has_value()) {
+            construct(&m_value, std::move(other.m_value));
+        }
+    }
 
     /**
      * Construct a new Expected<T> from T& where:
@@ -448,6 +460,12 @@ public:
     }
 
 private:
+    template<typename... Args>
+    static void construct(T *value, Args &&...args)
+    {
+        new ((void*)value) T(std::forward<Args>(args)...);
+    }
+
     union {
         T m_value;
     };
index c59f2fb744529e4a23ca2ac4725afecb0fbbd35a..3519e7c3fe91593db8ac13d48af4114bc92543ba 100644 (file)
@@ -300,6 +300,17 @@ typedef enum hailo_averaging_factor_e {
     HAILO_AVERAGE_FACTOR_MAX_ENUM = HAILO_MAX_ENUM
 } hailo_averaging_factor_t;
 
+/** Enum that represents buffers on the device for power measurements storing */
+typedef enum hailo_measurement_buffer_index_e {
+    HAILO_MEASUREMENT_BUFFER_INDEX_0 = 0,
+    HAILO_MEASUREMENT_BUFFER_INDEX_1,
+    HAILO_MEASUREMENT_BUFFER_INDEX_2,
+    HAILO_MEASUREMENT_BUFFER_INDEX_3,
+
+    /** Max enum value to maintain ABI Integrity */
+    HAILO_MEASUREMENT_BUFFER_INDEX_MAX_ENUM = HAILO_MAX_ENUM
+} hailo_measurement_buffer_index_t;
+
 /** Data of the power measurement samples */
 typedef struct {
     float32_t average_value;
@@ -326,12 +337,25 @@ typedef struct {
     uint32_t func;
 } hailo_pcie_device_info_t;
 
+/** Scheduler algorithm */
+typedef enum hailo_scheduling_algorithm_e {
+    /** Scheduling disabled */
+    HAILO_SCHEDULING_ALGORITHM_NONE = 0,
+    /** Round Robin */
+    HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN,
+
+    /** Max enum value to maintain ABI Integrity */
+    HAILO_SCHEDULING_ALGORITHM_MAX_ENUM = HAILO_MAX_ENUM
+} hailo_scheduling_algorithm_t;
+
 /** Virtual device parameters */
 typedef struct {
     /** Requested number of physical devices. if @a device_infos is not NULL, represents the number of ::hailo_pcie_device_info_t in @a device_infos */
     uint32_t device_count;
     /** Specific physical devices information to create the vdevice from. If NULL, the vdevice will try to occupy devices from the available pool */
     hailo_pcie_device_info_t *device_infos;
+    /** The scheduling algorithm to use for network group scheduling */
+    hailo_scheduling_algorithm_t scheduling_algorithm;
 } hailo_vdevice_params_t;
 
 /** Device architecture */
@@ -940,14 +964,7 @@ typedef enum {
 
 /** Hailo stream parameters */
 typedef struct {
-    union {
-        #ifndef _MSC_VER
-        // Windows combaseapi.h uses `inteface` as a keyword
-        hailo_stream_interface_t interface DEPRECATED("interface is deprecated. One should use stream_interface instead.");
-        #endif
-        hailo_stream_interface_t stream_interface;    
-    };
-    
+    hailo_stream_interface_t stream_interface;
     hailo_stream_direction_t direction;
     union {
         hailo_pcie_input_stream_params_t pcie_input_params;
@@ -1193,7 +1210,7 @@ typedef struct {
     char name[HAILO_MAX_NETWORK_NAME_SIZE];
 } hailo_network_info_t;
 
-/** Hailo device ID string - BDF for PCIe devices, MAC address for Ethernet devices, "Core" for core devices. **/
+/** Hailo device ID string - BDF for PCIe devices, IP address for Ethernet devices, "Core" for core devices. **/
 typedef struct {
     char id[HAILO_MAX_DEVICE_ID_LENGTH];
 } hailo_device_id_t;
@@ -1729,7 +1746,7 @@ HAILORTAPI hailo_status hailo_set_pause_frames(hailo_device device, bool rx_paus
 
 /**
  * Get device id which is the identification string of the device. BDF for PCIe devices, 
- * MAC address for Ethernet devices, "Core" for core devices.
+ * IP address for Ethernet devices, "Core" for core devices.
  *
  * @param[in]  device           A ::hailo_device object.
  * @param[out] id               The returned device id.
@@ -2004,8 +2021,6 @@ HAILORTAPI hailo_status hailo_power_measurement(hailo_device device, hailo_dvm_o
  * Start performing a long power measurement.
  * 
  * @param[in]   device               A ::hailo_device object.
- * @param[in]   delay_milliseconds   Amount of time between each measurement interval.
- *                                   This time period is sleep time of the core.
  * @param[in]   averaging_factor     Number of samples per time period, sensor configuration value.
  * @param[in]   sampling_period      Related conversion time, sensor configuration value.
  *                                   The sensor samples the power every sampling_period {ms} and averages every
@@ -2016,14 +2031,15 @@ HAILORTAPI hailo_status hailo_power_measurement(hailo_device device, hailo_dvm_o
  *                                   because it averages values that have already been averaged by the sensor.
  * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
  */
-HAILORTAPI hailo_status hailo_start_power_measurement(hailo_device device, uint32_t delay_milliseconds,
+HAILORTAPI hailo_status hailo_start_power_measurement(hailo_device device,
     hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period);
 
 /**
  * Set parameters for long power measurement.
  * 
  * @param[in]   device             A ::hailo_device object.
- * @param[in]   index              Index of the buffer on the firmware the data would be saved at.
+ * @param[in]   buffer_index       A ::hailo_measurement_buffer_index_t represents the buffer on the firmware the data would be saved at.
+ *                                 Should match the one passed to ::hailo_get_power_measurement.
  * @param[in]   dvm                Which DVM will be measured. Default (::HAILO_DVM_OPTIONS_AUTO) will be different according to the board: <br>
  *                                 - Default (::HAILO_DVM_OPTIONS_AUTO) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
  *                                 It sums ::HAILO_DVM_OPTIONS_VDD_CORE, ::HAILO_DVM_OPTIONS_MIPI_AVDD and ::HAILO_DVM_OPTIONS_AVDD_H.
@@ -2033,20 +2049,21 @@ HAILORTAPI hailo_status hailo_start_power_measurement(hailo_device device, uint3
  *                                 will select the default value according to the supported features.
  * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
  */
-HAILORTAPI hailo_status hailo_set_power_measurement(hailo_device device, uint32_t index,
+HAILORTAPI hailo_status hailo_set_power_measurement(hailo_device device, hailo_measurement_buffer_index_t buffer_index,
     hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type);
 
 /**
  * Read measured power from a long power measurement
  * 
  * @param[in]   device                A ::hailo_device object.
- * @param[in]   index                 Index of the buffer on the firmware the data would be saved at.
+ * @param[in]   buffer_index          A ::hailo_measurement_buffer_index_t represents the buffer on the firmware the data would be saved at.
+ *                                    Should match the one passed to ::hailo_set_power_measurement.
  * @param[in]   should_clear          Flag indicating if the results saved at the firmware will be deleted after reading.
  * @param[out]  measurement_data      The measurement data, ::hailo_power_measurement_data_t. Measured units are
  *                                    determined due to ::hailo_power_measurement_types_t passed to ::hailo_set_power_measurement
  * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
  */
-HAILORTAPI hailo_status hailo_get_power_measurement(hailo_device device, uint32_t index, bool should_clear,
+HAILORTAPI hailo_status hailo_get_power_measurement(hailo_device device, hailo_measurement_buffer_index_t buffer_index, bool should_clear,
      hailo_power_measurement_data_t *measurement_data);
 
 /**
@@ -2425,6 +2442,41 @@ HAILORTAPI hailo_status hailo_get_output_stream(
 HAILORTAPI hailo_status hailo_get_latency_measurement(hailo_configured_network_group configured_network_group,
     const char *network_name, hailo_latency_measurement_result_t *result);
 
+/**
+ * Sets the maximum time period that may pass before getting run time from the scheduler,
+ *  even without reaching the minimum required send requests (e.g. threshold - see hailo_set_scheduler_threshold()),
+ *  as long as at least one send request has been sent.
+ *  This time period is measured since the last time the scheduler gave this network group run time.
+ *
+ * @param[in]  configured_network_group     NetworkGroup for which to set the scheduler timeout.
+ * @param[in]  timeout_ms                   Timeout in milliseconds.
+ * @param[in]  network_name                 Network name for which to set the timeout.
+ *                                          If NULL is passed, the timeout will be set for all the networks in the network group.
+ * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+ * @note Using this function is only allowed when scheduling_algorithm is not ::HAILO_SCHEDULING_ALGORITHM_NONE, and before the creation of any vstreams.
+ * @note The default timeout is 0ms.
+ * @note Currently, setting the timeout for a specific network is not supported.
+ */
+HAILORTAPI hailo_status hailo_set_scheduler_timeout(hailo_configured_network_group configured_network_group,
+    uint32_t timeout_ms, const char *network_name);
+
+/**
+ * Sets the minimum number of send requests required before the network is considered ready to get run time from the scheduler.
+ * If at least one send request has been sent, but the threshold is not reached within a set time period (e.g. timeout - see hailo_set_scheduler_timeout()),
+ *  the scheduler will consider the network ready regardless.
+ *
+ * @param[in]  configured_network_group     NetworkGroup for which to set the scheduler threshold.
+ * @param[in]  threshold                    Threshold in number of frames.
+ * @param[in]  network_name                 Network name for which to set the threshold.
+ *                                          If NULL is passed, the threshold will be set for all the networks in the network group.
+ * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+ * @note Using this function is only allowed when scheduling_algorithm is not ::HAILO_SCHEDULING_ALGORITHM_NONE, and before the creation of any vstreams.
+ * @note The default threshold is 1.
+ * @note Currently, setting the threshold for a specific network is not supported.
+ */
+HAILORTAPI hailo_status hailo_set_scheduler_threshold(hailo_configured_network_group configured_network_group,
+    uint32_t threshold, const char *network_name);
+
 /** @} */ // end of group_network_group_functions
 
 /** @defgroup group_stream_functions Stream functions
@@ -3051,110 +3103,6 @@ HAILORTAPI hailo_status hailo_get_network_infos(hailo_configured_network_group n
  *  @{
  */
 
-/**
- * Returns the network latency (only available if latency measurement was enabled).
- *
- * @param[in]  configured_network_group     NetworkGroup to get the latency measurement from.
- * @param[out] result                       Output latency result.
- * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
- * @note This function is deprecated. One should use 'hailo_get_latency_measurement()'
- */
-HAILORTAPI hailo_status hailo_get_latency_measurement_from_network_group(hailo_configured_network_group configured_network_group,
-    hailo_latency_measurement_result_t *result)
-    DEPRECATED("'hailo_get_latency_measurement_from_network_group' is deprecated. One should use 'hailo_get_latency_measurement()'.");
-
-
-typedef hailo_input_transform_context hailo_input_transformer DEPRECATED("hailo_input_transformer is deprecated. One should use hailo_input_transform_context");
-typedef hailo_output_transform_context hailo_output_transformer DEPRECATED("hailo_output_transformer is deprecated. One should use hailo_output_transform_context");
-
-/**
- * Creates an input transformer object. Allocates all necessary buffers used for the transformation (pre-process).
- * 
- * @param[in]     stream_info - A ::hailo_stream_info_t object
- * @param[in]     transform_params - A ::hailo_transform_params_t user transformation parameters.
- * @param[out]    transformer - A ::hailo_input_transform_context
- * 
- * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a hailo_status error.
- * 
- * @note To release the transformer, call the ::hailo_release_input_transformer function
- *      with the returned ::hailo_input_transform_context.
- * 
- */
-HAILORTAPI hailo_status hailo_create_input_transformer(const hailo_stream_info_t *stream_info,
-    const hailo_transform_params_t *transform_params, hailo_input_transform_context *transformer)
-    DEPRECATED("hailo_create_input_transformer is deprecated. One should use hailo_create_input_transform_context");
-
-/**
- * Releases a transformer object including all allocated buffers.
- * 
- * @param[in]    transformer - A ::hailo_input_transform_context object.
- * 
- * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a hailo_status error.
- */
-HAILORTAPI hailo_status hailo_release_input_transformer(hailo_input_transform_context transformer)
-    DEPRECATED("hailo_release_input_transformer is deprecated. One should use hailo_release_input_transform_context");
-
-/**
- * Transforms an input frame pointed to by @a src directly to the buffer pointed to by @a dst.
- * 
- * @param[in]  transformer          A ::hailo_input_transform_context.
- * @param[in]  src                  A pointer to a buffer to be transformed.
- * @param[in]  src_size             The number of bytes to transform. This number must be equal to the input host_frame_size,
- *                                  and less than or equal to the size of @a src buffer.
- * @param[out] dst                  A pointer to a buffer that receives the transformed data.
- * @param[in]  dst_size             The number of bytes in @a dst buffer. This number must be equal to the input hw_frame_size,
- *                                  and less than or equal to the size of @a dst buffer.
- * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
- * @warning The buffers must not overlap.
- */
-HAILORTAPI hailo_status hailo_transform_frame_by_input_transformer(hailo_input_transform_context transformer,
-    const void *src, size_t src_size, void *dst, size_t dst_size)
-    DEPRECATED("hailo_transform_frame_by_input_transformer is deprecated. One should use hailo_transform_frame_by_input_transform_context");
-
-/**
- * Creates an output transformer object. Allocates all necessary buffers used for the transformation (post-process).
- * 
- * @param[in]     stream_info - A ::hailo_stream_info_t object
- * @param[in]     transform_params - A ::hailo_transform_params_t user transformation parameters.
- * @param[out]    transformer - A ::hailo_output_transform_context
- * 
- * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a hailo_status error.
- * 
- * @note To release the transform_context, call the ::hailo_release_output_transform_context function
- *      with the returned ::hailo_output_transform_context.
- * 
- */
-HAILORTAPI hailo_status hailo_create_output_transformer(const hailo_stream_info_t *stream_info,
-    const hailo_transform_params_t *transform_params, hailo_output_transform_context *transformer)
-    DEPRECATED("hailo_create_output_transformer is deprecated. One should use hailo_create_output_transform_context");
-
-/**
- * Releases a transformer object including all allocated buffers.
- * 
- * @param[in]    transformer - A ::hailo_output_transform_context object.
- * 
- * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a hailo_status error.
- */
-HAILORTAPI hailo_status hailo_release_output_transformer(hailo_output_transform_context transformer)
-    DEPRECATED("hailo_release_output_transformer is deprecated. One should use hailo_release_output_transform_context");
-
-/**
- * Transforms an output frame pointed to by @a src directly to the buffer pointed to by @a dst.
- * 
- * @param[in]  transformer          A ::hailo_output_transform_context.
- * @param[in]  src                  A pointer to a buffer to be transformed.
- * @param[in]  src_size             The number of bytes to transform. This number must be equal to the output hw_frame_size,
- *                                  and less than or equal to the size of @a src buffer.
- * @param[out] dst                  A pointer to a buffer that receives the transformed data.
- * @param[in]  dst_size             The number of bytes in @a dst buffer. This number must be equal to the output host_frame_size,
- *                                  and less than or equal to the size of @a dst buffer.
- * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
- * @warning The buffers must not overlap.
- */
-HAILORTAPI hailo_status hailo_transform_frame_by_output_transformer(hailo_output_transform_context transformer,
-    const void *src, size_t src_size, void *dst, size_t dst_size)
-    DEPRECATED("hailo_transform_frame_by_output_transformer is deprecated. One should use hailo_transform_frame_by_output_transform_context");;
-
 /** @} */ // end of group_deprecated_functions_and_defines
 
 
index f161de11db980e928a2ef2421c3434236ab9d649..a3b9faeae7040c081f513c1b675c626d65404d77 100644 (file)
@@ -30,6 +30,7 @@ public:
     static const uint32_t MAX_DEFUSED_LAYER_COUNT = 9;
     static const size_t HW_DATA_ALIGNMENT = 8;
     static const uint64_t NMS_DELIMITER = 0xFFFFFFFFFFFFFFFF;
+    static const uint64_t NMS_DUMMY_DELIMITER = 0xFFFFFFFFFFFFFFFE;
     static const uint32_t MUX_INFO_COUNT = 32;
     static const uint32_t MAX_MUX_PREDECESSORS = 4;
     static const uint16_t ETH_INPUT_BASE_PORT = 32401;
index 9c192e06850020fcb19d71cd6a667885dccae574..3de2c475533e318d2a38d84cada398df28934620 100644 (file)
@@ -57,6 +57,11 @@ public:
     ActivatedNetworkGroup &operator=(ActivatedNetworkGroup &&other) = delete;
     ActivatedNetworkGroup(ActivatedNetworkGroup &&other) noexcept = default;
 
+    /**
+     * @return The network group name.
+     */
+    virtual const std::string &get_network_group_name() const = 0;
+
     virtual Expected<Buffer> get_intermediate_buffer(const IntermediateBufferKey &key) = 0;
     
     /**
@@ -191,8 +196,7 @@ public:
      * @return Upon success, returns Expected of a pointer to ActivatedNetworkGroup object.
      *         Otherwise, returns Unexpected of ::hailo_status error.
      */
-    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(
-        const hailo_activate_network_group_params_t &network_group_params) = 0;
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(const hailo_activate_network_group_params_t &network_group_params) = 0;
 
     /**
      * Block until network group is activated, or until timeout is passed.
@@ -303,12 +307,46 @@ public:
      */
     virtual Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(const std::string &network_name="") const = 0;
 
+    /**
+     * Sets the maximum time period that may pass before getting run time from the scheduler,
+     *  even without reaching the minimum required send requests (e.g. threshold - see set_scheduler_threshold()),
+     *  as long as at least one send request has been sent.
+     *  This time period is measured since the last time the scheduler gave this network group run time.
+     *
+     * @param[in]  timeout              Timeout in milliseconds.
+     * @param[in]  network_name         Network name for which to set the timeout.
+     *                                  If not passed, the timeout will be set for all the networks in the network group.
+     * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     * @note Using this function is only allowed when scheduling_algorithm is not ::HAILO_SCHEDULING_ALGORITHM_NONE, and before the creation of any vstreams.
+     * @note The default timeout is 0ms.
+     * @note Currently, setting the timeout for a specific network is not supported.
+     */
+    virtual hailo_status set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name="") = 0;
+
+    /**
+     * Sets the minimum number of send requests required before the network is considered ready to get run time from the scheduler.
+     * If at least one send request has been sent, but the threshold is not reached within a set time period (e.g. timeout - see hailo_set_scheduler_timeout()),
+     *  the scheduler will consider the network ready regardless.
+     *
+     * @param[in]  threshold            Threshold in number of frames.
+     * @param[in]  network_name         Network name for which to set the threshold.
+     *                                  If not passed, the threshold will be set for all the networks in the network group.
+     * @return Upon success, returns ::HAILO_SUCCESS. Otherwise, returns a ::hailo_status error.
+     * @note Using this function is only allowed when scheduling_algorithm is not ::HAILO_SCHEDULING_ALGORITHM_NONE, and before the creation of any vstreams.
+     * @note The default threshold is 1.
+     * @note Currently, setting the threshold for a specific network is not supported.
+     */
+    virtual hailo_status set_scheduler_threshold(uint32_t threshold, const std::string &network_name="") = 0;
+
     virtual AccumulatorPtr get_activation_time_accumulator() const = 0;
     virtual AccumulatorPtr get_deactivation_time_accumulator() const = 0;
 
 protected:
     ConfiguredNetworkGroup() = default;
 
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_internal(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) = 0;
+
 private:
     friend class ActivatedNetworkGroup;
 };
index 8fa34681c5bbcfe337cceadd600e65dd2baaf797..7820d37a986a935fe446bca3a41026b0427fd661 100644 (file)
 // underlying_handle_t
 #ifndef underlying_handle_t
 #if defined(_MSC_VER)
-typedef HANDLE underlying_handle_t; 
+typedef HANDLE underlying_handle_t;
+#elif defined(__linux__) || defined(__QNX__)
+typedef int underlying_handle_t;
 #else
-typedef int underlying_handle_t; 
+#error "Unsupported Platform"
 #endif
 #endif
 
index fa80905b755d8baa6c6bb7361389c4985bbcee00..51bb26cbf9edeea2ebfeb29461a5fe8a72cd24e9 100644 (file)
@@ -11,6 +11,7 @@
 #define _HAILO_QUANTIZATION_HPP_
 
 #include "hailo/hailort.h"
+#include "hailo/hailort_common.hpp"
 #include <math.h>
 #include <fenv.h>
 
index 4269a3f143aae83e99dab90705966a193167e209..41a7bc6931a67b43484c9fcd2f314f6cb708e429 100644 (file)
@@ -78,6 +78,11 @@ public:
      */
     virtual EventPtr &get_network_group_activated_event() = 0;
 
+    /**
+     * @returns whether the stream is managed by a network group scheduler.
+     */
+    virtual bool is_scheduled() = 0;
+
     /**
      * Writes the entire buffer to the stream without transformations
      *
@@ -124,7 +129,7 @@ protected:
     // Note: Implement sync_write_all_raw_buffer_no_transform_impl for the actual stream interaction in sub classes
     virtual hailo_status sync_write_all_raw_buffer_no_transform_impl(void *buffer, size_t offset, size_t size) = 0;
 
-    virtual hailo_status activate_stream() = 0;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) = 0;
     virtual hailo_status deactivate_stream() = 0;
 
     virtual Expected<size_t> sync_write_raw_buffer(const MemoryView &buffer) = 0;
@@ -182,6 +187,11 @@ public:
      * @returns a pointer for network group activated event.
      */
     virtual EventPtr &get_network_group_activated_event() = 0;
+
+    /**
+     * @returns whether the stream is managed by a network group scheduler.
+     */
+    virtual bool is_scheduled() = 0;
     
     /**
      * @returns the stream's info.
@@ -231,7 +241,7 @@ protected:
     OutputStream() = default;
     OutputStream(OutputStream&&);
 
-    virtual hailo_status activate_stream() = 0;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) = 0;
     virtual hailo_status deactivate_stream() = 0;
     virtual hailo_status read_all(MemoryView &buffer) = 0;
 
index 4d059f4809fd41a41af2b068fd2442302bdd78aa..54abd0d16ea1a60b52e590e5efc6c5cbb5f47a5c 100644 (file)
@@ -141,8 +141,6 @@ private:
     Buffer m_transpose_buffer;
 };
 
-typedef InputTransformContext InputTransformer DEPRECATED("InputTransformer is deprecated. One should use InputTransformContext");
-
 /*! Object used for output stream transformation*/
 class HAILORTAPI OutputTransformContext
 {
@@ -247,8 +245,6 @@ protected:
     const bool m_should_reorder;
 };
 
-typedef OutputTransformContext OutputTransformer DEPRECATED("OutputTransformer is deprecated. One should use OutputTransformContext");
-
 /*! Object used to demux muxed stream */
 class HAILORTAPI OutputDemuxer {
 public:
index 3a59d9c52b6ecc4946df7052bc4f8f58f255820b..b60e1a63b70e39e83bcde11178652e0ce2231e10 100644 (file)
@@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.0.0)
 
 find_package(Threads REQUIRED)
 
+include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
 include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/common_compiler_options.cmake)
 
 FUNCTION(relative_to_absolute_paths output)
@@ -43,18 +45,24 @@ set(HAILORT_CPP_SOURCES
     context_switch/vdma_config_network_group.cpp
     context_switch/vdma_config_activated_network_group.cpp
     context_switch/network_group.cpp
+    context_switch/network_group_wrapper.cpp
     context_switch/resource_manager.cpp
+    context_switch/pipeline_multiplexer.cpp
     intermediate_buffer.cpp
+    config_buffer.cpp
     d2h_events_parser.cpp
     mipi_stream.cpp
 
     hlpcie.cpp
     vdma_channel.cpp
-    vdma_buffer.cpp
     vdma_descriptor_list.cpp
     vdma_device.cpp
     vdma_stream.cpp
 
+    vdma/mapped_buffer.cpp
+    vdma/sg_buffer.cpp
+    vdma/continuous_buffer.cpp
+
     pcie_device.cpp
     pcie_stream.cpp
 
@@ -68,6 +76,8 @@ set(HAILORT_CPP_SOURCES
 
     vstream.cpp
     inference_pipeline.cpp
+
+    network_group_scheduler.cpp
 )
 
 set(common_dir "${PROJECT_SOURCE_DIR}/common/src")
@@ -116,6 +126,10 @@ target_link_libraries(libhailort PRIVATE Threads::Threads)
 target_link_libraries(libhailort PRIVATE hef_proto)
 target_link_libraries(libhailort PRIVATE spdlog::spdlog)
 target_link_libraries(libhailort PRIVATE readerwriterqueue)
+target_link_libraries(libhailort PRIVATE microprofile)
+if(CMAKE_SYSTEM_NAME STREQUAL QNX)
+    target_link_libraries(libhailort PRIVATE pevents pci)
+endif()
 
 set(HAILORT_PUBLIC_HEADERS
     ${HAILORT_INC_DIR}/hailo/hailort.h
@@ -174,7 +188,44 @@ target_compile_definitions(libhailort PUBLIC
 )
 
 install(TARGETS libhailort
-   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-   CONFIGURATIONS Release
-   PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/hailo"
-   CONFIGURATIONS Release)
+    EXPORT HailoRTTargets
+    CONFIGURATIONS Release
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/hailo"
+    INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+)
+
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+    install(CODE "execute_process(COMMAND ldconfig)")
+endif()
+
+# Export libhailort
+set(CMAKE_SCRIPTS_DIR ${CMAKE_CURRENT_BINARY_DIR})
+configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
+  "${CMAKE_SCRIPTS_DIR}/HailoRTConfig.cmake"
+  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/HailoRT
+)
+write_basic_package_version_file(
+  "${CMAKE_SCRIPTS_DIR}/HailoRTConfigVersion.cmake"
+  VERSION "${HAILORT_MAJOR_VERSION}.${HAILORT_MINOR_VERSION}.${HAILORT_REVISION_VERSION}"
+  COMPATIBILITY ExactVersion
+)
+
+# Support builds without installation
+set(HailoRT_DIR "${CMAKE_SCRIPTS_DIR}" PARENT_SCOPE)
+
+# Package installation
+install(FILES
+        "${CMAKE_SCRIPTS_DIR}/HailoRTConfig.cmake"
+        "${CMAKE_SCRIPTS_DIR}/HailoRTConfigVersion.cmake"
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/HailoRT
+    COMPONENT libhailort
+)
+install(EXPORT HailoRTTargets
+    FILE HailoRTTargets.cmake
+    NAMESPACE HailoRT::
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/HailoRT
+    COMPONENT libhailort
+)
diff --git a/hailort/libhailort/src/Config.cmake.in b/hailort/libhailort/src/Config.cmake.in
new file mode 100644 (file)
index 0000000..b69f0e2
--- /dev/null
@@ -0,0 +1,10 @@
+@PACKAGE_INIT@
+
+if(TARGET libhailort)
+    if(${HailoRT_FIND_VERSION} VERSION_EQUAL "${HAILORT_MAJOR_VERSION}.${HAILORT_MINOR_VERSION}.${HAILORT_REVISION_VERSION}")
+        add_library(HailoRT::libhailort ALIAS libhailort)
+    endif()
+else()
+    include("${CMAKE_CURRENT_LIST_DIR}/HailoRTTargets.cmake")
+    check_required_components(HailoRT)
+endif()
\ No newline at end of file
diff --git a/hailort/libhailort/src/config_buffer.cpp b/hailort/libhailort/src/config_buffer.cpp
new file mode 100644 (file)
index 0000000..96cae2a
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file config_buffer.cpp
+ * @brief Manages configuration vdma buffer. The configuration buffer contains nn-configurations in a specific
+ *        hw format (ccw).
+ */
+
+#include "config_buffer.hpp"
+#include "vdma/sg_buffer.hpp"
+#include "vdma/continuous_buffer.hpp"
+
+#include <numeric>
+
+namespace hailort {
+
+Expected<ConfigBuffer> ConfigBuffer::create(HailoRTDriver &driver, uint8_t channel_index,
+    const std::vector<uint32_t> &cfg_sizes)
+{
+    const auto buffer_size = std::accumulate(cfg_sizes.begin(), cfg_sizes.end(), 0);
+
+    auto buffer_ptr = should_use_ccb(driver) ?
+        create_ccb_buffer(driver, buffer_size) :
+        create_sg_buffer(driver, channel_index, cfg_sizes);
+    CHECK_EXPECTED(buffer_ptr);
+
+    return ConfigBuffer(buffer_ptr.release(), buffer_size);
+}
+
+ConfigBuffer::ConfigBuffer(std::unique_ptr<vdma::VdmaBuffer> &&buffer,
+    size_t total_buffer_size)
+    : m_buffer(std::move(buffer)),
+      m_total_buffer_size(total_buffer_size), m_acc_buffer_offset(0), m_acc_desc_count(0),
+      m_current_buffer_size(0)
+{}
+
+Expected<uint32_t> ConfigBuffer::program_descriptors()
+{
+    auto descriptors_count =
+        m_buffer->program_descriptors(m_acc_buffer_offset,  VdmaInterruptsDomain::NONE, VdmaInterruptsDomain::DEVICE,
+        m_acc_desc_count, false);
+    CHECK_EXPECTED(descriptors_count);
+
+    m_acc_desc_count += descriptors_count.value();
+    m_acc_buffer_offset = 0;
+
+    return descriptors_count;
+}
+
+hailo_status ConfigBuffer::write(const void *data, size_t data_size)
+{
+    size_t total_offset = (m_acc_desc_count * m_buffer->desc_page_size()) + m_acc_buffer_offset;
+    auto status = m_buffer->write(data, data_size, total_offset);
+    CHECK_SUCCESS(status);
+
+    m_acc_buffer_offset += data_size;
+    m_current_buffer_size += data_size;
+    return HAILO_SUCCESS;
+}
+
+size_t ConfigBuffer::get_total_cfg_size()
+{
+    return m_total_buffer_size;
+}
+
+vdma::VdmaBuffer::Type ConfigBuffer::buffer_type() const
+{
+    return m_buffer->type();
+}
+
+size_t ConfigBuffer::get_current_buffer_size()
+{
+    return m_current_buffer_size;
+}
+
+uint16_t ConfigBuffer::desc_page_size() const
+{
+    return m_buffer->desc_page_size();
+}
+
+uint64_t ConfigBuffer::dma_address() const
+{
+    return m_buffer->dma_address();
+}
+
+uint32_t ConfigBuffer::total_desc_count() const
+{
+    return m_buffer->descs_count();
+}
+
+uint32_t ConfigBuffer::acc_desc_count() const
+{
+    return m_acc_desc_count;
+}
+
+Expected<std::unique_ptr<vdma::VdmaBuffer>> ConfigBuffer::create_sg_buffer(HailoRTDriver &driver,
+    uint8_t channel_index, const std::vector<uint32_t> &cfg_sizes)
+{
+    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_multiple_transfers(driver, 1, cfg_sizes);
+    CHECK_EXPECTED(desc_sizes_pair);
+
+    auto page_size = desc_sizes_pair->first;
+    auto descs_count = desc_sizes_pair->second;
+
+    auto buffer = vdma::SgBuffer::create(driver, descs_count, page_size, HailoRTDriver::DmaDirection::H2D,
+        channel_index);
+    CHECK_EXPECTED(buffer);
+
+    auto buffer_ptr = make_unique_nothrow<vdma::SgBuffer>(buffer.release());
+    CHECK_NOT_NULL_AS_EXPECTED(buffer_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    return std::unique_ptr<vdma::VdmaBuffer>(std::move(buffer_ptr));
+}
+
+Expected<std::unique_ptr<vdma::VdmaBuffer>> ConfigBuffer::create_ccb_buffer(HailoRTDriver &driver,
+    uint32_t buffer_size)
+{
+    buffer_size = vdma::ContinuousBuffer::get_buffer_size(buffer_size);
+    auto buffer = vdma::ContinuousBuffer::create(buffer_size, driver);
+    CHECK_EXPECTED(buffer);
+
+    auto buffer_ptr = make_unique_nothrow<vdma::ContinuousBuffer>(buffer.release());
+    CHECK_NOT_NULL_AS_EXPECTED(buffer_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    return std::unique_ptr<vdma::VdmaBuffer>(std::move(buffer_ptr));
+}
+
+bool ConfigBuffer::should_use_ccb(HailoRTDriver &driver)
+{
+    switch (driver.dma_type()) {
+    case HailoRTDriver::DmaType::PCIE:
+        return false;
+    case HailoRTDriver::DmaType::DRAM:
+        return true;
+    default:
+        assert(true);
+        return false;
+    }
+}
+
+} /* hailort */
\ No newline at end of file
diff --git a/hailort/libhailort/src/config_buffer.hpp b/hailort/libhailort/src/config_buffer.hpp
new file mode 100644 (file)
index 0000000..4a92e89
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file config_buffer.hpp
+ * @brief Manages configuration vdma buffer. The configuration buffer contains nn-configurations in a specific
+ *        hw format (ccw).
+ */
+
+#ifndef _HAILO_CONFIG_BUFFER_HPP_
+#define _HAILO_CONFIG_BUFFER_HPP_
+
+#include "vdma/vdma_buffer.hpp"
+
+namespace hailort {
+
+
+class ConfigBuffer final
+{
+public:
+    static Expected<ConfigBuffer> create(HailoRTDriver &driver, uint8_t channel_index,
+        const std::vector<uint32_t> &cfg_sizes);
+
+    // Write data to config channel
+    hailo_status write(const void *data, size_t data_size);
+
+    // Program the descriptors for the data written so far
+    Expected<uint32_t> program_descriptors();
+
+    size_t get_current_buffer_size();
+
+    /* Get all the config size. It's not the same as the VdmaBuffer::size() 
+    since we might add NOPs to the data (Pre-fetch mode) */
+    size_t get_total_cfg_size();
+
+    vdma::VdmaBuffer::Type buffer_type() const;
+    uint16_t desc_page_size() const;
+    uint64_t dma_address() const;
+    uint32_t total_desc_count() const;
+
+    uint32_t acc_desc_count() const;
+
+private:
+    ConfigBuffer(std::unique_ptr<vdma::VdmaBuffer> &&buffer, size_t total_buffer_size);
+
+    static Expected<std::unique_ptr<vdma::VdmaBuffer>> create_sg_buffer(HailoRTDriver &driver,
+        uint8_t channel_index, const std::vector<uint32_t> &cfg_sizes);
+    static Expected<std::unique_ptr<vdma::VdmaBuffer>> create_ccb_buffer(HailoRTDriver &driver,
+        uint32_t buffer_size);
+
+    static bool should_use_ccb(HailoRTDriver &driver);
+
+    std::unique_ptr<vdma::VdmaBuffer> m_buffer;
+    const size_t m_total_buffer_size; 
+    size_t m_acc_buffer_offset;
+    uint32_t m_acc_desc_count;
+    size_t m_current_buffer_size;
+};
+
+} /* hailort */
+
+#endif /* _HAILO_CONFIG_BUFFER_HPP_ */
\ No newline at end of file
index f22470076fc9cb59896c6847c1de1c05dc73d901..0911f66ab9893184b37b895a5578f65c3746fd59 100644 (file)
@@ -36,7 +36,7 @@ class ConfigManager
     virtual ~ConfigManager() {}
     virtual ConfigManagerType get_manager_type() = 0;
     virtual Expected<ConfiguredNetworkGroupVector> add_hef(Hef &hef, const std::map<std::string,
-        ConfigureNetworkParams> &configure_params={}) = 0;
+        ConfigureNetworkParams> &configure_params, bool is_scheduler_used = false) = 0;
 
   protected:
     hailo_status validate_boundary_streams_were_created(Hef &hef, const std::string &network_group_name, ConfiguredNetworkGroup &network_group)
index 7fe37b8d5037cb536cec2c8d202c4accacddbcfd..80b4f960b49ba6a643fe01dbe66929d4b1af195f 100644 (file)
@@ -14,6 +14,7 @@ namespace hailort
 {
 
 Expected<HcpConfigActivatedNetworkGroup> HcpConfigActivatedNetworkGroup::create(Device &device, std::vector<WriteMemoryInfo> &config,
+        const std::string &network_group_name,
         const hailo_activate_network_group_params_t &network_group_params,
         std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
         std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,
@@ -36,20 +37,29 @@ Expected<HcpConfigActivatedNetworkGroup> HcpConfigActivatedNetworkGroup::create(
         CHECK_SUCCESS_AS_EXPECTED(status);
     }
 
-    HcpConfigActivatedNetworkGroup object(device, active_net_group_holder, network_group_params, input_streams, output_streams,
+    HcpConfigActivatedNetworkGroup object(device, active_net_group_holder, network_group_name, network_group_params, input_streams, output_streams,
         power_mode, std::move(network_group_activated_event), status);
     CHECK_SUCCESS_AS_EXPECTED(status);
     return object;
 }
 
-HcpConfigActivatedNetworkGroup::HcpConfigActivatedNetworkGroup(Device &device,
-    HcpConfigActiveAppHolder &active_net_group_holder, const hailo_activate_network_group_params_t &network_group_params,
-    std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
-    std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,    
-    hailo_power_mode_t power_mode, EventPtr &&network_group_activated_event, hailo_status &status) :
-      ActivatedNetworkGroupBase(network_group_params, input_streams, output_streams,
-        std::move(network_group_activated_event), status),
-      m_active_net_group_holder(active_net_group_holder), m_is_active(true), m_power_mode(power_mode), m_device(device)
+HcpConfigActivatedNetworkGroup::HcpConfigActivatedNetworkGroup(
+        Device &device,
+        HcpConfigActiveAppHolder &active_net_group_holder,
+        const std::string &network_group_name,
+        const hailo_activate_network_group_params_t &network_group_params,
+        std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
+        std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,    
+        hailo_power_mode_t power_mode,
+        EventPtr &&network_group_activated_event,
+        hailo_status &status) :
+    ActivatedNetworkGroupBase(network_group_params, CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE,
+                              input_streams, output_streams, std::move(network_group_activated_event), status),
+    m_active_net_group_holder(active_net_group_holder),
+    m_is_active(true),
+    m_power_mode(power_mode),
+    m_device(device),
+    m_network_group_name(network_group_name)
 {
     // Validate ActivatedNetworkGroup status
     if (HAILO_SUCCESS != status) {
@@ -66,4 +76,9 @@ HcpConfigActivatedNetworkGroup::~HcpConfigActivatedNetworkGroup()
     }
 }
 
+const std::string &HcpConfigActivatedNetworkGroup::get_network_group_name() const
+{
+    return m_network_group_name;
+}
+
 } /* namespace hailort */
index d0e67ff8f573dd9a038d1ca07930b7488eba5373..d3143474fe58128ae8e736560c6c602348c147c5 100644 (file)
@@ -40,7 +40,7 @@ namespace hailort
 {
 
 Expected<ConfiguredNetworkGroupVector> HcpConfigManager::add_hef(Hef &hef,
-    const NetworkGroupsParamsMap &configure_params)
+    const NetworkGroupsParamsMap &configure_params, bool /*is_scheduler_used*/)
 {
     auto &hef_network_groups = hef.pimpl->network_groups();
     auto current_net_group_index = static_cast<uint8_t>(m_net_groups.size());
@@ -95,7 +95,15 @@ Expected<ConfiguredNetworkGroupVector> HcpConfigManager::add_hef(Hef &hef,
         auto net_group_ptr = make_shared_nothrow<HcpConfigNetworkGroup>(std::move(single_context_app));
         CHECK_AS_EXPECTED(nullptr != net_group_ptr, HAILO_OUT_OF_HOST_MEMORY);
         m_net_groups.emplace_back(net_group_ptr);
-        added_network_groups.emplace_back(std::static_pointer_cast<ConfiguredNetworkGroup>(net_group_ptr));
+
+        auto net_group_wrapper = ConfiguredNetworkGroupWrapper::create(net_group_ptr);
+        CHECK_EXPECTED(net_group_wrapper);
+
+        auto net_group_wrapper_ptr = make_shared_nothrow<ConfiguredNetworkGroupWrapper>(net_group_wrapper.release());
+        CHECK_AS_EXPECTED(nullptr != net_group_wrapper_ptr, HAILO_OUT_OF_HOST_MEMORY);
+        m_net_group_wrappers.emplace_back(net_group_wrapper_ptr);
+
+        added_network_groups.emplace_back(std::static_pointer_cast<ConfiguredNetworkGroup>(net_group_wrapper_ptr));
 
         current_net_group_index++;
 
index 735597c0d00a8d3e0d6def16bcd14287d4130f8c..f48c993f6b3f182e0da7038ad46c4ceb481e1bf6 100644 (file)
@@ -15,12 +15,12 @@ HcpConfigNetworkGroup::HcpConfigNetworkGroup(Device &device, HcpConfigActiveAppH
           m_config(std::move(config)), m_active_net_group_holder(active_net_group_holder), m_device(device)
 {}
 
-Expected<std::unique_ptr<ActivatedNetworkGroup>> HcpConfigNetworkGroup::activate(
-    const hailo_activate_network_group_params_t &network_group_params)
+Expected<std::unique_ptr<ActivatedNetworkGroup>> HcpConfigNetworkGroup::activate_impl(
+    const hailo_activate_network_group_params_t &network_group_params, uint16_t /* dynamic_batch_size */)
 {
     auto start_time = std::chrono::steady_clock::now();
 
-    auto activated_net_group = HcpConfigActivatedNetworkGroup::create(m_device, m_config, network_group_params,
+    auto activated_net_group = HcpConfigActivatedNetworkGroup::create(m_device, m_config, get_network_group_name(), network_group_params,
         m_input_streams, m_output_streams, m_active_net_group_holder, m_config_params.power_mode,
         m_network_group_activated_event);
     CHECK_EXPECTED(activated_net_group);
@@ -46,4 +46,33 @@ Expected<uint8_t> HcpConfigNetworkGroup::get_boundary_channel_index(uint8_t stre
         static_cast<uint8_t>(stream_index + OUTPUT_CHANNEL_INDEX_OFFSET);
 }
 
+hailo_status HcpConfigNetworkGroup::set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name)
+{
+    (void) timeout;
+    (void) network_name;
+    return HAILO_INVALID_OPERATION;
+}
+
+hailo_status HcpConfigNetworkGroup::set_scheduler_threshold(uint32_t threshold, const std::string &network_name)
+{
+    (void) threshold;
+    (void) network_name;
+    return HAILO_INVALID_OPERATION;
+}
+
+Expected<std::shared_ptr<LatencyMetersMap>> HcpConfigNetworkGroup::get_latnecy_meters()
+{
+    /* hcp does not support latnecy. return empty map */
+    LatencyMetersMap empty_map; 
+    return make_shared_nothrow<LatencyMetersMap>(empty_map);
+}
+
+Expected<std::shared_ptr<VdmaChannel>> HcpConfigNetworkGroup::get_boundary_vdma_channel_by_stream_name(
+    const std::string &stream_name)
+{
+    LOGGER__ERROR("get_boundary_vdma_channel_by_stream_name function for stream name {} is not supported in hcp config manager", 
+        stream_name);
+    return make_unexpected(HAILO_INVALID_OPERATION);
+}
+
 } /* namespace hailort */
index c749eb86840ece964d892ab4cae5e7299d5080c6..0a1386446f2bbab2948645abd06cfde18d574a50 100644 (file)
@@ -453,6 +453,7 @@ hailo_status HEF_METADATA__add_enable_lcu_default_action(
         uint8_t **action_data_current_offset,
         uint8_t cluster_index,
         uint8_t lcu_index,
+        uint8_t network_index,
         bool is_repeated)
 {
     hailo_status status = HAILO_UNINITIALIZED;
@@ -465,6 +466,7 @@ hailo_status HEF_METADATA__add_enable_lcu_default_action(
     enable_lcu_action.header.is_repeated = is_repeated;
     enable_lcu_action.cluster_index = cluster_index;
     enable_lcu_action.lcu_index = lcu_index;
+    enable_lcu_action.network_index = network_index;
 
     status = hef_metadata__update_slicing_info(context_info,  action_data_current_offset,
         sizeof(enable_lcu_action), true);
@@ -609,17 +611,13 @@ hailo_status HEF_METADATA__add_network_boundary_output_edge_layer(
 }
 
 hailo_status HEF_METADATA__add_inter_context_output_edge_layer(
-        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
-        uint8_t **edge_layer_current_offset,
-        uint8_t stream_index, 
-        uint8_t vdma_channel_index,
-        uint8_t network_index,
-        const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-        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__context_switch_context_info_t *context_info,
+    uint8_t **edge_layer_current_offset,
+    uint8_t stream_index, 
+    uint8_t vdma_channel_index,
+    uint8_t network_index,
+    const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
+    const CONTROL_PROTOCOL__host_buffer_info_t &host_buffer_info)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__inter_context_output_t *edge_layer_info = nullptr;
@@ -647,11 +645,7 @@ hailo_status HEF_METADATA__add_inter_context_output_edge_layer(
             network_index,
             nn_stream_config);
 
-    edge_layer_info->frame_credits_in_bytes = frame_credits_in_bytes;
-    edge_layer_info->host_desc_address_info.host_descriptors_base_address = host_descriptors_base_address; 
-    edge_layer_info->host_desc_address_info.initial_host_available_descriptors = initial_host_available_descriptors; 
-    edge_layer_info->desc_page_size = desc_page_size;
-    edge_layer_info->host_desc_address_info.desc_list_depth = desc_list_depth;
+    edge_layer_info->host_buffer_info = host_buffer_info;
 
     *(edge_layer_current_offset) += sizeof(*edge_layer_info);
 
@@ -667,10 +661,9 @@ hailo_status HEF_METADATA__add_ddr_buffer_output_edge_layer(
         const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
         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)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__ddr_buffer_output_t *edge_layer_info = nullptr;
@@ -702,22 +695,22 @@ hailo_status HEF_METADATA__add_ddr_buffer_output_edge_layer(
 
     edge_layer_info->frame_credits_in_bytes = frame_credits_in_bytes;
     edge_layer_info->host_desc_address_info.host_descriptors_base_address = host_descriptors_base_address; 
-    edge_layer_info->host_desc_address_info.initial_host_available_descriptors = initial_host_available_descriptors; 
     edge_layer_info->desc_page_size = desc_page_size;
     edge_layer_info->host_desc_address_info.desc_list_depth = desc_list_depth;
-    edge_layer_info->fw_managed_channel = fw_managed_channel;
+    edge_layer_info->buffered_rows_count = buffered_rows_count;
 
     return HAILO_SUCCESS;
 }
 
 hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
-        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
-        uint8_t **edge_layer_current_offset,
-        uint8_t stream_index, 
-        uint8_t vdma_channel_index,
-        uint8_t network_index,
-        const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-        uint16_t desc_page_size)
+    CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+    uint8_t **edge_layer_current_offset,
+    uint8_t stream_index, 
+    uint8_t vdma_channel_index,
+    uint8_t network_index,
+    const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
+    uint16_t desc_page_size,
+    uint32_t initial_credit_size)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__network_boundary_input_t *edge_layer_info = nullptr;
@@ -746,6 +739,7 @@ hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
             nn_stream_config);
 
     edge_layer_info->desc_page_size = desc_page_size;
+    edge_layer_info->initial_credit_size = initial_credit_size;
 
     *(edge_layer_current_offset) += sizeof(*edge_layer_info);
 
@@ -753,16 +747,14 @@ hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
 }
 
 hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
-        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
-        uint8_t **edge_layer_current_offset,
-        uint8_t stream_index, 
-        uint8_t vdma_channel_index,
-        uint8_t network_index,
-        const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-        uint16_t context_credits_in_descriptors,
-        uint64_t host_descriptors_base_address,
-        uint8_t desc_list_depth,
-        uint16_t desc_page_size)
+    CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+    uint8_t **edge_layer_current_offset,
+    uint8_t stream_index, 
+    uint8_t vdma_channel_index,
+    uint8_t network_index,
+    const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
+    const CONTROL_PROTOCOL__host_buffer_info_t &host_buffer_info,
+    uint32_t initial_credit_size)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__inter_context_input_t *edge_layer_info = nullptr;
@@ -790,11 +782,8 @@ hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
             network_index,
             nn_stream_config);
 
-    edge_layer_info->context_credits_in_descriptors = context_credits_in_descriptors;
-    edge_layer_info->host_desc_address_info.host_descriptors_base_address = host_descriptors_base_address; 
-    edge_layer_info->host_desc_address_info.initial_host_available_descriptors = 0;
-    edge_layer_info->host_desc_address_info.desc_list_depth = desc_list_depth;
-    edge_layer_info->desc_page_size = desc_page_size;
+    edge_layer_info->host_buffer_info = host_buffer_info;
+    edge_layer_info->initial_credit_size = initial_credit_size;
 
     *(edge_layer_current_offset) += sizeof(*edge_layer_info);
 
@@ -802,15 +791,15 @@ hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
 }
 
 hailo_status HEF_METADATA__add_ddr_buffer_input_edge_layer(
-        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
-        uint8_t **edge_layer_current_offset,
-        uint8_t stream_index, 
-        uint8_t vdma_channel_index,
-        uint8_t network_index,
-        const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-        uint64_t host_descriptors_base_address,
-        uint8_t desc_list_depth,
-        bool fw_managed_channel)
+    CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+    uint8_t **edge_layer_current_offset,
+    uint8_t stream_index, 
+    uint8_t vdma_channel_index,
+    uint8_t network_index,
+    const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
+    uint64_t host_descriptors_base_address,
+    uint8_t desc_list_depth,
+    uint32_t initial_credit_size)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__ddr_buffer_input_t *edge_layer_info = nullptr;
@@ -839,9 +828,8 @@ hailo_status HEF_METADATA__add_ddr_buffer_input_edge_layer(
             nn_stream_config);
 
     edge_layer_info->host_desc_address_info.host_descriptors_base_address = host_descriptors_base_address; 
-    edge_layer_info->host_desc_address_info.initial_host_available_descriptors = 0;
     edge_layer_info->host_desc_address_info.desc_list_depth = desc_list_depth;
-    edge_layer_info->fw_managed_channel = fw_managed_channel;
+    edge_layer_info->initial_credit_size = initial_credit_size;
 
     *(edge_layer_current_offset) += sizeof(*edge_layer_info);
 
@@ -907,6 +895,32 @@ hailo_status HEF_METADATA__add_ddr_buffering_start(
 
     return HAILO_SUCCESS;
 }
+
+hailo_status HEF_METADATA__burst_credits_task_start(
+        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+        uint8_t **action_data_current_offset,
+        bool is_repeated)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    CONTROL_PROTOCOL__BURST_CREDITS_TASK_START_ACTION_T burst_credits_task_start{};
+
+    CHECK_ARG_NOT_NULL(action_data_current_offset);
+    CHECK_ARG_NOT_NULL(*action_data_current_offset);
+
+    burst_credits_task_start.header.action_type = CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_BURST_CREDITS_TASK_START;
+    burst_credits_task_start.header.is_repeated = is_repeated;
+
+    status = hef_metadata__update_slicing_info(context_info, 
+            action_data_current_offset, 
+            sizeof(burst_credits_task_start),
+            true);
+    CHECK_SUCCESS(status);
+
+    memcpy((*action_data_current_offset), &burst_credits_task_start, sizeof(burst_credits_task_start));
+    *(action_data_current_offset) += sizeof(burst_credits_task_start);
+
+    return HAILO_SUCCESS;
+}
 /* End of context switch info build functions */
 
 } /* namespace hailort */
index ae39ecf3e25240fef00713a9f328f41a3ebbb645..d57f15070cd732285d6579867875f57e868271c7 100644 (file)
@@ -224,6 +224,7 @@ hailo_status HEF_METADATA__add_enable_lcu_non_default_action(
  * @param[out]    action - pointer to the action
  * @param[in]     cluster_index - cluster index
  * @param[in]     lcu_index - lcu_index
+ * @param[in]     network_index - network index
  * @param[in]     is_repeated - 'true' if the action is part of a "repeated sequence" (a group of consecutive actions
  *                              with the same type)
  *
@@ -233,6 +234,7 @@ hailo_status HEF_METADATA__add_enable_lcu_default_action(
     uint8_t **action_data_current_offset,
     uint8_t cluster_index,
     uint8_t lcu_index,
+    uint8_t network_index,
     bool is_repeated);
 
 /**
@@ -301,13 +303,7 @@ hailo_status HEF_METADATA__add_network_boundary_output_edge_layer(
  * @param[in]     vdma_channel_index - channel index
  * @param[in]     network_index - network index 
  * @param[in]     nn_stream_config
- * @param[in]     frame_credits_in_bytes - context credits in bytes
- * @param[in]     host_descriptors_base_address - host descritpors base address
- * @param[in]     initial_host_available_descriptors - initial host available descriptors, initialized by the FW once new context
- *                start
- * @param[in]     desc_page_size - descriptor page_size in bytes
- * @param[in]     desc_list_depth - descriptor list depth
- * 
+ * @param[in]     host_buffer_info - info about host buffer
  */
 hailo_status HEF_METADATA__add_inter_context_output_edge_layer(
     CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
@@ -316,11 +312,7 @@ hailo_status HEF_METADATA__add_inter_context_output_edge_layer(
     uint8_t vdma_channel_index, 
     uint8_t network_index,
     const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-    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);
+    const CONTROL_PROTOCOL__host_buffer_info_t &host_buffer_info);
 
 /**
  * build edge layer - vdma DDR buffer output
@@ -333,11 +325,9 @@ hailo_status HEF_METADATA__add_inter_context_output_edge_layer(
  * @param[in]     nn_stream_config
  * @param[in]     frame_credits_in_bytes - context credits in bytes
  * @param[in]     host_descriptors_base_address - host descritpors base address
- * @param[in]     initial_host_available_descriptors - initial host available descriptors, initialized by the FW once new context
- *                start
  * @param[in]     desc_page_size - descriptor page_size in bytes
  * @param[in]     desc_list_depth - descriptor list depth
- * @param[in]     fw_managed_channel - descriptor list depth
+ * @param[in]     buffered_rows_count - amount of rows to buffer.
  *
  */
 hailo_status HEF_METADATA__add_ddr_buffer_output_edge_layer(
@@ -349,10 +339,9 @@ hailo_status HEF_METADATA__add_ddr_buffer_output_edge_layer(
     const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
     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);
 
 /**
  * build edge layer - vdma network boundary input
@@ -364,6 +353,7 @@ hailo_status HEF_METADATA__add_ddr_buffer_output_edge_layer(
  * @param[in]     network_index - network index 
  * @param[in]     nn_stream_config
  * @param[in]     desc_page_size - desc page size in bytes
+ * @param[in]     initial_credit_size - initial credit size, if 0 is set the firmware takes its default value.
  *
  */
 hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
@@ -373,7 +363,8 @@ hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
     uint8_t vdma_channel_index, 
     uint8_t network_index,
     const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-    uint16_t desc_page_size);
+    uint16_t desc_page_size,
+    uint32_t initial_credit_size);
 
 /**
  * build edge layer - vdma intermediate buffer input
@@ -384,9 +375,8 @@ hailo_status HEF_METADATA__add_network_boundary_input_edge_layer(
  * @param[in]     vdma_channel_index - channel index
  * @param[in]     network_index - network index 
  * @param[in]     nn_stream_config
- * @param[in]     context_credits_in_descriptors - context credits in descriptors
- * @param[in]     host_descriptors_base_address - host descritpors base address
- * @param[in]     desc_page_size - desc page size in bytes
+ * @param[in]     host_buffer_info - info about host buffer
+ * @param[in]     initial_credit_size - initial credit size, if 0 is set the firmware takes its default value.
  *
  */
 hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
@@ -396,10 +386,8 @@ hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
     uint8_t vdma_channel_index, 
     uint8_t network_index,
     const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-    uint16_t context_credits_in_descriptors,
-    uint64_t host_descriptors_base_address,
-    uint8_t desc_list_depth,
-    uint16_t desc_page_size);
+    const CONTROL_PROTOCOL__host_buffer_info_t &host_buffer_info,
+    uint32_t initial_credit_size);
 
 /**
  * build edge layer - vdma ddr buffer input
@@ -410,11 +398,9 @@ hailo_status HEF_METADATA__add_inter_context_input_edge_layer(
  * @param[in]     vdma_channel_index - channel index
  * @param[in]     network_index - network index 
  * @param[in]     nn_stream_config
- * @param[in]     context_credits_in_descriptors - context credits in descriptors
  * @param[in]     host_descriptors_base_address - host descritpors base address
  * @param[in]     desc_list_depth - descriptor list depth
- * @param[in]     fw_managed_channel - descriptor list depth
- *
+ * @param[in]     initial_credit_size - initial credit size, if 0 is set the firmware takes its default value.
  */
 hailo_status HEF_METADATA__add_ddr_buffer_input_edge_layer(
     CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
@@ -425,7 +411,7 @@ hailo_status HEF_METADATA__add_ddr_buffer_input_edge_layer(
     const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
     uint64_t host_descriptors_base_address,
     uint8_t desc_list_depth,
-    bool fw_managed_channel);
+    uint32_t initial_credit_size);
 
 /**
  * Build add ddr pair info action
@@ -448,6 +434,7 @@ hailo_status HEF_METADATA__add_ddr_pair_info(
     const uint32_t descriptors_per_frame,
     const uint16_t programmed_descriptors_count,
     bool is_repeated);
+
 /**
  * Build add ddr buffering start
  *
@@ -462,6 +449,20 @@ hailo_status HEF_METADATA__add_ddr_buffering_start(
     uint8_t **action_data_current_offset,
     bool is_repeated);
 
+/**
+ * Build add burst credits task start
+ *
+ * @param[in]     context_info - struct holding all the context info
+ * @param[out]    action_data_current_offset - pointer to the action
+ * @param[in]     is_repeated - 'true' if the action is part of a "repeated sequence" (a group of consecutive actions
+ *                              with the same type)
+ *
+ */
+hailo_status HEF_METADATA__burst_credits_task_start(
+        CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+        uint8_t **action_data_current_offset,
+        bool is_repeated);
+
 } /* namespace hailort */
 
 #endif /* __CONTEXT_SWITCH__ */
index 081ceb760d5998971da9fd54cb2ea3ae6508aedd..9ae43b73c15fc85668485b2e056cd46566bb07c8 100644 (file)
@@ -28,9 +28,8 @@
 
 #include "hailo/hailort.h"
 #include "intermediate_buffer.hpp"
-#include "vdma_buffer.hpp"
+#include "config_buffer.hpp"
 #include "vdma_channel.hpp"
-#include "vdma_descriptor_list.hpp"
 #include "control_protocol.hpp"
 #include "pcie_device.hpp"
 
@@ -124,40 +123,6 @@ private:
     std::string m_layer_name;
 };
 
-
-class ConfigResources final
-{
-public:
-    ConfigResources(HailoRTDriver &driver, VdmaBuffer &&buffer, VdmaDescriptorList &&descriptor,
-        uint16_t requested_desc_page_size, size_t total_buffer_size);
-
-    // Write data to config channel
-    hailo_status write(const void *data, size_t data_size);
-
-    // Program the descriptors for the data written so far
-    Expected<uint16_t> program_descriptors();
-
-    uint16_t get_page_size();
-
-    size_t get_current_buffer_size();
-
-    /* Get all the config size. It's not the same as the VdmaBuffer::size() 
-    since we might add NOPs to the data (Pre-fetch mode) */
-    size_t get_total_cfg_size();
-
-private:
-    VdmaBuffer m_buffer;
-    VdmaDescriptorList m_descriptor;
-    const uint16_t m_desc_page_size;
-    const size_t m_total_buffer_size; 
-    size_t m_acc_buffer_offset;
-    uint16_t m_acc_desc_count;
-    size_t m_current_buffer_size;
-
-    friend class ResourcesManager;
-};
-
-
 class ResourcesManager final
 {
 public:
@@ -180,16 +145,20 @@ public:
         m_inter_context_channels(std::move(other.m_inter_context_channels)),
         m_config_channels(std::move(other.m_config_channels)), m_ddr_buffer_channels(std::move(other.m_ddr_buffer_channels)),
         m_network_group_metadata(std::move(other.m_network_group_metadata)), m_net_group_index(other.m_net_group_index),
-        m_network_index_map(std::move(other.m_network_index_map)) {}
+        m_network_index_map(std::move(other.m_network_index_map)),
+        m_latency_meters(std::move(other.m_latency_meters)),
+        m_boundary_channels(std::move(other.m_boundary_channels)) {}
 
     ExpectedRef<IntermediateBuffer> create_inter_context_buffer(uint32_t transfer_size, uint8_t src_stream_index,
-        uint8_t src_context_index, const std::string &partial_network_name);
+        uint8_t src_context_index, const std::string &network_name);
     ExpectedRef<IntermediateBuffer> get_intermediate_buffer(const IntermediateBufferKey &key);
-    Expected<std::pair<uint16_t, uint32_t>> get_desc_buffer_sizes_for_boundary_channel(uint32_t transfer_size,
-        const std::string &partial_network_name);
+    Expected<std::shared_ptr<VdmaChannel>> create_boundary_vdma_channel(uint8_t channel_index, uint32_t transfer_size, 
+        const std::string &network_name, const std::string &stream_name,
+        VdmaChannel::Direction channel_direction);
+
     ExpectedRef<IntermediateBuffer> create_ddr_buffer(DdrChannelsInfo &ddr_info, uint8_t context_index);
 
-    Expected<CONTROL_PROTOCOL__application_header_t> get_control_network_group_header();
+    Expected<CONTROL_PROTOCOL__application_header_t> get_control_network_group_header(bool is_scheduler_used);
 
     using context_info_t = CONTROL_PROTOCOL__context_switch_context_info_t;
 
@@ -203,12 +172,12 @@ public:
         return m_contexts;
     }
 
-    std::vector<ConfigResources> &preliminary_config() 
+    std::vector<ConfigBuffer> &preliminary_config() 
     {
         return m_preliminary_config; 
     }
 
-    std::vector<ConfigResources> &dynamic_config(uint8_t context_index)
+    std::vector<ConfigBuffer> &dynamic_config(uint8_t context_index)
     {
         assert(context_index < m_dynamic_config.size());
         return m_dynamic_config[context_index]; 
@@ -253,6 +222,11 @@ public:
         return m_vdma_device.get_dev_id();
     }
 
+    LatencyMetersMap &get_latnecy_meters()
+    {
+        return m_latency_meters;
+    }
+
     Expected<uint8_t> get_boundary_channel_index(uint8_t stream_index,
         hailo_stream_direction_t direction, const std::string &layer_name);
     Expected<hailo_stream_interface_t> get_default_streams_interface();
@@ -260,24 +234,28 @@ public:
     Expected<Buffer> read_intermediate_buffer(const IntermediateBufferKey &key);
 
     hailo_status set_number_of_cfg_channels(const uint8_t number_of_cfg_channels);
-    static Expected<ConfigResources> create_config_resources(uint8_t channel_index,
-        const std::vector<uint32_t> &cfg_sizes, HailoRTDriver &driver);
     void update_preliminary_config_buffer_info();
     void update_dynamic_contexts_buffer_info();
 
-    hailo_status create_vdma_channels();
+    hailo_status create_internal_vdma_channels();
     hailo_status register_fw_managed_vdma_channels();
     hailo_status unregister_fw_managed_vdma_channels();
+    hailo_status set_inter_context_channels_dynamic_batch_size(uint16_t dynamic_batch_size);
     hailo_status open_ddr_channels();
     void abort_ddr_channels();
     void close_ddr_channels();
-    hailo_status enable_state_machine();
+    hailo_status enable_state_machine(uint16_t dynamic_batch_size);
     hailo_status reset_state_machine();
-    Expected<uint16_t> get_network_batch_size_from_partial_name(const std::string &partial_network_name) const;
-    hailo_status fill_network_batch_size(CONTROL_PROTOCOL__application_header_t &app_header);
+    Expected<uint16_t> get_network_batch_size(const std::string &network_name) const;
+    Expected<std::shared_ptr<VdmaChannel>> get_boundary_vdma_channel_by_stream_name(const std::string &stream_name);
+
 private:
-    ExpectedRef<IntermediateBuffer> create_intermediate_buffer(uint32_t transfer_size, uint16_t batch_size,
-        const IntermediateBufferKey &key);
+    ExpectedRef<IntermediateBuffer> create_intermediate_buffer(IntermediateBuffer::ChannelType channel_type,
+        uint32_t transfer_size, uint16_t batch_size, const IntermediateBufferKey &key);
+    void update_config_buffer_info(std::vector<ConfigBuffer> &config_buffers,
+        CONTROL_PROTOCOL__context_switch_context_info_t &context);
+    hailo_status fill_infer_features(CONTROL_PROTOCOL__application_header_t &app_header);
+    hailo_status fill_network_batch_size(CONTROL_PROTOCOL__application_header_t &app_header, bool is_scheduler_used);
 
     std::vector<DdrChannelsInfo> m_ddr_infos;
     std::vector<CONTROL_PROTOCOL__context_switch_context_info_t> m_contexts;
@@ -285,24 +263,27 @@ private:
     VdmaDevice &m_vdma_device;
     HailoRTDriver &m_driver;
     const ConfigureNetworkParams m_config_params;
-    std::vector<ConfigResources> m_preliminary_config;
+    std::vector<ConfigBuffer> m_preliminary_config;
     // m_dynamic_config[context_index][config_index]
-    std::vector<std::vector<ConfigResources>> m_dynamic_config;
-    std::map<IntermediateBufferKey, std::unique_ptr<IntermediateBuffer>> m_intermediate_buffers;
+    std::vector<std::vector<ConfigBuffer>> m_dynamic_config;
+    std::map<IntermediateBufferKey, IntermediateBuffer> m_intermediate_buffers;
     std::vector<VdmaChannel> m_inter_context_channels;
     std::vector<VdmaChannel> m_config_channels;
     std::vector<VdmaChannel> m_ddr_buffer_channels;
     std::shared_ptr<NetworkGroupMetadata> m_network_group_metadata;
     uint8_t m_net_group_index;
     const std::vector<std::string> m_network_index_map;
+    LatencyMetersMap m_latency_meters; // Latency meter per network
+    std::map<std::string, std::shared_ptr<VdmaChannel>> m_boundary_channels; //map of string name and connected vDMA channel
 
     ResourcesManager(VdmaDevice &vdma_device, HailoRTDriver &driver,
-        const ConfigureNetworkParams config_params, std::vector<ConfigResources> &&preliminary_config,
-        std::vector<std::vector<ConfigResources>> &&dynamic_config, std::shared_ptr<NetworkGroupMetadata> &&network_group_metadata, uint8_t net_group_index,
-        const std::vector<std::string> &&network_index_map) :
+        const ConfigureNetworkParams config_params, std::vector<ConfigBuffer> &&preliminary_config,
+        std::vector<std::vector<ConfigBuffer>> &&dynamic_config, std::shared_ptr<NetworkGroupMetadata> &&network_group_metadata, uint8_t net_group_index,
+        const std::vector<std::string> &&network_index_map, LatencyMetersMap &&latency_meters) :
           m_vdma_device(vdma_device), m_driver(driver), m_config_params(config_params),
           m_preliminary_config(std::move(preliminary_config)), m_dynamic_config(std::move(dynamic_config)),
-          m_network_group_metadata(std::move(network_group_metadata)), m_net_group_index(net_group_index), m_network_index_map(std::move(network_index_map)) {};
+          m_network_group_metadata(std::move(network_group_metadata)), m_net_group_index(net_group_index), m_network_index_map(std::move(network_index_map)),
+          m_latency_meters(std::move(latency_meters)) {};
 
 };
 
index 980bee9b6d23c06e08b18f879247ddf771466372..e1ff0828f1b16880fadf9c419a0c5b86c68723c2 100644 (file)
@@ -30,10 +30,12 @@ public:
 
     static Expected<VdmaConfigActivatedNetworkGroup> create(
         VdmaConfigActiveAppHolder &active_net_group_holder,
+        const std::string &network_group_name,
         std::vector<std::shared_ptr<ResourcesManager>> resources_managers,
         const hailo_activate_network_group_params_t &network_group_params,
+        uint16_t dynamic_batch_size,
         std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
-        std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,         
+        std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,
         EventPtr network_group_activated_event,
         AccumulatorPtr deactivation_time_accumulator);
 
@@ -44,11 +46,14 @@ public:
     VdmaConfigActivatedNetworkGroup &operator=(VdmaConfigActivatedNetworkGroup &&other) = delete;
     VdmaConfigActivatedNetworkGroup(VdmaConfigActivatedNetworkGroup &&other) noexcept;
 
+    virtual const std::string &get_network_group_name() const override;
     virtual Expected<Buffer> get_intermediate_buffer(const IntermediateBufferKey &key) override;
 
 private:
     VdmaConfigActivatedNetworkGroup(
+      const std::string &network_group_name,
       const hailo_activate_network_group_params_t &network_group_params,
+      uint16_t dynamic_batch_size,
       std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
       std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,
       std::vector<std::shared_ptr<ResourcesManager>> &&resources_managers,
@@ -64,6 +69,7 @@ private:
     static void ddr_send_thread_main(DdrChannelsInfo ddr_info,
       std::shared_ptr<std::atomic<uint16_t>> desc_list_num_ready);
 
+  std::string m_network_group_name;
   bool m_should_reset_state_machine;
   VdmaConfigActiveAppHolder &m_active_net_group_holder;
   // One ResourcesManager per connected physical device. Currently only one device is supported.
index 4dd8d99e0631af3baa5fbbdd4d0e701f3c4ded83..1aa950698cdf455292001c3c33d1db0310088262 100644 (file)
@@ -12,6 +12,7 @@
 #define HAILO_VDMA_CONFIG_MANAGER_HPP_
 
 #include "context_switch/config_manager.hpp"
+#include "context_switch/network_group_wrapper.hpp"
 #include "context_switch/multi_context/vdma_config_network_group.hpp"
 #include "hailo/hailort.h"
 #include "hailo/device.hpp"
@@ -20,8 +21,7 @@
 #include "common/utils.hpp"
 #include "hlpcie.hpp"
 #include "vdma_channel.hpp"
-#include "vdma_buffer.hpp"
-#include "vdma_descriptor_list.hpp"
+#include "network_group_scheduler.hpp"
 
 #include <vector>
 #include <map>
@@ -38,24 +38,26 @@ public:
     static Expected<VdmaConfigManager> create(VDevice &vdevice);
     virtual ConfigManagerType get_manager_type();
     virtual Expected<ConfiguredNetworkGroupVector> add_hef(Hef &hef,
-        const NetworkGroupsParamsMap &configure_params={});
+        const NetworkGroupsParamsMap &configure_params, bool is_scheduler_used=false);
 
     static hailo_status update_network_batch_size(ConfigureNetworkParams &configure_params);
 
-    virtual ~VdmaConfigManager() {}
+    virtual ~VdmaConfigManager() = default;
     VdmaConfigManager(const VdmaConfigManager &other) noexcept = delete;
     VdmaConfigManager &operator=(const VdmaConfigManager &other) = delete;
     VdmaConfigManager &operator=(VdmaConfigManager &&other) = delete;
     VdmaConfigManager(VdmaConfigManager &&other) noexcept = default;
 
   private:
-    VdmaConfigManager(std::vector<std::reference_wrapper<VdmaDevice>> &&devices, bool is_vdevice);
+    VdmaConfigManager(std::vector<std::reference_wrapper<VdmaDevice>> &&devices, bool is_vdevice, NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
     // TODO: (SDK-16665) Dont need is_active flag for dtor?
     std::vector<std::reference_wrapper<VdmaDevice>> m_devices;
     std::vector<std::shared_ptr<VdmaConfigNetworkGroup>> m_net_groups;
+    std::vector<std::shared_ptr<ConfiguredNetworkGroupWrapper>> m_net_group_wrappers;
     VdmaConfigActiveAppHolder m_active_net_group_holder;
     bool m_is_vdevice;
+    NetworkGroupSchedulerWeakPtr m_network_group_scheduler;
 };
 
 } /* namespace hailort */
index f57b1306f9371e6e3f72e2496478b8136086fcf5..477b2988dc89182d4e3de6041c27011d10dbb0e0 100644 (file)
@@ -13,9 +13,7 @@
 #define _HAILO_CONTEXT_SWITCH_VDMA_CONFIG_NETWORK_GROUP_HPP_
 
 #include "hailo/hailort.h"
-#include "vdma_buffer.hpp"
 #include "vdma_channel.hpp"
-#include "vdma_descriptor_list.hpp"
 #include "common/utils.hpp"
 #include "context_switch/multi_context/vdma_config_activated_network_group.hpp"
 #include "control_protocol.h"
@@ -23,6 +21,7 @@
 #include "hailort_defaults.hpp"
 #include "context_switch/network_group_internal.hpp"
 #include "context_switch/multi_context/resource_manager.hpp"
+#include "network_group_scheduler.hpp"
 
 #include <cstdint>
 #include <assert.h>
@@ -41,26 +40,33 @@ public:
     static Expected<VdmaConfigNetworkGroup> create(VdmaConfigActiveAppHolder &active_net_group_holder,
         const ConfigureNetworkParams &config_params, 
         std::vector<std::shared_ptr<ResourcesManager>> resources_managers,
-        std::shared_ptr<NetworkGroupMetadata> network_group_metadata);
+        std::shared_ptr<NetworkGroupMetadata> network_group_metadata, NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
     std::vector<std::shared_ptr<ResourcesManager>> &get_resources_managers()
     {
         return m_resources_managers;
     }
 
-    hailo_status create_vdevice_streams_from_config_params();
+    hailo_status create_vdevice_streams_from_config_params(network_group_handle_t network_group_handle);
     hailo_status create_output_vdevice_stream_from_config_params(
-        const hailo_stream_parameters_t &stream_params, const std::string &stream_name);
+        const hailo_stream_parameters_t &stream_params, const std::string &stream_name, network_group_handle_t network_group_handle);
     hailo_status create_input_vdevice_stream_from_config_params(
-        const hailo_stream_parameters_t &stream_params, const std::string &stream_name);
+        const hailo_stream_parameters_t &stream_params, const std::string &stream_name, network_group_handle_t network_group_handle);
 
-    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(
-      const hailo_activate_network_group_params_t &network_group_params = HailoRTDefaults::get_network_group_params()) override;
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_impl(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) override;
 
     virtual Expected<hailo_stream_interface_t> get_default_streams_interface() override;
 
     virtual Expected<uint8_t> get_boundary_channel_index(uint8_t stream_index, hailo_stream_direction_t direction,
         const std::string &layer_name) override;
+    virtual Expected<std::shared_ptr<LatencyMetersMap>> get_latnecy_meters() override;
+    virtual Expected<std::shared_ptr<VdmaChannel>> get_boundary_vdma_channel_by_stream_name(
+        const std::string &stream_name) override;
+
+    void set_network_group_handle(network_group_handle_t handle);
+    virtual hailo_status set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name) override;
+    virtual hailo_status set_scheduler_threshold(uint32_t threshold, const std::string &network_name) override;
 
     virtual ~VdmaConfigNetworkGroup() = default;
     VdmaConfigNetworkGroup(const VdmaConfigNetworkGroup &other) = delete;
@@ -68,16 +74,19 @@ public:
     VdmaConfigNetworkGroup &operator=(VdmaConfigNetworkGroup &&other) = delete;
     VdmaConfigNetworkGroup(VdmaConfigNetworkGroup &&other) noexcept : ConfiguredNetworkGroupBase(std::move(other)),
       m_active_net_group_holder(other.m_active_net_group_holder),
-      m_resources_managers(std::move(other.m_resources_managers)) {}
+      m_resources_managers(std::move(other.m_resources_managers)), m_network_group_scheduler(std::move(other.m_network_group_scheduler)) {}
 
 private:
     VdmaConfigNetworkGroup(VdmaConfigActiveAppHolder &active_net_group_holder,
         const ConfigureNetworkParams &config_params, 
         std::vector<std::shared_ptr<ResourcesManager>> &&resources_managers,
-        const NetworkGroupMetadata &network_group_metadata, hailo_status &status);
+        const NetworkGroupMetadata &network_group_metadata, NetworkGroupSchedulerWeakPtr network_group_scheduler, hailo_status &status);
 
     VdmaConfigActiveAppHolder &m_active_net_group_holder;
     std::vector<std::shared_ptr<ResourcesManager>> m_resources_managers;
+    NetworkGroupSchedulerWeakPtr m_network_group_scheduler;
+    network_group_handle_t m_network_group_handle;
+
 };
 
 } /* namespace hailort */
index 41ce33f8257e04ed13abe06c27ee2dd8092ce3b1..d364754275914694e579a77f2c5eccd7641d08da 100644 (file)
@@ -1,3 +1,12 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file network_group.cpp
+ * @brief: Configured Network Group and Activated Network Group
+ **/
+
 #include "hailo/transform.hpp"
 #include "network_group_internal.hpp"
 #include "hef_internal.hpp"
@@ -14,7 +23,9 @@ namespace hailort
 {
 
 ActivatedNetworkGroupBase::ActivatedNetworkGroupBase(const hailo_activate_network_group_params_t &network_group_params,
-        std::map<std::string, std::unique_ptr<InputStream>> &input_streams, std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,         
+        uint16_t dynamic_batch_size,
+        std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
+        std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,         
         EventPtr &&network_group_activated_event, hailo_status &status) :
     m_network_group_params(network_group_params),
     m_input_streams(input_streams),
@@ -27,7 +38,7 @@ ActivatedNetworkGroupBase::ActivatedNetworkGroupBase(const hailo_activate_networ
         return;
     }
 
-    status = activate_low_level_streams();
+    status = activate_low_level_streams(dynamic_batch_size);
     if (HAILO_SUCCESS != status) {
         LOGGER__ERROR("Failed to activate low level streams");
         return;
@@ -40,49 +51,14 @@ ActivatedNetworkGroupBase::ActivatedNetworkGroupBase(const hailo_activate_networ
     }
 }
 
-Expected<LatencyMeterPtr> ConfiguredNetworkGroupBase::create_hw_latency_meter(Device &device,
-    const std::vector<LayerInfo> &layers)
-{
-    std::set<uint32_t> d2h_channel_indexes;
-
-    // TODO: dont support hw latency meter with MIPI input
-
-    if (Device::Type::PCIE != device.get_type()) {
-        LOGGER__WARNING("HW Latency measurement is supported only on PCIe devices");
-        return make_unexpected(HAILO_INVALID_OPERATION);
-    }
-
-    size_t h2d_streams_count = 0;
-    for (const auto &layer : layers) {
-        if (layer.direction == HAILO_D2H_STREAM) {
-            if (HAILO_FORMAT_ORDER_HAILO_NMS == layer.format.order) {
-                LOGGER__WARNING("HW Latency measurement is not supported on NMS networks");
-                return make_unexpected(HAILO_INVALID_OPERATION);
-            }
-
-            d2h_channel_indexes.insert(layer.index);
-        }
-        else {
-            h2d_streams_count++;
-        }
-    }
-
-    if (h2d_streams_count > 1) {
-        LOGGER__WARNING("HW Latency measurement is supported on networks with a single input");
-        return make_unexpected(HAILO_INVALID_OPERATION);
-    }
-
-    return make_shared_nothrow<LatencyMeter>(d2h_channel_indexes, MAX_IRQ_TIMESTAMPS_SIZE);
-}
-
-hailo_status ActivatedNetworkGroupBase::activate_low_level_streams()
+hailo_status ActivatedNetworkGroupBase::activate_low_level_streams(uint16_t dynamic_batch_size)
 {
     for (auto &name_pair : m_input_streams) {
-        auto status = name_pair.second->activate_stream();
+        auto status = name_pair.second->activate_stream(dynamic_batch_size);
         CHECK_SUCCESS(status);
     }
     for (auto &name_pair : m_output_streams) {
-        auto status = name_pair.second->activate_stream();
+        auto status = name_pair.second->activate_stream(dynamic_batch_size);
         CHECK_SUCCESS(status);
     }
 
@@ -132,6 +108,14 @@ Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroup::activat
     return activate(network_group_params);
 }
 
+Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroupBase::activate(
+    const hailo_activate_network_group_params_t &network_group_params)
+{
+    CHECK_AS_EXPECTED(!m_is_scheduling, HAILO_INVALID_OPERATION,
+        "Manually activating a network group is not allowed when the network group scheduler is active!");
+    return activate_internal(network_group_params, CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE);
+}
+
 Expected<std::chrono::nanoseconds> get_latency(LatencyMeterPtr &latency_meter, bool clear)
 {
     auto hw_latency = latency_meter->get_latency(clear);
@@ -148,10 +132,14 @@ Expected<LatencyMeasurementResult> ConfiguredNetworkGroupBase::get_latency_measu
     bool clear = ((m_config_params.latency & HAILO_LATENCY_CLEAR_AFTER_GET) == HAILO_LATENCY_CLEAR_AFTER_GET);
     LatencyMeasurementResult result = {};
 
+    auto latency_meters_exp = get_latnecy_meters();
+    CHECK_EXPECTED(latency_meters_exp);
+    auto latency_meters = latency_meters_exp.release();
+
     if (network_name.empty()) {
         std::chrono::nanoseconds latency_sum(0);
         uint32_t measurements_count = 0;
-        for (auto &latency_meter_pair : m_latency_meter) {
+        for (auto &latency_meter_pair : *latency_meters.get()) {
             auto hw_latency = get_latency(latency_meter_pair.second, clear);
             if (HAILO_NOT_AVAILABLE == hw_latency.status()) {
                 continue;
@@ -166,13 +154,11 @@ Expected<LatencyMeasurementResult> ConfiguredNetworkGroupBase::get_latency_measu
         }
         result.avg_hw_latency = latency_sum / measurements_count;
     } else {
-        auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-        CHECK_EXPECTED(partial_network_name);
-        if(!contains(m_latency_meter, partial_network_name.value())) {
-            LOGGER__DEBUG("No latency measurements was found for network {}", partial_network_name.value());
-            return make_unexpected(HAILO_NOT_AVAILABLE);
+        if(!contains(*latency_meters, network_name)) {
+            LOGGER__DEBUG("No latency measurements was found for network {}", network_name);
+            return make_unexpected(HAILO_NOT_FOUND);
         }
-        auto hw_latency = get_latency(m_latency_meter.at(partial_network_name.value()), clear);
+        auto hw_latency = get_latency(latency_meters->at(network_name), clear);
         if (HAILO_NOT_AVAILABLE == hw_latency.status()) {
             return make_unexpected(HAILO_NOT_AVAILABLE);
         }
@@ -182,8 +168,6 @@ Expected<LatencyMeasurementResult> ConfiguredNetworkGroupBase::get_latency_measu
     return result;
 }
 
-
-
 Expected<OutputStreamWithParamsVector> ConfiguredNetworkGroupBase::get_output_streams_from_vstream_names(
     const std::map<std::string, hailo_vstream_params_t> &outputs_params)
 {
@@ -282,13 +266,19 @@ Expected<LayerInfo> ConfiguredNetworkGroupBase::get_layer_info(const std::string
 ConfiguredNetworkGroupBase::ConfiguredNetworkGroupBase(
     const ConfigureNetworkParams &config_params, const uint8_t net_group_index, 
     const NetworkGroupMetadata &network_group_metadata, hailo_status &status) :
-        ConfiguredNetworkGroup::ConfiguredNetworkGroup(),
+        ConfiguredNetworkGroupBase(config_params, net_group_index, network_group_metadata, false, status)
+{}
+
+ConfiguredNetworkGroupBase::ConfiguredNetworkGroupBase(
+    const ConfigureNetworkParams &config_params, const uint8_t net_group_index, 
+    const NetworkGroupMetadata &network_group_metadata, bool is_scheduling, hailo_status &status) :
         m_config_params(config_params),
+        m_min_configured_batch_size(get_smallest_configured_batch_size(config_params)),
         m_net_group_index(net_group_index),
-        m_latency_meter(),
         m_network_group_metadata(network_group_metadata),
         m_activation_time_accumulator(),
-        m_deactivation_time_accumulator()
+        m_deactivation_time_accumulator(),
+        m_is_scheduling(is_scheduling)
 {
     auto event = Event::create_shared(Event::State::not_signalled);
     if (nullptr == event) {
@@ -315,6 +305,33 @@ ConfiguredNetworkGroupBase::ConfiguredNetworkGroupBase(
     status = HAILO_SUCCESS;
 }
 
+uint16_t ConfiguredNetworkGroupBase::get_smallest_configured_batch_size(const ConfigureNetworkParams &config_params)
+{
+    // There are two possible situations:
+    // 1) All networks in the network group have the same configured (and hence smallest) batch_size =>
+    //    We return that batch size.
+    // 2) Not all of the networks have the same configured (and hence smallest) batch_size. Currently, when
+    //    using dynamic_batch_sizes, all networks will use the same dynamic_batch_size (until HRT-6535 is done).
+    //    Hence, we must not set a dynamic_batch_size to a value greater than the smallest configured network
+    //    batch_size (e.g. all the resources allocated are for at most the configured network batch_size).
+    return std::min_element(config_params.network_params_by_name.begin(), config_params.network_params_by_name.end(),
+        [](const auto& lhs, const auto& rhs) { return lhs.second.batch_size < rhs.second.batch_size; })->second.batch_size;
+}
+
+Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroupBase::activate_internal(
+    const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size)
+{
+    CHECK_AS_EXPECTED(dynamic_batch_size <= m_min_configured_batch_size, HAILO_INVALID_ARGUMENT,
+        "Dynamic batch size ({}) must be less than/equal to the smallest configured batch size ({})",
+        dynamic_batch_size, m_min_configured_batch_size);
+    return activate_impl(network_group_params, dynamic_batch_size);
+}
+
+Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroupBase::force_activate(uint16_t dynamic_batch_size)
+{
+    return activate_internal(HailoRTDefaults::get_network_group_params(), dynamic_batch_size);
+}
+
 const std::string &ConfiguredNetworkGroupBase::get_network_group_name() const
 {
     return m_network_group_metadata.network_group_name();
@@ -326,11 +343,8 @@ Expected<uint16_t> ConfiguredNetworkGroupBase::get_stream_batch_size(const std::
     CHECK_EXPECTED(layer_infos);
     for (const auto &layer_info : layer_infos.release()) {
         if (layer_info.name == stream_name) {
-            auto partial_network_name = layer_info.partial_network_name;
             for (auto const &network_params_pair : m_config_params.network_params_by_name) {
-                auto network_name = network_params_pair.first;
-                auto found = network_name.find(HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name);
-                if (found != std::string::npos) {
+                if (network_params_pair.first == layer_info.network_name) {
                     auto batch_size = network_params_pair.second.batch_size;
                     return batch_size;
                 }
@@ -341,15 +355,17 @@ Expected<uint16_t> ConfiguredNetworkGroupBase::get_stream_batch_size(const std::
     return make_unexpected(HAILO_NOT_FOUND);
 }
 
+const ConfigureNetworkParams ConfiguredNetworkGroupBase::get_config_params() const
+{
+    return m_config_params;
+}
+
 hailo_status ConfiguredNetworkGroupBase::create_input_stream_from_config_params(Device &device,
     const hailo_stream_parameters_t &stream_params, const std::string &stream_name)
 {
     auto edge_layer = get_layer_info(stream_name);
     CHECK_EXPECTED_AS_STATUS(edge_layer);
 
-    auto partial_network_name = edge_layer->partial_network_name;
-    auto latency_meter = (contains(m_latency_meter, partial_network_name)) ? m_latency_meter.at(partial_network_name) : nullptr;
-
     CHECK(device.is_stream_interface_supported(stream_params.stream_interface), HAILO_INVALID_OPERATION,
         "Device does not supports the given stream interface streams. Please update input_stream_params for stream {}.",
         stream_name);
@@ -360,11 +376,11 @@ hailo_status ConfiguredNetworkGroupBase::create_input_stream_from_config_params(
                 auto batch_size_exp = get_stream_batch_size(stream_name);
                 CHECK_EXPECTED_AS_STATUS(batch_size_exp);
                 const auto stream_index = edge_layer->index;
-                const auto channel_index = get_boundary_channel_index(stream_index, HAILO_H2D_STREAM, stream_name);
-                CHECK_EXPECTED_AS_STATUS(channel_index, "Failed to get channel index for input stream {}", stream_index);
+                auto vdma_channel_ptr = get_boundary_vdma_channel_by_stream_name(stream_name);
+                CHECK_EXPECTED_AS_STATUS(vdma_channel_ptr, "Failed to get vdma channel for output stream {}", stream_index);
 
-                auto input_stream = PcieInputStream::create(device, channel_index.value(),
-                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event, latency_meter);
+                auto input_stream = PcieInputStream::create(device, vdma_channel_ptr.release(),
+                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event);
                 CHECK_EXPECTED_AS_STATUS(input_stream);
                 m_input_streams.insert(make_pair(stream_name, input_stream.release()));
             }
@@ -374,11 +390,11 @@ hailo_status ConfiguredNetworkGroupBase::create_input_stream_from_config_params(
                 auto batch_size_exp = get_stream_batch_size(stream_name);
                 CHECK_EXPECTED_AS_STATUS(batch_size_exp);
                 const auto stream_index = edge_layer->index;
-                const auto channel_index = get_boundary_channel_index(stream_index, HAILO_H2D_STREAM, stream_name);
-                CHECK_EXPECTED_AS_STATUS(channel_index, "Failed to get channel index for input stream {}", stream_index);
+                auto vdma_channel_ptr = get_boundary_vdma_channel_by_stream_name(stream_name);
+                CHECK_EXPECTED_AS_STATUS(vdma_channel_ptr, "Failed to get vdma channel for output stream {}", stream_index);
 
-                auto input_stream = CoreInputStream::create(device, channel_index.value(),
-                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event, latency_meter);
+                auto input_stream = CoreInputStream::create(device, vdma_channel_ptr.release(),
+                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event);
                 CHECK_EXPECTED_AS_STATUS(input_stream);
                 m_input_streams.insert(make_pair(stream_name, input_stream.release()));
             }
@@ -415,9 +431,6 @@ hailo_status ConfiguredNetworkGroupBase::create_output_stream_from_config_params
     auto edge_layer = get_layer_info(stream_name);
     CHECK_EXPECTED_AS_STATUS(edge_layer);
 
-    auto partial_network_name = edge_layer->partial_network_name;
-    auto latency_meter = (contains(m_latency_meter, partial_network_name)) ? m_latency_meter.at(partial_network_name) : nullptr;
-
     CHECK(device.is_stream_interface_supported(stream_params.stream_interface), HAILO_INVALID_OPERATION,
         "Device does not supports the given stream interface streams. Please update input_stream_params for stream {}.",
         stream_name);
@@ -428,11 +441,11 @@ hailo_status ConfiguredNetworkGroupBase::create_output_stream_from_config_params
                 auto batch_size_exp = get_stream_batch_size(stream_name);
                 CHECK_EXPECTED_AS_STATUS(batch_size_exp);
                 const auto stream_index = edge_layer->index;
-                const auto channel_index = get_boundary_channel_index(stream_index, HAILO_D2H_STREAM, stream_name);
-                CHECK_EXPECTED_AS_STATUS(channel_index, "Failed to get channel index for output stream {}", stream_index);
+                auto vdma_channel_ptr = get_boundary_vdma_channel_by_stream_name(stream_name);
+                CHECK_EXPECTED_AS_STATUS(vdma_channel_ptr, "Failed to get vdma channel for output stream {}", stream_index);
 
-                auto output_stream = PcieOutputStream::create(device, channel_index.value(),
-                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event, latency_meter);
+                auto output_stream = PcieOutputStream::create(device, vdma_channel_ptr.release(), 
+                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event);
                 CHECK_EXPECTED_AS_STATUS(output_stream);
                 m_output_streams.insert(make_pair(stream_name, output_stream.release()));
             }
@@ -442,12 +455,11 @@ hailo_status ConfiguredNetworkGroupBase::create_output_stream_from_config_params
                 auto batch_size_exp = get_stream_batch_size(stream_name);
                 CHECK_EXPECTED_AS_STATUS(batch_size_exp);
                 const auto stream_index = edge_layer->index;
-                const auto channel_index = get_boundary_channel_index(stream_index, HAILO_D2H_STREAM, stream_name);
-                CHECK_EXPECTED_AS_STATUS(channel_index, "Failed to get channel index for output stream {}", stream_index);
+                auto vdma_channel_ptr = get_boundary_vdma_channel_by_stream_name(stream_name);
+                CHECK_EXPECTED_AS_STATUS(vdma_channel_ptr, "Failed to get vdma channel for output stream {}", stream_index);
 
-                auto output_stream = CoreOutputStream::create(device, channel_index.value(),
-                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event,
-                    latency_meter);
+                auto output_stream = CoreOutputStream::create(device, vdma_channel_ptr.release(), 
+                    edge_layer.value(), batch_size_exp.value(), m_network_group_activated_event);
                 CHECK_EXPECTED_AS_STATUS(output_stream);
                 m_output_streams.insert(make_pair(stream_name, output_stream.release()));
             }
@@ -473,20 +485,6 @@ hailo_status ConfiguredNetworkGroupBase::create_output_stream_from_config_params
 
 hailo_status ConfiguredNetworkGroupBase::create_streams_from_config_params(Device &device)
 {
-    if ((m_config_params.latency & HAILO_LATENCY_MEASURE) == HAILO_LATENCY_MEASURE) {
-        // Best affort for starting latency meter.
-        auto networks_names = m_network_group_metadata.get_partial_network_names();
-        for (auto &network_name : networks_names) {
-            auto layer_infos = m_network_group_metadata.get_all_layer_infos(network_name);
-            CHECK_EXPECTED_AS_STATUS(layer_infos);
-            auto latency_meter = ConfiguredNetworkGroupBase::create_hw_latency_meter(device, layer_infos.value());
-            if (latency_meter) {
-                m_latency_meter.emplace(network_name, latency_meter.release());
-                LOGGER__DEBUG("Starting hw latency measurement for network {}", network_name);
-            }
-        }
-    }
-
     for (const auto &stream_parameters_pair : m_config_params.stream_params_by_name) {
         switch (stream_parameters_pair.second.direction) {
             case HAILO_H2D_STREAM:
@@ -516,10 +514,7 @@ hailo_status ConfiguredNetworkGroupBase::create_streams_from_config_params(Devic
 
 Expected<InputStreamRefVector> ConfiguredNetworkGroupBase::get_input_streams_by_network(const std::string &network_name)
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    auto input_stream_infos = m_network_group_metadata.get_input_stream_infos(partial_network_name.value());
+    auto input_stream_infos = m_network_group_metadata.get_input_stream_infos(network_name);
     CHECK_EXPECTED(input_stream_infos);
 
     InputStreamRefVector result;
@@ -533,10 +528,7 @@ Expected<InputStreamRefVector> ConfiguredNetworkGroupBase::get_input_streams_by_
 
 Expected<OutputStreamRefVector> ConfiguredNetworkGroupBase::get_output_streams_by_network(const std::string &network_name)
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    auto output_stream_infos = m_network_group_metadata.get_output_stream_infos(partial_network_name.value());
+    auto output_stream_infos = m_network_group_metadata.get_output_stream_infos(network_name);
     CHECK_EXPECTED(output_stream_infos);
 
     OutputStreamRefVector result;
@@ -658,10 +650,7 @@ Expected<std::map<std::string, hailo_vstream_params_t>> ConfiguredNetworkGroupBa
     bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
     const std::string &network_name)
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    auto input_vstream_infos = m_network_group_metadata.get_input_vstream_infos(partial_network_name.value());
+    auto input_vstream_infos = m_network_group_metadata.get_input_vstream_infos(network_name);
     CHECK_EXPECTED(input_vstream_infos);
 
     std::map<std::string, hailo_vstream_params_t> res;
@@ -675,10 +664,7 @@ Expected<std::map<std::string, hailo_vstream_params_t>> ConfiguredNetworkGroupBa
     bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
     const std::string &network_name)
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    auto output_vstream_infos = m_network_group_metadata.get_output_vstream_infos(partial_network_name.value());
+    auto output_vstream_infos = m_network_group_metadata.get_output_vstream_infos(network_name);
     CHECK_EXPECTED(output_vstream_infos);
 
     std::map<std::string, hailo_vstream_params_t> res;
@@ -696,37 +682,25 @@ Expected<std::vector<hailo_network_info_t>> ConfiguredNetworkGroupBase::get_netw
 Expected<std::vector<hailo_stream_info_t>> ConfiguredNetworkGroupBase::get_all_stream_infos(
     const std::string &network_name) const
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    return m_network_group_metadata.get_all_stream_infos(partial_network_name.value());
+    return m_network_group_metadata.get_all_stream_infos(network_name);
 }
 
 Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupBase::get_input_vstream_infos(
     const std::string &network_name) const
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    return m_network_group_metadata.get_input_vstream_infos(partial_network_name.value());
+    return m_network_group_metadata.get_input_vstream_infos(network_name);
 }
 
 Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupBase::get_output_vstream_infos(
     const std::string &network_name) const
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    return m_network_group_metadata.get_output_vstream_infos(partial_network_name.value());
+    return m_network_group_metadata.get_output_vstream_infos(network_name);
 }
 
 Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupBase::get_all_vstream_infos(
     const std::string &network_name) const
 {
-    auto partial_network_name = m_network_group_metadata.get_partial_network_name(network_name);
-    CHECK_EXPECTED(partial_network_name);
-
-    return m_network_group_metadata.get_all_vstream_infos(partial_network_name.value());
+    return m_network_group_metadata.get_all_vstream_infos(network_name);
 }
 
 AccumulatorPtr ConfiguredNetworkGroupBase::get_activation_time_accumulator() const
index bab75ce5bb46f274640380007fcc8b00e0b39403..d863990ecbca3596a53741588d586e4d79a5cc93 100644 (file)
@@ -5,15 +5,16 @@
 /**
  * @file network_group_internal.hpp
  * @brief Class declaration for ConfiguredNetworkGroupBase and ActivatedNetworkGroupBase that implement the basic ConfiguredNetworkGroup
- *        and ActivatedNetworkGroup interfaces. All internal classes that are relavant should inherit from the
+ *        and ActivatedNetworkGroup interfaces. All internal classes that are relevant should inherit from the
  *        ConfiguredNetworkGroupBase and ActivatedNetworkGroupBase classes.
- *        Hence, the hiearchy is as follows:
+ *        Hence, the hierarchy is as follows:
  *        -----------------------------------------------------------------------------
- *        |                        ConfiguredNetworkGroup                             |  (External "interface")
- *        |                                  |                                        |
- *        |                      ConfiguredNetworkGroupBase                           |  (Base classes)
- *        |                          /                \                               |
- *        |           VdmaConfigNetworkGroup       HcpConfigNetworkGroup              | (Actual implementations)
+ *        |                          ConfiguredNetworkGroup                           |  (External "interface")
+ *        |                   ________________|___________________                    |
+ *        |                  /                                    \                   |
+ *        |            ConfiguredNetworkGroupBase       ConfiguredNetworkGroupWrapper |  (Base classes)
+ *        |               /                  \                                        |
+ *        |  VdmaConfigNetworkGroup     HcpConfigNetworkGroup                         | (Actual implementations)
  *        -----------------------------------------------------------------------------
  *        |                         ActivatedNetworkGroup                             |  (External "interface")
  *        |                                   |                                       |
@@ -31,6 +32,8 @@
 #include "hailo/network_group.hpp"
 #include "hef_internal.hpp"
 #include "common/latency_meter.hpp"
+#include "control_protocol.h"
+#include "vdma_channel.hpp"
 
 namespace hailort
 {
@@ -52,12 +55,13 @@ protected:
     hailo_activate_network_group_params_t m_network_group_params;
 
     ActivatedNetworkGroupBase(const hailo_activate_network_group_params_t &network_group_params,
+        uint16_t dynamic_batch_size,
         std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
         std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,         
         EventPtr &&network_group_activated_event, hailo_status &status);
 
 private:
-    hailo_status activate_low_level_streams();
+    hailo_status activate_low_level_streams(uint16_t dynamic_batch_size);
     hailo_status validate_network_group_params(const hailo_activate_network_group_params_t &network_group_params);
 
     std::map<std::string, std::unique_ptr<InputStream>> &m_input_streams;
@@ -74,6 +78,9 @@ public:
     ConfiguredNetworkGroupBase &operator=(ConfiguredNetworkGroupBase &&other) = delete;
     ConfiguredNetworkGroupBase(ConfiguredNetworkGroupBase &&other) = default;
 
+    Expected<std::unique_ptr<ActivatedNetworkGroup>> force_activate(
+        uint16_t dynamic_batch_size = CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE);
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(const hailo_activate_network_group_params_t &network_group_params) override;
     virtual hailo_status wait_for_activation(const std::chrono::milliseconds &timeout) override;
 
     virtual const std::string &get_network_group_name() const override;
@@ -126,9 +133,18 @@ public:
     
     Expected<uint16_t> get_stream_batch_size(const std::string &stream_name);
 
+    const ConfigureNetworkParams get_config_params() const;
+
 protected:
     ConfiguredNetworkGroupBase(const ConfigureNetworkParams &config_params, const uint8_t m_net_group_index, 
         const NetworkGroupMetadata &network_group_metadata, hailo_status &status);
+    ConfiguredNetworkGroupBase(const ConfigureNetworkParams &config_params, const uint8_t m_net_group_index, 
+        const NetworkGroupMetadata &network_group_metadata, bool is_scheduling, hailo_status &status);
+
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_internal(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) override;
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_impl(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) = 0;
 
     hailo_status create_output_stream_from_config_params(Device &device,
         const hailo_stream_parameters_t &stream_params, const std::string &stream_name);
@@ -142,16 +158,25 @@ protected:
 
     virtual Expected<uint8_t> get_boundary_channel_index(uint8_t stream_index, hailo_stream_direction_t direction,
         const std::string &layer_name) = 0;
+    virtual Expected<std::shared_ptr<LatencyMetersMap>> get_latnecy_meters() = 0;
+    virtual Expected<std::shared_ptr<VdmaChannel>> get_boundary_vdma_channel_by_stream_name(const std::string &stream_name) = 0;
 
     const ConfigureNetworkParams m_config_params;
+    const uint16_t m_min_configured_batch_size; // TODO: remove after HRT-6535
     uint8_t m_net_group_index;
-    std::map<std::string, LatencyMeterPtr> m_latency_meter; // Latency meter per network
     std::map<std::string, std::unique_ptr<InputStream>> m_input_streams;
     std::map<std::string, std::unique_ptr<OutputStream>> m_output_streams;
     EventPtr m_network_group_activated_event;
     const NetworkGroupMetadata m_network_group_metadata;
     AccumulatorPtr m_activation_time_accumulator;
     AccumulatorPtr m_deactivation_time_accumulator;
+
+private:
+    friend class ConfiguredNetworkGroupWrapper;
+
+    static uint16_t get_smallest_configured_batch_size(const ConfigureNetworkParams &config_params);
+
+    bool m_is_scheduling;
 };
 
 } /* namespace hailort */
diff --git a/hailort/libhailort/src/context_switch/network_group_wrapper.cpp b/hailort/libhailort/src/context_switch/network_group_wrapper.cpp
new file mode 100644 (file)
index 0000000..3181e5c
--- /dev/null
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file network_group_wrapper.cpp
+ * @brief: Network Group Wrapper
+ **/
+
+#include "network_group_wrapper.hpp"
+
+namespace hailort
+{
+
+const std::string &ConfiguredNetworkGroupWrapper::get_network_group_name() const
+{
+    return m_configured_network_group->get_network_group_name();
+}
+
+Expected<hailo_stream_interface_t> ConfiguredNetworkGroupWrapper::get_default_streams_interface()
+{
+    return m_configured_network_group->get_default_streams_interface();
+}
+
+std::vector<std::reference_wrapper<InputStream>> ConfiguredNetworkGroupWrapper::get_input_streams_by_interface(hailo_stream_interface_t stream_interface)
+{
+    return m_configured_network_group->get_input_streams_by_interface(stream_interface);
+}
+
+std::vector<std::reference_wrapper<OutputStream>> ConfiguredNetworkGroupWrapper::get_output_streams_by_interface(hailo_stream_interface_t stream_interface)
+{
+    return m_configured_network_group->get_output_streams_by_interface(stream_interface);
+}
+
+ExpectedRef<InputStream> ConfiguredNetworkGroupWrapper::get_input_stream_by_name(const std::string& name)
+{
+    return m_configured_network_group->get_input_stream_by_name(name);
+}
+ExpectedRef<OutputStream> ConfiguredNetworkGroupWrapper::get_output_stream_by_name(const std::string& name)
+{
+    return m_configured_network_group->get_output_stream_by_name(name);
+}
+
+Expected<InputStreamRefVector> ConfiguredNetworkGroupWrapper::get_input_streams_by_network(const std::string &network_name)
+{
+    return m_configured_network_group->get_input_streams_by_network(network_name);
+}
+
+Expected<OutputStreamRefVector> ConfiguredNetworkGroupWrapper::get_output_streams_by_network(const std::string &network_name)
+{
+    return m_configured_network_group->get_output_streams_by_network(network_name);
+}
+
+InputStreamRefVector ConfiguredNetworkGroupWrapper::get_input_streams()
+{
+    return m_configured_network_group->get_input_streams();
+}
+
+OutputStreamRefVector ConfiguredNetworkGroupWrapper::get_output_streams()
+{
+    return m_configured_network_group->get_output_streams();
+}
+
+Expected<LatencyMeasurementResult> ConfiguredNetworkGroupWrapper::get_latency_measurement(const std::string &network_name)
+{
+    return m_configured_network_group->get_latency_measurement(network_name);
+}
+
+Expected<OutputStreamWithParamsVector> ConfiguredNetworkGroupWrapper::get_output_streams_from_vstream_names(
+    const std::map<std::string, hailo_vstream_params_t> &outputs_params)
+{
+    return m_configured_network_group->get_output_streams_from_vstream_names(outputs_params);
+}
+
+Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroupWrapper::activate_internal(const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size)
+{
+    return m_configured_network_group->activate_internal(network_group_params, dynamic_batch_size);
+}
+
+hailo_status ConfiguredNetworkGroupWrapper::wait_for_activation(const std::chrono::milliseconds &timeout)
+{
+    return m_configured_network_group->wait_for_activation(timeout);
+}
+
+Expected<std::map<std::string, hailo_vstream_params_t>> ConfiguredNetworkGroupWrapper::make_input_vstream_params(
+    bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
+    const std::string &network_name)
+{
+    return m_configured_network_group->make_input_vstream_params(quantized, format_type, timeout_ms, queue_size, network_name);
+}
+Expected<std::map<std::string, hailo_vstream_params_t>> ConfiguredNetworkGroupWrapper::make_output_vstream_params(
+    bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
+    const std::string &network_name)
+{
+    return m_configured_network_group->make_output_vstream_params(quantized, format_type, timeout_ms, queue_size, network_name);
+}
+
+Expected<std::vector<std::map<std::string, hailo_vstream_params_t>>> ConfiguredNetworkGroupWrapper::make_output_vstream_params_groups(
+    bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size)
+{
+    return m_configured_network_group->make_output_vstream_params_groups(quantized, format_type, timeout_ms, queue_size);
+}
+
+Expected<std::vector<std::vector<std::string>>> ConfiguredNetworkGroupWrapper::get_output_vstream_groups()
+{
+    return m_configured_network_group->get_output_vstream_groups();
+}
+
+Expected<std::vector<hailo_network_info_t>> ConfiguredNetworkGroupWrapper::get_network_infos() const
+{
+    return m_configured_network_group->get_network_infos();
+}
+
+Expected<std::vector<hailo_stream_info_t>> ConfiguredNetworkGroupWrapper::get_all_stream_infos(const std::string &network_name) const
+{
+    return m_configured_network_group->get_all_stream_infos(network_name);
+}
+
+Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupWrapper::get_input_vstream_infos(const std::string &network_name) const
+{
+    return m_configured_network_group->get_input_vstream_infos(network_name);
+}
+
+Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupWrapper::get_output_vstream_infos(const std::string &network_name) const
+{
+    return m_configured_network_group->get_output_vstream_infos(network_name);
+}
+
+Expected<std::vector<hailo_vstream_info_t>> ConfiguredNetworkGroupWrapper::get_all_vstream_infos(const std::string &network_name) const
+{
+    return m_configured_network_group->get_all_vstream_infos(network_name);
+}
+
+hailo_status ConfiguredNetworkGroupWrapper::set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name)
+{
+    return m_configured_network_group->set_scheduler_timeout(timeout, network_name);
+}
+hailo_status ConfiguredNetworkGroupWrapper::set_scheduler_threshold(uint32_t threshold, const std::string &network_name)
+{
+    return m_configured_network_group->set_scheduler_threshold(threshold, network_name);
+}
+
+AccumulatorPtr ConfiguredNetworkGroupWrapper::get_activation_time_accumulator() const
+{
+    return m_configured_network_group->get_activation_time_accumulator();
+}
+
+AccumulatorPtr ConfiguredNetworkGroupWrapper::get_deactivation_time_accumulator() const
+{
+    return m_configured_network_group->get_deactivation_time_accumulator();
+}
+
+std::shared_ptr<ConfiguredNetworkGroupBase> ConfiguredNetworkGroupWrapper::get_configured_network() const
+{
+    return m_configured_network_group;
+}
+
+ConfiguredNetworkGroupWrapper::ConfiguredNetworkGroupWrapper(std::shared_ptr<ConfiguredNetworkGroupBase> configured_network_group) :
+    m_configured_network_group(configured_network_group)
+{}
+
+Expected<ConfiguredNetworkGroupWrapper> ConfiguredNetworkGroupWrapper::create(std::shared_ptr<ConfiguredNetworkGroupBase> configured_network_group)
+{
+    return ConfiguredNetworkGroupWrapper(configured_network_group);
+}
+
+Expected<ConfiguredNetworkGroupWrapper> ConfiguredNetworkGroupWrapper::clone()
+{
+    auto wrapper = create(m_configured_network_group);
+    CHECK_EXPECTED(wrapper);
+
+    return wrapper;
+}
+
+Expected<std::unique_ptr<ActivatedNetworkGroup>> ConfiguredNetworkGroupWrapper::activate(const hailo_activate_network_group_params_t &network_group_params)
+{
+    return m_configured_network_group->activate(network_group_params);
+}
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/src/context_switch/network_group_wrapper.hpp b/hailort/libhailort/src/context_switch/network_group_wrapper.hpp
new file mode 100644 (file)
index 0000000..a23f6ac
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file network_group_wrapper.hpp
+ * @brief Class declaration for ConfiguredNetworkGroupWrapper, a wrapper around ConfiguredNetworkGroupBase which is used
+ *        to support multiple ConfiguredNetworkGroup objects that encapsulate the same actual configured network group.
+ **/
+
+#ifndef _HAILO_NETWORK_GROUP_WRAPPER_HPP_
+#define _HAILO_NETWORK_GROUP_WRAPPER_HPP_
+
+#include "hailo/hailort.h"
+#include "hailo/network_group.hpp"
+#include "network_group_internal.hpp"
+
+namespace hailort
+{
+
+class ConfiguredNetworkGroupWrapper : public ConfiguredNetworkGroup
+{
+public:
+    virtual ~ConfiguredNetworkGroupWrapper() = default;
+    ConfiguredNetworkGroupWrapper(const ConfiguredNetworkGroupWrapper &other) = delete;
+    ConfiguredNetworkGroupWrapper &operator=(const ConfiguredNetworkGroupWrapper &other) = delete;
+    ConfiguredNetworkGroupWrapper &operator=(ConfiguredNetworkGroupWrapper &&other) = delete;
+    ConfiguredNetworkGroupWrapper(ConfiguredNetworkGroupWrapper &&other) = default;
+
+    static Expected<ConfiguredNetworkGroupWrapper> create(std::shared_ptr<ConfiguredNetworkGroupBase> configured_network_group);
+    Expected<ConfiguredNetworkGroupWrapper> clone();
+
+    virtual const std::string &get_network_group_name() const override;
+    virtual Expected<hailo_stream_interface_t> get_default_streams_interface() override;
+
+    virtual std::vector<std::reference_wrapper<InputStream>> get_input_streams_by_interface(hailo_stream_interface_t stream_interface) override;
+    virtual std::vector<std::reference_wrapper<OutputStream>> get_output_streams_by_interface(hailo_stream_interface_t stream_interface) override;
+    virtual ExpectedRef<InputStream> get_input_stream_by_name(const std::string& name) override;
+    virtual ExpectedRef<OutputStream> get_output_stream_by_name(const std::string& name) override;
+    virtual Expected<InputStreamRefVector> get_input_streams_by_network(const std::string &network_name="") override;
+    virtual Expected<OutputStreamRefVector> get_output_streams_by_network(const std::string &network_name="") override;
+    virtual InputStreamRefVector get_input_streams() override;
+    virtual OutputStreamRefVector get_output_streams() override;
+    virtual Expected<LatencyMeasurementResult> get_latency_measurement(const std::string &network_name="") override;
+    virtual Expected<OutputStreamWithParamsVector> get_output_streams_from_vstream_names(
+        const std::map<std::string, hailo_vstream_params_t> &outputs_params) override;
+
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(const hailo_activate_network_group_params_t &network_group_params) override;
+    virtual hailo_status wait_for_activation(const std::chrono::milliseconds &timeout) override;
+
+    virtual Expected<std::map<std::string, hailo_vstream_params_t>> make_input_vstream_params(
+        bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
+        const std::string &network_name="") override;
+    virtual Expected<std::map<std::string, hailo_vstream_params_t>> make_output_vstream_params(
+        bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size,
+        const std::string &network_name="") override;
+    virtual Expected<std::vector<std::map<std::string, hailo_vstream_params_t>>> make_output_vstream_params_groups(
+        bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size) override;
+    virtual Expected<std::vector<std::vector<std::string>>> get_output_vstream_groups() override;
+
+    virtual Expected<std::vector<hailo_network_info_t>> get_network_infos() const override;
+    virtual Expected<std::vector<hailo_stream_info_t>> get_all_stream_infos(const std::string &network_name="") const override;
+    virtual Expected<std::vector<hailo_vstream_info_t>> get_input_vstream_infos(const std::string &network_name="") const override;
+    virtual Expected<std::vector<hailo_vstream_info_t>> get_output_vstream_infos(const std::string &network_name="") const override;
+    virtual Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(const std::string &network_name="") const override;
+
+    virtual hailo_status set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name) override;
+    virtual hailo_status set_scheduler_threshold(uint32_t threshold, const std::string &network_name) override;
+
+    virtual AccumulatorPtr get_activation_time_accumulator() const override;
+    virtual AccumulatorPtr get_deactivation_time_accumulator() const override;
+
+    std::shared_ptr<ConfiguredNetworkGroupBase> get_configured_network() const;
+
+protected:
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_internal(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) override;
+
+private:
+    ConfiguredNetworkGroupWrapper(std::shared_ptr<ConfiguredNetworkGroupBase> configured_network_group);
+
+    std::shared_ptr<ConfiguredNetworkGroupBase> m_configured_network_group;
+};
+
+}
+
+#endif /* _HAILO_NETWORK_GROUP_WRAPPER_HPP_ */
\ No newline at end of file
diff --git a/hailort/libhailort/src/context_switch/pipeline_multiplexer.cpp b/hailort/libhailort/src/context_switch/pipeline_multiplexer.cpp
new file mode 100644 (file)
index 0000000..c39d88c
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file pipeline_multiplexer.cpp
+ * @brief: Pipeline Multiplexer
+ **/
+
+#include "pipeline_multiplexer.hpp"
+#include "common/utils.hpp"
+
+namespace hailort
+{
+
+PipelineMultiplexer::PipelineMultiplexer() :
+    m_is_enabled(false),
+    m_mutex(),
+    m_readers(),
+    m_write_mutex()
+{}
+
+hailo_status PipelineMultiplexer::add_reader(EventPtr &reader_event)
+{
+    std::unique_lock<std::mutex> lock(m_mutex);
+
+    auto was_empty = m_readers.empty();
+    m_readers.push(reader_event);
+    if (was_empty) {
+        auto status = reader_event->signal();
+        CHECK_SUCCESS(status);
+    }
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status PipelineMultiplexer::signal_done_reading()
+{
+    std::unique_lock<std::mutex> lock(m_mutex);
+
+    if (m_readers.empty()) {
+        return HAILO_INTERNAL_FAILURE;
+    }
+    m_readers.front()->reset();
+    m_readers.pop();
+
+    if (!m_readers.empty()) {
+        m_readers.front()->signal();
+    }
+
+    return HAILO_SUCCESS;
+}
+
+void PipelineMultiplexer::enable()
+{
+    m_is_enabled = true;
+}
+
+bool PipelineMultiplexer::is_enabled() const
+{
+    return m_is_enabled;
+}
+
+void PipelineMultiplexer::acquire_write_lock()
+{
+    m_write_mutex.lock();
+}
+
+void PipelineMultiplexer::release_write_lock()
+{
+    m_write_mutex.unlock();
+}
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/src/context_switch/pipeline_multiplexer.hpp b/hailort/libhailort/src/context_switch/pipeline_multiplexer.hpp
new file mode 100644 (file)
index 0000000..74a5fb8
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file pipeline_multiplexer.hpp
+ * @brief The pipeline multiplexer is a synchronization mechanism that allows communication
+ *        between different pipelines that use the same low-level streams.
+ **/
+
+#ifndef _HAILO_PIPELINE_MULTIPLEXER_HPP_
+#define _HAILO_PIPELINE_MULTIPLEXER_HPP_
+
+#include "hailo/event.hpp"
+
+#include <queue>
+#include <mutex>
+
+namespace hailort
+{
+
+class PipelineMultiplexer
+{
+public:
+    virtual ~PipelineMultiplexer() = default;
+    PipelineMultiplexer(const PipelineMultiplexer &other) = delete;
+    PipelineMultiplexer &operator=(const PipelineMultiplexer &other) = delete;
+    PipelineMultiplexer &operator=(PipelineMultiplexer &&other) = delete;
+    PipelineMultiplexer(PipelineMultiplexer &&other) = delete;
+
+    PipelineMultiplexer();
+
+    hailo_status add_reader(EventPtr &reader_event);
+    hailo_status signal_done_reading();
+
+    void enable();
+    bool is_enabled() const;
+
+    void acquire_write_lock();
+    void release_write_lock();
+
+private:
+    bool m_is_enabled;
+    std::mutex m_mutex;
+    std::queue<EventPtr> m_readers;
+
+    std::mutex m_write_mutex;
+};
+
+} /* namespace hailort */
+
+#endif /* _HAILO_PIPELINE_MULTIPLEXER_HPP_ */
index 35b6c1853b4d1def80948c4db786ffe13f92c44e..141be48216a057b7a566af7d45ffb621c61e6c82 100644 (file)
 namespace hailort
 {
 
-
-ConfigResources::ConfigResources(HailoRTDriver &driver, VdmaBuffer &&buffer,
-    VdmaDescriptorList &&descriptor, uint16_t requested_desc_page_size, size_t total_buffer_size)
-    : m_buffer(std::move(buffer)), m_descriptor(std::move(descriptor)),
-      m_desc_page_size(driver.calc_desc_page_size(requested_desc_page_size)), 
-      m_total_buffer_size(total_buffer_size), m_acc_buffer_offset(0), m_acc_desc_count(0),
-      m_current_buffer_size(0)
-{}
-
-Expected<uint16_t> ConfigResources::program_descriptors()
-{
-    auto descriptors_count =
-        m_descriptor.program_descriptors(m_acc_buffer_offset,  VdmaInterruptsDomain::NONE, VdmaInterruptsDomain::DEVICE,
-        m_acc_desc_count, false);
-    CHECK_EXPECTED(descriptors_count);
-
-    /* TODO - remove static cast */
-    m_acc_desc_count = static_cast<uint16_t>(m_acc_desc_count + descriptors_count.value());
-    m_acc_buffer_offset = 0;
-
-    return descriptors_count;
-}
-
-hailo_status ConfigResources::write(const void *data, size_t data_size)
-{
-    size_t total_offset = (m_acc_desc_count * m_desc_page_size) + m_acc_buffer_offset;
-    auto status = m_buffer.write(data, data_size, total_offset);
-    CHECK_SUCCESS(status);
-
-    m_acc_buffer_offset += data_size;
-    m_current_buffer_size += data_size;
-    return HAILO_SUCCESS;
-}
-
-uint16_t ConfigResources::get_page_size()
-{
-    return m_desc_page_size;
-}
-
-size_t ConfigResources::get_total_cfg_size()
-{
-    return m_total_buffer_size;
-}
-
-size_t ConfigResources::get_current_buffer_size()
-{
-    return m_current_buffer_size;
-}
-
-Expected<ConfigResources> ResourcesManager::create_config_resources(uint8_t channel_index,
-    const std::vector<uint32_t> &cfg_sizes, HailoRTDriver &driver)
-{
-    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_multiple_transfers(driver, 1, cfg_sizes);
-    CHECK_EXPECTED(desc_sizes_pair);
-
-    auto page_size = desc_sizes_pair->first;
-    auto descs_count = desc_sizes_pair->second;
-
-    auto buffer_size = std::accumulate(cfg_sizes.begin(), cfg_sizes.end(), 0);
-
-    auto buffer = VdmaBuffer::create((page_size * descs_count), HailoRTDriver::DmaDirection::H2D, driver);
-    CHECK_EXPECTED(buffer);
-
-    auto desc_list = VdmaDescriptorList::create(descs_count, page_size, driver);
-    CHECK_EXPECTED(desc_list);
-
-    auto status = desc_list->configure_to_use_buffer(buffer.value(), channel_index);
-    CHECK_SUCCESS_AS_EXPECTED(status);
-
-    return ConfigResources(driver, buffer.release(), desc_list.release(), page_size, buffer_size);
-}
-
 static Expected<std::vector<std::string>> build_network_index_map(ProtoHEFNetworkGroupPtr network_group_proto,
     const NetworkGroupSupportedFeatures &supported_features)
 {
-    std::vector<std::string> partial_network_name_vector;
+    std::vector<std::string> network_names_vector;
     if (supported_features.multi_network_support) {
         auto network_count = network_group_proto.get()->networks_names_size();
         CHECK_AS_EXPECTED((network_count > 0), HAILO_INTERNAL_FAILURE, 
             "Hef support multiple networks, but no networks found in the proto");
-        partial_network_name_vector.reserve(network_count);
+        network_names_vector.reserve(network_count);
         for (uint8_t network_index = 0; network_index < network_count; network_index++) {
             auto partial_network_name = network_group_proto.get()->networks_names(network_index);
-            partial_network_name_vector.push_back(partial_network_name);
+            auto network_name = HefUtils::get_network_name(*network_group_proto, partial_network_name);
+            network_names_vector.push_back(network_name);
         }
     } else {
         /* In case there is no defines networks, add single network with the same name as the network group */
-        partial_network_name_vector.reserve(1);
+        network_names_vector.reserve(1);
         auto net_group_name = network_group_proto->network_group_metadata().network_group_name();
-        auto partial_network_name = HailoRTDefaults::get_partial_network_name();
-        partial_network_name_vector.push_back(partial_network_name);
+        network_names_vector.push_back(HailoRTDefaults::get_network_name(net_group_name));
     }
 
-    return partial_network_name_vector;
+    return network_names_vector;
+}
+
+static Expected<LatencyMeterPtr> create_hw_latency_meter(const std::vector<LayerInfo> &layers)
+{
+    std::set<uint32_t> d2h_channel_indexes;
+
+    size_t h2d_streams_count = 0;
+    for (const auto &layer : layers) {
+        if (layer.direction == HAILO_D2H_STREAM) {
+            if (HAILO_FORMAT_ORDER_HAILO_NMS == layer.format.order) {
+                LOGGER__WARNING("HW Latency measurement is not supported on NMS networks");
+                return make_unexpected(HAILO_INVALID_OPERATION);
+            }
+
+            d2h_channel_indexes.insert(layer.index);
+        }
+        else {
+            h2d_streams_count++;
+        }
+    }
+
+    if (h2d_streams_count > 1) {
+        LOGGER__WARNING("HW Latency measurement is supported on networks with a single input");
+        return make_unexpected(HAILO_INVALID_OPERATION);
+    }
+
+    return make_shared_nothrow<LatencyMeter>(d2h_channel_indexes, MAX_IRQ_TIMESTAMPS_SIZE);
+}
+
+static Expected<LatencyMetersMap> create_latency_meters_from_config_params( 
+    const ConfigureNetworkParams &config_params, std::shared_ptr<NetworkGroupMetadata> network_group_metadata)
+{
+    LatencyMetersMap latency_meters_map; 
+
+    if ((config_params.latency & HAILO_LATENCY_MEASURE) == HAILO_LATENCY_MEASURE) {
+        // Best affort for starting latency meter.
+        auto networks_names = network_group_metadata->get_network_names();
+        for (auto &network_name : networks_names) {
+            auto layer_infos = network_group_metadata->get_all_layer_infos(network_name);
+            CHECK_EXPECTED(layer_infos);
+            auto latency_meter = create_hw_latency_meter(layer_infos.value());
+            if (latency_meter) {
+                latency_meters_map.emplace(network_name, latency_meter.release());
+                LOGGER__DEBUG("Starting hw latency measurement for network {}", network_name);
+            }
+        }
+    }
+
+    return latency_meters_map;
 }
 
 Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, HailoRTDriver &driver,
@@ -115,7 +92,7 @@ Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, Hai
     uint8_t cfg_channels_count = (0 == network_group_proto->network_group_metadata().cfg_channels_count()) ?
         1u : static_cast<uint8_t>(network_group_proto->network_group_metadata().cfg_channels_count());
 
-    std::vector<ConfigResources> preliminary_configs_vector;
+    std::vector<ConfigBuffer> preliminary_configs_vector;
     auto cfg_count_preliminary = parsing_info.cfg_infos_preliminary_config.size();
     CHECK_AS_EXPECTED(cfg_channels_count >= cfg_count_preliminary, HAILO_INTERNAL_FAILURE,
         "preliminary cfg count ({}) is bigger than the size passed to the network_group ({})",
@@ -124,18 +101,18 @@ Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, Hai
     for (uint8_t cfg_index = MIN_H2D_CHANNEL_INDEX; cfg_index < cfg_count_preliminary; cfg_index++) {
         CHECK_AS_EXPECTED(contains(parsing_info.cfg_infos_preliminary_config, cfg_index), HAILO_INTERNAL_FAILURE,
             "Mismmatch for cfg index {}", cfg_index);
-        auto buffer_resource = ResourcesManager::create_config_resources(cfg_index,
-            parsing_info.cfg_infos_preliminary_config.at(cfg_index), driver);
+        auto buffer_resource = ConfigBuffer::create(driver, cfg_index,
+            parsing_info.cfg_infos_preliminary_config.at(cfg_index));
         CHECK_EXPECTED(buffer_resource);
 
         preliminary_configs_vector.emplace_back(buffer_resource.release());
     }
 
-    std::vector<std::vector<ConfigResources>> dynamic_cfg_vectors;
+    std::vector<std::vector<ConfigBuffer>> dynamic_cfg_vectors;
     dynamic_cfg_vectors.reserve(network_group_proto->contexts_size());
 
     for (int ctxt_index = 0; ctxt_index < network_group_proto->contexts_size(); ctxt_index++) {
-        std::vector<ConfigResources> dynamic_cfg_vector_per_context;
+        std::vector<ConfigBuffer> dynamic_cfg_vector_per_context;
         auto cfg_count_ctxt = parsing_info.cfg_infos_per_context[ctxt_index].size();
 
         CHECK_AS_EXPECTED(cfg_channels_count >= cfg_count_ctxt, HAILO_INTERNAL_FAILURE,
@@ -146,8 +123,8 @@ Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, Hai
         for (uint8_t cfg_index = MIN_H2D_CHANNEL_INDEX; cfg_index < cfg_count_ctxt; cfg_index++) {
             CHECK_AS_EXPECTED(contains(parsing_info.cfg_infos_per_context[ctxt_index], cfg_index),
                 HAILO_INTERNAL_FAILURE, "Mismmatch for cfg index {}", cfg_index);
-            auto buffer_resource = ResourcesManager::create_config_resources(cfg_index,
-                parsing_info.cfg_infos_per_context[ctxt_index].at(cfg_index), driver);
+            auto buffer_resource = ConfigBuffer::create(driver, cfg_index,
+                parsing_info.cfg_infos_per_context[ctxt_index].at(cfg_index));
             CHECK_EXPECTED(buffer_resource);
 
             dynamic_cfg_vector_per_context.emplace_back(buffer_resource.release());
@@ -157,9 +134,12 @@ Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, Hai
 
     auto network_index_map = build_network_index_map(network_group_proto, network_group_metadata->supported_features());
     CHECK_EXPECTED(network_index_map);
+
+    auto latency_meters = create_latency_meters_from_config_params(config_params, network_group_metadata);
+    CHECK_EXPECTED(latency_meters);
     ResourcesManager resources_manager(vdma_device, driver, config_params,
         std::move(preliminary_configs_vector), std::move(dynamic_cfg_vectors), std::move(network_group_metadata), net_group_index,
-        std::move(network_index_map.release()));
+        std::move(network_index_map.release()), latency_meters.release());
 
     auto status = resources_manager.set_number_of_cfg_channels(cfg_channels_count);
     CHECK_SUCCESS_AS_EXPECTED(status);
@@ -167,22 +147,27 @@ Expected<ResourcesManager> ResourcesManager::create(VdmaDevice &vdma_device, Hai
     return resources_manager;
 }
 
-hailo_status ResourcesManager::fill_network_batch_size(CONTROL_PROTOCOL__application_header_t &app_header)
+hailo_status ResourcesManager::fill_infer_features(CONTROL_PROTOCOL__application_header_t &app_header)
+{
+    app_header.infer_features.preliminary_run_asap = m_network_group_metadata->supported_features().preliminary_run_asap;
+    return HAILO_SUCCESS;
+}
+
+hailo_status ResourcesManager::fill_network_batch_size(CONTROL_PROTOCOL__application_header_t &app_header, bool is_scheduler_used)
 {
     app_header.networks_count = static_cast<uint8_t>(m_config_params.network_params_by_name.size());
     for (const auto &network_pair : m_config_params.network_params_by_name) {
-        auto network_name = network_pair.first;
+        auto network_name_from_params = network_pair.first;
         uint8_t network_index = 0;
         for (network_index = 0; network_index < m_network_index_map.size(); network_index++) {
-            auto const partial_network_name = m_network_index_map[network_index];
-            auto found = network_name.find(HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name);
-            if (found != std::string::npos) {
-                app_header.batch_size[network_index] = network_pair.second.batch_size;
+            auto const network_name_from_map = m_network_index_map[network_index];
+            if (network_name_from_map == network_name_from_params) {
+                app_header.batch_size[network_index] = (is_scheduler_used) ? HAILO_DEFAULT_BATCH_SIZE : network_pair.second.batch_size;
                 break;
             }
         }
         if (m_network_index_map.size() == network_index) {
-            LOGGER__ERROR("Failed to find network with network name {}", network_name);
+            LOGGER__ERROR("Failed to find network with network name {}", network_name_from_params);
             return HAILO_NOT_FOUND;
         }
     }
@@ -190,7 +175,7 @@ hailo_status ResourcesManager::fill_network_batch_size(CONTROL_PROTOCOL__applica
     return HAILO_SUCCESS;
 }
 
-hailo_status ResourcesManager::create_vdma_channels()
+hailo_status ResourcesManager::create_internal_vdma_channels()
 {
     std::vector<uint8_t> intermediate_channels_idx;
     std::vector<uint8_t> cfg_channels_idx;
@@ -234,15 +219,67 @@ hailo_status ResourcesManager::create_vdma_channels()
     return HAILO_SUCCESS;
 }
 
+Expected<std::shared_ptr<VdmaChannel>> ResourcesManager::create_boundary_vdma_channel(
+    uint8_t channel_index, uint32_t transfer_size, const std::string &network_name, const std::string &stream_name,
+    VdmaChannel::Direction channel_direction)
+{
+    auto network_batch_size = get_network_batch_size(network_name);
+    CHECK_EXPECTED(network_batch_size);
+    uint32_t min_active_trans = MIN_ACTIVE_TRANSFERS_SCALE * network_batch_size.value();
+    uint32_t max_active_trans = MAX_ACTIVE_TRANSFERS_SCALE * network_batch_size.value();
+
+    CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(min_active_trans), HAILO_INVALID_ARGUMENT, 
+        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
+    CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(max_active_trans), HAILO_INVALID_ARGUMENT, 
+        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
+    auto edge_layer = m_network_group_metadata->get_layer_info_by_stream_name(stream_name);
+    CHECK_EXPECTED(edge_layer);
+    auto latency_meter = (contains(m_latency_meters, edge_layer->network_name)) ? m_latency_meters.at(edge_layer->network_name) : nullptr;
+    auto stream_index = edge_layer.value().index;
+
+    /* TODO - HRT-6829- page_size should be calculated inside the vDMA channel class create function */
+    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(m_driver,
+        static_cast<uint16_t>(min_active_trans), static_cast<uint16_t>(max_active_trans), transfer_size);
+    CHECK_EXPECTED(desc_sizes_pair);
+
+    const auto page_size = desc_sizes_pair->first;
+    const auto descs_count = desc_sizes_pair->second;
+    auto channel = VdmaChannel::create(channel_index, channel_direction, m_driver, page_size,
+        stream_index, latency_meter, network_batch_size.value());
+    CHECK_EXPECTED(channel);
+    const auto status = channel->allocate_resources(descs_count);
+    CHECK_SUCCESS_AS_EXPECTED(status);
+
+    auto channel_ptr = make_shared_nothrow<VdmaChannel>(channel.release());
+    CHECK_NOT_NULL_AS_EXPECTED(channel_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    m_boundary_channels.emplace(stream_name, channel_ptr);
+
+    return channel_ptr;
+}
+
+Expected<std::shared_ptr<VdmaChannel>> ResourcesManager::get_boundary_vdma_channel_by_stream_name(const std::string &stream_name)
+{
+    auto boundary_channel_it = m_boundary_channels.find(stream_name);
+    if (std::end(m_boundary_channels) == boundary_channel_it) {
+        return make_unexpected(HAILO_NOT_FOUND);
+    }
+
+    return std::shared_ptr<VdmaChannel>(m_boundary_channels[stream_name]);
+}
+
 ExpectedRef<IntermediateBuffer> ResourcesManager::create_inter_context_buffer(uint32_t transfer_size,
-    uint8_t src_stream_index, uint8_t src_context_index, const std::string &partial_network_name)
+    uint8_t src_stream_index, uint8_t src_context_index, const std::string &network_name)
 {
-    auto network_batch_size_exp = get_network_batch_size_from_partial_name(partial_network_name);
+    auto network_batch_size_exp = get_network_batch_size(network_name);
     CHECK_EXPECTED(network_batch_size_exp);
     auto network_batch_size = network_batch_size_exp.value();
 
     const auto intermediate_buffer_key = std::make_pair(src_context_index, src_stream_index);
-    auto intermediate_buffer = create_intermediate_buffer(transfer_size, network_batch_size, intermediate_buffer_key);
+    auto intermediate_buffer = create_intermediate_buffer(IntermediateBuffer::ChannelType::INTER_CONTEXT, transfer_size,
+        network_batch_size, intermediate_buffer_key);
     CHECK_EXPECTED(intermediate_buffer);
     auto intermediate_buffer_ref = intermediate_buffer.release();
 
@@ -259,51 +296,25 @@ ExpectedRef<IntermediateBuffer> ResourcesManager::get_intermediate_buffer(const
         return make_unexpected(HAILO_NOT_FOUND);
     }
 
-    return std::ref(*intermediate_buffer_it->second);
-}
-
-Expected<std::pair<uint16_t, uint32_t>> ResourcesManager::get_desc_buffer_sizes_for_boundary_channel(
-    uint32_t transfer_size, const std::string &partial_network_name)
-{
-    auto network_batch_size = get_network_batch_size_from_partial_name(partial_network_name);
-    CHECK_EXPECTED(network_batch_size);
-    uint32_t min_active_trans = MIN_ACTIVE_TRANSFERS_SCALE * network_batch_size.value();
-    uint32_t max_active_trans = MAX_ACTIVE_TRANSFERS_SCALE * network_batch_size.value();
-
-    CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(min_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
-
-    CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(max_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
-
-    return VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(m_driver,
-        static_cast<uint16_t>(min_active_trans), static_cast<uint16_t>(max_active_trans), transfer_size);
+    return std::ref(intermediate_buffer_it->second);
 }
 
-Expected<CONTROL_PROTOCOL__application_header_t> ResourcesManager::get_control_network_group_header()
+Expected<CONTROL_PROTOCOL__application_header_t> ResourcesManager::get_control_network_group_header(bool is_scheduler_used)
 {
     CONTROL_PROTOCOL__application_header_t  app_header = {};
     app_header.dynamic_contexts_count = static_cast<uint8_t>(m_contexts.size() - 1);
     app_header.host_boundary_channels_bitmap = 0;
-    app_header.host_ddr_channels_bitmap = 0;
 
     /* Bitmask of all boundary and DDR channels*/
     int host_boundary_channels_bitmap_local = 0;
-    int host_ddr_channels_bitmap_local = 0;
     for (size_t i = MIN_H2D_CHANNEL_INDEX; i <= MAX_D2H_CHANNEL_INDEX; i++) {
         /* Set boundary channels */
         if (m_channels_info[i].is_type(ChannelInfo::Type::BOUNDARY) && m_channels_info[i].is_used()) {
             host_boundary_channels_bitmap_local |= 1 << i;
         }
-        /* DDR buffer channels are host controlled only if the HEF does not support padded ddr buffers */
-        else if ((m_channels_info[i].is_type(ChannelInfo::Type::DDR) && (!get_supported_features().padded_ddr_buffers)) &&
-            (m_channels_info[i].is_used())) {
-            host_ddr_channels_bitmap_local |= 1 << i;
-        }
     }
 
     app_header.host_boundary_channels_bitmap = static_cast<uint32_t>(host_boundary_channels_bitmap_local);
-    app_header.host_ddr_channels_bitmap = static_cast<uint32_t>(host_ddr_channels_bitmap_local);
 
     uint8_t cfg_handle_idx = 0;
     for (uint8_t ch_idx = MIN_H2D_CHANNEL_INDEX; ch_idx <= MAX_H2D_CHANNEL_INDEX; ch_idx++) {
@@ -314,9 +325,9 @@ Expected<CONTROL_PROTOCOL__application_header_t> ResourcesManager::get_control_n
             cfg_handle_idx++;
         }
     }
-    app_header.cfg_channels_count = cfg_handle_idx;
     app_header.power_mode = static_cast<uint8_t>(m_config_params.power_mode);
-    fill_network_batch_size(app_header);
+    CHECK_SUCCESS_AS_EXPECTED(fill_infer_features(app_header), "Invalid infer features");
+    CHECK_SUCCESS_AS_EXPECTED(fill_network_batch_size(app_header, is_scheduler_used), "Invalid network batch sizes");
     return app_header;
 }
 
@@ -334,6 +345,18 @@ Expected<uint8_t> ResourcesManager::get_available_channel_index(std::set<uint8_t
             continue;
         }
 
+        // In preliminary_run_asap, channels are reused across contexts (same channels in the preliminary
+        // context and first dynamic context).
+        if (get_supported_features().preliminary_run_asap) {
+            if (m_channels_info[index].is_used() &&
+               (m_channels_info[index].get_layer_name() == layer_name) &&
+               (m_channels_info[index].is_type(required_type))) {
+                LOGGER__TRACE("Reusing channel {} for layer {} (running in preliminary_run_asap mode)",
+                    index, layer_name);
+                return index;
+            }
+        }
+
         // Use the empty channel if available
         if (!m_channels_info[index].is_used()) {
             m_channels_info[index].set_type(required_type);
@@ -341,21 +364,11 @@ Expected<uint8_t> ResourcesManager::get_available_channel_index(std::set<uint8_t
             return index;
         }
 
-        // If DDR is managed by the FW - allow reuse of channels for DDR / inter_context
-        if (get_supported_features().padded_ddr_buffers) {
-            if (((ChannelInfo::Type::BOUNDARY != required_type) && (ChannelInfo::Type::CFG != required_type)) &&
-                ((m_channels_info[index].is_type(ChannelInfo::Type::DDR)) || (m_channels_info[index].is_type(ChannelInfo::Type::INTER_CONTEXT)))) {
-                m_channels_info[index].set_type(required_type);
-                m_channels_info[index].set_layer_name(layer_name);
-                return index;
-            }
-        } else {
-            // If not - allow reuse of channels for within the same type
-            if (m_channels_info[index].is_type(required_type)) {
-                m_channels_info[index].set_type(required_type);
-                m_channels_info[index].set_layer_name(layer_name);
-                return index;
-            }
+        if (((ChannelInfo::Type::BOUNDARY != required_type) && (ChannelInfo::Type::CFG != required_type)) &&
+            ((m_channels_info[index].is_type(ChannelInfo::Type::DDR)) || (m_channels_info[index].is_type(ChannelInfo::Type::INTER_CONTEXT)))) {
+            m_channels_info[index].set_type(required_type);
+            m_channels_info[index].set_layer_name(layer_name);
+            return index;
         }
     }
 
@@ -385,13 +398,7 @@ Expected<uint8_t> ResourcesManager::get_boundary_channel_index(uint8_t stream_in
 void ResourcesManager::update_preliminary_config_buffer_info()
 {
     // Preliminary_config is the first 'context' m_contexts vector
-    assert(CONTROL_PROTOCOL__MAX_CFG_CHANNELS >= m_preliminary_config.size());
-    auto i = 0;
-    for (const auto &config : m_preliminary_config) {
-        m_contexts[0].context_cfg_base_address[i] = config.m_descriptor.dma_address();
-        m_contexts[0].context_total_descriptors[i] = config.m_acc_desc_count;
-        i++;
-    }
+    update_config_buffer_info(m_preliminary_config, m_contexts[0]);
 }
 
 void ResourcesManager::update_dynamic_contexts_buffer_info()
@@ -399,14 +406,8 @@ void ResourcesManager::update_dynamic_contexts_buffer_info()
     // Preliminary_config is the first 'context' m_contexts vector
     assert((m_dynamic_config.size() + 1) == m_contexts.size());
     int ctxt_index = 1;
-    for (const auto &cfg_context : m_dynamic_config) {
-        assert(CONTROL_PROTOCOL__MAX_CFG_CHANNELS >= cfg_context.size());
-        auto i = 0;
-        for (auto &cfg : cfg_context) {
-            m_contexts[ctxt_index].context_cfg_base_address[i] = cfg.m_descriptor.dma_address();
-            m_contexts[ctxt_index].context_total_descriptors[i] = cfg.m_acc_desc_count;
-            i++;
-        }
+    for (auto &cfg_context : m_dynamic_config) {
+        update_config_buffer_info(cfg_context, m_contexts[ctxt_index]);
         ctxt_index++;
     }
 }
@@ -420,7 +421,7 @@ ExpectedRef<IntermediateBuffer> ResourcesManager::create_ddr_buffer(DdrChannelsI
     const uint32_t transfer_size = ddr_info.row_size * DDR_NUMBER_OF_ROWS_PER_INTERRUPT;
 
     auto intermediate_buffer_key = std::make_pair(context_index, ddr_info.d2h_stream_index);
-    return create_intermediate_buffer(transfer_size, static_cast<uint16_t>(number_of_transfers),
+    return create_intermediate_buffer(IntermediateBuffer::ChannelType::DDR, transfer_size, static_cast<uint16_t>(number_of_transfers),
         intermediate_buffer_key);
 }
 
@@ -462,12 +463,9 @@ hailo_status ResourcesManager::register_fw_managed_vdma_channels()
         CHECK_SUCCESS(status);
     }
 
-    /* If ddr supported padded buffers - DDR buffers are managed by the FW */
-    if (get_supported_features().padded_ddr_buffers) {
-        for (auto &ch : m_ddr_buffer_channels) {
-            status = ch.register_fw_controlled_channel();
-            CHECK_SUCCESS(status);
-        }
+    for (auto &ch : m_ddr_buffer_channels) {
+        status = ch.register_fw_controlled_channel();
+        CHECK_SUCCESS(status);
     }
 
     return HAILO_SUCCESS;
@@ -488,28 +486,34 @@ hailo_status ResourcesManager::unregister_fw_managed_vdma_channels()
         CHECK_SUCCESS(status);
     }
 
-    /* If ddr supported padded buffers - DDR buffers are managed by the FW */
-    if (get_supported_features().padded_ddr_buffers) {
-        for (auto &ch : m_ddr_buffer_channels) {
-            status = ch.unregister_fw_controlled_channel();
-            CHECK_SUCCESS(status);
-        }
+    for (auto &ch : m_ddr_buffer_channels) {
+        status = ch.unregister_fw_controlled_channel();
+        CHECK_SUCCESS(status);
+    }
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status ResourcesManager::set_inter_context_channels_dynamic_batch_size(uint16_t dynamic_batch_size)
+{
+    for (auto &key_buff_pair : m_intermediate_buffers) {
+        const auto status = key_buff_pair.second.reprogram_inter_context(dynamic_batch_size);
+        CHECK_SUCCESS(status);
     }
 
     return HAILO_SUCCESS;
 }
 
-Expected<uint16_t> ResourcesManager::get_network_batch_size_from_partial_name(const std::string &partial_network_name) const
+Expected<uint16_t> ResourcesManager::get_network_batch_size(const std::string &network_name) const
 {
     for (auto const &network_map: m_config_params.network_params_by_name) {
-        auto const network_name = network_map.first;
-        auto found = network_name.find(HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name);
-        if (found != std::string::npos) {
+        auto const network_name_from_params = network_map.first;
+        if (network_name_from_params == network_name) {
             return Expected<uint16_t>(network_map.second.batch_size);
         }
     }
 
-    LOGGER__ERROR("Failed to find network with network name {}", partial_network_name);
+    LOGGER__ERROR("Failed to find network with network name {}", network_name);
 
     return make_unexpected(HAILO_NOT_FOUND);
 }
@@ -523,11 +527,11 @@ Expected<Buffer> ResourcesManager::read_intermediate_buffer(const IntermediateBu
         return make_unexpected(HAILO_NOT_FOUND);
     }
 
-    auto &intermediate_buffer = *intermediate_buffer_it->second;
+    auto &intermediate_buffer = intermediate_buffer_it->second;
     return intermediate_buffer.read();
 }
 
-hailo_status ResourcesManager::enable_state_machine()
+hailo_status ResourcesManager::enable_state_machine(uint16_t dynamic_batch_size)
 {
     if (Device::Type::CORE == m_vdma_device.get_type()) {
         // On core device, the nn_manager is not responsible to reset the nn-core so
@@ -536,7 +540,7 @@ hailo_status ResourcesManager::enable_state_machine()
         CHECK_SUCCESS(status);
     }
 
-    return Control::enable_network_group(m_vdma_device, m_net_group_index);
+    return Control::enable_network_group(m_vdma_device, m_net_group_index, dynamic_batch_size);
 }
 
 hailo_status ResourcesManager::reset_state_machine()
@@ -544,49 +548,35 @@ hailo_status ResourcesManager::reset_state_machine()
     return Control::reset_context_switch_state_machine(m_vdma_device);
 }
 
-hailo_status ResourcesManager::open_ddr_channels()
+ExpectedRef<IntermediateBuffer> ResourcesManager::create_intermediate_buffer(
+    IntermediateBuffer::ChannelType channel_type, uint32_t transfer_size, uint16_t batch_size,
+    const IntermediateBufferKey &key)
 {
-    for (auto& ddr_info : m_ddr_infos) {
-        for (auto &ch : m_ddr_buffer_channels) {
-            if (ddr_info.d2h_channel_index == ch.channel_index) {
-                auto status = ch.start_channel(*ddr_info.intermediate_buffer->get_desc_list());
-                CHECK_SUCCESS(status);
-                ddr_info.d2h_ch = &ch;
-            }
-            if (ddr_info.h2d_channel_index == ch.channel_index) {
-                auto status = ch.start_channel(*ddr_info.intermediate_buffer->get_desc_list());
-                CHECK_SUCCESS(status);
-                ddr_info.h2d_ch = &ch;
-            }
-        }
-    }
-    return HAILO_SUCCESS;
-}
+    auto intermediate_buffer = IntermediateBuffer::create(m_driver, channel_type, transfer_size, batch_size);
+    CHECK_EXPECTED(intermediate_buffer);
 
-void ResourcesManager::abort_ddr_channels() // Best effort func
-{
-    for (auto &ch : m_ddr_buffer_channels) {
-        auto status = ch.abort();
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed to abort DDR channel {}", ch.channel_index);
-        }
-    }
+    auto emplace_res = m_intermediate_buffers.emplace(key, intermediate_buffer.release());
+    return std::ref(emplace_res.first->second);
 }
 
-void ResourcesManager::close_ddr_channels() // Best effort func
+void ResourcesManager::update_config_buffer_info(std::vector<ConfigBuffer> &config_buffers,
+    CONTROL_PROTOCOL__context_switch_context_info_t &context)
 {
-    m_ddr_buffer_channels.clear();
-}
+    assert(CONTROL_PROTOCOL__MAX_CFG_CHANNELS >= config_buffers.size());
+    context.cfg_channels_count = static_cast<uint8_t>(config_buffers.size());
 
-ExpectedRef<IntermediateBuffer> ResourcesManager::create_intermediate_buffer(uint32_t transfer_size, uint16_t batch_size,
-    const IntermediateBufferKey &key)
-{
-    auto intermediate_buffer = IntermediateBuffer::create(IntermediateBuffer::Type::EXTERNAL_DESC, m_driver, transfer_size,
-        batch_size);
-    CHECK_EXPECTED(intermediate_buffer);
+    auto i = 0;
+    for (const auto &config : config_buffers) {
+        context.config_buffer_infos[i].buffer_type = static_cast<uint8_t>(
+            (config.buffer_type() == vdma::VdmaBuffer::Type::SCATTER_GATHER) ?
+                CONTROL_PROTOCOL__HOST_BUFFER_TYPE_EXTERNAL_DESC : CONTROL_PROTOCOL__HOST_BUFFER_TYPE_CCB);
+        context.config_buffer_infos[i].dma_address = config.dma_address();
+        context.config_buffer_infos[i].desc_page_size = config.desc_page_size();
+        context.config_buffer_infos[i].total_desc_count = config.total_desc_count();
+        context.config_buffer_infos[i].bytes_in_pattern = config.acc_desc_count() * config.desc_page_size();
 
-    auto emplace_res = m_intermediate_buffers.emplace(key, intermediate_buffer.release());
-    return std::ref(*emplace_res.first->second);
+        i++;
+    }
 }
 
 } /* namespace hailort */
index 05a90b0bf94a09b4f7f9fcbb74fbc3f796aa7114..a81871d25fdaaef135f3494af5c5a55db3844db3 100644 (file)
@@ -36,6 +36,7 @@ class HcpConfigActivatedNetworkGroup : public ActivatedNetworkGroupBase
 {
   public:
     static Expected<HcpConfigActivatedNetworkGroup> create(Device &device, std::vector<WriteMemoryInfo> &config,
+        const std::string &network_group_name,
         const hailo_activate_network_group_params_t &network_group_params,
         std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
         std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,        
@@ -49,7 +50,9 @@ class HcpConfigActivatedNetworkGroup : public ActivatedNetworkGroupBase
     HcpConfigActivatedNetworkGroup(HcpConfigActivatedNetworkGroup &&other) noexcept :
       ActivatedNetworkGroupBase(std::move(other)), m_active_net_group_holder(other.m_active_net_group_holder),
       m_is_active(std::exchange(other.m_is_active, false)), m_power_mode(other.m_power_mode),
-      m_device(other.m_device) {};
+      m_device(other.m_device), m_network_group_name(std::move(other.m_network_group_name)) {};
+
+    virtual const std::string &get_network_group_name() const override;
 
     virtual Expected<Buffer> get_intermediate_buffer(const IntermediateBufferKey &/*key*/) override
     {
@@ -60,6 +63,7 @@ class HcpConfigActivatedNetworkGroup : public ActivatedNetworkGroupBase
 
   private:
       HcpConfigActivatedNetworkGroup(Device &device, HcpConfigActiveAppHolder &active_net_group_holder,
+        const std::string &network_group_name,
         const hailo_activate_network_group_params_t &network_group_params,
         std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
         std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,        
@@ -69,6 +73,7 @@ class HcpConfigActivatedNetworkGroup : public ActivatedNetworkGroupBase
     bool m_is_active;
     hailo_power_mode_t m_power_mode;
     Device &m_device;
+    std::string m_network_group_name;
 };
 
 } /* namespace hailort */
index 5ccc4cbeadf612a1564d84d17593bd04b2969318..e463edb2abe70cb3fffd7a8277ef564532180c96 100644 (file)
@@ -13,6 +13,7 @@
 #define HAILO_HCP_CONFIG_MANAGER_HPP_
 
 #include "context_switch/config_manager.hpp"
+#include "context_switch/network_group_wrapper.hpp"
 #include "context_switch/single_context/hcp_config_network_group.hpp"
 #include "hailo/hailort.h"
 #include "hailo/device.hpp"
@@ -33,7 +34,7 @@ public:
     virtual ConfigManagerType get_manager_type();
 
     virtual Expected<ConfiguredNetworkGroupVector> add_hef(Hef &hef,
-        const NetworkGroupsParamsMap &configure_params={});
+        const NetworkGroupsParamsMap &configure_params, bool is_scheduler_used = false);
 
     HcpConfigManager(const HcpConfigManager &other) = delete;
     HcpConfigManager &operator=(const HcpConfigManager &other) = delete;
@@ -43,6 +44,7 @@ public:
 private:
     // TODO: (SDK-16665) Dont need is_active flag for dtor?
     std::vector<std::shared_ptr<HcpConfigNetworkGroup>> m_net_groups;
+    std::vector<std::shared_ptr<ConfiguredNetworkGroupWrapper>> m_net_group_wrappers;
     Device &m_device;
     HcpConfigActiveAppHolder m_active_net_group_holder;
 };
index 378d67e4a00481e3bc06a38588a1111eec440de8..c346381d9b65e95b490720f7d1ae32190c80a520 100644 (file)
@@ -35,12 +35,17 @@ public:
         const ConfigureNetworkParams &config_params, uint8_t net_group_index,
         NetworkGroupMetadata &&network_group_metadata, hailo_status &status);
 
-    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate(
-    const hailo_activate_network_group_params_t &network_group_params = HailoRTDefaults::get_network_group_params()) override;
+    virtual Expected<std::unique_ptr<ActivatedNetworkGroup>> activate_impl(
+        const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size) override;
     virtual Expected<hailo_stream_interface_t> get_default_streams_interface() override;
 
     virtual Expected<uint8_t> get_boundary_channel_index(uint8_t stream_index, hailo_stream_direction_t direction,
         const std::string &layer_name) override;
+    virtual Expected<std::shared_ptr<LatencyMetersMap>> get_latnecy_meters() override;
+    virtual Expected<std::shared_ptr<VdmaChannel>> get_boundary_vdma_channel_by_stream_name(
+        const std::string &stream_name) override;
+    virtual hailo_status set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name) override;
+    virtual hailo_status set_scheduler_threshold(uint32_t threshold, const std::string &network_name) override;
 
     virtual ~HcpConfigNetworkGroup() = default;
     HcpConfigNetworkGroup(const HcpConfigNetworkGroup &other) = delete;
index bbf47a87af9b6443b54371d2fae208c0be4d3c58..20dac3c9c680f61fe9d2c11d2c09a6a161bc9c23 100644 (file)
@@ -16,8 +16,10 @@ namespace hailort
 
 Expected<VdmaConfigActivatedNetworkGroup> VdmaConfigActivatedNetworkGroup::create(
     VdmaConfigActiveAppHolder &active_net_group_holder,
+    const std::string &network_group_name,
     std::vector<std::shared_ptr<ResourcesManager>> resources_managers,
     const hailo_activate_network_group_params_t &network_group_params,
+    uint16_t dynamic_batch_size,
     std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
     std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,         
     EventPtr network_group_activated_event,
@@ -29,7 +31,7 @@ Expected<VdmaConfigActivatedNetworkGroup> VdmaConfigActivatedNetworkGroup::creat
     CHECK_ARG_NOT_NULL_AS_EXPECTED(deactivation_time_accumulator);
 
     auto status = HAILO_UNINITIALIZED;
-    VdmaConfigActivatedNetworkGroup object(network_group_params, input_streams, output_streams,
+    VdmaConfigActivatedNetworkGroup object(network_group_name, network_group_params, dynamic_batch_size, input_streams, output_streams,
         std::move(resources_managers), active_net_group_holder, std::move(network_group_activated_event),
         deactivation_time_accumulator, status);
     CHECK_SUCCESS_AS_EXPECTED(status);
@@ -38,22 +40,25 @@ Expected<VdmaConfigActivatedNetworkGroup> VdmaConfigActivatedNetworkGroup::creat
 }
 
 VdmaConfigActivatedNetworkGroup::VdmaConfigActivatedNetworkGroup(
-    const hailo_activate_network_group_params_t &network_group_params,
-    std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
-    std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,
-    std::vector<std::shared_ptr<ResourcesManager>> &&resources_managers,
-    VdmaConfigActiveAppHolder &active_net_group_holder,
-    EventPtr &&network_group_activated_event,
-    AccumulatorPtr deactivation_time_accumulator,
-    hailo_status &status) :
-        ActivatedNetworkGroupBase(network_group_params, input_streams, output_streams,
-            std::move(network_group_activated_event), status),
-        m_should_reset_state_machine(true),
-        m_active_net_group_holder(active_net_group_holder),
-        m_resources_managers(std::move(resources_managers)),
-        m_ddr_send_threads(),
-        m_ddr_recv_threads(),
-        m_deactivation_time_accumulator(deactivation_time_accumulator)
+        const std::string &network_group_name,
+        const hailo_activate_network_group_params_t &network_group_params,
+        uint16_t dynamic_batch_size,
+        std::map<std::string, std::unique_ptr<InputStream>> &input_streams,
+        std::map<std::string, std::unique_ptr<OutputStream>> &output_streams,
+        std::vector<std::shared_ptr<ResourcesManager>> &&resources_managers,
+        VdmaConfigActiveAppHolder &active_net_group_holder,
+        EventPtr &&network_group_activated_event,
+        AccumulatorPtr deactivation_time_accumulator,
+        hailo_status &status) :
+    ActivatedNetworkGroupBase(network_group_params, dynamic_batch_size, input_streams,
+                              output_streams, std::move(network_group_activated_event), status),
+    m_network_group_name(network_group_name),
+    m_should_reset_state_machine(true),
+    m_active_net_group_holder(active_net_group_holder),
+    m_resources_managers(std::move(resources_managers)),
+    m_ddr_send_threads(),
+    m_ddr_recv_threads(),
+    m_deactivation_time_accumulator(deactivation_time_accumulator)
 {
     // Validate ActivatedNetworkGroup status
     if (HAILO_SUCCESS != status) {
@@ -67,19 +72,16 @@ VdmaConfigActivatedNetworkGroup::VdmaConfigActivatedNetworkGroup(
             LOGGER__ERROR("Failed to start fw managed vdma channels.");
             return;
         }
-    }
 
-    /* If ddr buffers are not SDK padded, host should control the DDR buffering */
-    if (!m_resources_managers[0]->get_supported_features().padded_ddr_buffers) { // All ResourceManagers shares the same supported_features
-        status = init_ddr_resources();
+        status = resources_manager->set_inter_context_channels_dynamic_batch_size(dynamic_batch_size);
         if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed to initialize DDR resources.");
+            LOGGER__ERROR("Failed to set inter-context channels dynamic batch size.");
             return;
         }
     }
 
     for (auto &resources_manager : m_resources_managers) {
-        status = resources_manager->enable_state_machine();
+        status = resources_manager->enable_state_machine(dynamic_batch_size);
         if (HAILO_SUCCESS != status) {
             LOGGER__ERROR("Failed to activate state-machine");
             return;
@@ -89,6 +91,7 @@ VdmaConfigActivatedNetworkGroup::VdmaConfigActivatedNetworkGroup(
 
 VdmaConfigActivatedNetworkGroup::VdmaConfigActivatedNetworkGroup(VdmaConfigActivatedNetworkGroup &&other) noexcept :
     ActivatedNetworkGroupBase(std::move(other)),
+    m_network_group_name(std::move(other.m_network_group_name)),
     m_should_reset_state_machine(std::exchange(other.m_should_reset_state_machine, false)),
     m_active_net_group_holder(other.m_active_net_group_holder),
     m_resources_managers(std::move(other.m_resources_managers)),
@@ -106,15 +109,6 @@ VdmaConfigActivatedNetworkGroup::~VdmaConfigActivatedNetworkGroup()
     auto status = HAILO_UNINITIALIZED;
     const auto start_time = std::chrono::steady_clock::now();
 
-    // If ddr buffers are not SDK padded, host should control the DDR buffering
-    // Note: All ResourceManagers share the same supported_features
-    if (!m_resources_managers[0]->get_supported_features().padded_ddr_buffers) {
-        status = cleanup_ddr_resources();
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed to cleanup DDR resources.");
-        }
-    }
-
     m_active_net_group_holder.clear();
     deactivate_resources();
 
@@ -138,6 +132,11 @@ VdmaConfigActivatedNetworkGroup::~VdmaConfigActivatedNetworkGroup()
     m_deactivation_time_accumulator->add_data_point(elapsed_time_ms);
 }
 
+const std::string &VdmaConfigActivatedNetworkGroup::get_network_group_name() const
+{
+    return m_network_group_name;
+}
+
 Expected<Buffer> VdmaConfigActivatedNetworkGroup::get_intermediate_buffer(const IntermediateBufferKey &key)
 {
     CHECK_AS_EXPECTED(1 == m_resources_managers.size(), HAILO_INVALID_OPERATION,
@@ -146,184 +145,4 @@ Expected<Buffer> VdmaConfigActivatedNetworkGroup::get_intermediate_buffer(const
     return m_resources_managers[0]->read_intermediate_buffer(key);
 }
 
-hailo_status VdmaConfigActivatedNetworkGroup::init_ddr_resources()
-{
-    for (auto &resources_manager : m_resources_managers) {
-        auto status = resources_manager->open_ddr_channels();
-        CHECK_SUCCESS(status);
-
-        for (auto &ddr_info : resources_manager->ddr_infos()) {
-            auto num_ready = make_shared_nothrow<std::atomic<uint16_t>>(static_cast<uint16_t>(0));
-            CHECK_NOT_NULL(num_ready, HAILO_OUT_OF_HOST_MEMORY);
-
-            m_ddr_send_threads.push_back(std::thread(ddr_send_thread_main, ddr_info, num_ready));
-            m_ddr_recv_threads.push_back(std::thread(ddr_recv_thread_main, ddr_info, num_ready));
-        }
-    }
-    return HAILO_SUCCESS;
-}
-
-hailo_status VdmaConfigActivatedNetworkGroup::cleanup_ddr_resources()
-{
-    hailo_status status = HAILO_SUCCESS; // Success oriented
-
-    for (auto &resources_manager : m_resources_managers) {
-        resources_manager->abort_ddr_channels();
-    }
-
-    for (auto& thread : m_ddr_send_threads) {
-        thread.join();
-    }
-    m_ddr_send_threads.clear();
-
-    for (auto& thread : m_ddr_recv_threads) {
-        thread.join();
-    }
-    m_ddr_recv_threads.clear();
-
-    for (auto &resources_manager : m_resources_managers) {
-        resources_manager->close_ddr_channels();
-    }
-
-    return status;
-}
-
-void VdmaConfigActivatedNetworkGroup::ddr_send_thread_main(DdrChannelsInfo ddr_info,
-    std::shared_ptr<std::atomic<uint16_t>> desc_list_num_ready)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    const auto timeout = std::chrono::milliseconds(DDR_THREAD_DEFAULT_TIMEOUT_MS);
-    uint16_t last_num_proc = 0;
-    uint32_t acc_sent_descs = 0;
-    auto descs_per_interrupt = ddr_info.intermediate_buffer->descriptors_in_frame();
-    assert(0 == (ddr_info.min_buffered_rows % DDR_NUMBER_OF_ROWS_PER_INTERRUPT));
-    auto interrupts_per_min_buffered_rows = ddr_info.min_buffered_rows / DDR_NUMBER_OF_ROWS_PER_INTERRUPT;
-    uint32_t descs_per_min_buffered_rows = interrupts_per_min_buffered_rows * descs_per_interrupt;
-
-    if (nullptr == ddr_info.h2d_ch) {
-        LOGGER__ERROR("Failed to find DDR H2D channel {}.", ddr_info.h2d_channel_index);
-        return;
-    }
-    if (nullptr == ddr_info.d2h_ch) {
-        LOGGER__ERROR("Failed to find DDR D2H channel {}.", ddr_info.d2h_channel_index);
-        return;
-    }
-
-    while (true) {
-        /* H2D */
-        status = ddr_info.h2d_ch->wait_channel_interrupts_for_ddr(timeout);
-        if (HAILO_SUCCESS != status) {
-            goto l_exit;
-        }
-
-        /* D2H */
-        auto hw_num_proc = ddr_info.h2d_ch->get_hw_num_processed_ddr(ddr_info.desc_list_size_mask);
-        if (!hw_num_proc) {
-            LOGGER__ERROR("Failed to get DDR_H2D_Channel {} num_processed.", ddr_info.h2d_channel_index);
-            status = hw_num_proc.status();
-            goto l_exit;
-        }
-
-        auto transferred_descs = (last_num_proc <= hw_num_proc.value()) ?
-            static_cast<uint16_t>(hw_num_proc.value() - last_num_proc) :
-            static_cast<uint16_t>(ddr_info.intermediate_buffer->descs_count() - last_num_proc + hw_num_proc.value());
-        acc_sent_descs += transferred_descs;
-        last_num_proc = hw_num_proc.value();
-
-        auto sent_batches = acc_sent_descs / descs_per_min_buffered_rows;
-        if (0 < sent_batches) {
-            auto desc_count = ddr_info.intermediate_buffer->program_host_managed_ddr(ddr_info.row_size,
-                (ddr_info.min_buffered_rows * sent_batches), *desc_list_num_ready);
-            if (!desc_count) {
-                LOGGER__ERROR("Failed to program descs for DDR");
-                status = desc_count.status();
-                goto l_exit;
-            }
-            acc_sent_descs -= desc_count.value();
-            *desc_list_num_ready =
-                static_cast<uint16_t>((desc_count.value() + *desc_list_num_ready) & ddr_info.desc_list_size_mask);
-
-            status = ddr_info.d2h_ch->inc_num_available_for_ddr(desc_count.value(),
-                ddr_info.desc_list_size_mask);
-            if (HAILO_SUCCESS != status) {
-                goto l_exit;
-            }
-        }
-    }
-l_exit:
-    if (HAILO_SUCCESS != status) {
-        if ((HAILO_STREAM_INTERNAL_ABORT == status) || (HAILO_STREAM_NOT_ACTIVATED == status)) {
-            LOGGER__INFO("DDR thread main for channels {}:(h2d), {}:(d2h) exit with status {}",ddr_info.h2d_channel_index,
-                ddr_info.d2h_channel_index, status);
-        } else {
-            LOGGER__ERROR("DDR thread main for channels {}:(h2d), {}:(d2h) exit with status {}",ddr_info.h2d_channel_index,
-                ddr_info.d2h_channel_index, status);
-        }
-    }
-    return;
-}
-
-void VdmaConfigActivatedNetworkGroup::ddr_recv_thread_main(DdrChannelsInfo ddr_info,
-    std::shared_ptr<std::atomic<uint16_t>> desc_list_num_ready)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    uint16_t last_num_proc = 0;
-    uint16_t transferred_descs = 0;
-    const auto timeout = std::chrono::milliseconds(DDR_THREAD_DEFAULT_TIMEOUT_MS);
-
-    if (nullptr == ddr_info.h2d_ch) {
-        LOGGER__ERROR("Failed to find DDR H2D channel {}.", ddr_info.h2d_channel_index);
-        return;
-    }
-    if (nullptr == ddr_info.d2h_ch) {
-        LOGGER__ERROR("Failed to find DDR D2H channel {}.", ddr_info.d2h_channel_index);
-        return;
-    }
-
-    *desc_list_num_ready = ddr_info.initial_programed_descs;
-
-    status = ddr_info.d2h_ch->set_num_avail_value(ddr_info.initial_programed_descs);
-    if (HAILO_SUCCESS != status) {
-        goto l_exit;
-    }
-
-    while (true) {
-        /* D2H */
-        status = ddr_info.d2h_ch->wait_channel_interrupts_for_ddr(timeout);
-        if (HAILO_SUCCESS != status) {
-            goto l_exit;
-        }
-
-        /* H2D */
-        auto hw_num_proc = ddr_info.d2h_ch->get_hw_num_processed_ddr(ddr_info.desc_list_size_mask);
-        if (!hw_num_proc) {
-            LOGGER__ERROR("Failed to get DDR_D2H_Channel {} num_processed.", ddr_info.d2h_channel_index);
-            status = hw_num_proc.status();
-            goto l_exit;
-        }
-
-        transferred_descs = (last_num_proc <= hw_num_proc.value()) ?
-            static_cast<uint16_t>(hw_num_proc.value() - last_num_proc) :
-            static_cast<uint16_t>(ddr_info.intermediate_buffer->descs_count() - last_num_proc + hw_num_proc.value());
-        last_num_proc = hw_num_proc.value();
-
-        status = ddr_info.h2d_ch->inc_num_available_for_ddr(transferred_descs,
-            ddr_info.desc_list_size_mask);
-        if (HAILO_SUCCESS != status) {
-            goto l_exit;
-        }
-    }
-l_exit:
-    if (HAILO_SUCCESS != status) {
-        if ((HAILO_STREAM_INTERNAL_ABORT == status) || (HAILO_STREAM_NOT_ACTIVATED == status)) {
-            LOGGER__INFO("DDR thread main for channels {}:(h2d), {}:(d2h) exit with status {}",ddr_info.h2d_channel_index,
-                ddr_info.d2h_channel_index, status);
-        } else {
-            LOGGER__ERROR("DDR thread main for channels {}:(h2d), {}:(d2h) exit with status {}",ddr_info.h2d_channel_index,
-                ddr_info.d2h_channel_index, status);
-        }
-    }
-    return;
-}
-
 } /* namespace hailort */
index 0a3bc7e75c9ec7ebcfaddd3bd051057cb509e022..dd87f5cf3a3c533ef7813adbf8ec1d264fdac0ac 100644 (file)
@@ -23,6 +23,7 @@
 #include "hailo/hef.hpp"
 #include "control.hpp"
 #include "hailort_defaults.hpp"
+#include "vdevice_internal.hpp"
 
 #include "pcie_device.hpp"
 #include "hlpcie.hpp"
@@ -38,7 +39,9 @@ Expected<VdmaConfigManager> VdmaConfigManager::create(VdmaDevice &device)
     const bool is_vdevice = false;
     std::vector<std::reference_wrapper<VdmaDevice>> devices;
     devices.push_back(device);
-    VdmaConfigManager manager(std::move(devices), is_vdevice);
+
+    auto empty_weak_ptr = NetworkGroupSchedulerWeakPtr();
+    VdmaConfigManager manager(std::move(devices), is_vdevice, empty_weak_ptr);
     return manager;
 }
 
@@ -56,16 +59,15 @@ Expected<VdmaConfigManager> VdmaConfigManager::create(VDevice &vdevice)
         pcie_devices.emplace_back(static_cast<PcieDevice&>(dev.get()));
     }
 
-
-    VdmaConfigManager manager(std::move(pcie_devices), is_vdevice);
+    VdmaConfigManager manager(std::move(pcie_devices), is_vdevice, static_cast<VDeviceBase&>(vdevice).network_group_scheduler());
     return manager;
 }
 
-VdmaConfigManager::VdmaConfigManager(std::vector<std::reference_wrapper<VdmaDevice>> &&devices, bool is_vdevice)
-    : m_devices(std::move(devices)), m_net_groups(), m_is_vdevice(is_vdevice) {}
+VdmaConfigManager::VdmaConfigManager(std::vector<std::reference_wrapper<VdmaDevice>> &&devices, bool is_vdevice, NetworkGroupSchedulerWeakPtr network_group_scheduler)
+    : m_devices(std::move(devices)), m_net_groups(), m_net_group_wrappers(), m_is_vdevice(is_vdevice), m_network_group_scheduler(network_group_scheduler) {}
 
 Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
-    const NetworkGroupsParamsMap &configure_params)
+    const NetworkGroupsParamsMap &configure_params, bool scheduler_is_used)
 {
     auto &hef_network_groups = hef.pimpl->network_groups();
     auto current_net_group_index = static_cast<uint8_t>(m_net_groups.size());
@@ -128,7 +130,7 @@ Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
         }
 
         auto net_group = VdmaConfigNetworkGroup::create(m_active_net_group_holder, config_params,
-            resources_managers, network_group_metadata_ptr);
+            resources_managers, network_group_metadata_ptr, m_network_group_scheduler);
         current_net_group_index++;
 
         auto net_group_ptr = make_shared_nothrow<VdmaConfigNetworkGroup>(net_group.release());
@@ -137,7 +139,16 @@ Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
 
         // TODO: move this func into VdmaConfigNetworkGroup c'tor
         if (m_is_vdevice) {
-            status = net_group_ptr->create_vdevice_streams_from_config_params();
+            auto network_group_handle = INVALID_NETWORK_GROUP_HANDLE;
+            auto network_group_scheduler = m_network_group_scheduler.lock();
+            if (network_group_scheduler) {
+                auto network_group_handle_exp = network_group_scheduler->add_network_group(net_group_ptr);
+                CHECK_EXPECTED(network_group_handle_exp);
+                network_group_handle = network_group_handle_exp.value();
+                net_group_ptr->set_network_group_handle(network_group_handle);
+            }
+
+            status = net_group_ptr->create_vdevice_streams_from_config_params(network_group_handle);
             CHECK_SUCCESS_AS_EXPECTED(status);
         } else {
             status = net_group_ptr->create_streams_from_config_params(net_group_ptr->get_resources_managers()[0]->get_device());
@@ -148,7 +159,14 @@ Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
         status = validate_boundary_streams_were_created(hef, network_group_proto->network_group_metadata().network_group_name(), *net_group_ptr);
         CHECK_SUCCESS_AS_EXPECTED(status);
 
-        added_network_groups.emplace_back(std::static_pointer_cast<ConfiguredNetworkGroup>(net_group_ptr));
+        auto net_group_wrapper = ConfiguredNetworkGroupWrapper::create(net_group_ptr);
+        CHECK_EXPECTED(net_group_wrapper);
+
+        auto net_group_wrapper_ptr = make_shared_nothrow<ConfiguredNetworkGroupWrapper>(net_group_wrapper.release());
+        CHECK_AS_EXPECTED(nullptr != net_group_wrapper_ptr, HAILO_OUT_OF_HOST_MEMORY);
+        m_net_group_wrappers.emplace_back(net_group_wrapper_ptr);
+
+        added_network_groups.emplace_back(std::static_pointer_cast<ConfiguredNetworkGroup>(net_group_wrapper_ptr));
     }
     std::string unmatched_keys = "";
     for (const auto &pair : configure_params_copy) {
@@ -175,7 +193,7 @@ Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
         for (size_t i = 0, contexts = 0; i < m_net_groups.size(); ++i) {
             for (auto &resource_manager : m_net_groups[i]->get_resources_managers()) {
                 if (0 == strcmp(device.get().get_dev_id(), resource_manager->get_dev_id())) {
-                    auto net_group_header_exp = resource_manager->get_control_network_group_header();
+                    auto net_group_header_exp = resource_manager->get_control_network_group_header(scheduler_is_used);
                     CHECK_EXPECTED(net_group_header_exp);
                     context_switch_info.context_switch_main_header.application_header[i] = net_group_header_exp.value();
                     auto net_group_contexts = resource_manager->get_contexts();
@@ -190,13 +208,25 @@ Expected<ConfiguredNetworkGroupVector> VdmaConfigManager::add_hef(Hef &hef,
             }
         }
 
-        // Reset context_switch status
-        auto status = Control::reset_context_switch_state_machine(device.get());
-        CHECK_SUCCESS_AS_EXPECTED(status);
+        {
+            // Add instance that guards scheduler to deactivate network_group temporary
+            auto scheduler_idle_guard = NetworkGroupScheduler::create_scheduler_idle_guard();
+            if (m_is_vdevice) {
+                auto network_group_scheduler = m_network_group_scheduler.lock();
+                if (network_group_scheduler) {
+                    auto status = scheduler_idle_guard->set_scheduler(network_group_scheduler);
+                    CHECK_SUCCESS_AS_EXPECTED(status);
+                }
+            }
 
-        // Write context_switch info
-        status = Control::write_context_switch_info(device.get(), &context_switch_info);
-        CHECK_SUCCESS_AS_EXPECTED(status);
+            // Reset context_switch status
+            auto status = Control::reset_context_switch_state_machine(device.get());
+            CHECK_SUCCESS_AS_EXPECTED(status);
+
+            // Write context_switch info
+            status = Control::write_context_switch_info(device.get(), &context_switch_info);
+            CHECK_SUCCESS_AS_EXPECTED(status);
+        }
     }
 
     return added_network_groups;
@@ -218,8 +248,8 @@ hailo_status VdmaConfigManager::update_network_batch_size(ConfigureNetworkParams
     CHECK((single_network_default_batch || multi_network_default_batch), HAILO_INVALID_OPERATION, 
         "User provided non batch size for network group and for network as well. User is adviced to work with network's batch size only");
 
-    /* In case user works with network group, overide the network batch size.*/
     if (!single_network_default_batch && multi_network_default_batch) {
+        /* In case user works with network group, overide the network batch size.*/
         for (auto &network_params : config_params.network_params_by_name) {
             network_params.second.batch_size = config_params.batch_size;
         }
index fd5610d96500c7ef399ef0662eab26d34f3ae7bb..c0187b4f02679f4e146261c64bded8e0b5797724 100644 (file)
@@ -11,12 +11,12 @@ namespace hailort
 Expected<VdmaConfigNetworkGroup> VdmaConfigNetworkGroup::create(VdmaConfigActiveAppHolder &active_net_group_holder,
         const ConfigureNetworkParams &config_params, 
         std::vector<std::shared_ptr<ResourcesManager>> resources_managers,
-        std::shared_ptr<NetworkGroupMetadata> network_group_metadata)
+        std::shared_ptr<NetworkGroupMetadata> network_group_metadata, NetworkGroupSchedulerWeakPtr network_group_scheduler)
 {
     auto status = HAILO_UNINITIALIZED;
 
     VdmaConfigNetworkGroup object(active_net_group_holder, config_params,
-        std::move(resources_managers), *network_group_metadata, status);
+        std::move(resources_managers), *network_group_metadata, network_group_scheduler, status);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
     return object;
@@ -25,19 +25,21 @@ Expected<VdmaConfigNetworkGroup> VdmaConfigNetworkGroup::create(VdmaConfigActive
 VdmaConfigNetworkGroup::VdmaConfigNetworkGroup(VdmaConfigActiveAppHolder &active_net_group_holder,
     const ConfigureNetworkParams &config_params,
     std::vector<std::shared_ptr<ResourcesManager>> &&resources_managers,
-    const NetworkGroupMetadata &network_group_metadata, hailo_status &status) :
+    const NetworkGroupMetadata &network_group_metadata, NetworkGroupSchedulerWeakPtr network_group_scheduler, hailo_status &status) :
         ConfiguredNetworkGroupBase(config_params,
-        resources_managers[0]->get_network_group_index(),
-        network_group_metadata, status), // All ResourceManagers shares the same net_group_index
+            resources_managers[0]->get_network_group_index(), // All ResourceManagers shares the same net_group_index
+            network_group_metadata, !network_group_scheduler.expired(), status),
         m_active_net_group_holder(active_net_group_holder),
-        m_resources_managers(std::move(resources_managers)) {}
+        m_resources_managers(std::move(resources_managers)),
+        m_network_group_scheduler(network_group_scheduler),
+        m_network_group_handle(INVALID_NETWORK_GROUP_HANDLE) {}
 
-Expected<std::unique_ptr<ActivatedNetworkGroup>> VdmaConfigNetworkGroup::activate(
-      const hailo_activate_network_group_params_t &network_group_params)
+Expected<std::unique_ptr<ActivatedNetworkGroup>> VdmaConfigNetworkGroup::activate_impl(
+      const hailo_activate_network_group_params_t &network_group_params, uint16_t dynamic_batch_size)
 {
     auto start_time = std::chrono::steady_clock::now();
     auto activated_net_group = VdmaConfigActivatedNetworkGroup::create(
-        m_active_net_group_holder, m_resources_managers, network_group_params,
+        m_active_net_group_holder, get_network_group_name(), m_resources_managers, network_group_params, dynamic_batch_size,
         m_input_streams, m_output_streams, m_network_group_activated_event, m_deactivation_time_accumulator);
     const auto elapsed_time_ms = std::chrono::duration<double, std::milli>(
         std::chrono::steady_clock::now() - start_time).count();
@@ -77,25 +79,11 @@ Expected<uint8_t> VdmaConfigNetworkGroup::get_boundary_channel_index(uint8_t str
     return m_resources_managers[0]->get_boundary_channel_index(stream_index, direction, layer_name);
 }
 
-hailo_status VdmaConfigNetworkGroup::create_vdevice_streams_from_config_params()
+hailo_status VdmaConfigNetworkGroup::create_vdevice_streams_from_config_params(network_group_handle_t network_group_handle)
 {
-    if ((m_config_params.latency & HAILO_LATENCY_MEASURE) == HAILO_LATENCY_MEASURE) {
-        if (1 == m_resources_managers.size()) {
-            // Best affort for starting latency meter.
-            auto networks_names = m_network_group_metadata.get_partial_network_names();
-            for (auto &network_name : networks_names) {
-                auto layer_infos = m_network_group_metadata.get_all_layer_infos(network_name);
-                CHECK_EXPECTED_AS_STATUS(layer_infos);
-                auto latency_meter = ConfiguredNetworkGroupBase::create_hw_latency_meter(m_resources_managers[0]->get_device(),
-                    layer_infos.value());
-                if (latency_meter) {
-                    m_latency_meter.emplace(network_name, latency_meter.release());
-                    LOGGER__DEBUG("Starting hw latency measurement for network {}", network_name);
-                }
-            }
-        } else {
-            LOGGER__WARNING("Latency measurement is not supported on more than 1 physical device.");
-        }
+    // TODO - HRT-6931 - raise error on this case 
+    if (((m_config_params.latency & HAILO_LATENCY_MEASURE) == HAILO_LATENCY_MEASURE) && (1 < m_resources_managers.size())) {
+        LOGGER__WARNING("Latency measurement is not supported on more than 1 physical device.");
     }
 
     for (const auto &stream_parameters_pair : m_config_params.stream_params_by_name) {
@@ -103,14 +91,14 @@ hailo_status VdmaConfigNetworkGroup::create_vdevice_streams_from_config_params()
             case HAILO_H2D_STREAM:
                 {
                     auto status = create_input_vdevice_stream_from_config_params(stream_parameters_pair.second,
-                        stream_parameters_pair.first);
+                        stream_parameters_pair.first, network_group_handle);
                     CHECK_SUCCESS(status);
                 }
                 break;
             case HAILO_D2H_STREAM:
                 {
                     auto status = create_output_vdevice_stream_from_config_params(stream_parameters_pair.second,
-                        stream_parameters_pair.first);
+                        stream_parameters_pair.first, network_group_handle);
                     CHECK_SUCCESS(status);
                 }
                 break;
@@ -124,18 +112,16 @@ hailo_status VdmaConfigNetworkGroup::create_vdevice_streams_from_config_params()
 }
 
 hailo_status VdmaConfigNetworkGroup::create_input_vdevice_stream_from_config_params(const hailo_stream_parameters_t &stream_params,
-    const std::string &stream_name)
+    const std::string &stream_name, network_group_handle_t network_group_handle)
 {
     auto edge_layer = get_layer_info(stream_name);
     CHECK_EXPECTED_AS_STATUS(edge_layer);
 
-    auto partial_network_name = edge_layer->partial_network_name;
-    auto latency_meter = (contains(m_latency_meter, partial_network_name)) ? m_latency_meter.at(partial_network_name) : nullptr;
-
     CHECK(HAILO_STREAM_INTERFACE_PCIE == stream_params.stream_interface, HAILO_INVALID_OPERATION,
         "Only PCIe streams are supported on VDevice usage. {} has {} interface.", stream_name, stream_params.stream_interface);
     auto input_stream = VDeviceInputStream::create(m_resources_managers, edge_layer.value(),
-        stream_name, m_network_group_activated_event, latency_meter);
+        stream_name, network_group_handle, m_network_group_activated_event,
+        m_network_group_scheduler);
     CHECK_EXPECTED_AS_STATUS(input_stream);
     m_input_streams.insert(make_pair(stream_name, input_stream.release()));
 
@@ -143,22 +129,67 @@ hailo_status VdmaConfigNetworkGroup::create_input_vdevice_stream_from_config_par
 }
 
 hailo_status VdmaConfigNetworkGroup::create_output_vdevice_stream_from_config_params(const hailo_stream_parameters_t &stream_params,
-    const std::string &stream_name)
+    const std::string &stream_name, network_group_handle_t network_group_handle)
 {
     auto edge_layer = get_layer_info(stream_name);
     CHECK_EXPECTED_AS_STATUS(edge_layer);
 
-    auto partial_network_name = edge_layer->partial_network_name;
-    auto latency_meter = (contains(m_latency_meter, partial_network_name)) ? m_latency_meter.at(partial_network_name) : nullptr;
-
     CHECK(HAILO_STREAM_INTERFACE_PCIE == stream_params.stream_interface, HAILO_INVALID_OPERATION,
         "Only PCIe streams are supported on VDevice usage. {} has {} interface.", stream_name, stream_params.stream_interface);
     auto output_stream = VDeviceOutputStream::create(m_resources_managers, edge_layer.value(),
-        stream_name, m_network_group_activated_event, latency_meter);
+        stream_name, network_group_handle, m_network_group_activated_event,
+        m_network_group_scheduler);
     CHECK_EXPECTED_AS_STATUS(output_stream);
     m_output_streams.insert(make_pair(stream_name, output_stream.release()));
 
     return HAILO_SUCCESS;
 }
 
+void VdmaConfigNetworkGroup::set_network_group_handle(network_group_handle_t handle)
+{
+    m_network_group_handle = handle;
+}
+
+hailo_status VdmaConfigNetworkGroup::set_scheduler_timeout(const std::chrono::milliseconds &timeout, const std::string &network_name)
+{
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    CHECK(network_group_scheduler, HAILO_INVALID_OPERATION,
+        "Cannot set scheduler timeout for network group {}, as it is configured on a vdevice which does not have scheduling enabled", get_network_group_name());
+    if (network_name != HailoRTDefaults::get_network_name(get_network_group_name())) {
+        CHECK(network_name.empty(), HAILO_NOT_IMPLEMENTED, "Setting scheduler timeout for a specific network is currently not supported");
+    }
+    auto status = network_group_scheduler->set_timeout(m_network_group_handle, timeout, network_name);
+    CHECK_SUCCESS(status);
+    return HAILO_SUCCESS;
+}
+
+hailo_status VdmaConfigNetworkGroup::set_scheduler_threshold(uint32_t threshold, const std::string &network_name)
+{
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    CHECK(network_group_scheduler, HAILO_INVALID_OPERATION,
+        "Cannot set scheduler threshold for network group {}, as it is configured on a vdevice which does not have scheduling enabled", get_network_group_name());
+    if (network_name != HailoRTDefaults::get_network_name(get_network_group_name())) {
+        CHECK(network_name.empty(), HAILO_NOT_IMPLEMENTED, "Setting scheduler threshold for a specific network is currently not supported");
+    }
+    auto status = network_group_scheduler->set_threshold(m_network_group_handle, threshold, network_name);
+    CHECK_SUCCESS(status);
+    return HAILO_SUCCESS;
+}
+
+Expected<std::shared_ptr<LatencyMetersMap>> VdmaConfigNetworkGroup::get_latnecy_meters()
+{
+    auto latency_meters = m_resources_managers[0]->get_latnecy_meters();
+    return make_shared_nothrow<LatencyMetersMap>(latency_meters);
+}
+
+Expected<std::shared_ptr<VdmaChannel>> VdmaConfigNetworkGroup::get_boundary_vdma_channel_by_stream_name(const std::string &stream_name)
+{
+    if (1 < m_resources_managers.size()) {
+        LOGGER__ERROR("get_boundary_vdma_channel_by_stream_name function is not supported on more than 1 physical device.");
+        return make_unexpected(HAILO_INVALID_OPERATION);
+    }
+
+    return m_resources_managers[0]->get_boundary_vdma_channel_by_stream_name(stream_name);
+}
+
 } /* namespace hailort */
index 12cb00fd0dd0262e7791877de0d541de5b028ea7..b20b4cc71bae5170b02259af7cfbee7f6bc8d074 100644 (file)
@@ -25,6 +25,9 @@ namespace hailort
 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
 #endif
 
+#define POWER_MEASUREMENT_DELAY_MS(__sample_period, __average_factor) \
+    (static_cast<uint32_t>((__sample_period) / 1000.0 * (__average_factor) * 2 * 1.2))
+
 #define OVERCURRENT_PROTECTION_WARNING ( \
         "Using the overcurrent protection dvm for power measurement will disable the ovecurrent protection.\n" \
         "If only taking one measurement, the protection will resume automatically.\n" \
@@ -1097,7 +1100,7 @@ exit:
     return status;
 }
 
-hailo_status Control::set_power_measurement(Device &device, uint32_t index, CONTROL_PROTOCOL__dvm_options_t dvm,
+hailo_status Control::set_power_measurement(Device &device, hailo_measurement_buffer_index_t buffer_index, CONTROL_PROTOCOL__dvm_options_t dvm,
     CONTROL_PROTOCOL__power_measurement_types_t measurement_type)
 {
     hailo_status status = HAILO_UNINITIALIZED;
@@ -1110,11 +1113,11 @@ hailo_status Control::set_power_measurement(Device &device, uint32_t index, CONT
     CONTROL_PROTOCOL__payload_t *payload = NULL;
     CONTROL_PROTOCOL__set_power_measurement_response_t *response = NULL;
 
-    CHECK(CONTROL_PROTOCOL__MAX_NUMBER_OF_POWER_MEASUREMETS > index,
-        HAILO_INVALID_ARGUMENT, "Invalid power measurement index {}", index);
+    CHECK(CONTROL_PROTOCOL__MAX_NUMBER_OF_POWER_MEASUREMETS > buffer_index,
+        HAILO_INVALID_ARGUMENT, "Invalid power measurement index {}", buffer_index);
 
     common_status = CONTROL_PROTOCOL__pack_set_power_measurement_request(&request, &request_size, device.get_control_sequence(),
-            index, dvm, measurement_type);
+            buffer_index, dvm, measurement_type);
     status = (HAILO_COMMON_STATUS__SUCCESS == common_status) ? HAILO_SUCCESS : HAILO_INTERNAL_FAILURE;
     if (HAILO_SUCCESS != status) {
         goto exit;
@@ -1144,7 +1147,7 @@ exit:
     return status;
 }
 
-hailo_status Control::get_power_measurement(Device &device, uint32_t index, bool should_clear,
+hailo_status Control::get_power_measurement(Device &device, hailo_measurement_buffer_index_t buffer_index, bool should_clear,
     hailo_power_measurement_data_t *measurement_data)
 {
     hailo_status status = HAILO_UNINITIALIZED;
@@ -1158,11 +1161,11 @@ hailo_status Control::get_power_measurement(Device &device, uint32_t index, bool
     CONTROL_PROTOCOL__get_power_measurement_response_t *get_power_response = NULL;
 
     /* Validate arguments */
-    CHECK(CONTROL_PROTOCOL__MAX_NUMBER_OF_POWER_MEASUREMETS > index,
-        HAILO_INVALID_ARGUMENT, "Invalid power measurement index {}", index);
+    CHECK(CONTROL_PROTOCOL__MAX_NUMBER_OF_POWER_MEASUREMETS > buffer_index,
+        HAILO_INVALID_ARGUMENT, "Invalid power measurement index {}", buffer_index);
     CHECK_ARG_NOT_NULL(measurement_data);
     common_status = CONTROL_PROTOCOL__pack_get_power_measurement_request(&request, &request_size, device.get_control_sequence(),
-            index, should_clear);
+            buffer_index, should_clear);
     status = (HAILO_COMMON_STATUS__SUCCESS == common_status) ? HAILO_SUCCESS : HAILO_INTERNAL_FAILURE;
     if (HAILO_SUCCESS != status) {
         goto exit;
@@ -1194,7 +1197,7 @@ exit:
     return status;
 }
 
-hailo_status Control::start_power_measurement(Device &device, uint32_t delay_milliseconds,
+hailo_status Control::start_power_measurement(Device &device,
     CONTROL_PROTOCOL__averaging_factor_t averaging_factor , CONTROL_PROTOCOL__sampling_period_t sampling_period)
 {
     hailo_status status = HAILO_UNINITIALIZED;
@@ -1206,6 +1209,13 @@ hailo_status Control::start_power_measurement(Device &device, uint32_t delay_mil
     CONTROL_PROTOCOL__response_header_t *header = NULL;
     CONTROL_PROTOCOL__payload_t *payload = NULL;
 
+    uint32_t delay_milliseconds = 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 == delay_milliseconds) {
+        delay_milliseconds = 1;
+    }
+
     common_status = CONTROL_PROTOCOL__pack_start_power_measurement_request(&request, &request_size, device.get_control_sequence(),
             delay_milliseconds, averaging_factor, sampling_period);
     status = (HAILO_COMMON_STATUS__SUCCESS == common_status) ? HAILO_SUCCESS : HAILO_INTERNAL_FAILURE;
@@ -2392,18 +2402,14 @@ hailo_status Control::context_switch_set_context_info(Device &device,
 
         context_info_single_control.is_first_control_per_context = is_first_control_per_context;
         context_info_single_control.is_last_control_per_context = is_last_control_per_context;
-        static_assert(sizeof(context_info_single_control.context_cfg_base_address) == sizeof(context_info->context_cfg_base_address),
-            "mismatch in sizes of context_cfg_base_address");
-        static_assert(sizeof(context_info_single_control.context_cfg_total_descriptors) == sizeof(context_info->context_total_descriptors),
-            "mismatch in sizes of context_cfg_total_descriptors");
+        static_assert(sizeof(context_info_single_control.config_buffer_infos) == sizeof(context_info->config_buffer_infos),
+            "mismatch in sizes of config_buffer_infos");
         static_assert(sizeof(context_info_single_control.context_stream_remap_data) == sizeof(context_info->context_stream_remap_data),
             "mismatch in sizes of context_stream_remap_data");
-        memcpy(context_info_single_control.context_cfg_base_address,
-                context_info->context_cfg_base_address,
-                sizeof(context_info_single_control.context_cfg_base_address));
-        memcpy(context_info_single_control.context_cfg_total_descriptors,
-                context_info->context_total_descriptors,
-                sizeof(context_info_single_control.context_cfg_total_descriptors));
+        context_info_single_control.cfg_channels_count = context_info->cfg_channels_count;
+        memcpy(context_info_single_control.config_buffer_infos,
+            context_info->config_buffer_infos,
+            sizeof(context_info_single_control.config_buffer_infos));
 
         memcpy(&(context_info_single_control.context_stream_remap_data),
                 &(context_info->context_stream_remap_data),
@@ -2717,7 +2723,7 @@ hailo_status Control::download_context_action_list(Device &device, uint8_t conte
 
 hailo_status Control::change_context_switch_status(Device &device,
         CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status,
-        uint8_t network_group_index)
+        uint8_t network_group_index, uint16_t dynamic_batch_size)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     HAILO_COMMON_STATUS_t common_status = HAILO_COMMON_STATUS__UNINITIALIZED;
@@ -2729,7 +2735,7 @@ hailo_status Control::change_context_switch_status(Device &device,
     CONTROL_PROTOCOL__payload_t *payload = NULL;
 
     common_status = CONTROL_PROTOCOL__pack_change_context_switch_status_request(&request, &request_size,
-            device.get_control_sequence(), state_machine_status, network_group_index);
+            device.get_control_sequence(), state_machine_status, network_group_index, dynamic_batch_size);
     status = (HAILO_COMMON_STATUS__SUCCESS == common_status) ? HAILO_SUCCESS : HAILO_INTERNAL_FAILURE;
     if (HAILO_SUCCESS != status) {
         goto exit;
@@ -2752,14 +2758,18 @@ exit:
     return status;
 }
 
-hailo_status Control::enable_network_group(Device &device, uint8_t network_group_index)
+hailo_status Control::enable_network_group(Device &device, uint8_t network_group_index, uint16_t dynamic_batch_size)
 {
-    return Control::change_context_switch_status(device, CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_ENABLED, network_group_index);
+    return Control::change_context_switch_status(device, CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_ENABLED,
+        network_group_index, dynamic_batch_size);
 }
 
 hailo_status Control::reset_context_switch_state_machine(Device &device)
 {
-    return Control::change_context_switch_status(device, CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_RESET, 0);
+    static const auto IGNORE_NETWORK_GROUP_INDEX = 0;
+    static const auto IGNORE_DYNAMIC_BATCH_SIZE = 0;
+    return Control::change_context_switch_status(device, CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_RESET,
+        IGNORE_NETWORK_GROUP_INDEX, IGNORE_DYNAMIC_BATCH_SIZE);
 }
 
 hailo_status Control::wd_enable(Device &device, uint8_t cpu_id, bool should_enable)
@@ -2993,7 +3003,7 @@ exit:
     return status;
 }
 
-hailo_status Control::switch_network_group(Device &device, uint8_t network_group_index)
+hailo_status Control::switch_network_group(Device &device, uint8_t network_group_index, uint16_t dynamic_batch_size)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     HAILO_COMMON_STATUS_t common_status = HAILO_COMMON_STATUS__UNINITIALIZED;
@@ -3004,11 +3014,10 @@ hailo_status Control::switch_network_group(Device &device, uint8_t network_group
     CONTROL_PROTOCOL__response_header_t *header = NULL;
     CONTROL_PROTOCOL__payload_t *payload = NULL;
 
-
     LOGGER__DEBUG("Set network_group_index {}", network_group_index);
 
     common_status = CONTROL_PROTOCOL__pack_switch_application_request(&request, &request_size, device.get_control_sequence(),
-            network_group_index);
+            network_group_index, dynamic_batch_size);
     status = (HAILO_COMMON_STATUS__SUCCESS == common_status) ? HAILO_SUCCESS : HAILO_INTERNAL_FAILURE;
     if (HAILO_SUCCESS != status) {
         goto exit;
index 3702993f53d9ffb79e38511e668125646a73c0bf..57f303c3fa0192366330da91edffb73de7f26995 100644 (file)
@@ -293,8 +293,7 @@ public:
      *
      * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a static hailo_status error.
      */
-    static hailo_status enable_network_group(Device &device, 
-            uint8_t network_group_index);
+    static hailo_status enable_network_group(Device &device, uint8_t network_group_index, uint16_t dynamic_batch_size);
     /**
      *  reset context switch state machine
      * 
@@ -335,10 +334,12 @@ public:
      * 
      * @param[in]     device - The Hailo device.
      * @param[in]     network_group_index - network_group index 
+     * @param[in]     dynamic_batch_size - dynamic_batch size (or CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE if it's
+     *                                     to be ignored) 
      *
      * @return Upon success, returns @a HAILO_SUCCESS. Otherwise, returns an @a static hailo_status error.
      */
-    static hailo_status switch_network_group(Device &device, uint8_t network_group_index);
+    static hailo_status switch_network_group(Device &device, uint8_t network_group_index, uint16_t dynamic_batch_size);
 
     /**
      *  Enable/disable halt transmition following Rx pause frame
@@ -383,11 +384,11 @@ public:
     // TODO: needed?
     static hailo_status power_measurement(Device &device, CONTROL_PROTOCOL__dvm_options_t dvm,
         CONTROL_PROTOCOL__power_measurement_types_t measurement_type, float32_t *measurement);
-    static hailo_status set_power_measurement(Device &device, uint32_t index, CONTROL_PROTOCOL__dvm_options_t dvm,
+    static hailo_status set_power_measurement(Device &device, hailo_measurement_buffer_index_t buffer_index, CONTROL_PROTOCOL__dvm_options_t dvm,
         CONTROL_PROTOCOL__power_measurement_types_t measurement_type);
-    static hailo_status get_power_measurement(Device &device, uint32_t index, bool should_clear,
+    static hailo_status get_power_measurement(Device &device, hailo_measurement_buffer_index_t buffer_index, bool should_clear,
         hailo_power_measurement_data_t *measurement_data);
-    static hailo_status start_power_measurement(Device &device, uint32_t delay_milliseconds,
+    static hailo_status start_power_measurement(Device &device,
         CONTROL_PROTOCOL__averaging_factor_t averaging_factor, CONTROL_PROTOCOL__sampling_period_t sampling_period);
     static hailo_status stop_power_measurement(Device &device);
 
@@ -404,7 +405,7 @@ private:
             CONTROL_PROTOCOL__context_switch_context_info_single_control_t *context_info);
     static hailo_status change_context_switch_status(Device &device, 
             CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status,
-            uint8_t network_group_index);
+            uint8_t network_group_index, uint16_t dynamic_batch_size);
 };
 
 } /* namespace hailort */
index e400560e887286efe438521daca678fa16e533c7..ef17df82f6370988f0797d49cff659fdf9fa5351 100644 (file)
@@ -1696,19 +1696,17 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_context_switch_set_context_info_req
     request->parameters.context_switch_set_context_info_request.is_last_control_per_context = 
         context_info->is_last_control_per_context;
 
-    /* context cfg base address */
-    request->parameters.context_switch_set_context_info_request.context_cfg_base_address_length = 
-        BYTE_ORDER__htonl(sizeof(request->parameters.context_switch_set_context_info_request.context_cfg_base_address));
-    memcpy(&(request->parameters.context_switch_set_context_info_request.context_cfg_base_address), 
-            &(context_info->context_cfg_base_address), 
-            sizeof(request->parameters.context_switch_set_context_info_request.context_cfg_base_address));
-
-    /* context total descriptors */
-    request->parameters.context_switch_set_context_info_request.context_cfg_total_descriptors_length = 
-        BYTE_ORDER__htonl(sizeof(request->parameters.context_switch_set_context_info_request.context_cfg_total_descriptors));
-    memcpy(&(request->parameters.context_switch_set_context_info_request.context_cfg_total_descriptors), 
-            &(context_info->context_cfg_total_descriptors), 
-            sizeof(request->parameters.context_switch_set_context_info_request.context_cfg_total_descriptors));
+    /* cfg_channels_count */
+    request->parameters.context_switch_set_context_info_request.cfg_channels_count_length = 
+        BYTE_ORDER__htonl(sizeof(request->parameters.context_switch_set_context_info_request.cfg_channels_count));
+    request->parameters.context_switch_set_context_info_request.cfg_channels_count = context_info->cfg_channels_count;
+
+    /* context cfg buffer info */
+    request->parameters.context_switch_set_context_info_request.config_buffer_infos_length = 
+        BYTE_ORDER__htonl(sizeof(request->parameters.context_switch_set_context_info_request.config_buffer_infos));
+    memcpy(&(request->parameters.context_switch_set_context_info_request.config_buffer_infos), 
+            &(context_info->config_buffer_infos), 
+            sizeof(request->parameters.context_switch_set_context_info_request.config_buffer_infos));
 
     /* context unused stream index */
     request->parameters.context_switch_set_context_info_request.context_stream_remap_data_length = 
@@ -1834,7 +1832,8 @@ exit:
 
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_change_context_switch_status_request(
         CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, 
-        CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status, uint8_t application_index)
+        CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status, uint8_t application_index,
+        uint16_t dynamic_batch_size)
 {
     HAILO_COMMON_STATUS_t status = HAILO_COMMON_STATUS__UNINITIALIZED;
     size_t local_request_size = 0;
@@ -1847,7 +1846,7 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_change_context_switch_status_reques
     /* Header */
     local_request_size = CONTROL_PROTOCOL__REQUEST_BASE_SIZE + 
         sizeof(CONTROL_PROTOCOL__change_context_switch_status_request_t);
-    control_protocol__pack_request_header(request, sequence, HAILO_CONTROL_OPCODE_CHANGE_CONTEXT_SWITCH_STATUS, 2);
+    control_protocol__pack_request_header(request, sequence, HAILO_CONTROL_OPCODE_CHANGE_CONTEXT_SWITCH_STATUS, 3);
 
     /* state_machine_status */
     request->parameters.change_context_switch_status_request.state_machine_status_length = 
@@ -1860,6 +1859,11 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_change_context_switch_status_reques
     request->parameters.change_context_switch_status_request.application_index_length = 
         BYTE_ORDER__htonl(sizeof(request->parameters.change_context_switch_status_request.application_index));
     request->parameters.change_context_switch_status_request.application_index = application_index;
+
+    /* dynamic_batch_size */
+    request->parameters.change_context_switch_status_request.dynamic_batch_size_length = 
+        BYTE_ORDER__htonl(sizeof(request->parameters.change_context_switch_status_request.dynamic_batch_size));
+    request->parameters.change_context_switch_status_request.dynamic_batch_size = dynamic_batch_size;
     
     *request_size = local_request_size;
     status = HAILO_COMMON_STATUS__SUCCESS;
@@ -2092,7 +2096,7 @@ exit:
 }
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_switch_application_request(
         CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, 
-        uint8_t application_index)
+        uint8_t application_index, uint16_t dynamic_batch_size)
 {
     HAILO_COMMON_STATUS_t status = HAILO_COMMON_STATUS__UNINITIALIZED;
     size_t local_request_size = 0;
@@ -2110,6 +2114,11 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_switch_application_request(
     request->parameters.switch_application_request.application_index_length =
         BYTE_ORDER__htonl(sizeof(request->parameters.switch_application_request.application_index));
     request->parameters.switch_application_request.application_index = application_index;
+
+    /* dynamic_batch_size */
+    request->parameters.switch_application_request.dynamic_batch_size_length =
+        BYTE_ORDER__htonl(sizeof(request->parameters.switch_application_request.dynamic_batch_size));
+    request->parameters.switch_application_request.dynamic_batch_size = dynamic_batch_size;
         
     *request_size = local_request_size;
     status = HAILO_COMMON_STATUS__SUCCESS;
index c59129a88c4a318c2548e156443b4df10855baa7..0337f7b5df57d9d7c19afb717b5e7047ce4568ee 100644 (file)
@@ -46,8 +46,8 @@ typedef struct {
 } CONTEXT_SWITCH__context_control_slicing_data_t;
 
 typedef struct {
-    uint64_t context_cfg_base_address[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
-    uint16_t context_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];
     uint32_t context_network_data_length;
     CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
     uint8_t context_network_data[CONTROL_PROTOCOL__CONTEXT_NETWORK_DATA_MAX_SIZE];
@@ -130,7 +130,8 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_download_context_action_list_reques
         size_t *request_size, uint32_t sequence, uint8_t context_index, uint16_t action_list_offset);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_change_context_switch_status_request(
         CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence,
-        CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status, uint8_t application_index);
+        CONTROL_PROTOCOL__CONTEXT_SWITCH_STATUS_t state_machine_status, uint8_t application_index,
+        uint16_t dynamic_batch_size);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_wd_enable(
     CONTROL_PROTOCOL__request_t *request,
     size_t *request_size,
@@ -153,7 +154,7 @@ HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_d2h_event_manager_set_host_info_req
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_d2h_event_manager_send_host_info_event_request( CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, 
         uint8_t event_priority);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_switch_application_request(CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, 
-        uint8_t application_index);
+        uint8_t application_index, uint16_t dynamic_batch_size);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_get_chip_temperature_request(CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_read_board_config(CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, uint32_t address, uint32_t data_length);
 HAILO_COMMON_STATUS_t CONTROL_PROTOCOL__pack_write_board_config_request(CONTROL_PROTOCOL__request_t *request, size_t *request_size, uint32_t sequence, uint32_t address, const uint8_t *data, uint32_t data_length);
index 27d98973d4e9578251fab775635255206b6341ad..6ba66fe4cc27a59e57d0303f3093d1d111e03f8c 100644 (file)
@@ -13,8 +13,8 @@ namespace hailort
 {
 
 Expected<std::unique_ptr<CoreInputStream>> CoreInputStream::create(Device &device,
-    uint8_t channel_index, const LayerInfo &edge_layer,
-    uint16_t batch_size, EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer,
+    uint16_t batch_size, EventPtr network_group_activated_event)
 {
     hailo_status status = HAILO_UNINITIALIZED;
 
@@ -23,8 +23,8 @@ Expected<std::unique_ptr<CoreInputStream>> CoreInputStream::create(Device &devic
 
     CoreDevice *core_device = reinterpret_cast<CoreDevice*>(&device);
     std::unique_ptr<CoreInputStream> local_stream(new (std::nothrow) CoreInputStream(*core_device,
-        channel_index, edge_layer, std::move(network_group_activated_event), batch_size,
-        latency_meter, DEFAULT_TRANSFER_TIMEOUT, status));
+        std::move(channel), edge_layer, std::move(network_group_activated_event), batch_size,
+        DEFAULT_TRANSFER_TIMEOUT, status));
     CHECK((nullptr != local_stream), make_unexpected(HAILO_OUT_OF_HOST_MEMORY));
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -33,20 +33,19 @@ Expected<std::unique_ptr<CoreInputStream>> CoreInputStream::create(Device &devic
 
 CoreInputStream::CoreInputStream(
     CoreDevice &device,
-    uint8_t channel_index,
+    std::shared_ptr<VdmaChannel> channel,
     const LayerInfo &edge_layer,
     EventPtr network_group_activated_event,
     uint16_t batch_size,
-    LatencyMeterPtr latency_meter,
     const std::chrono::milliseconds &transfer_timeout,
     hailo_status &status) :
-        VdmaInputStream(device, channel_index, edge_layer, network_group_activated_event,
-            batch_size, latency_meter, transfer_timeout, HAILO_STREAM_INTERFACE_CORE, status)
+        VdmaInputStream(device, std::move(channel), edge_layer, network_group_activated_event,
+            batch_size, transfer_timeout, HAILO_STREAM_INTERFACE_CORE, status)
 {}
 
 Expected<std::unique_ptr<CoreOutputStream>> CoreOutputStream::create(Device &device,
-    uint8_t channel_index, const LayerInfo &edge_layer, uint16_t batch_size,
-    EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, 
+    uint16_t batch_size, EventPtr network_group_activated_event)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CHECK_AS_EXPECTED(device.get_type() == Device::Type::CORE, HAILO_INTERNAL_FAILURE,
@@ -54,8 +53,8 @@ Expected<std::unique_ptr<CoreOutputStream>> CoreOutputStream::create(Device &dev
 
     CoreDevice *core_device = reinterpret_cast<CoreDevice*>(&device);
     std::unique_ptr<CoreOutputStream> local_stream(new (std::nothrow) CoreOutputStream(*core_device,
-        channel_index, edge_layer, std::move(network_group_activated_event),
-        batch_size, latency_meter, DEFAULT_TRANSFER_TIMEOUT, status));
+        std::move(channel), edge_layer, std::move(network_group_activated_event),
+        batch_size, DEFAULT_TRANSFER_TIMEOUT, status));
     CHECK((nullptr != local_stream), make_unexpected(HAILO_OUT_OF_HOST_MEMORY));
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -64,15 +63,14 @@ Expected<std::unique_ptr<CoreOutputStream>> CoreOutputStream::create(Device &dev
 
 CoreOutputStream::CoreOutputStream(
     CoreDevice &device,
-    uint8_t channel_index,
+    std::shared_ptr<VdmaChannel> channel,
     const LayerInfo &edge_layer,
     EventPtr network_group_activated_event,
     uint16_t batch_size,
-    LatencyMeterPtr latency_meter,
     const std::chrono::milliseconds &transfer_timeout,
     hailo_status &status) :
-        VdmaOutputStream(device, channel_index, edge_layer,
-            network_group_activated_event, batch_size, latency_meter, transfer_timeout, status)
+        VdmaOutputStream(device, std::move(channel), edge_layer,
+            network_group_activated_event, batch_size, transfer_timeout, status)
 {}
 
 } /* namespace hailort */
index c0b95a8faf5fad143bb6a6604166f56ece4b47e0..dceef1c44894c441a66c40f15a453e986614fb0b 100644 (file)
@@ -22,20 +22,19 @@ public:
     CoreInputStream(CoreInputStream &&other) = default;
     virtual ~CoreInputStream() = default;
 
-    static Expected<std::unique_ptr<CoreInputStream>> create(Device &device, uint8_t channel_index,
-        const LayerInfo &edge_layer, uint16_t batch_size, EventPtr network_group_activated_event,
-        LatencyMeterPtr latency_meter = nullptr);
+    static Expected<std::unique_ptr<CoreInputStream>> create(Device &device,
+        std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, uint16_t batch_size, 
+        EventPtr network_group_activated_event);
 
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_CORE; }
 
 private:
     CoreInputStream(
         CoreDevice &device,
-        uint8_t channel_index,
+        std::shared_ptr<VdmaChannel> channel,
         const LayerInfo &edge_layer,
         EventPtr network_group_activated_event,
         uint16_t batch_size,
-        LatencyMeterPtr latency_meter,
         const std::chrono::milliseconds &transfer_timeout,
         hailo_status &status);
 };
@@ -45,20 +44,19 @@ public:
     CoreOutputStream(CoreOutputStream &&other) = default;
     virtual ~CoreOutputStream() = default;
 
-    static Expected<std::unique_ptr<CoreOutputStream>> create(Device &device, uint8_t channel_index,
-        const LayerInfo &edge_layer, uint16_t batch_size, EventPtr network_group_activated_event,
-        LatencyMeterPtr latency_meter);
+    static Expected<std::unique_ptr<CoreOutputStream>> create(Device &device,
+        std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, uint16_t batch_size, 
+        EventPtr network_group_activated_event);
 
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_CORE; }
 
 private:
     explicit CoreOutputStream(
         CoreDevice &device,
-        uint8_t channel_index,
+        std::shared_ptr<VdmaChannel> channel,
         const LayerInfo &edge_layer,
         EventPtr network_group_activated_event,
         uint16_t batch_size,
-        LatencyMeterPtr latency_meter,
         const std::chrono::milliseconds &transfer_timeout,
         hailo_status &status);
 };
index aef126bd7749c840b82a54ddf81cc7d87fcda282..7c70aedde41a443bbe2bf71bdb2d05021fa4470a 100644 (file)
@@ -239,21 +239,45 @@ Expected<float32_t> Device::power_measurement(hailo_dvm_options_t dvm, hailo_pow
     return res;
 }
 
-hailo_status Device::start_power_measurement(uint32_t delay_milliseconds, hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
+hailo_status Device::start_power_measurement(uint32_t /*unused*/, hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
 {
-    return Control::start_power_measurement(*this, delay_milliseconds, static_cast<CONTROL_PROTOCOL__averaging_factor_t>(averaging_factor),
-        static_cast<CONTROL_PROTOCOL__sampling_period_t>(sampling_period));
+    // TODO: Remove deprecated function
+    LOGGER__WARNING("'Device::start_power_measurement(uint32_t unused, hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)' is deprecated. "\
+        "One should use ''Device::start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)");
+    return start_power_measurement(averaging_factor, sampling_period);
 }
 
 hailo_status Device::set_power_measurement(uint32_t index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)
 {
-    return Control::set_power_measurement(*this, index, static_cast<CONTROL_PROTOCOL__dvm_options_t>(dvm), static_cast<CONTROL_PROTOCOL__power_measurement_types_t>(measurement_type));
+    // TODO: Remove deprecated function
+    LOGGER__WARNING("'Device::set_power_measurement(uint32_t index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)' is deprecated. "\
+        "One should use ''Device::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)");
+    return set_power_measurement(static_cast<hailo_measurement_buffer_index_t>(index), dvm, measurement_type);
 }
 
 Expected<hailo_power_measurement_data_t> Device::get_power_measurement(uint32_t index, bool should_clear)
+{
+    // TODO: Remove deprecated function
+    LOGGER__WARNING("'Device::get_power_measurement(uint32_t index, bool should_clear)' is deprecated. "\
+        "One should use ''Device::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear)");
+    return get_power_measurement(static_cast<hailo_measurement_buffer_index_t>(index), should_clear);
+}
+
+hailo_status Device::start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
+{
+    return Control::start_power_measurement(*this, static_cast<CONTROL_PROTOCOL__averaging_factor_t>(averaging_factor),
+        static_cast<CONTROL_PROTOCOL__sampling_period_t>(sampling_period));
+}
+
+hailo_status Device::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)
+{
+    return Control::set_power_measurement(*this, buffer_index, static_cast<CONTROL_PROTOCOL__dvm_options_t>(dvm), static_cast<CONTROL_PROTOCOL__power_measurement_types_t>(measurement_type));
+}
+
+Expected<hailo_power_measurement_data_t> Device::get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear)
 {
     hailo_power_measurement_data_t measurement_data = {};
-    auto status = Control::get_power_measurement(*this, index, should_clear, &measurement_data);
+    auto status = Control::get_power_measurement(*this, buffer_index, should_clear, &measurement_data);
     CHECK_SUCCESS_AS_EXPECTED(status);
     return measurement_data;
 }
@@ -439,4 +463,10 @@ Expected<Buffer> Device::download_context_action_list(uint8_t context_index, uin
     return final_action_list.release();
 }
 
+hailo_status Device::set_context_action_list_timestamp_batch(uint16_t batch_index)
+{
+    static const bool ENABLE_USER_CONFIG = true;
+    return Control::config_context_switch_timestamp(*this, batch_index, ENABLE_USER_CONFIG);
+}
+
 } /* namespace hailort */
index c1b1e374c3496081db3cb1f50f840d9750a46514..4a6d87fe5d8a17fe04534bd58b3c772dfae886fd 100644 (file)
@@ -79,14 +79,17 @@ hailo_status DeviceBase::reset(hailo_reset_device_mode_t mode)
     return reset_impl(reset_type);
 }
 
-hailo_status DeviceBase::set_notification_callback(NotificationCallback func, hailo_notification_id_t notification_id, void *opaque)
+hailo_status DeviceBase::set_notification_callback(const NotificationCallback &func, hailo_notification_id_t notification_id, void *opaque)
 {
     CHECK((0 <= notification_id) && (HAILO_NOTIFICATION_ID_COUNT > notification_id), HAILO_INVALID_ARGUMENT,
         "Notification id value is invalid");
     CHECK_ARG_NOT_NULL(func);
 
+    auto func_ptr = make_shared_nothrow<NotificationCallback>(func);
+    CHECK_NOT_NULL(func_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
     const std::lock_guard<std::mutex> lock(m_callbacks_lock);
-    m_d2h_callbacks[notification_id].func = func;
+    m_d2h_callbacks[notification_id].func = func_ptr;
     m_d2h_callbacks[notification_id].opaque = opaque;
     return HAILO_SUCCESS;
 }
@@ -558,7 +561,7 @@ void DeviceBase::d2h_notification_thread_main(const std::string &device_id)
 
         LOGGER__INFO("[{}] Got notification from fw with id: {}", device_id, hailo_notification_id);
 
-        NotificationCallback callback_func = nullptr;
+        std::shared_ptr<NotificationCallback> callback_func = nullptr;
         void *callback_opaque = nullptr;
         {
             const std::lock_guard<std::mutex> lock(m_callbacks_lock);
@@ -574,7 +577,7 @@ void DeviceBase::d2h_notification_thread_main(const std::string &device_id)
             callback_notification.sequence = notification.header.sequence;
             static_assert(sizeof(callback_notification.body) == sizeof(notification.message_parameters), "D2H notification size mismatch");
             memcpy(&callback_notification.body, &notification.message_parameters, sizeof(notification.message_parameters));
-            callback_func(*this, callback_notification, callback_opaque);
+            (*callback_func)(*this, callback_notification, callback_opaque);
         }
     }
 }
index cc0a7d5e9902be2555456cc57fad9980621aa616..344f8eb5c8e8b38cecfdecec12cbdd49bb035cd5 100644 (file)
@@ -55,7 +55,7 @@ public:
     virtual Expected<ConfiguredNetworkGroupVector> configure(Hef &hef,
         const NetworkGroupsParamsMap &configure_params={}) override;
     virtual hailo_status reset(hailo_reset_device_mode_t mode) override;
-    virtual hailo_status set_notification_callback(NotificationCallback func, hailo_notification_id_t notification_id, void *opaque) override;
+    virtual hailo_status set_notification_callback(const NotificationCallback &func, hailo_notification_id_t notification_id, void *opaque) override;
     virtual hailo_status remove_notification_callback(hailo_notification_id_t notification_id) override;
     virtual void activate_notifications(const std::string &device_id);
     virtual void start_notification_fetch_thread(D2hEventQueue *write_queue);
@@ -122,7 +122,7 @@ private:
     Expected<firmware_type_t> get_fw_type();
 
     typedef struct {
-        NotificationCallback func;
+        std::shared_ptr<NotificationCallback> func;
         void *opaque;
     } d2h_notification_callback_t;
 
index e82c48dc5101e4760e3d535b63b0734fa23ce17f..8b7bd10d09b5115225c70d84dfbc225c9ff2e033 100644 (file)
@@ -78,7 +78,8 @@ hailo_status EthernetInputStream::deactivate_stream()
     return HAILO_SUCCESS;
 }
 
-hailo_status EthernetInputStream::activate_stream()
+// Note: Ethernet streams don't work with dynamic batch sizes
+hailo_status EthernetInputStream::activate_stream(uint16_t /* dynamic_batch_size */)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__config_stream_params_t params = {};
@@ -460,7 +461,8 @@ hailo_status EthernetOutputStream::deactivate_stream()
     return HAILO_SUCCESS;
 }
 
-hailo_status EthernetOutputStream::activate_stream()
+// Note: Ethernet streams don't work with dynamic batch sizes
+hailo_status EthernetOutputStream::activate_stream(uint16_t /* dynamic_batch_size */)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__config_stream_params_t params = {};
index 241c49585e68b44e64e96e188d43fbffa891a825..1cc7153ff1b82a30ddf52923de02738a4f7a802b 100644 (file)
@@ -79,7 +79,7 @@ public:
         const LayerInfo &edge_layer, const hailo_eth_input_stream_params_t &params, EventPtr network_group_activated_event);
 
     uint16_t get_remote_port();
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_ETH; }
     virtual std::chrono::milliseconds get_timeout() const override;
@@ -194,7 +194,7 @@ public:
     static Expected<std::unique_ptr<EthernetOutputStream>> create(Device &device, const LayerInfo &edge_layer,
         const hailo_eth_output_stream_params_t &params, EventPtr network_group_activated_event);
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_ETH; }
     virtual std::chrono::milliseconds get_timeout() const override;
index 605e176bbc3203cb297fefd494f11622961fe8bf..04559e86dff06011e49dcf224b96d70e21e47a8a 100644 (file)
@@ -67,8 +67,8 @@ private:
     //       * Hence, SHUTDOWN_INDEX must come before WAITABLE_INDEX!
     static const size_t SHUTDOWN_INDEX = 0;
     static const size_t WAITABLE_INDEX = 1;
-    #if defined(_MSC_VER)
-    using WaitHandleArray = std::array<underlying_handle_t, 2>;
+    #if defined(_MSC_VER) || defined(__QNX__)
+    using WaitHandleArray = std::array<underlying_waitable_handle_t, 2>;
     #else
     using WaitHandleArray = std::array<struct pollfd, 2>;
     #endif
index c7719284fe3cab9935efae0ccd3d5da4e78ee1a5..26aff5910563469937d11e2738c0cf3500e12c6e 100644 (file)
@@ -295,30 +295,30 @@ hailo_status hailo_power_measurement(hailo_device device, hailo_dvm_options_t dv
     return HAILO_SUCCESS;
 }
 
-hailo_status hailo_start_power_measurement(hailo_device device, uint32_t delay_milliseconds,
+hailo_status hailo_start_power_measurement(hailo_device device,
     hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
 {
     CHECK_ARG_NOT_NULL(device);
-    auto status = Control::start_power_measurement(*reinterpret_cast<Device*>(device), delay_milliseconds, static_cast<CONTROL_PROTOCOL__averaging_factor_t>(averaging_factor), static_cast<CONTROL_PROTOCOL__sampling_period_t>(sampling_period));
+    auto status = Control::start_power_measurement(*reinterpret_cast<Device*>(device), static_cast<CONTROL_PROTOCOL__averaging_factor_t>(averaging_factor), static_cast<CONTROL_PROTOCOL__sampling_period_t>(sampling_period));
     CHECK_SUCCESS(status);
     return HAILO_SUCCESS;
 }
 
-hailo_status hailo_set_power_measurement(hailo_device device, uint32_t index,
+hailo_status hailo_set_power_measurement(hailo_device device, hailo_measurement_buffer_index_t buffer_index,
     hailo_dvm_options_t dvm, hailo_power_measurement_types_t measurement_type)
 {
     CHECK_ARG_NOT_NULL(device);
-    auto status = Control::set_power_measurement(*reinterpret_cast<Device*>(device), index, static_cast<CONTROL_PROTOCOL__dvm_options_t>(dvm), static_cast<CONTROL_PROTOCOL__power_measurement_types_t>(measurement_type));
+    auto status = Control::set_power_measurement(*reinterpret_cast<Device*>(device), buffer_index, static_cast<CONTROL_PROTOCOL__dvm_options_t>(dvm), static_cast<CONTROL_PROTOCOL__power_measurement_types_t>(measurement_type));
     CHECK_SUCCESS(status);
     return HAILO_SUCCESS;
 }
 
-hailo_status hailo_get_power_measurement(hailo_device device, uint32_t index, bool should_clear,
+hailo_status hailo_get_power_measurement(hailo_device device, hailo_measurement_buffer_index_t buffer_index, bool should_clear,
     hailo_power_measurement_data_t *measurement_data)
 {
     CHECK_ARG_NOT_NULL(device);
     CHECK_ARG_NOT_NULL(measurement_data);
-    auto status = Control::get_power_measurement(*reinterpret_cast<Device*>(device), index, should_clear, measurement_data);
+    auto status = Control::get_power_measurement(*reinterpret_cast<Device*>(device), buffer_index, should_clear, measurement_data);
     CHECK_SUCCESS(status);
     return HAILO_SUCCESS;
 }
@@ -847,14 +847,15 @@ hailo_status hailo_hef_get_all_vstream_infos(hailo_hef hef, const char *name,
     return HAILO_SUCCESS;
 }
 
-hailo_status hailo_get_latency_measurement_from_network_group(hailo_configured_network_group configured_network_group,
-    hailo_latency_measurement_result_t *result)
+HAILORTAPI hailo_status hailo_get_latency_measurement(hailo_configured_network_group configured_network_group,
+    const char *network_name, hailo_latency_measurement_result_t *result)
 {
-    LOGGER__WARNING("'hailo_get_latency_measurement_from_network_group' is deprecated. One shuold use 'hailo_get_latency_measurement()'.");
     CHECK_ARG_NOT_NULL(configured_network_group);
     CHECK_ARG_NOT_NULL(result);
 
-    auto latency_result = ((ConfiguredNetworkGroup*)configured_network_group)->get_latency_measurement();
+    std::string network_name_str = (nullptr == network_name) ? "" : network_name;
+
+    auto latency_result = ((ConfiguredNetworkGroup*)configured_network_group)->get_latency_measurement(network_name_str);
     CHECK_EXPECTED_AS_STATUS(latency_result);
 
     hailo_latency_measurement_result_t local_result {};
@@ -864,22 +865,22 @@ hailo_status hailo_get_latency_measurement_from_network_group(hailo_configured_n
     return HAILO_SUCCESS;
 }
 
-HAILORTAPI hailo_status hailo_get_latency_measurement(hailo_configured_network_group configured_network_group,
-    const char *network_name, hailo_latency_measurement_result_t *result)
+hailo_status hailo_set_scheduler_timeout(hailo_configured_network_group configured_network_group,
+    uint32_t timeout_ms, const char *network_name)
 {
     CHECK_ARG_NOT_NULL(configured_network_group);
-    CHECK_ARG_NOT_NULL(result);
 
     std::string network_name_str = (nullptr == network_name) ? "" : network_name;
+    return ((ConfiguredNetworkGroup*)configured_network_group)->set_scheduler_timeout(std::chrono::milliseconds(timeout_ms), network_name_str);
+}
 
-    auto latency_result = ((ConfiguredNetworkGroup*)configured_network_group)->get_latency_measurement(network_name_str);
-    CHECK_EXPECTED_AS_STATUS(latency_result);
-
-    hailo_latency_measurement_result_t local_result {};
-    local_result.avg_hw_latency_ms = std::chrono::duration<double, std::milli>(latency_result->avg_hw_latency).count();
+hailo_status hailo_set_scheduler_threshold(hailo_configured_network_group configured_network_group,
+    uint32_t threshold, const char *network_name)
+{
+    CHECK_ARG_NOT_NULL(configured_network_group);
 
-    *result = local_result;
-    return HAILO_SUCCESS;
+    std::string network_name_str = (nullptr == network_name) ? "" : network_name;
+    return ((ConfiguredNetworkGroup*)configured_network_group)->set_scheduler_threshold(threshold, network_name_str);
 }
 
 hailo_status hailo_calculate_eth_input_rate_limits(hailo_hef hef, const char *network_group_name, uint32_t fps,
@@ -1153,96 +1154,6 @@ hailo_status hailo_transform_frame_by_output_transform_context(hailo_output_tran
     return HAILO_SUCCESS;
 }
 
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_create_input_transformer(const hailo_stream_info_t *stream_info,
-    const hailo_transform_params_t *transform_params, hailo_input_transform_context *transformer)
-{
-    CHECK_ARG_NOT_NULL(stream_info);
-    CHECK_ARG_NOT_NULL(transform_params);
-    CHECK_ARG_NOT_NULL(transformer);
-
-    LOGGER__WARNING("'hailo_create_input_transformer' is deprecated. One shold use 'hailo_create_input_transform_context'");
-
-    auto local_transformer = InputTransformContext::create(*stream_info, *transform_params);
-    CHECK_EXPECTED_AS_STATUS(local_transformer);
-
-    *transformer = reinterpret_cast<hailo_input_transform_context>(local_transformer.release().release());
-    return HAILO_SUCCESS;
-}
-
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_release_input_transformer(hailo_input_transform_context transformer)
-{
-    CHECK_ARG_NOT_NULL(transformer);
-
-    LOGGER__WARNING("'hailo_release_input_transformer' is deprecated. One shold use 'hailo_release_input_transform_context'");
-
-    delete reinterpret_cast<InputTransformContext*>(transformer);
-    return HAILO_SUCCESS;
-}
-
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_transform_frame_by_input_transformer(hailo_input_transform_context transformer,
-    const void *src, size_t src_size, void *dst, size_t dst_size)
-{
-    CHECK_ARG_NOT_NULL(transformer);
-    CHECK_ARG_NOT_NULL(src);
-    CHECK_ARG_NOT_NULL(dst);
-
-    LOGGER__WARNING("'hailo_transform_frame_by_input_transformer' is deprecated. One shold use 'hailo_transform_frame_by_input_transform_context'");
-
-    MemoryView dst_buffer(dst, dst_size);
-    auto status = reinterpret_cast<InputTransformContext*>(transformer)->transform(
-        MemoryView::create_const(src, src_size), dst_buffer);
-    CHECK_SUCCESS(status);
-    return HAILO_SUCCESS;
-}
-
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_create_output_transformer(const hailo_stream_info_t *stream_info,
-    const hailo_transform_params_t *transform_params, hailo_output_transform_context *transformer)
-{
-    CHECK_ARG_NOT_NULL(stream_info);
-    CHECK_ARG_NOT_NULL(transform_params);
-    CHECK_ARG_NOT_NULL(transformer);
-
-    LOGGER__WARNING("'hailo_create_output_transformer' is deprecated. One shold use 'hailo_create_output_transform_context'");
-
-    auto local_transformer = OutputTransformContext::create(*stream_info, *transform_params);
-    CHECK_EXPECTED_AS_STATUS(local_transformer);
-
-    *transformer = reinterpret_cast<hailo_output_transform_context>(local_transformer.release().release());
-    return HAILO_SUCCESS;
-}
-
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_release_output_transformer(hailo_output_transform_context transformer)
-{
-    CHECK_ARG_NOT_NULL(transformer);
-    LOGGER__WARNING("'hailo_release_output_transformer' is deprecated. One shold use 'hailo_release_output_transform_context'");
-
-    delete reinterpret_cast<OutputTransformContext*>(transformer);
-    return HAILO_SUCCESS;
-}
-
-// TODO (HRT-6080): Remove deprecated function
-hailo_status hailo_transform_frame_by_output_transformer(hailo_output_transform_context transformer,
-    const void *src, size_t src_size, void *dst, size_t dst_size)
-{
-    CHECK_ARG_NOT_NULL(transformer);
-    CHECK_ARG_NOT_NULL(src);
-    CHECK_ARG_NOT_NULL(dst);
-
-    LOGGER__WARNING("'hailo_transform_frame_by_output_transformer' is deprecated. One shold use 'hailo_transform_frame_by_output_transform_context'");
-
-    MemoryView dst_buffer(dst, dst_size);
-    auto status = reinterpret_cast<OutputTransformContext*>(transformer)->transform(MemoryView::create_const(src,
-        src_size), dst_buffer);
-    CHECK_SUCCESS(status);
-    return HAILO_SUCCESS;
-}
-
 hailo_status hailo_create_demuxer_by_stream(hailo_output_stream stream,
     const hailo_demux_params_t *demux_params, hailo_output_demuxer *demuxer)
 {
index 6b6fcbcddff9eac015a6547cec5368a086a8339f..f6bf80db58c2a07872a32033a30672f8582dd1c2 100644 (file)
@@ -17,5 +17,6 @@ const uint32_t HailoRTCommon::BBOX_PARAMS;
 const uint32_t HailoRTCommon::MAX_DEFUSED_LAYER_COUNT;
 const size_t HailoRTCommon::HW_DATA_ALIGNMENT;
 const uint64_t HailoRTCommon::NMS_DELIMITER;
+const uint64_t HailoRTCommon::NMS_DUMMY_DELIMITER;
 
 } /* namespace hailort */
index 73704fead91860c09d2a8ece37f660a4c117a94b..ad428b7a824a0c329553acff05c35ed2c00d66f5 100644 (file)
@@ -52,9 +52,9 @@ constexpr hailo_format_order_t DEFAULT_FORMAT_ARGMAX_ORDER_MAP[] = {
 };
 
 
-#define HAILO_DEFAULT_PARTIAL_NETWORK_NAME (std::string("default_network_name"))
 #define HAILO_DEFAULT_NETWORK_NAME_QUALIFIER (std::string("/"))
 
+
 class HailoRTDefaults
 {
 public:
@@ -323,16 +323,11 @@ public:
     {
         std::string default_network_name = net_group_name + 
             HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + 
-            HAILO_DEFAULT_PARTIAL_NETWORK_NAME;
+            net_group_name;
 
         return default_network_name;
     }
 
-    static std::string get_partial_network_name()
-    {
-        return HAILO_DEFAULT_PARTIAL_NETWORK_NAME;
-    }    
-
     static hailo_format_t expand_auto_format(const hailo_format_t &host_format, const hailo_format_t &hw_format)
     {
         auto host_format_copy = host_format;
index ba0d2762e763d8ff69d4e3e2f69883c7d67861f8..3c5f624ee50e4c85cbda0d3e26b3f2129ccf4485 100644 (file)
@@ -404,18 +404,19 @@ hailo_status Hef::Impl::fill_networks_metadata()
         auto sorted_output_names = HefUtils::get_sorted_output_names(*network_group);
         CHECK_EXPECTED_AS_STATUS(sorted_output_names);
 
-        std::vector<std::string> sorted_partial_network_names;
+        std::vector<std::string> sorted_network_names;
         if (supported_features.multi_network_support) {
-            sorted_partial_network_names.reserve(network_group->networks_names().size());
+            sorted_network_names.reserve(network_group->networks_names().size());
             for (auto &partial_network_name : network_group->networks_names()) {
-                sorted_partial_network_names.push_back(partial_network_name);
+                auto network_name = HefUtils::get_network_name(*network_group, partial_network_name);
+                sorted_network_names.push_back(network_name);
             }
         } else {
-            sorted_partial_network_names.push_back(HAILO_DEFAULT_PARTIAL_NETWORK_NAME);
+            sorted_network_names.push_back(HailoRTDefaults::get_network_name(network_group->network_group_metadata().network_group_name()));
         }
 
         NetworkGroupMetadata metadata(network_group->network_group_metadata().network_group_name(),
-            layer_infos.release(), sorted_output_names.release(), supported_features, sorted_partial_network_names);
+            layer_infos.release(), sorted_output_names.release(), supported_features, sorted_network_names);
         m_network_group_metadata.emplace(
             network_group->network_group_metadata().network_group_name(), metadata);
     }
@@ -489,13 +490,15 @@ NetworkGroupSupportedFeatures Hef::Impl::get_supported_features(const ProtoHEFHe
         const std::vector<ProtoHEFExtension> &hef_extensions, const ProtoHEFIncludedFeatures &included_features,
         const std::vector<ProtoHEFOptionalExtension> &hef_optional_extensions)
 {
-    NetworkGroupSupportedFeatures supported_features = {};
+    NetworkGroupSupportedFeatures supported_features{};
     supported_features.padded_ddr_buffers = check_hef_extension(ProtoHEFExtensionType::PADDED_DDR_BUFFERS, header,
         hef_extensions, included_features);
     supported_features.multi_network_support = check_hef_optional_extension(ProtoHEFExtensionType::MULTI_NETWORK_VARIABLE_BATCH_SIZE,
         header, hef_optional_extensions);
-   supported_features.multi_context = check_hef_extension(ProtoHEFExtensionType::IS_MULTI_CONTEXTS, header,
+    supported_features.multi_context = check_hef_extension(ProtoHEFExtensionType::IS_MULTI_CONTEXTS, header,
         hef_extensions, included_features);
+    supported_features.preliminary_run_asap = check_hef_extension(ProtoHEFExtensionType::PRELIMINARY_RUN_ASAP,
+        header, hef_extensions, included_features);
 
     return supported_features;
 }
@@ -672,27 +675,27 @@ bool HefConfigurator::is_hw_padding_supported(const ProtoHEFEdgeLayer &edge_laye
 }
 
 Expected<std::vector<hailo_stream_info_t>> Hef::Impl::get_input_stream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_input_stream_infos(partial_network_name);
+    return network_group_metadata->get_input_stream_infos(network_name);
 }
 
 Expected<std::vector<hailo_stream_info_t>> Hef::Impl::get_output_stream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_output_stream_infos(partial_network_name);
+    return network_group_metadata->get_output_stream_infos(network_name);
 }
 
 Expected<std::vector<hailo_stream_info_t>> Hef::Impl::get_all_stream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_all_stream_infos(partial_network_name);
+    return network_group_metadata->get_all_stream_infos(network_name);
 }
 
 Expected<std::vector<hailo_network_info_t>> Hef::Impl::get_network_infos(const std::string &net_group_name)
@@ -730,27 +733,27 @@ Expected<hailo_stream_info_t> Hef::Impl::get_stream_info_by_name(const std::stri
 }
 
 Expected<std::vector<hailo_vstream_info_t>> Hef::Impl::get_input_vstream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_input_vstream_infos(partial_network_name);
+    return network_group_metadata->get_input_vstream_infos(network_name);
 }
 
 Expected<std::vector<hailo_vstream_info_t>> Hef::Impl::get_output_vstream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_output_vstream_infos(partial_network_name);
+    return network_group_metadata->get_output_vstream_infos(network_name);
 }
 
 Expected<std::vector<hailo_vstream_info_t>> Hef::Impl::get_all_vstream_infos(const std::string &net_group_name,
-    const std::string &partial_network_name)
+    const std::string &network_name)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED(network_group_metadata);
-    return network_group_metadata->get_all_vstream_infos(partial_network_name);
+    return network_group_metadata->get_all_vstream_infos(network_name);
 }
 
 const std::vector<ProtoHEFNetworkGroupPtr>& Hef::Impl::network_groups() const
@@ -808,29 +811,26 @@ Expected<std::pair<std::string, std::string>> Hef::Impl::get_network_group_and_n
         network_group_name = m_groups[0]->network_group_metadata().network_group_name();
         LOGGER__INFO("No name was given. Addressing all networks of default network_group: {}",
             network_group_name);
-        return std::make_pair(network_group_name, HAILO_DEFAULT_PARTIAL_NETWORK_NAME);
-    } else if (HAILO_DEFAULT_PARTIAL_NETWORK_NAME == name) {
-        /* HAILO_DEFAULT_PARTIAL_NETWORK_NAME is passed for HEFs that doesnt support network groups.
-           We know that multiple networks_groups in single HEF is'nt supported for those HEFs. */
-        network_group_name = m_groups[0]->network_group_metadata().network_group_name();
-        return std::make_pair(network_group_name, HAILO_DEFAULT_PARTIAL_NETWORK_NAME);
+        auto network_name = HailoRTDefaults::get_network_name(network_group_name);
+        return std::make_pair(network_group_name, network_name);
     } else {
         for (const auto &network_group : m_groups) {
             network_group_name = network_group->network_group_metadata().network_group_name();
             // Look for network_group with the given name
             if (name == network_group_name) {
-                return std::make_pair(network_group_name, HAILO_DEFAULT_PARTIAL_NETWORK_NAME);
+                auto network_name = HailoRTDefaults::get_network_name(network_group_name);
+                return std::make_pair(network_group_name, network_name);
             }
             // Look for network with the given name
             for (const auto &partial_network_name : network_group->networks_names()) {
-                auto full_network_name = network_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name;
+                auto full_network_name = HefUtils::get_network_name(network_group_name, partial_network_name);
                 if (name == full_network_name) {
-                    return std::make_pair(network_group_name, partial_network_name);
+                    return std::make_pair(network_group_name, full_network_name);
                 }
             }
             // Handle case of deafult_network_name
-            if (name == network_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + HAILO_DEFAULT_PARTIAL_NETWORK_NAME) {
-                return std::make_pair(network_group_name, HAILO_DEFAULT_PARTIAL_NETWORK_NAME);
+            if (name == HailoRTDefaults::get_network_name(network_group_name)) {
+                return std::make_pair(network_group_name, name);
             }
         }
     }
@@ -968,7 +968,7 @@ hailo_status HefUtils::fill_layer_info(const ProtoHEFEdgeLayerInfo &info,
     }
     layer_info.name = info.name();
 
-    layer_info.partial_network_name = partial_network_name;
+    layer_info.network_name = HefUtils::get_network_name(net_group, partial_network_name);
     layer_info.is_mux = false;
     layer_info.direction = direction;
     layer_info.quant_info.limvals_max = info.numeric_info().limvals_max();
@@ -989,7 +989,7 @@ hailo_status HefUtils::fill_layer_info(const ProtoHEFEdgeLayerInfo &info,
                 // This creates a new LayerInfo for the fused layer *for each defused layer*, even though they all share the same fused layer.
                 // TODO Make it so all defused layer reference the same LayerInfo of the fused layer.
                 LayerInfo fused_layer_info = {};
-                status = fill_fused_nms_info(fused_layer, fused_layer_info, layer_info.quant_info, partial_network_name);
+                status = fill_fused_nms_info(fused_layer, fused_layer_info, layer_info.quant_info, layer_info.network_name);
                 CHECK_SUCCESS(status);
                 layer_info.fused_nms_layer.push_back(fused_layer_info);
                 break;
@@ -1002,7 +1002,7 @@ hailo_status HefUtils::fill_layer_info(const ProtoHEFEdgeLayerInfo &info,
 }
 
 hailo_status HefUtils::fill_fused_nms_info(const ProtoHEFEdgeLayerFused &info, LayerInfo &layer_info,
-    hailo_quant_info_t &defuse_quant_info, const std::string &partial_network_name)
+    hailo_quant_info_t &defuse_quant_info, const std::string &network_name)
 {
     auto base_info = info.layer_info().edge_layer_base();
     auto format_order_exp = HailoRTDefaults::get_device_format_order(base_info.format());
@@ -1030,7 +1030,7 @@ hailo_status HefUtils::fill_fused_nms_info(const ProtoHEFEdgeLayerFused &info, L
         return HAILO_INTERNAL_FAILURE;
     }
     layer_info.name = info.layer_info().name();
-    layer_info.partial_network_name = partial_network_name;
+    layer_info.network_name = network_name;
     layer_info.is_mux = false;
     layer_info.direction = HAILO_D2H_STREAM;
     // Due to bug in SDK quant info of fused layer is empty, so we use the quant info of  the defused layer
@@ -1064,7 +1064,7 @@ hailo_status HefUtils::fill_mux_info(const ProtoHEFEdgeLayerMux &info,
     }
     layer_info.name = info.name();
 
-    layer_info.partial_network_name = partial_network_name;
+    layer_info.network_name = HefUtils::get_network_name(net_group, partial_network_name);
     layer_info.is_mux = true;
     layer_info.predecessor.reserve(info.mux_data().number_of_predecessors());
     layer_info.height_gcd = info.mux_data().height_gcd();
@@ -1232,10 +1232,18 @@ inline std::pair<uint8_t, uint16_t> old_hef_parse_initial_l3(uint32_t initial_l3
     return std::make_pair(initial_l3_cut, initial_l3_offset);
 }
 
+static uint32_t get_initial_credit_size(const ProtoHEFEdgeLayer &edge_layer_info)
+{
+    // On old HEFs the max shmifo is not defined, so 0 wil be returned and the firmware will choose the default value.
+    return edge_layer_info.layer_info().edge_layer_base().max_shmifo_size();
+} 
+
 static hailo_status fill_boundary_input_layer(CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
-        uint8_t **context_meta_data_head_pointer, uint8_t stream_index, const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
-        ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager,
-        const std::string &layer_name, uint8_t network_index)
+    uint8_t **context_meta_data_head_pointer, uint8_t stream_index, const ProtoHEFEdgeLayer &edge_layer_info,
+    const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config,
+    ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager,
+    const std::string &layer_name, const std::string &network_name, uint8_t network_index, 
+    uint32_t frame_credits_in_bytes)
 {
     auto channel_index = resources_manager.get_available_channel_index(
         channels_parsing_info.H2D_channels_in_use, ChannelInfo::Type::BOUNDARY, VdmaChannel::Direction::H2D, layer_name);
@@ -1246,15 +1254,20 @@ static hailo_status fill_boundary_input_layer(CONTROL_PROTOCOL__context_switch_c
     CHECK_EXPECTED_AS_STATUS(channel_info);
     channel_info->get().set_pcie_stream_index(stream_index);
 
+    auto vdma_channel = resources_manager.create_boundary_vdma_channel(channel_index.value(), frame_credits_in_bytes,
+        network_name, layer_name, VdmaChannel::Direction::H2D);
+    CHECK_EXPECTED_AS_STATUS(vdma_channel);
+
     // Lock the channel for further use in this net_group
     channels_parsing_info.H2D_channels_in_use.insert(channel_index.value());
 
     LOGGER__DEBUG("Boundary input stream: {} h2d_pcie_channel: {}.", stream_index, channel_index.value());
 
     /* Update metadata */
+    const uint32_t initial_credit_size = get_initial_credit_size(edge_layer_info);
     auto status = HEF_METADATA__add_network_boundary_input_edge_layer(context_info, 
         context_meta_data_head_pointer, stream_index, channel_index.value(), network_index, nn_stream_config,
-        DEFAULT_DESC_PAGE_SIZE);
+        vdma_channel.value()->get_page_size(), initial_credit_size);
     CHECK_SUCCESS(status);
 
     return HAILO_SUCCESS;
@@ -1306,17 +1319,17 @@ static hailo_status fill_inter_context_input_layer(CONTROL_PROTOCOL__context_swi
         stream_index, src_context, dst_context, h2d_channel_index.value());
 
     /* Update metadata */
+    const uint32_t initial_credit_size = get_initial_credit_size(*edge_layer_info);
     return HEF_METADATA__add_inter_context_input_edge_layer(context_info, context_meta_data_head_pointer,
         stream_index, h2d_channel_index.value(), network_index, nn_stream_config,
-        intermediate_buffer.descriptors_in_frame(), intermediate_buffer.dma_address(), intermediate_buffer.depth(),
-        intermediate_buffer.desc_page_size());
+        intermediate_buffer.get_host_buffer_info(), initial_credit_size);
 }
 
 static hailo_status fill_boundary_output_layer(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
         uint8_t **context_meta_data_head_pointer, ResourcesManager &resources_manager, uint8_t stream_index,
         const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config, uint32_t frame_credits_in_bytes,
         ContextSwitchChannelsParsingInfo &channels_parsing_info, const std::string &layer_name, uint8_t network_index, 
-        const std::string &partial_network_name)
+        const std::string &network_name)
 {
    auto channel_index = resources_manager.get_available_channel_index(channels_parsing_info.D2H_channels_in_use,
        ChannelInfo::Type::BOUNDARY, VdmaChannel::Direction::D2H, layer_name);
@@ -1327,19 +1340,21 @@ static hailo_status fill_boundary_output_layer(CONTROL_PROTOCOL__context_switch_
     CHECK_EXPECTED_AS_STATUS(channel_info);
     channel_info->get().set_pcie_stream_index(stream_index);
 
+
+    auto vdma_channel = resources_manager.create_boundary_vdma_channel(channel_index.value(), frame_credits_in_bytes,
+        network_name, layer_name, VdmaChannel::Direction::D2H);
+    CHECK_EXPECTED_AS_STATUS(vdma_channel);
+    auto page_size = vdma_channel.value()->get_page_size();
+
     // Lock the channel for further use in this net_group
     channels_parsing_info.D2H_channels_in_use.insert(channel_index.value());
 
-    auto desc_sizes_pair = resources_manager.get_desc_buffer_sizes_for_boundary_channel(frame_credits_in_bytes,
-        partial_network_name);
-    CHECK_EXPECTED_AS_STATUS(desc_sizes_pair);
-
     LOGGER__DEBUG("Boundary output stream: {} d2h_pcie_channel: {}.", stream_index, channel_index.value());
 
     /* Update metadata */
     auto status = HEF_METADATA__add_network_boundary_output_edge_layer(context_info, 
             context_meta_data_head_pointer, stream_index, channel_index.value(), network_index,
-            nn_stream_config, frame_credits_in_bytes, desc_sizes_pair->first);
+            nn_stream_config, frame_credits_in_bytes, page_size);
     CHECK_SUCCESS(status);
 
     return HAILO_SUCCESS;
@@ -1349,7 +1364,7 @@ static hailo_status fill_inter_context_output_layer(CONTROL_PROTOCOL__context_sw
         uint8_t **context_meta_data_head_pointer, ResourcesManager &resources_manager, uint8_t src_context,
         uint8_t stream_index, const CONTROL_PROTOCOL__nn_stream_config_t &nn_stream_config, uint32_t frame_credits_in_bytes,
         const ProtoHEFEdgeLayer *edge_layer_info, ContextSwitchChannelsParsingInfo &channels_parsing_info,
-        std::set<uint8_t> &channels_to_unlock, uint8_t network_index, const std::string &partial_network_name)
+        std::set<uint8_t> &channels_to_unlock, uint8_t network_index, const std::string &network_name)
 {
     std::vector<uint8_t> connected_h2d_channels;
 
@@ -1366,7 +1381,7 @@ static hailo_status fill_inter_context_output_layer(CONTROL_PROTOCOL__context_sw
     channels_to_unlock.insert(d2h_channel_index.value());
 
     auto intermediate_buffer_exp = resources_manager.create_inter_context_buffer(frame_credits_in_bytes,
-        stream_index, src_context, partial_network_name);
+        stream_index, src_context, network_name);
     CHECK_EXPECTED_AS_STATUS(intermediate_buffer_exp);
     auto &intermediate_buffer = intermediate_buffer_exp->get();
 
@@ -1375,9 +1390,7 @@ static hailo_status fill_inter_context_output_layer(CONTROL_PROTOCOL__context_sw
 
     /* Update metadata */
     auto status = HEF_METADATA__add_inter_context_output_edge_layer(context_info, context_meta_data_head_pointer,
-        stream_index, d2h_channel_index.value(), network_index, nn_stream_config, frame_credits_in_bytes, 
-        intermediate_buffer.dma_address(), intermediate_buffer.descriptors_in_frame(),
-        intermediate_buffer.desc_page_size(), intermediate_buffer.depth());
+        stream_index, d2h_channel_index.value(), network_index, nn_stream_config, intermediate_buffer.get_host_buffer_info());
     CHECK_SUCCESS(status);
 
     return HAILO_SUCCESS;
@@ -1391,32 +1404,30 @@ static hailo_status fill_ddr_layer_multi_context(CONTROL_PROTOCOL__context_switc
 {
     /* Find out if the connected layer has already been parsed */
     uint8_t channel_index = 0;
+
+    CHECK(resources_manager.get_supported_features().padded_ddr_buffers, HAILO_INVALID_HEF,
+        "Failed opening non-compatible HEF that uses the following deprecated features: host-managed DDR buffers." 
+        "Please re-compile the HEF using a newer Dataflow Compiler version (v3.11.0 or newer)");
+    
     if (HAILO_H2D_STREAM == direction) {
         auto channel_index_expected = resources_manager.get_available_channel_index(channels_parsing_info.H2D_channels_in_use,
             ChannelInfo::Type::DDR, VdmaChannel::Direction::H2D);
         CHECK_EXPECTED_AS_STATUS(channel_index_expected);
         channel_index = channel_index_expected.value();
         channels_parsing_info.H2D_channels_in_use.insert(channel_index);
-        /* If managed by the FW - allow reuse of the channel in between contexts */
-        if (resources_manager.get_supported_features().padded_ddr_buffers) {
-            channels_to_unlock.insert(channel_index);
-        }
+        channels_to_unlock.insert(channel_index);
     } else if (HAILO_D2H_STREAM == direction) {
         auto channel_index_expected = resources_manager.get_available_channel_index(channels_parsing_info.D2H_channels_in_use,
             ChannelInfo::Type::DDR, VdmaChannel::Direction::D2H);
         CHECK_EXPECTED_AS_STATUS(channel_index_expected);
         channel_index = channel_index_expected.value();
         channels_parsing_info.D2H_channels_in_use.insert(channel_index);
-        /* If managed by the FW - allow reuse of the channel in between contexts */
-        if (resources_manager.get_supported_features().padded_ddr_buffers) {
-            channels_to_unlock.insert(channel_index);
-        }
+        channels_to_unlock.insert(channel_index);
     } else {
         LOGGER__ERROR("Invalid layer direction");
         return HAILO_INVALID_ARGUMENT;
     }
 
-    auto fw_managed_channel = resources_manager.get_supported_features().padded_ddr_buffers;
     for (auto &ddr_info : resources_manager.ddr_infos()) {
         if (HAILO_H2D_STREAM == direction) {
             /* we have the info already, just validate saved info, add ch_index, and return success! */
@@ -1427,9 +1438,11 @@ static hailo_status fill_ddr_layer_multi_context(CONTROL_PROTOCOL__context_switc
                 ddr_info.h2d_channel_index = channel_index;
                 LOGGER__DEBUG("DDR layer: input stream_index: {}, output stream_index: {}, h2d_pcie_channel {}, d2h_pcie_channel: {}.",
                     ddr_info.h2d_stream_index, ddr_info.d2h_stream_index, ddr_info.h2d_channel_index, ddr_info.d2h_channel_index);
+                const uint32_t initial_credit_size = get_initial_credit_size(edge_layer_proto);
                 return HEF_METADATA__add_ddr_buffer_input_edge_layer(context_switch_info,
                     context_meta_data_head_pointer, ddr_info.h2d_stream_index, ddr_info.h2d_channel_index, network_index,
-                    nn_stream_config, ddr_info.intermediate_buffer->dma_address(), ddr_info.intermediate_buffer->depth(), fw_managed_channel);
+                    nn_stream_config, ddr_info.intermediate_buffer->dma_address(), ddr_info.intermediate_buffer->depth(),
+                    initial_credit_size);
             }
         } else if (HAILO_D2H_STREAM == direction) {
             /* we have the info already, just validate saved info, add ch_index, and return success! */
@@ -1443,8 +1456,8 @@ static hailo_status fill_ddr_layer_multi_context(CONTROL_PROTOCOL__context_switc
                 return HEF_METADATA__add_ddr_buffer_output_edge_layer(context_switch_info,
                     context_meta_data_head_pointer, ddr_info.d2h_stream_index, ddr_info.d2h_channel_index, network_index,
                     nn_stream_config, frame_credits_in_bytes, ddr_info.intermediate_buffer->dma_address(), 
-                    static_cast<uint16_t>(ddr_info.intermediate_buffer->descs_count() - 1), ddr_info.intermediate_buffer->desc_page_size(), 
-                    ddr_info.intermediate_buffer->depth(), fw_managed_channel);
+                    ddr_info.intermediate_buffer->desc_page_size(), ddr_info.intermediate_buffer->depth(),
+                    ddr_info.min_buffered_rows);
             }
         } else {
             LOGGER__ERROR("Invalid layer direction");
@@ -1486,40 +1499,32 @@ static hailo_status fill_ddr_layer_multi_context(CONTROL_PROTOCOL__context_switc
 
     local_info.intermediate_buffer = &ddr_buffer->get();
 
-    if (resources_manager.get_supported_features().padded_ddr_buffers) {
-        CHECK(0 == (DEFAULT_DESC_PAGE_SIZE % local_info.intermediate_buffer->desc_page_size()), HAILO_INTERNAL_FAILURE,
-            "In padded DDR buffers, desc list page size must be dividor of {}", DEFAULT_DESC_PAGE_SIZE);
-        CHECK(0 == (local_info.row_size % local_info.intermediate_buffer->desc_page_size()), HAILO_INTERNAL_FAILURE, 
-            "If HEF supports padded DDR buffers, row size must be a multiple of descriptor page size");
-        local_info.descriptors_per_frame = (local_info.row_size / local_info.intermediate_buffer->desc_page_size()) * 
-            edge_layer_proto.layer_info().edge_layer_base().core_buffers_per_frame();
-
-        auto programed_descs = ddr_buffer->get().program_ddr();
-        CHECK_EXPECTED_AS_STATUS(programed_descs);
-        local_info.initial_programed_descs = programed_descs.release();
-    } else {
-        LOGGER__WARNING("HEF from an old version detected. For optimal perfomance, please consider re-compile the HEF");
-        auto programed_descs = ddr_buffer->get().program_host_managed_ddr(local_info.row_size,
-            local_info.min_buffered_rows * DDR_THREADS_MIN_BUFFERED_ROWS_INITIAL_SCALE, 0);
-        CHECK_EXPECTED_AS_STATUS(programed_descs);
-        local_info.initial_programed_descs = programed_descs.release();
-        local_info.descriptors_per_frame = 0; // unused for host controlled ddr buffering
-    }
+    CHECK(0 == (DEFAULT_DESC_PAGE_SIZE % local_info.intermediate_buffer->desc_page_size()), HAILO_INTERNAL_FAILURE,
+        "In padded DDR buffers, desc list page size must be dividor of {}", DEFAULT_DESC_PAGE_SIZE);
+    CHECK(0 == (local_info.row_size % local_info.intermediate_buffer->desc_page_size()), HAILO_INTERNAL_FAILURE, 
+        "If HEF supports padded DDR buffers, row size must be a multiple of descriptor page size");
+    local_info.descriptors_per_frame = (local_info.row_size / local_info.intermediate_buffer->desc_page_size()) * 
+        edge_layer_proto.layer_info().edge_layer_base().core_buffers_per_frame();
+
+    auto programed_descs = ddr_buffer->get().program_ddr();
+    CHECK_EXPECTED_AS_STATUS(programed_descs);
+    local_info.initial_programed_descs = programed_descs.release();
     local_info.desc_list_size_mask = static_cast<uint32_t>(local_info.intermediate_buffer->descs_count() - 1);
 
     // Add layer to metadata
     if (HAILO_H2D_STREAM == direction) {
+        const uint32_t initial_credit_size = get_initial_credit_size(edge_layer_proto);
         auto status = HEF_METADATA__add_ddr_buffer_input_edge_layer(context_switch_info,
             context_meta_data_head_pointer, local_info.h2d_stream_index, local_info.h2d_channel_index, network_index,
             nn_stream_config, local_info.intermediate_buffer->dma_address(), local_info.intermediate_buffer->depth(),
-            fw_managed_channel);
+            initial_credit_size);
         CHECK_SUCCESS(status);
     } else if (HAILO_D2H_STREAM == direction) {
         auto status = HEF_METADATA__add_ddr_buffer_output_edge_layer(context_switch_info,
             context_meta_data_head_pointer, local_info.d2h_stream_index, local_info.d2h_channel_index,
             network_index, nn_stream_config, frame_credits_in_bytes, local_info.intermediate_buffer->dma_address(), 
-            static_cast<uint16_t>(local_info.intermediate_buffer->descs_count() - 1), local_info.intermediate_buffer->desc_page_size(), 
-            local_info.intermediate_buffer->depth(), fw_managed_channel);
+            local_info.intermediate_buffer->desc_page_size(), local_info.intermediate_buffer->depth(),
+            local_info.min_buffered_rows);
         CHECK_SUCCESS(status);
     } else {
         LOGGER__ERROR("Invalid layer direction");
@@ -1539,15 +1544,27 @@ Expected<std::string> HefUtils::get_partial_network_name_by_index(const ProtoHEF
             network_index, network_group_proto.networks_names_size());
         return std::string(network_group_proto.networks_names(network_index));
     } else {
-        return HailoRTDefaults::get_partial_network_name();
+        auto partial_network_name = network_group_proto.network_group_metadata().network_group_name();
+        return partial_network_name;
     }
 }
 
+std::string HefUtils::get_network_name(const std::string &net_group_name, const std::string &partial_network_name)
+{
+    return net_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name;
+}
+
+std::string HefUtils::get_network_name(const ProtoHEFNetworkGroup &net_group, const std::string &partial_network_name)
+{
+    return HefUtils::get_network_name(net_group.network_group_metadata().network_group_name(), partial_network_name);
+}
+
 static hailo_status parse_and_fill_h2d_layer_multi_context(
     CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
     uint8_t **context_meta_data_head_pointer, const ProtoHEFEdgeLayer &edge_layer_proto,
     ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager,
-    uint8_t context_index, std::set<uint8_t> &channels_to_unlock)
+    uint8_t context_index, std::set<uint8_t> &channels_to_unlock, const std::string &network_name,
+    uint8_t network_index)
 {
     uint8_t stream_index = 0;
     uint32_t frame_credits_in_bytes = 0;
@@ -1565,8 +1582,6 @@ static hailo_status parse_and_fill_h2d_layer_multi_context(
         edge_layer_proto.context_switch_info().edge_connection_type());
     CHECK_EXPECTED_AS_STATUS(nn_stream_config, "Failed parse nn stream config");
     auto layer_name = edge_layer_proto.layer_info().name();
-    auto support_multi_networks = resources_manager.get_supported_features().multi_network_support;
-    auto network_index = static_cast<uint8_t>((support_multi_networks) ? edge_layer_proto.network_index() : 0);
 
     /* credits work on periph bytes */
     frame_credits_in_bytes = (nn_stream_config->periph_bytes_per_buffer * nn_stream_config->core_buffers_per_frame);
@@ -1574,7 +1589,8 @@ static hailo_status parse_and_fill_h2d_layer_multi_context(
     switch (edge_layer_proto.context_switch_info().edge_connection_type()) {
         case ProtoHEFEdgeConnectionType::PROTO__EDGE_CONNECTION_TYPE__BOUNDARY:
             return fill_boundary_input_layer(context_info, context_meta_data_head_pointer, stream_index,
-                *nn_stream_config, channels_parsing_info, resources_manager, layer_name, network_index);
+                edge_layer_proto, *nn_stream_config, channels_parsing_info, resources_manager, layer_name,
+                network_name, network_index, frame_credits_in_bytes);
 
         case ProtoHEFEdgeConnectionType::PROTO__EDGE_CONNECTION_TYPE__INTERMEDIATE:
             return fill_inter_context_input_layer(context_info, context_meta_data_head_pointer, resources_manager,
@@ -1592,11 +1608,12 @@ static hailo_status parse_and_fill_h2d_layer_multi_context(
     }
 }
 
-static hailo_status parse_and_fill_d2h_layer_multi_context(ProtoHEFNetworkGroupPtr network_group_proto, 
-        CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
-        uint8_t **context_meta_data_head_pointer, const ProtoHEFEdgeLayer &edge_layer_proto,
-        ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager,
-        uint8_t context_index, std::set<uint8_t> &channels_to_unlock)
+static hailo_status parse_and_fill_d2h_layer_multi_context(
+    CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
+    uint8_t **context_meta_data_head_pointer, const ProtoHEFEdgeLayer &edge_layer_proto,
+    ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager,
+    uint8_t context_index, std::set<uint8_t> &channels_to_unlock, const std::string &network_name,
+    uint8_t network_index)
 {
     uint8_t stream_index = 0;
     uint32_t frame_credits_in_bytes = 0;
@@ -1633,23 +1650,17 @@ static hailo_status parse_and_fill_d2h_layer_multi_context(ProtoHEFNetworkGroupP
         return HAILO_INVALID_HEF;
     }
 
-    auto support_multi_networks = resources_manager.get_supported_features().multi_network_support;
-    auto network_index = static_cast<uint8_t>((support_multi_networks) ? edge_layer_proto.network_index() : 0);
-    auto partial_network_name = HefUtils::get_partial_network_name_by_index(*network_group_proto, network_index, 
-        resources_manager.get_supported_features());
-    CHECK_EXPECTED_AS_STATUS(partial_network_name);
-    
     switch (edge_layer_proto.context_switch_info().edge_connection_type()) {
         case ProtoHEFEdgeConnectionType::PROTO__EDGE_CONNECTION_TYPE__BOUNDARY:
             return fill_boundary_output_layer(context_info, context_meta_data_head_pointer, resources_manager,
                 stream_index, nn_stream_config, frame_credits_in_bytes, channels_parsing_info, layer_name,
-                network_index, partial_network_name.value());
+                network_index, network_name);
 
         case ProtoHEFEdgeConnectionType::PROTO__EDGE_CONNECTION_TYPE__INTERMEDIATE:
             CHECK(!is_mux, HAILO_INVALID_HEF, "Inter-context layer can't be mux.");
             return fill_inter_context_output_layer(context_info, context_meta_data_head_pointer, resources_manager,
                 context_index, stream_index, nn_stream_config, frame_credits_in_bytes,
-                &edge_layer_proto, channels_parsing_info, channels_to_unlock, network_index, partial_network_name.value());
+                &edge_layer_proto, channels_parsing_info, channels_to_unlock, network_index, network_name);
 
         case ProtoHEFEdgeConnectionType::PROTO__EDGE_CONNECTION_TYPE__DDR:
             return fill_ddr_layer_multi_context(context_info, context_meta_data_head_pointer, resources_manager, context_index,
@@ -1662,7 +1673,39 @@ static hailo_status parse_and_fill_d2h_layer_multi_context(ProtoHEFNetworkGroupP
     }
 }
 
-static hailo_status parse_and_fill_layers_mapping_multi_context(ProtoHEFNetworkGroupPtr network_group_proto, 
+static hailo_status fill_ddr_buffers_info(CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
+    uint8_t **context_meta_data_head_pointer, ResourcesManager &resources_manager, uint8_t context_index)
+{
+    const CONTROL_PROTOCOL__TRIGGER_t none_trigger = HEF_METADATA__build_none_trigger();
+    bool found_ddr_pair_for_context = false;
+    // See: HRT-5373
+    static const bool NOT_REPEATED = false;
+
+    for (auto& ddr_info : resources_manager.ddr_infos()) {
+        if (context_index == ddr_info.context_index) {
+            /* Any action must have a trigger */
+            auto status = HEF_METADATA__add_trigger_to_trigger_group(context_info, context_meta_data_head_pointer, 
+                &none_trigger);
+            CHECK_SUCCESS(status, "failed to add NONE trigger before ddr buffer pair infos");
+            /* Add ddr pair info action */
+            status = HEF_METADATA__add_ddr_pair_info(context_info, context_meta_data_head_pointer, 
+                ddr_info.h2d_channel_index, ddr_info.d2h_channel_index, ddr_info.descriptors_per_frame, 
+                ddr_info.initial_programed_descs, NOT_REPEATED);
+            CHECK_SUCCESS(status,"failed to add ddr pair info");
+            found_ddr_pair_for_context = true;
+        }
+    }
+
+    if (found_ddr_pair_for_context) {
+        /* No need to add NONE trigger. This action can be inside the last none trigger of the last DDR pair */
+        auto status = HEF_METADATA__add_ddr_buffering_start(context_info, context_meta_data_head_pointer, NOT_REPEATED);
+        CHECK_SUCCESS(status,"failed to add ddr buffer start action");
+    }
+
+    return HAILO_SUCCESS;
+}
+
+static hailo_status parse_and_fill_edge_layers_mapping(ProtoHEFNetworkGroupPtr network_group_proto, 
         CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
         uint8_t **context_meta_data_head_pointer, const ProtoHEFContextMetadata *context_metadata, 
         ContextSwitchChannelsParsingInfo &channels_parsing_info, ResourcesManager &resources_manager, uint8_t context_index)
@@ -1671,16 +1714,28 @@ static hailo_status parse_and_fill_layers_mapping_multi_context(ProtoHEFNetworkG
     // We use those sets to unlock resources at the end of each context parsing to prevent reuse within the same context
     std::set<uint8_t> channels_to_unlock = {};
 
-    CHECK(0 < context_metadata->edge_layers_size(), HAILO_INVALID_HEF, "No edge layers in this context");
+    const auto number_of_edge_layers = context_metadata->edge_layers_size();
+    CHECK(0 < number_of_edge_layers, HAILO_INVALID_HEF, "No edge layers in this context");
+    CHECK(IS_FIT_IN_UINT8(number_of_edge_layers), HAILO_INVALID_HEF, 
+        "Failed to parse HEF. Invalid edge_layers_size: {}.", number_of_edge_layers);
 
     for (const auto &edge_layer_proto : context_metadata->edge_layers()) {
+        auto support_multi_networks = resources_manager.get_supported_features().multi_network_support;
+        auto network_index = static_cast<uint8_t>((support_multi_networks) ? edge_layer_proto.network_index() : 0);
+        auto partial_network_name = HefUtils::get_partial_network_name_by_index(*network_group_proto, network_index,
+            resources_manager.get_supported_features());
+        CHECK_EXPECTED_AS_STATUS(partial_network_name);
+        auto network_name = HefUtils::get_network_name(*network_group_proto, partial_network_name.value());
+
         if (ProtoHEFEdgeLayerDirection::PROTO__EDGE_LAYER_DIRECTION__HOST_TO_DEVICE == edge_layer_proto.direction()) {
             status = parse_and_fill_h2d_layer_multi_context(context_info, context_meta_data_head_pointer,
-                edge_layer_proto, channels_parsing_info, resources_manager, context_index, channels_to_unlock);
+                edge_layer_proto, channels_parsing_info, resources_manager, context_index, channels_to_unlock,
+                network_name, network_index);
             CHECK_SUCCESS(status);
         } else if (ProtoHEFEdgeLayerDirection::PROTO__EDGE_LAYER_DIRECTION__DEVICE_TO_HOST == edge_layer_proto.direction()) {
-            status = parse_and_fill_d2h_layer_multi_context(network_group_proto, context_info, context_meta_data_head_pointer, 
-                edge_layer_proto, channels_parsing_info, resources_manager, context_index, channels_to_unlock);
+            status = parse_and_fill_d2h_layer_multi_context(context_info, context_meta_data_head_pointer, 
+                edge_layer_proto, channels_parsing_info, resources_manager, context_index, channels_to_unlock,
+                network_name, network_index);
             CHECK_SUCCESS(status);
         } else {
             LOGGER__ERROR("Invalid argument: stream_direction");
@@ -1702,37 +1757,8 @@ static hailo_status parse_and_fill_layers_mapping_multi_context(ProtoHEFNetworkG
         }
     }
 
-    return HAILO_SUCCESS;
-}
-
-static hailo_status fill_ddr_buffers_info(CONTROL_PROTOCOL__context_switch_context_info_t *context_info, 
-    uint8_t **context_meta_data_head_pointer, ResourcesManager &resources_manager, uint8_t context_index)
-{
-    const CONTROL_PROTOCOL__TRIGGER_t none_trigger = HEF_METADATA__build_none_trigger();
-    bool found_ddr_pair_for_context = false;
-    // See: HRT-5373
-    static const bool NOT_REPEATED = false;
-
-    for (auto& ddr_info : resources_manager.ddr_infos()) {
-        if (context_index == ddr_info.context_index) {
-            /* Any action must have a trigger */
-            auto status = HEF_METADATA__add_trigger_to_trigger_group(context_info, context_meta_data_head_pointer, 
-                &none_trigger);
-            CHECK_SUCCESS(status, "failed to add NONE trigger before ddr buffer pair infos");
-            /* Add ddr pair info action */
-            status = HEF_METADATA__add_ddr_pair_info(context_info, context_meta_data_head_pointer, 
-                ddr_info.h2d_channel_index, ddr_info.d2h_channel_index, ddr_info.descriptors_per_frame, 
-                ddr_info.initial_programed_descs, NOT_REPEATED);
-            CHECK_SUCCESS(status,"failed to add ddr pair info");
-            found_ddr_pair_for_context = true;
-        }
-    }
-
-    if (found_ddr_pair_for_context) {
-        /* No need to add NONE trigger. This action can be inside the last none trigger of the last DDR pair */
-        auto status = HEF_METADATA__add_ddr_buffering_start(context_info, context_meta_data_head_pointer, NOT_REPEATED);
-        CHECK_SUCCESS(status,"failed to add ddr buffer start action");
-    }
+    status = fill_ddr_buffers_info(context_info, context_meta_data_head_pointer, resources_manager, context_index);
+    CHECK_SUCCESS(status);
 
     return HAILO_SUCCESS;
 }
@@ -1819,14 +1845,15 @@ static std::map<uint32_t, uint8_t> get_start_indexes_of_repeated_actions(
     return result;
 }
 
-static std::set<uint32_t> get_end_indexes_of_write_ccw_actions(
+static std::set<uint32_t> get_end_indexes_of_action_type(
     const std::vector<ContextSwitchConfigActionPtr> &actions,
-    const std::vector<std::pair<uint32_t, uint32_t>> &repeated_indexes)
+    const std::vector<std::pair<uint32_t, uint32_t>> &repeated_indexes,
+    const ContextSwitchConfigAction::Type &required_action_type)
 {
     std::set<uint32_t> result;
     for (const auto &index_pair : repeated_indexes) {
         const auto curr_action_type = actions[index_pair.first]->get_type();
-        if (ContextSwitchConfigAction::Type::WriteDataCcw != curr_action_type) {
+        if (required_action_type != curr_action_type) {
             continue;
         }
 
@@ -1837,7 +1864,7 @@ static std::set<uint32_t> get_end_indexes_of_write_ccw_actions(
 }
 
 static hailo_status proccess_write_ccw_action(const ContextSwitchConfigActionPtr &configuration_action,
-    std::vector<ConfigResources> &config_resources, std::set<uint8_t> &pending_cfg_ch_buffer,
+    std::vector<ConfigBuffer> &config_resources, std::set<uint8_t> &pending_cfg_ch_buffer,
     std::vector<uint16_t> &total_ccw_bursts, const std::set<uint32_t> &end_indexes_of_write_ccw_actions, 
     const uint32_t &action_index, const bool support_pre_fetch, 
     std::vector<ContextSwitchConfigActionPtr> &processed_configuration_actions)
@@ -1862,11 +1889,16 @@ static hailo_status proccess_write_ccw_action(const ContextSwitchConfigActionPtr
         /* Add the last CCW write into the buffer */
         processed_configuration_actions.emplace_back(configuration_action);
 
-        /* Build descriptor list for this buffer */
-        auto create_desc_action = CreateConfigDescAndFetchAction::create(config_resources, pending_cfg_ch_buffer, 
-            total_ccw_bursts, support_pre_fetch);
-        CHECK_EXPECTED_AS_STATUS(create_desc_action);
-        processed_configuration_actions.emplace_back(create_desc_action.release());
+        CHECK(total_ccw_bursts.size() == config_resources.size(), HAILO_INTERNAL_FAILURE, "Invalid cfg channels count");
+        for (const auto cfg_channel : pending_cfg_ch_buffer) {
+            CHECK(cfg_channel < config_resources.size(), HAILO_INTERNAL_FAILURE, "Invalid cfg channel index");
+
+            auto fetch_config_action = support_pre_fetch ?
+                AddCcwBurstAction::create(cfg_channel, total_ccw_bursts[cfg_channel]) :
+                CreateConfigDescAndFetchAction::create(cfg_channel, config_resources[cfg_channel]);
+            CHECK_EXPECTED_AS_STATUS(fetch_config_action);
+            processed_configuration_actions.emplace_back(fetch_config_action.release());
+        }
 
         /* Cleanups */
         pending_cfg_ch_buffer.clear();
@@ -1880,15 +1912,31 @@ static hailo_status proccess_write_ccw_action(const ContextSwitchConfigActionPtr
     return HAILO_SUCCESS;
 }
 
+static hailo_status proccess_trigger_new_data_input_action(const ContextSwitchConfigActionPtr &configuration_action,
+    const std::set<uint32_t> &end_indexes_of_trigger_new_data_input_actions, 
+    const uint32_t &action_index, std::vector<ContextSwitchConfigActionPtr> &processed_configuration_actions)
+{
+    // At the end of a consecutive group of TriggerNewDataFromDataInput actions, we can trigger the BurstCreditsTask
+    // in the FW, via StartBurstCreditsTaskAction.
+    processed_configuration_actions.emplace_back(configuration_action);
+    if (contains(end_indexes_of_trigger_new_data_input_actions, action_index)) {
+        auto start_burst_credits_task_action = StartBurstCreditsTaskAction::create();
+        CHECK_EXPECTED_AS_STATUS(start_burst_credits_task_action);
+        processed_configuration_actions.emplace_back(start_burst_credits_task_action.release());
+    }
+
+    return HAILO_SUCCESS;
+}
 
 // Adds context switch configuration actions that don't appear in the HEF:
 // * If groups of consecutive actions can be "merged" as repeated actions (saving room the FW's
 //   action list) a RepeatedHeaderAction is placed before the relevant actions.
 //   See also: CONTROL_PROTOCOL__REPEATED_ACTION_t's documnetion in control_protocol.h.
 // * At the end of each consecutive group of WriteDataCcwAction, a CreateConfigDescAndFetchAction is added.
+// * At the end of each consecutive group of TriggerNewDataFromDataInput, a StartBurstCreditsTaskAction is added.
 static Expected<std::vector<ContextSwitchConfigActionPtr>> process_configuration_actions(
     std::vector<ContextSwitchConfigActionPtr> &input_configuration_actions,
-    std::vector<ConfigResources> &config_resources, const bool support_pre_fetch)
+    std::vector<ConfigBuffer> &config_resources, const bool support_pre_fetch)
 {
     std::vector<ContextSwitchConfigActionPtr> processed_configuration_actions;
     
@@ -1896,8 +1944,12 @@ static Expected<std::vector<ContextSwitchConfigActionPtr>> process_configuration
     std::vector<uint16_t> total_ccw_bursts(config_resources.size(), 0);
 
     const auto repeated_indexes = get_repreated_actions_boundary_indices(input_configuration_actions);
-    const auto start_indexes_of_repeated_actions = get_start_indexes_of_repeated_actions(input_configuration_actions, repeated_indexes);
-    const auto end_indexes_of_write_ccw_actions = get_end_indexes_of_write_ccw_actions(input_configuration_actions, repeated_indexes);
+    const auto start_indexes_of_repeated_actions = get_start_indexes_of_repeated_actions(
+        input_configuration_actions, repeated_indexes);
+    const auto end_indexes_of_write_ccws = get_end_indexes_of_action_type(input_configuration_actions,
+        repeated_indexes, ContextSwitchConfigAction::Type::WriteDataCcw);
+    const auto end_indexes_of_trigger_new_data_from_inputs = get_end_indexes_of_action_type(
+        input_configuration_actions, repeated_indexes, ContextSwitchConfigAction::Type::TriggerNewDataFromDataInput);
     for (uint32_t action_index = 0; action_index < input_configuration_actions.size(); action_index++) {
         // A group of actions can be "merged" as repeated actions.
         // Hence we add a RepeatedHeaderAction and mark all the actions in this group as "reapted"
@@ -1914,11 +1966,13 @@ static Expected<std::vector<ContextSwitchConfigActionPtr>> process_configuration
 
         // Add the current action
         const auto &configuration_action = input_configuration_actions[action_index];
-
         if (ContextSwitchConfigAction::Type::WriteDataCcw == configuration_action->get_type()) {
             auto status = proccess_write_ccw_action(configuration_action, config_resources, pending_cfg_ch_buffer,
-                total_ccw_bursts, end_indexes_of_write_ccw_actions, action_index, 
-                support_pre_fetch, processed_configuration_actions);
+                total_ccw_bursts, end_indexes_of_write_ccws, action_index, support_pre_fetch, processed_configuration_actions);
+            CHECK_SUCCESS_AS_EXPECTED(status);
+        } else if (ContextSwitchConfigAction::Type::TriggerNewDataFromDataInput == configuration_action->get_type()) {
+            auto status = proccess_trigger_new_data_input_action(configuration_action, end_indexes_of_trigger_new_data_from_inputs,
+                action_index, processed_configuration_actions);
             CHECK_SUCCESS_AS_EXPECTED(status);
         } else {
             // Add the current action
@@ -1937,7 +1991,7 @@ static bool is_mercury_device_type(const ProtoHEFHwArch &hw_arch)
 }
 
 static hailo_status parse_actions_in_operation(const ProtoHEFOperation &operation,
-    Device &device, const ProtoHEFHwArch &hw_arch, std::vector<ConfigResources> &config_resources, 
+    Device &device, const ProtoHEFHwArch &hw_arch, std::vector<ConfigBuffer> &config_resources, 
     const ResourcesManager &resources_manager, ProtoHEFNetworkGroupPtr network_group_proto, 
     CONTROL_PROTOCOL__context_switch_context_info_t &context_info, uint8_t **context_meta_data_head_pointer)
 {
@@ -1977,26 +2031,16 @@ static hailo_status fill_context_recepies_for_multi_context(ProtoHEFNetworkGroup
     uint8_t *context_meta_data_head_pointer = context_info.context_network_data;
 
     // Add edge layers mapping
-    status = parse_and_fill_layers_mapping_multi_context(network_group_proto, &context_info, &context_meta_data_head_pointer, 
+    status = parse_and_fill_edge_layers_mapping(network_group_proto, &context_info, &context_meta_data_head_pointer, 
         &proto_context.metadata(), channels_parsing_info, resources_manager, context_index);
     CHECK_SUCCESS(status);
 
-    auto number_of_edge_layers = proto_context.metadata().edge_layers_size();
-    CHECK(IS_FIT_IN_UINT8(number_of_edge_layers), HAILO_INVALID_HEF, 
-        "Failed to parse HEF. Invalid edge_layers_size: {}.", number_of_edge_layers);
-
-    // For the case of DDR buffers in FW - add DDR info after parsing all edge layers and before parsing all other actions
-    if (resources_manager.get_supported_features().padded_ddr_buffers) {
-        status = fill_ddr_buffers_info(&context_info, &context_meta_data_head_pointer, resources_manager, context_index);
-        CHECK_SUCCESS(status);
-    }
-
     CHECK(IS_FIT_IN_UINT8(proto_context.operations_size()), HAILO_INVALID_HEF,
         "Failed to parse HEF. Invalid operations_count: {}.", proto_context.operations_size());
 
     context_info.context_stream_remap_data.should_use_stream_remap = static_cast<uint8_t>(proto_context.metadata().shmiglue_info().should_use_shmiglue());
 
-    /* Parse context */
+    // Parse context
     for (const auto &operation : proto_context.operations()) {
         const auto operation_trigger = ContextSwitchTrigger::create(operation.trigger());
         CHECK_EXPECTED_AS_STATUS(operation_trigger);
@@ -2017,14 +2061,24 @@ static hailo_status fill_context_recepies_for_multi_context(ProtoHEFNetworkGroup
 
 static hailo_status fill_preliminary_config_recepies_for_multi_context(const ProtoHEFHwArch &hw_arch,
     CONTROL_PROTOCOL__context_switch_context_info_t &context_info, ResourcesManager &resources_manager,
-    ProtoHEFNetworkGroupPtr network_group_proto, const ProtoHEFPreliminaryConfig &proto_preliminary_config, Device &device)
+    ContextSwitchChannelsParsingInfo &channels_parsing_info, ProtoHEFNetworkGroupPtr network_group_proto,
+    const ProtoHEFPreliminaryConfig &proto_preliminary_config, Device &device)
 {
     uint8_t *context_meta_data_head_pointer = context_info.context_network_data;
 
     CHECK(IS_FIT_IN_UINT8(proto_preliminary_config.operation_size()), HAILO_INVALID_HEF,
         "Failed to parse HEF. Invalid operations_count: {}.", proto_preliminary_config.operation_size());
 
-    /* Parse preliminary config */
+    if (resources_manager.get_supported_features().preliminary_run_asap) {
+        // Add edge layers mapping (only preliminary_run_asap networks have edge layers in the preliminary context)
+        static const auto PRELIMINARY_CONTEXT_INDEX = 0;
+        auto status = parse_and_fill_edge_layers_mapping(network_group_proto, &context_info, &context_meta_data_head_pointer, 
+            &(network_group_proto->contexts(PRELIMINARY_CONTEXT_INDEX).metadata()), channels_parsing_info, resources_manager,
+            PRELIMINARY_CONTEXT_INDEX);
+        CHECK_SUCCESS(status);
+    }
+
+    // Parse preliminary config
     for (const auto &operation_proto : proto_preliminary_config.operation()) {
         const auto operation_trigger = ContextSwitchTrigger::create(operation_proto.trigger());
         CHECK_EXPECTED_AS_STATUS(operation_trigger);
@@ -2036,7 +2090,7 @@ static hailo_status fill_preliminary_config_recepies_for_multi_context(const Pro
         CHECK_SUCCESS(status);
     }
 
-    // update context_network_data_length per context, and preliminary_context_descriptors count in main header
+    // Update context_network_data_length per context, and preliminary_context_descriptors count in main header
     context_info.context_network_data_length =
         static_cast<uint32_t>(context_meta_data_head_pointer - context_info.context_network_data);
 
@@ -2071,24 +2125,32 @@ Expected<std::shared_ptr<ResourcesManager>> Hef::Impl::create_resources_manager(
     auto preliminary_context = resources_manager->add_new_context();
     CHECK_EXPECTED(preliminary_context);
 
+    // TODO: Support sharing of ContextSwitchChannelsParsingInfo between fill_preliminary_config_recepies_for_multi_context
+    //       and fill_context_recepies_for_multi_context (HRT-6683).
+    //       When running in preliminary_run_asap mode the channels used by the first dynamic context and by the preliminary
+    //       context are the same channels. We need to add the sane edge_layers for both contexts (look for calls to 
+    //       hef_metadata__add_edge_layer_header) so that the needed actions will be added to the action list. However,
+    //       due to the logic in ResourceManager::get_available_channel_index's blacklist channels that should be the same
+    //       will get different indexes. Need to refactor the logic of that function and the entire channel index allocation logic.
+    ContextSwitchChannelsParsingInfo channels_parsing_info_preliminary{};
     auto status = fill_preliminary_config_recepies_for_multi_context(hw_arch, preliminary_context.value().get(),
-        resources_manager.value(), network_group_proto, network_group_proto->preliminary_config(), device);
+        resources_manager.value(), channels_parsing_info_preliminary, network_group_proto, network_group_proto->preliminary_config(),
+        device);
     CHECK_SUCCESS_AS_EXPECTED(status);
     resources_manager->update_preliminary_config_buffer_info();
 
-    ContextSwitchChannelsParsingInfo channels_parsing_info = {};
-
+    ContextSwitchChannelsParsingInfo channels_parsing_info_dynamic{};
     for (uint8_t context_index = 0; context_index < network_group_proto->contexts_size(); ++context_index) {
         auto new_context = resources_manager->add_new_context();
         CHECK_EXPECTED(new_context);
 
         status = fill_context_recepies_for_multi_context(network_group_proto, hw_arch, new_context.value().get(), resources_manager.value(),
-            context_index, network_group_proto->contexts(context_index), device, channels_parsing_info);
+            context_index, network_group_proto->contexts(context_index), device, channels_parsing_info_dynamic);
         CHECK_SUCCESS_AS_EXPECTED(status);
     }
     resources_manager->update_dynamic_contexts_buffer_info();
 
-    status = resources_manager->create_vdma_channels();
+    status = resources_manager->create_internal_vdma_channels();
     CHECK_SUCCESS_AS_EXPECTED(status);
 
     auto resources_manager_ptr = make_shared_nothrow<ResourcesManager>(resources_manager.release());
@@ -2383,7 +2445,7 @@ hailo_status ContextSwitchTrigger::add_to_trigger_group(CONTROL_PROTOCOL__contex
 }
 
 Expected<ContextSwitchConfigActionPtr> ContextSwitchConfigAction::create(const ProtoHEFAction &proto_action, Device &device,
-    std::vector<ConfigResources> &config, const ResourcesManager &resources_manager, const ProtoHEFNetworkGroup &net_group,
+    std::vector<ConfigBuffer> &config, const ResourcesManager &resources_manager, const ProtoHEFNetworkGroup &net_group,
     bool support_pre_fetch)
 {
     switch (proto_action.action_case()) {
@@ -2516,7 +2578,7 @@ bool WriteDataAction::supports_repeated_block() const
 }
 
 Expected<ContextSwitchConfigActionPtr> WriteDataCcwAction::create(const ProtoHEFAction& proto_action,
-    std::vector<ConfigResources> &config, bool support_pre_fetch)
+    std::vector<ConfigBuffer> &config, bool support_pre_fetch)
 {
     // Add buffer to cfg_ch buffer without making descriptors (saving offset as the total data so far)
     CHECK_AS_EXPECTED(proto_action.write_data_ccw().cfg_channel_index() < config.size(), HAILO_INVALID_HEF,
@@ -2525,39 +2587,34 @@ Expected<ContextSwitchConfigActionPtr> WriteDataCcwAction::create(const ProtoHEF
     CHECK_AS_EXPECTED(IS_FIT_IN_UINT8(proto_action.write_data_ccw().cfg_channel_index()), HAILO_INVALID_HEF,
         "Invalid cfg channel index");
     
-    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) WriteDataCcwAction(proto_action, config,
-        support_pre_fetch));
+    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) WriteDataCcwAction(proto_action,
+        config[proto_action.write_data_ccw().cfg_channel_index()], support_pre_fetch));
     CHECK_AS_EXPECTED((nullptr != result), HAILO_OUT_OF_HOST_MEMORY);
     return result;
 }
 
-WriteDataCcwAction::WriteDataCcwAction(const ProtoHEFAction& proto_action, std::vector<ConfigResources> &config,
+WriteDataCcwAction::WriteDataCcwAction(const ProtoHEFAction& proto_action, ConfigBuffer &config,
     bool support_pre_fetch) :
     ContextSwitchConfigAction(Type::WriteDataCcw, proto_action),
     m_config(config),
     m_support_pre_fetch(support_pre_fetch)
 {}
 
-bool WriteDataCcwAction::should_pad_with_nops()
+bool WriteDataCcwAction::is_last_ccw_write()
 {
-    if (!m_support_pre_fetch) {
-        return false;
-    }
-
     auto write_size = m_proto_action.write_data_ccw().data().length();
-    auto cfg_channel = m_proto_action.write_data_ccw().cfg_channel_index();
     /* If last operation in context - Add nops to fill the buffer */
-    if ((write_size + m_config[cfg_channel].get_current_buffer_size()) != m_config[cfg_channel].get_total_cfg_size()) {
+    if ((write_size + m_config.get_current_buffer_size()) != m_config.get_total_cfg_size()) {
         return false;
     }
 
     return true;
 }
 
-hailo_status WriteDataCcwAction::pad_with_nops(uint8_t cfg_channel_index)
+hailo_status WriteDataCcwAction::pad_with_nops()
 {
-    auto page_size = m_config[cfg_channel_index].get_page_size();
-    auto buffer_size = m_config[cfg_channel_index].get_total_cfg_size();
+    auto page_size = m_config.desc_page_size();
+    auto buffer_size = m_config.get_total_cfg_size();
     auto buffer_residue = buffer_size % page_size;
     if (0 != buffer_residue % CCW_HEADER_SIZE) {
         LOGGER__ERROR("CFG channel buffer size must be a multiple of CCW header size ({})", CCW_HEADER_SIZE);
@@ -2570,7 +2627,7 @@ hailo_status WriteDataCcwAction::pad_with_nops(uint8_t cfg_channel_index)
            CCW of all zeros (64’h0) should be treated as NOP – ignore CCW and expect CCW in next 64b word. 
            When CSM recognize it is a NOP it pops it from the channel FIFO without forward any address/data/command, 
            does not contribute to CRC calculations but return credits to the peripheral as usual. */
-        m_config[cfg_channel_index].write(reinterpret_cast<const void *>(&CCW_NOP), sizeof(CCW_NOP));
+        m_config.write(reinterpret_cast<const void *>(&CCW_NOP), sizeof(CCW_NOP));
     }
 
     return HAILO_SUCCESS;
@@ -2579,13 +2636,22 @@ hailo_status WriteDataCcwAction::pad_with_nops(uint8_t cfg_channel_index)
 
 hailo_status WriteDataCcwAction::execute(CONTROL_PROTOCOL__context_switch_context_info_t *, uint8_t **)
 {
-    if (should_pad_with_nops()) {
-        auto status = pad_with_nops(static_cast<uint8_t>(m_proto_action.write_data_ccw().cfg_channel_index()));
+    const bool is_last_write = is_last_ccw_write();
+    if (m_support_pre_fetch && is_last_write) {
+        auto status = pad_with_nops();
         CHECK_SUCCESS(status);
     }
 
-    return m_config[m_proto_action.write_data_ccw().cfg_channel_index()].write(
-        m_proto_action.write_data_ccw().data().data(), m_proto_action.write_data_ccw().data().length());
+    auto status = m_config.write(m_proto_action.write_data_ccw().data().data(),
+        m_proto_action.write_data_ccw().data().length());
+    CHECK_SUCCESS(status);
+
+    if (m_support_pre_fetch && is_last_write) {
+        auto desc_count = m_config.program_descriptors();
+        CHECK_EXPECTED_AS_STATUS(desc_count);
+    }
+
+    return HAILO_SUCCESS;
 }
 
 bool WriteDataCcwAction::supports_repeated_block() const
@@ -2594,53 +2660,54 @@ bool WriteDataCcwAction::supports_repeated_block() const
     return false;
 }
 
-Expected<ContextSwitchConfigActionPtr> CreateConfigDescAndFetchAction::create(
-    std::vector<ConfigResources> &config_resources, const std::set<uint8_t> &pending_cfg_ch_buffer, 
-    const std::vector<uint16_t> &ccw_bursts, bool support_pre_fetch)
+Expected<ContextSwitchConfigActionPtr> AddCcwBurstAction::create(uint8_t channel_index, uint16_t ccw_bursts)
 {
-    CHECK_AS_EXPECTED(pending_cfg_ch_buffer.size() > 0, HAILO_INTERNAL_FAILURE,
-        "Expected 1 or more pending_cfg_ch_buffer, however 0 were found");
-    CHECK_AS_EXPECTED(ccw_bursts.size() == config_resources.size(), HAILO_INTERNAL_FAILURE,
-        "CCW burst vector size must match the config resources size");
-
-    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) CreateConfigDescAndFetchAction(config_resources, 
-        pending_cfg_ch_buffer, ccw_bursts, support_pre_fetch));
+    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) AddCcwBurstAction(channel_index, ccw_bursts));
     CHECK_AS_EXPECTED((nullptr != result), HAILO_OUT_OF_HOST_MEMORY);
     return result;
 }
 
-CreateConfigDescAndFetchAction::CreateConfigDescAndFetchAction(std::vector<ConfigResources> &config, const std::set<uint8_t> &pending_cfg_ch_buffer,
-        const std::vector<uint16_t> &ccw_bursts, bool support_pre_fetch) :
-    ContextSwitchConfigAction(Type::CreateDescForCcw),
-    m_config(config),
-    m_pending_cfg_ch_buffer(pending_cfg_ch_buffer),
-    m_ccw_bursts(ccw_bursts),
-    m_support_pre_fetch(support_pre_fetch)
+AddCcwBurstAction::AddCcwBurstAction(uint8_t channel_index, uint16_t ccw_bursts) :
+    ContextSwitchConfigAction(Type::AddCcwBurst),
+    m_channel_index(channel_index),
+    m_ccw_bursts(ccw_bursts)
 {}
 
-hailo_status CreateConfigDescAndFetchAction::execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+hailo_status AddCcwBurstAction::execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
     uint8_t **context_meta_data_head_pointer)
 {
-    for (auto cfg_channel_index : m_pending_cfg_ch_buffer) {
+    return HEF_METADATA__add_ccw_bursts_action(context_info, context_meta_data_head_pointer,
+        m_ccw_bursts, m_channel_index, m_is_in_repeated_block);
+}
 
-        CHECK(cfg_channel_index < m_ccw_bursts.size(), HAILO_INTERNAL_FAILURE,
-            "cfg_channel_index vector size must then m_ccw_burst size");
+bool AddCcwBurstAction::supports_repeated_block() const
+{
+    return false;
+}
 
-        const auto desc_count = m_config[cfg_channel_index].program_descriptors();
-        CHECK_EXPECTED_AS_STATUS(desc_count);
+Expected<ContextSwitchConfigActionPtr> CreateConfigDescAndFetchAction::create(uint8_t channel_index, ConfigBuffer &config_buffer)
+{
+    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) CreateConfigDescAndFetchAction(channel_index, config_buffer));
+    CHECK_AS_EXPECTED((nullptr != result), HAILO_OUT_OF_HOST_MEMORY);
+    return result;
+}
 
-        if (m_support_pre_fetch) {
-            auto status = HEF_METADATA__add_ccw_bursts_action(context_info, context_meta_data_head_pointer, 
-                static_cast<uint16_t>(m_ccw_bursts[cfg_channel_index]), cfg_channel_index, m_is_in_repeated_block);
-            CHECK_SUCCESS(status);
-        } else {
-            auto status = HEF_METADATA__add_read_vdma_action(context_info, context_meta_data_head_pointer, desc_count.value(),
-                cfg_channel_index, m_is_in_repeated_block);
-            CHECK_SUCCESS(status);
-        }
-    }
+CreateConfigDescAndFetchAction::CreateConfigDescAndFetchAction(uint8_t channel_index, ConfigBuffer &config_buffer) :
+    ContextSwitchConfigAction(Type::CreateDescForCcw),
+    m_channel_index(channel_index),
+    m_config_buffer(config_buffer)
+{}
 
-    return HAILO_SUCCESS;
+hailo_status CreateConfigDescAndFetchAction::execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+    uint8_t **context_meta_data_head_pointer)
+{
+    const auto desc_count = m_config_buffer.program_descriptors();
+    CHECK_EXPECTED_AS_STATUS(desc_count);
+
+    CHECK(IS_FIT_IN_UINT16(desc_count.value()), HAILO_INVALID_OPERATION,
+        "On cfg with continuous mode, max descriptors size must fit in uint16_t");
+    return HEF_METADATA__add_read_vdma_action(context_info, context_meta_data_head_pointer,
+        static_cast<uint16_t>(desc_count.value()), m_channel_index, m_is_in_repeated_block);
 }
 
 bool CreateConfigDescAndFetchAction::supports_repeated_block() const
@@ -2652,6 +2719,31 @@ bool CreateConfigDescAndFetchAction::supports_repeated_block() const
     return false;
 }
 
+Expected<ContextSwitchConfigActionPtr> StartBurstCreditsTaskAction::create()
+{
+    auto result = ContextSwitchConfigActionPtr(new (std::nothrow) StartBurstCreditsTaskAction());
+    CHECK_AS_EXPECTED((nullptr != result), HAILO_OUT_OF_HOST_MEMORY);
+    return result;
+}
+
+StartBurstCreditsTaskAction::StartBurstCreditsTaskAction() :
+    ContextSwitchConfigAction(Type::StartBurstCreditsTask)
+{}
+
+hailo_status StartBurstCreditsTaskAction::execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+    uint8_t **context_meta_data_head_pointer)
+{
+    return HEF_METADATA__burst_credits_task_start(context_info, context_meta_data_head_pointer,
+        m_is_in_repeated_block);
+}
+
+bool StartBurstCreditsTaskAction::supports_repeated_block() const
+{
+    // We don't support repeated blocks for this action, since only one is added per group of consecutive
+    // TriggerNewDataFromDataInput actions.
+    return false;
+}
+
 Expected<ContextSwitchConfigActionPtr> RepeatedHeaderAction::create(
     CONTROL_PROTOCOL__ACTION_TYPE_t sub_action_type, uint8_t num_actions)
 {
@@ -2731,14 +2823,15 @@ Expected<ContextSwitchConfigActionPtr> EnableLcuAction::create(const ProtoHEFAct
     auto partial_network_name = HefUtils::get_partial_network_name_by_index(net_group, network_index,
         resources_manager.get_supported_features());
     CHECK_EXPECTED(partial_network_name);
-    auto batch_size = resources_manager.get_network_batch_size_from_partial_name(partial_network_name.value());
-    CHECK_EXPECTED(batch_size);
 
+    auto network_name = HefUtils::get_network_name(net_group, partial_network_name.value());
+
+    auto batch_size = resources_manager.get_network_batch_size(network_name);
+    CHECK_EXPECTED(batch_size);
     const auto kernel_done_address = static_cast<uint16_t>(proto_action.enable_lcu().lcu_kernel_done_address());
     const auto kernel_done_count = static_cast<uint32_t>(proto_action.enable_lcu().lcu_kernel_done_count());
     const auto is_default = (CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_ADDRESS == kernel_done_address) &&
-        (CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_COUNT == kernel_done_count) &&
-        (CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_BATCH_SIZE == batch_size.value());
+        (CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_COUNT == kernel_done_count);
     
     auto result = ContextSwitchConfigActionPtr(new (std::nothrow) EnableLcuAction(proto_action, is_default, network_index));
     CHECK_AS_EXPECTED((nullptr != result), HAILO_OUT_OF_HOST_MEMORY);
@@ -2769,7 +2862,7 @@ hailo_status EnableLcuAction::execute(CONTROL_PROTOCOL__context_switch_context_i
     const auto lcu_index = static_cast<uint8_t>(m_proto_action.enable_lcu().lcu_index());
     if (m_is_default) {
         return HEF_METADATA__add_enable_lcu_default_action(context_info, context_meta_data_head_pointer,
-            cluster_index, lcu_index, m_is_in_repeated_block);
+            cluster_index, lcu_index, m_network_index, m_is_in_repeated_block);
     } else {
         const auto kernel_done_address = static_cast<uint16_t>(m_proto_action.enable_lcu().lcu_kernel_done_address());
         const auto kernel_done_count = static_cast<uint32_t>(m_proto_action.enable_lcu().lcu_kernel_done_count());
@@ -3234,12 +3327,12 @@ Expected<std::map<std::string, hailo_vstream_params_t>> Hef::make_input_vstream_
 }
 
 Expected<std::map<std::string, hailo_vstream_params_t>> Hef::Impl::make_input_vstream_params(
-    const std::string &net_group_name, const std::string &partial_network_name, bool quantized, 
+    const std::string &net_group_name, const std::string &network_name, bool quantized, 
     hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size)
 {
     std::map<std::string, hailo_vstream_params_t> input_vstreams_params;
     auto status = fill_missing_input_vstream_params_with_default(net_group_name,
-        partial_network_name, input_vstreams_params, quantized, format_type, timeout_ms, queue_size);
+        network_name, input_vstreams_params, quantized, format_type, timeout_ms, queue_size);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
     return input_vstreams_params;
@@ -3257,24 +3350,24 @@ Expected<std::map<std::string, hailo_vstream_params_t>> Hef::make_output_vstream
 }
 
 Expected<std::map<std::string, hailo_vstream_params_t>> Hef::Impl::make_output_vstream_params(
-    const std::string &net_group_name, const std::string &partial_network_name, bool quantized, 
+    const std::string &net_group_name, const std::string &network_name, bool quantized, 
     hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size)
 {
     std::map<std::string, hailo_vstream_params_t> output_vstreams_params;
     auto status = fill_missing_output_vstream_params_with_default(net_group_name,
-        partial_network_name, output_vstreams_params, quantized, format_type, timeout_ms, queue_size);
+        network_name, output_vstreams_params, quantized, format_type, timeout_ms, queue_size);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
     return output_vstreams_params;
 }
 
 hailo_status Hef::Impl::fill_missing_input_vstream_params_with_default(const std::string &net_group_name,
-    const std::string &partial_network_name, std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
+    const std::string &network_name, std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
     bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED_AS_STATUS(network_group_metadata);
-    auto input_vstream_infos = network_group_metadata->get_input_vstream_infos(partial_network_name);
+    auto input_vstream_infos = network_group_metadata->get_input_vstream_infos(network_name);
     CHECK_EXPECTED_AS_STATUS(input_vstream_infos);
 
     return fill_missing_vstream_params_with_default(input_vstreams_params, input_vstream_infos.value(),
@@ -3282,12 +3375,12 @@ hailo_status Hef::Impl::fill_missing_input_vstream_params_with_default(const std
 }
 
 hailo_status Hef::Impl::fill_missing_output_vstream_params_with_default(const std::string &net_group_name,
-    const std::string &partial_network_name, std::map<std::string, hailo_vstream_params_t> &output_vstream_params,
+    const std::string &network_name, std::map<std::string, hailo_vstream_params_t> &output_vstream_params,
     bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size)
 {
     auto network_group_metadata = get_network_group_metadata(net_group_name);
     CHECK_EXPECTED_AS_STATUS(network_group_metadata);
-    auto output_vstream_infos =  network_group_metadata->get_output_vstream_infos(partial_network_name);
+    auto output_vstream_infos =  network_group_metadata->get_output_vstream_infos(network_name);
     CHECK_EXPECTED_AS_STATUS(output_vstream_infos);
 
     return fill_missing_vstream_params_with_default(output_vstream_params, output_vstream_infos.value(),
@@ -3400,16 +3493,16 @@ Expected<std::map<std::string, hailo_network_parameters_t>> Hef::Impl::create_ne
     if (network_gorup_metadata->supported_features().multi_network_support) {
         CHECK_AS_EXPECTED((net_group.value()->networks_names_size() != 0), HAILO_INTERNAL_FAILURE, 
         "Hef support multiple networks, but no networks found in the proto");
-        for (const auto &network : net_group.value()->networks_names()) {
-            auto network_name = net_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + network;
+        for (const auto &partial_network_name : net_group.value()->networks_names()) {
+            auto network_name = HefUtils::get_network_name(net_group_name, partial_network_name);
             auto params = HailoRTDefaults::get_network_parameters();
             results.emplace(std::make_pair(network_name, params));
         }
     } else {
         /* For hefs without the "networks_names" field, build default network name with default params */
         auto params = HailoRTDefaults::get_network_parameters();
-        auto network = HailoRTDefaults::get_network_name(net_group_name);
-        results.emplace(std::make_pair(network, params));
+        auto network_name = HailoRTDefaults::get_network_name(net_group_name);
+        results.emplace(std::make_pair(network_name, params));
     }
 
     return results;
@@ -3456,51 +3549,64 @@ Expected<std::map<std::string, hailo_stream_parameters_t>> Hef::Impl::create_str
 
 NetworkGroupMetadata::NetworkGroupMetadata(const std::string &network_group_name, std::vector<LayerInfo> &&layer_infos,
     std::vector<std::string> &&sorted_output_names, NetworkGroupSupportedFeatures &supported_features,
-    const std::vector<std::string> &sorted_partial_network_names)
+    const std::vector<std::string> &sorted_network_names)
     : m_network_group_name(network_group_name), m_sorted_output_names(std::move(sorted_output_names)), m_supported_features(supported_features),
-        m_sorted_partial_network_names(sorted_partial_network_names)
+        m_sorted_network_names(sorted_network_names)
 {
     for (auto &layer_info : layer_infos) {
         if (HAILO_H2D_STREAM == layer_info.direction) {
-            m_input_layer_infos[layer_info.partial_network_name].push_back(layer_info);
+            m_input_layer_infos[layer_info.network_name].push_back(layer_info);
         } else {
-            m_output_layer_infos[layer_info.partial_network_name].push_back(layer_info);
+            m_output_layer_infos[layer_info.network_name].push_back(layer_info);
+        }
+    }
+}
+
+Expected<LayerInfo> NetworkGroupMetadata::get_layer_info_by_stream_name(const std::string &stream_name) const
+{
+    auto layer_infos = get_all_layer_infos();
+    CHECK_EXPECTED(layer_infos);
+    for (auto layer_info : layer_infos.release()) {
+        if (layer_info.name == stream_name) {
+            return layer_info;
         }
     }
+    LOGGER__ERROR("Failed to find layer with name {}", stream_name);
+    return make_unexpected(HAILO_NOT_FOUND);    
 }
 
-Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_input_layer_infos(const std::string &partial_network_name) const
+Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_input_layer_infos(const std::string &network_name) const
 {
-    CHECK_AS_EXPECTED((partial_network_name == HAILO_DEFAULT_PARTIAL_NETWORK_NAME) || contains(m_input_layer_infos, partial_network_name),
-        HAILO_NOT_FOUND, "Network name {} is not found in networks metadata", partial_network_name);
+    CHECK_AS_EXPECTED((network_name.empty()) || (network_name == default_network_name()) || contains(m_input_layer_infos, network_name),
+        HAILO_NOT_FOUND, "Network name {} is not found in networks metadata", network_name);
     std::vector<LayerInfo> res;
     for (auto &layer_infos_pair : m_input_layer_infos) {
-        if ((partial_network_name == layer_infos_pair.first) || (partial_network_name == HAILO_DEFAULT_PARTIAL_NETWORK_NAME)) {
+        if ((network_name == layer_infos_pair.first) || (network_name.empty()) || (network_name == default_network_name())) {
             res.insert(res.end(), layer_infos_pair.second.begin(), layer_infos_pair.second.end());
         }
     }
     return res;
 }
 
-Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_output_layer_infos(const std::string &partial_network_name) const
+Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_output_layer_infos(const std::string &network_name) const
 {
-    CHECK_AS_EXPECTED((partial_network_name == HAILO_DEFAULT_PARTIAL_NETWORK_NAME) || contains(m_output_layer_infos, partial_network_name),
-        HAILO_NOT_FOUND, "Network name {} is not found in networks metadata", partial_network_name);
+    CHECK_AS_EXPECTED((network_name.empty()) || (network_name == default_network_name()) || contains(m_output_layer_infos, network_name),
+        HAILO_NOT_FOUND, "Network name {} is not found in networks metadata", network_name);
     std::vector<LayerInfo> res;
     for (auto &layer_infos_pair : m_output_layer_infos) {
-        if ((partial_network_name == layer_infos_pair.first) || (partial_network_name == HAILO_DEFAULT_PARTIAL_NETWORK_NAME)) {
+        if ((network_name == layer_infos_pair.first) || (network_name.empty()) || (network_name == default_network_name())) {
             res.insert(res.end(), layer_infos_pair.second.begin(), layer_infos_pair.second.end());
         }
     }
     return res;
 }
 
-Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_all_layer_infos(const std::string &partial_network_name) const
+Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_all_layer_infos(const std::string &network_name) const
 {
-    auto input_layer_infos = get_input_layer_infos(partial_network_name);
+    auto input_layer_infos = get_input_layer_infos(network_name);
     CHECK_EXPECTED(input_layer_infos);
 
-    auto output_layer_infos = get_output_layer_infos(partial_network_name);
+    auto output_layer_infos = get_output_layer_infos(network_name);
     CHECK_EXPECTED(output_layer_infos);
 
     std::vector<LayerInfo> res;
@@ -3511,28 +3617,28 @@ Expected<std::vector<LayerInfo>> NetworkGroupMetadata::get_all_layer_infos(const
     return res;
 }
 
-Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_input_stream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_input_stream_infos(const std::string &network_name) const
 {
-    auto input_layer_infos = get_input_layer_infos(partial_network_name);
+    auto input_layer_infos = get_input_layer_infos(network_name);
     CHECK_EXPECTED(input_layer_infos);
 
     return convert_layer_infos_to_stream_infos(input_layer_infos.value());
 }
 
-Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_output_stream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_output_stream_infos(const std::string &network_name) const
 {
-    auto output_layer_infos = get_output_layer_infos(partial_network_name);
+    auto output_layer_infos = get_output_layer_infos(network_name);
     CHECK_EXPECTED(output_layer_infos);
 
     return convert_layer_infos_to_stream_infos(output_layer_infos.value());
 }
 
-Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_all_stream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_all_stream_infos(const std::string &network_name) const
 {
-    auto input_stream_infos = get_input_stream_infos(partial_network_name);
+    auto input_stream_infos = get_input_stream_infos(network_name);
     CHECK_EXPECTED(input_stream_infos);
 
-    auto output_stream_infos = get_output_stream_infos(partial_network_name);
+    auto output_stream_infos = get_output_stream_infos(network_name);
     CHECK_EXPECTED(output_stream_infos);
 
     std::vector<hailo_stream_info_t> res;
@@ -3543,17 +3649,17 @@ Expected<std::vector<hailo_stream_info_t>> NetworkGroupMetadata::get_all_stream_
     return res;
 }
 
-Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_input_vstream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_input_vstream_infos(const std::string &network_name) const
 {
-    auto input_layer_infos = get_input_layer_infos(partial_network_name);
+    auto input_layer_infos = get_input_layer_infos(network_name);
     CHECK_EXPECTED(input_layer_infos);
 
     return convert_layer_infos_to_vstream_infos(input_layer_infos.value());
 }
 
-Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_output_vstream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_output_vstream_infos(const std::string &network_name) const
 {
-    auto output_layer_infos = get_output_layer_infos(partial_network_name);
+    auto output_layer_infos = get_output_layer_infos(network_name);
     CHECK_EXPECTED(output_layer_infos);
     
     auto res = convert_layer_infos_to_vstream_infos(output_layer_infos.value());
@@ -3584,12 +3690,12 @@ Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_output_vst
     return res;
 }
 
-Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_all_vstream_infos(const std::string &partial_network_name) const
+Expected<std::vector<hailo_vstream_info_t>> NetworkGroupMetadata::get_all_vstream_infos(const std::string &network_name) const
 {
-    auto input_vstream_infos = get_input_vstream_infos(partial_network_name);
+    auto input_vstream_infos = get_input_vstream_infos(network_name);
     CHECK_EXPECTED(input_vstream_infos);
 
-    auto output_vstream_infos = get_output_vstream_infos(partial_network_name);
+    auto output_vstream_infos = get_output_vstream_infos(network_name);
     CHECK_EXPECTED(output_vstream_infos);
 
     std::vector<hailo_vstream_info_t> res;
@@ -3659,7 +3765,7 @@ std::vector<hailo_vstream_info_t> NetworkGroupMetadata::convert_layer_infos_to_v
 {
     std::vector<hailo_vstream_info_t> res;
     for (auto &layer_info : layer_infos) {
-        auto vstream_infos = LayerInfoUtils::get_vstream_infos_from_layer_info(layer_info, m_network_group_name);
+        auto vstream_infos = LayerInfoUtils::get_vstream_infos_from_layer_info(layer_info);
         for (const auto &vstream_info : vstream_infos) {
             // In case of fused nms layers, several LayerInfos will contain data about the same fused layer
             if (!LayerInfoUtils::vstream_info_already_in_vector(res, vstream_info.name)) {
@@ -3670,31 +3776,13 @@ std::vector<hailo_vstream_info_t> NetworkGroupMetadata::convert_layer_infos_to_v
     return res;
 }
 
-Expected<std::string> NetworkGroupMetadata::get_partial_network_name(const std::string &network_name) const
-{
-    if (network_name.empty()) {
-        return HAILO_DEFAULT_PARTIAL_NETWORK_NAME;
-    }
-
-    for (const auto &partial_network_name : m_sorted_partial_network_names) {
-        auto found = network_name.find(HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name);
-        if (found != std::string::npos) {
-            return Expected<std::string>(partial_network_name);
-        }
-    }
-
-    LOGGER__ERROR("Found no partial network name for network name {}", network_name);
-    return make_unexpected(HAILO_NOT_FOUND);
-}
-
 Expected<std::vector<hailo_network_info_t>> NetworkGroupMetadata::get_network_infos() const
 {
     std::vector<hailo_network_info_t> network_infos;
     auto net_group_name = network_group_name();
-    network_infos.reserve(m_sorted_partial_network_names.size());
-    for (auto const &partial_network_name : m_sorted_partial_network_names) {
+    network_infos.reserve(m_sorted_network_names.size());
+    for (auto const &network_name : m_sorted_network_names) {
         hailo_network_info_t network_info = {};
-        auto network_name = net_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + partial_network_name;
         CHECK_AS_EXPECTED(HAILO_MAX_NETWORK_NAME_SIZE >= (network_name.length() + 1), HAILO_INTERNAL_FAILURE,
             "The network '{}' has a too long name (max is HAILO_MAX_NETWORK_NAME_SIZE)", network_name);  
         memcpy(network_info.name, network_name.c_str(), network_name.length() + 1);
index a0a0ca459cc2282706f88423fe6b863dc2de530e..31b93c209b39a1f966a8fc5f6468ad3cb3537e96 100644 (file)
@@ -48,7 +48,7 @@ namespace hailort
 {
 
 class ResourcesManager;
-class ConfigResources;
+class ConfigBuffer;
 class VdmaConfigActivatedNetworkGroup;
 using VdmaConfigActiveAppHolder = ActiveNetworkGroupHolder<VdmaConfigActivatedNetworkGroup>;
 using ProtoHEFNetworkGroupPtr = std::shared_ptr<ProtoHEFNetworkGroup>;
@@ -86,7 +86,8 @@ static const std::vector<ProtoHEFExtensionType> SUPPORTED_EXTENSIONS = {
     COMPRESSED_PARAMS, 
     TRANSPOSE_COMPONENT,
     IS_NMS_MULTI_CONTEXT,
-    OFFLOAD_ARGMAX
+    OFFLOAD_ARGMAX,
+    PRELIMINARY_RUN_ASAP // Extention added in platform 4.8 release
 };
 
 struct HefParsingInfo
@@ -102,6 +103,7 @@ struct NetworkGroupSupportedFeatures {
     bool padded_ddr_buffers;
     bool multi_network_support;
     bool multi_context;
+    bool preliminary_run_asap;
 };
 
 static inline bool is_h2d_boundary_info_layer(const ProtoHEFEdgeLayer& layer)
@@ -150,28 +152,24 @@ class HailoRTDriver;
 class NetworkGroupMetadata {
 public:
     NetworkGroupMetadata(const std::string &network_group_name, std::vector<LayerInfo> &&layer_infos, std::vector<std::string> &&sorted_output_names,
-        NetworkGroupSupportedFeatures &supported_features, const std::vector<std::string> &sorted_partial_network_names);
+        NetworkGroupSupportedFeatures &supported_features, const std::vector<std::string> &sorted_network_names);
 
-    Expected<std::vector<LayerInfo>> get_input_layer_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<LayerInfo>> get_output_layer_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<LayerInfo>> get_all_layer_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
+    Expected<std::vector<LayerInfo>> get_input_layer_infos(const std::string &network_name = "") const;
+    Expected<std::vector<LayerInfo>> get_output_layer_infos(const std::string &network_name = "") const;
+    Expected<std::vector<LayerInfo>> get_all_layer_infos(const std::string &network_name = "") const;
+    Expected<LayerInfo> get_layer_info_by_stream_name(const std::string &stream_name) const;
 
-    Expected<std::vector<hailo_stream_info_t>> get_input_stream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<hailo_stream_info_t>> get_output_stream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<hailo_stream_info_t>> get_all_stream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
+    Expected<std::vector<hailo_stream_info_t>> get_input_stream_infos(const std::string &network_name = "") const;
+    Expected<std::vector<hailo_stream_info_t>> get_output_stream_infos(const std::string &network_name = "") const;
+    Expected<std::vector<hailo_stream_info_t>> get_all_stream_infos(const std::string &network_name = "") const;
 
-    Expected<std::vector<hailo_vstream_info_t>> get_input_vstream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<hailo_vstream_info_t>> get_output_vstream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
-    Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(const std::string &partial_network_name = HAILO_DEFAULT_PARTIAL_NETWORK_NAME) const;
+    Expected<std::vector<hailo_vstream_info_t>> get_input_vstream_infos(const std::string &network_name = "") const;
+    Expected<std::vector<hailo_vstream_info_t>> get_output_vstream_infos(const std::string &network_name = "") const;
+    Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(const std::string &network_name = "") const;
 
     Expected<std::vector<std::string>> get_vstream_names_from_stream_name(const std::string &stream_name) const;
     Expected<std::vector<std::string>> get_stream_names_from_vstream_name(const std::string &vstream_name) const;
 
-    // Note - network name is build in the following way - "network_group_name / partial_network name"
-    // get partial network name returns the part of the name after the network group name and the "/" qualifier.
-    // The protobuf hold the partial network name.
-    Expected<std::string> get_partial_network_name(const std::string &network_name) const;
-
     Expected<std::vector<hailo_network_info_t>> get_network_infos() const;
 
     const std::string &network_group_name() const
@@ -179,6 +177,11 @@ public:
         return m_network_group_name;
     }
 
+    const std::string default_network_name() const
+    {
+        return HailoRTDefaults::get_network_name(m_network_group_name);
+    }
+
     const std::vector<std::string> get_sorted_output_names() const
     {
         return m_sorted_output_names;
@@ -189,9 +192,9 @@ public:
         return m_supported_features;
     }
 
-    const std::vector<std::string> get_partial_network_names() const
+    const std::vector<std::string> get_network_names() const
     {
-        return m_sorted_partial_network_names;
+        return m_sorted_network_names;
     }
 
 private:
@@ -205,7 +208,7 @@ private:
     std::string m_network_group_name;
     std::vector<std::string> m_sorted_output_names;
     NetworkGroupSupportedFeatures m_supported_features;
-    std::vector<std::string> m_sorted_partial_network_names;
+    std::vector<std::string> m_sorted_network_names;
 };
 
 class Hef::Impl final
@@ -225,20 +228,20 @@ public:
     Expected<std::vector<hailo_network_info_t>> get_network_infos(const std::string &net_group_name="");
 
     Expected<std::vector<hailo_stream_info_t>> get_input_stream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<std::vector<hailo_stream_info_t>> get_output_stream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<std::vector<hailo_stream_info_t>> get_all_stream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<hailo_stream_info_t> get_stream_info_by_name(const std::string &stream_name,
         hailo_stream_direction_t stream_direction, const std::string &net_group_name="");
 
     Expected<std::vector<hailo_vstream_info_t>> get_input_vstream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<std::vector<hailo_vstream_info_t>> get_output_vstream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
     Expected<std::vector<std::string>> get_sorted_output_names(const std::string &net_group_name="");
     Expected<size_t> get_number_of_input_streams(const std::string &net_group_name="");
     Expected<size_t> get_number_of_output_streams(const std::string &net_group_name="");
@@ -247,7 +250,7 @@ public:
     static bool contains_ddr_layers(const ProtoHEFNetworkGroup& net_group);
     static hailo_status validate_net_group_unique_layer_names(ProtoHEFNetworkGroupPtr net_group);
     Expected<std::vector<hailo_vstream_info_t>> get_network_input_vstream_infos(const std::string &net_group_name="",
-        const std::string &partial_network_name="");
+        const std::string &network_name="");
 
     Expected<std::vector<std::string>> get_stream_names_from_vstream_name(const std::string &vstream_name,
         const std::string &net_group_name="");
@@ -287,16 +290,16 @@ public:
         const hailo_mipi_input_stream_params_t &mipi_params);
 
     Expected<std::map<std::string, hailo_vstream_params_t>> make_input_vstream_params(
-        const std::string &net_group_name, const std::string &partial_network_name, bool quantized, 
+        const std::string &net_group_name, const std::string &network_name, bool quantized, 
         hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size);
     hailo_status fill_missing_input_vstream_params_with_default(const std::string &net_group_name,
-        const std::string &partial_network_name, std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
+        const std::string &network_name, std::map<std::string, hailo_vstream_params_t> &input_vstreams_params,
         bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size);
     Expected<std::map<std::string, hailo_vstream_params_t>> make_output_vstream_params(
-        const std::string &net_group_name, const std::string &partial_network_name, bool quantized, 
+        const std::string &net_group_name, const std::string &network_name, bool quantized, 
         hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size);
     hailo_status fill_missing_output_vstream_params_with_default(const std::string &net_group_name,
-        const std::string &partial_network_name, std::map<std::string, hailo_vstream_params_t> &output_vstream_params,
+        const std::string &network_name, std::map<std::string, hailo_vstream_params_t> &output_vstream_params,
         bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms, uint32_t queue_size);
     static hailo_status fill_missing_vstream_params_with_default(std::map<std::string, hailo_vstream_params_t> &vstream_params,
         std::vector<hailo_vstream_info_t> &name_to_format_info, bool quantized, hailo_format_type_t format_type, uint32_t timeout_ms,
@@ -334,9 +337,9 @@ private:
     static Expected<HefParsingInfo> get_parsing_info(ProtoHEFNetworkGroupPtr net_group);
 
     Expected<std::map<std::string, hailo_format_t>> get_inputs_vstream_names_and_format_info(
-        const std::string &net_group_name, const std::string &partial_network_name);
+        const std::string &net_group_name, const std::string &network_name);
     Expected<std::map<std::string, hailo_format_t>> get_outputs_vstream_names_and_format_info(
-        const std::string &net_group_name, const std::string &partial_network_name);
+        const std::string &net_group_name, const std::string &network_name);
 
     static Expected<std::string> get_vstream_name_from_original_name_mux(const std::string &original_name, const ProtoHefEdge &layer);
     static Expected<std::vector<std::string>> get_original_names_from_vstream_name_mux(const std::string &vstream_name, const ProtoHefEdge &layer);
@@ -394,6 +397,10 @@ public:
 
     static Expected<std::vector<hailo_network_info_t>> get_network_infos(const ProtoHEFNetworkGroup &net_group,
         const std::string &net_group_name, const NetworkGroupSupportedFeatures &supported_features);
+
+    static std::string get_network_name(const ProtoHEFNetworkGroup &net_group, const std::string &partial_network_name);
+    static std::string get_network_name(const std::string &net_group_name, const std::string &partial_network_name);
+
 private:
     static hailo_status fill_layer_info_with_base_info(const ProtoHEFEdgeLayerBase &base_info,
         const ProtoHEFEdgeConnectionType &edge_connection_type,
@@ -403,7 +410,7 @@ private:
         const ProtoHEFNetworkGroup &net_group, hailo_stream_direction_t direction,
         bool hw_padding_supported, const std::string &partial_network_name, LayerInfo &layer_info);
     static hailo_status fill_fused_nms_info(const ProtoHEFEdgeLayerFused &info,
-            LayerInfo &layer_info, hailo_quant_info_t &defuse_quant_info, const std::string &partial_network_name);
+            LayerInfo &layer_info, hailo_quant_info_t &defuse_quant_info, const std::string &network_name);
     static hailo_status fill_mux_info(const ProtoHEFEdgeLayerMux &info,
         const ProtoHEFEdgeConnectionType &edge_connection_type,
         const ProtoHEFNetworkGroup &net_group, hailo_stream_direction_t direction,
@@ -441,6 +448,7 @@ public:
         None,
         WriteData,
         WriteDataCcw,
+        AddCcwBurst,
         CreateDescForCcw,
         ReadVdma,
         TriggerSequencer,
@@ -453,11 +461,12 @@ public:
         WaitForModuleConfigDone,
         AddDdrPairInfo,
         AddDdrBufferingStart,
-        AddRrepeated
+        AddRrepeated,
+        StartBurstCreditsTask
     };
 
     static Expected<ContextSwitchConfigActionPtr> create(const ProtoHEFAction &proto_action, Device &device,
-        std::vector<ConfigResources> &config, const ResourcesManager &resources_manager, const ProtoHEFNetworkGroup &net_group,
+        std::vector<ConfigBuffer> &config, const ResourcesManager &resources_manager, const ProtoHEFNetworkGroup &net_group,
         bool support_pre_fetch);
 
     ContextSwitchConfigAction(ContextSwitchConfigAction &&) = default;
@@ -529,7 +538,7 @@ class WriteDataCcwAction : public ContextSwitchConfigAction
 {
 public:
     static Expected<ContextSwitchConfigActionPtr> create(const ProtoHEFAction& proto_action,
-        std::vector<ConfigResources> &config, bool support_pre_fetch);
+        std::vector<ConfigBuffer> &config, bool support_pre_fetch);
     WriteDataCcwAction(WriteDataCcwAction &&) = default;
     WriteDataCcwAction(const WriteDataCcwAction &) = delete;
     WriteDataCcwAction &operator=(WriteDataCcwAction &&) = delete;
@@ -541,21 +550,37 @@ public:
     virtual bool supports_repeated_block() const override;
 
 private:
-    WriteDataCcwAction(const ProtoHEFAction& proto_action, std::vector<ConfigResources> &config, 
+    WriteDataCcwAction(const ProtoHEFAction& proto_action, ConfigBuffer &config, 
         bool support_pre_fetch);
 
-    bool should_pad_with_nops();
-    hailo_status pad_with_nops(uint8_t cfg_channel_index);
+    bool is_last_ccw_write();
+    hailo_status pad_with_nops();
     
-    std::vector<ConfigResources> &m_config;
+    ConfigBuffer &m_config;
     const bool m_support_pre_fetch;
 };
 
+class AddCcwBurstAction : public ContextSwitchConfigAction
+{
+public:
+    static Expected<ContextSwitchConfigActionPtr> create(uint8_t channel_index, uint16_t ccw_bursts);
+
+    virtual hailo_status execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+        uint8_t **context_meta_data_head_pointer) override;
+    virtual bool supports_repeated_block() const override;
+
+private:
+    AddCcwBurstAction(uint8_t channel_index, uint16_t ccw_bursts);
+
+    const uint8_t m_channel_index;
+    const uint16_t m_ccw_bursts;
+};
+
 class CreateConfigDescAndFetchAction : public ContextSwitchConfigAction
 {
 public:
-    static Expected<ContextSwitchConfigActionPtr> create(std::vector<ConfigResources> &config_resources,
-        const std::set<uint8_t> &pending_cfg_ch_buffer, const std::vector<uint16_t> &ccw_burst, bool support_pre_fetch);
+    static Expected<ContextSwitchConfigActionPtr> create(uint8_t channel_index, ConfigBuffer &config_buffer);
+
     CreateConfigDescAndFetchAction(CreateConfigDescAndFetchAction &&) = default;
     CreateConfigDescAndFetchAction(const CreateConfigDescAndFetchAction &) = delete;
     CreateConfigDescAndFetchAction &operator=(CreateConfigDescAndFetchAction &&) = delete;
@@ -567,13 +592,29 @@ public:
     virtual bool supports_repeated_block() const override;
 
 private:
-    CreateConfigDescAndFetchAction(std::vector<ConfigResources> &config, const std::set<uint8_t> &pending_cfg_ch_buffer,
-        const std::vector<uint16_t> &ccw_burst, bool support_pre_fetch);
-        
-    std::vector<ConfigResources> &m_config;
-    const std::set<uint8_t> m_pending_cfg_ch_buffer;
-    const std::vector<uint16_t> m_ccw_bursts;
-    const bool m_support_pre_fetch;
+    CreateConfigDescAndFetchAction(uint8_t channel_index, ConfigBuffer &config_buffer);
+
+    const uint8_t m_channel_index;
+    ConfigBuffer &m_config_buffer;
+};
+
+class StartBurstCreditsTaskAction : public ContextSwitchConfigAction
+{
+public:
+    static Expected<ContextSwitchConfigActionPtr> create();
+
+    StartBurstCreditsTaskAction(StartBurstCreditsTaskAction &&) = default;
+    StartBurstCreditsTaskAction(const StartBurstCreditsTaskAction &) = delete;
+    StartBurstCreditsTaskAction &operator=(StartBurstCreditsTaskAction &&) = delete;
+    StartBurstCreditsTaskAction &operator=(const StartBurstCreditsTaskAction &) = delete;
+    virtual ~StartBurstCreditsTaskAction() = default;
+
+    virtual hailo_status execute(CONTROL_PROTOCOL__context_switch_context_info_t *context_info,
+        uint8_t **context_meta_data_head_pointer) override;
+    virtual bool supports_repeated_block() const override;
+
+private:
+    StartBurstCreditsTaskAction();
 };
 
 class RepeatedHeaderAction : public ContextSwitchConfigAction
index 897cbf75a906ada684e51b42b1fd4298dfc8d0ca..45d1ce6b4d8b4c88d43bb09455bdb3b3c5a6005d 100644 (file)
@@ -12,6 +12,7 @@
 #include "vstream_internal.hpp"
 #include "hailort_defaults.hpp"
 #include "context_switch/network_group_internal.hpp"
+#include "context_switch/network_group_wrapper.hpp"
 
 #include <sstream>
 
@@ -99,7 +100,7 @@ Expected<InferVStreams> InferVStreams::create(ConfiguredNetworkGroup &net_group,
 {
     auto network_infos = net_group.get_network_infos();
     CHECK_EXPECTED(network_infos);
-    auto is_multi_context = (dynamic_cast<ConfiguredNetworkGroupBase&>(net_group)).get_supported_features().multi_context;
+    auto is_multi_context = (dynamic_cast<ConfiguredNetworkGroupWrapper&>(net_group)).get_configured_network()->get_supported_features().multi_context;
     std::map<std::string, std::pair<size_t, size_t>> input_param_count_per_network;
     size_t total_inputs_found = 0;
     size_t total_outputs_found = 0;
index e34c1e5ceb1b6595db6d62106e285e9c05449c8c..540ee6a2b26d9e8f37a60dfe9283d14ae4d0678c 100644 (file)
  * @brief Manages intermediate buffer for inter-context or ddr channels.
  */
 
-#include "intermediate_buffer.hpp"
 #include "context_switch/multi_context/resource_manager.hpp"
+#include "intermediate_buffer.hpp"
+#include "vdma/sg_buffer.hpp"
+#include "vdma/continuous_buffer.hpp"
+
 
 namespace hailort
 {
 
-Expected<std::unique_ptr<IntermediateBuffer>> IntermediateBuffer::create(Type type, HailoRTDriver &driver,
-    const uint32_t transfer_size, const uint16_t batch_size)
+Expected<IntermediateBuffer> IntermediateBuffer::create(HailoRTDriver &driver,
+    ChannelType channel_type, const uint32_t transfer_size, const uint16_t batch_size)
 {
-    switch (type) {
-    case Type::EXTERNAL_DESC:
-        return ExternalDescIntermediateBuffer::create(driver, transfer_size, batch_size);
-    default:
-        LOGGER__ERROR("Invalid intermediate buffer type {}\n", static_cast<int>(type));
-        return make_unexpected(HAILO_INVALID_OPERATION);
+    auto buffer_ptr = should_use_ccb(driver, channel_type) ?
+        create_ccb_buffer(driver, transfer_size, batch_size) :
+        create_sg_buffer(driver, transfer_size, batch_size);
+    CHECK_EXPECTED(buffer_ptr);
+
+    return IntermediateBuffer(buffer_ptr.release(), transfer_size, batch_size);
+}
+
+hailo_status IntermediateBuffer::program_inter_context()
+{
+    size_t acc_offset = 0;
+    for (uint16_t i = 0; i < m_max_batch_size; i++) {
+        const auto first_desc_interrupts_domain = VdmaInterruptsDomain::NONE;
+        const auto last_desc_interrupts_domain = ((m_max_batch_size - 1) == i) ?
+            VdmaInterruptsDomain::DEVICE : VdmaInterruptsDomain::NONE;
+        static const auto BUFFER_NOT_CIRCULAR = false;
+        auto desc_count_local = m_buffer->program_descriptors(m_transfer_size, first_desc_interrupts_domain,
+            last_desc_interrupts_domain, acc_offset, BUFFER_NOT_CIRCULAR);
+        CHECK_EXPECTED_AS_STATUS(desc_count_local,
+            "Failed to program descs for intermediate channels. Given batch_size is too big.");
+        acc_offset += desc_count_local.value();
     }
+    return HAILO_SUCCESS;
 }
 
-Expected<std::unique_ptr<IntermediateBuffer>> ExternalDescIntermediateBuffer::create(HailoRTDriver &driver,
-    const uint32_t transfer_size, const uint16_t transfers_count)
+hailo_status IntermediateBuffer::reprogram_inter_context(uint16_t batch_size)
 {
-    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(driver,
-        transfers_count, transfers_count, transfer_size);
-    CHECK_EXPECTED(desc_sizes_pair);
-    auto desc_page_size = desc_sizes_pair->first;
-    auto descs_count = desc_sizes_pair->second;
+    const auto prev_batch_size = m_dynamic_batch_size;
+    auto status = set_dynamic_batch_size(batch_size);
+    CHECK_SUCCESS(status);
 
-    auto buffer = VdmaBuffer::create((descs_count * desc_page_size), HailoRTDriver::DmaDirection::BOTH, driver);
-    CHECK_EXPECTED(buffer);
+    if (prev_batch_size == m_dynamic_batch_size) {
+        LOGGER__TRACE("Batch size hasn't changed ({}); nothing to be done.", batch_size);
+        return HAILO_SUCCESS;
+    }
 
-    auto desc_buffer = VdmaDescriptorList::create(descs_count, desc_page_size, driver);
-    CHECK_EXPECTED(desc_buffer);
+    status = m_buffer->reprogram_device_interrupts_for_end_of_batch(m_transfer_size, prev_batch_size,
+        VdmaInterruptsDomain::NONE);
+    CHECK_SUCCESS(status, "Failed reprogramming device interrupts for the end of the previous batch (size {})",
+        prev_batch_size);
+    status = m_buffer->reprogram_device_interrupts_for_end_of_batch(m_transfer_size, m_dynamic_batch_size,
+        VdmaInterruptsDomain::DEVICE);
+    CHECK_SUCCESS(status, "Failed reprogramming device interrupts for the end of the current batch (size {})",
+        m_dynamic_batch_size);
 
-    // On dram-dma all descriptors should have channel index, until we implement CCB,
-    // we use some fake channel index. Currently the channel_index is not in used by
-    // the hw. TODO HRT-5835: remove channel_index. 
-    const uint8_t channel_index = 0;
-    auto status = desc_buffer->configure_to_use_buffer(buffer.value(), channel_index);
-    CHECK_SUCCESS_AS_EXPECTED(status);
+    return HAILO_SUCCESS;
+}
 
-    auto intermediate_buffer = make_unique_nothrow<ExternalDescIntermediateBuffer>(buffer.release(), desc_buffer.release(),
-        transfer_size, transfers_count);
-    CHECK_NOT_NULL_AS_EXPECTED(intermediate_buffer, HAILO_OUT_OF_HOST_MEMORY);
+Expected<uint16_t> IntermediateBuffer::program_ddr()
+{
+    const auto interrupts_domain = VdmaInterruptsDomain::NONE;
+    const auto total_size = m_buffer->descs_count() * m_buffer->desc_page_size();
 
-    return std::unique_ptr<IntermediateBuffer>(intermediate_buffer.release());
+    auto desc_count_local = m_buffer->program_descriptors(total_size,
+         interrupts_domain, interrupts_domain, 0, true);
+    CHECK_EXPECTED(desc_count_local);
+
+    return static_cast<uint16_t>(desc_count_local.release());
 }
 
-hailo_status ExternalDescIntermediateBuffer::program_inter_context()
+uint64_t IntermediateBuffer::dma_address() const
 {
-    size_t acc_offset = 0;
-    for (uint16_t i = 0; i < m_transfers_count; i++) {
-        auto first_desc_interrupts_domain = VdmaInterruptsDomain::NONE;
-        auto last_desc_interrupts_domain = ((m_transfers_count - 1) == i) ? VdmaInterruptsDomain::DEVICE : 
-                                                                     VdmaInterruptsDomain::NONE;
-        auto desc_count_local = m_desc_list.program_descriptors(m_transfer_size, first_desc_interrupts_domain,
-            last_desc_interrupts_domain, acc_offset, false);
-        CHECK_EXPECTED_AS_STATUS(desc_count_local,
-            "Failed to program descs for intermediate channels. Given batch_size is too big.");
-        acc_offset += desc_count_local.value();
-    }
-    return HAILO_SUCCESS;
+    return m_buffer->dma_address();
+}
+
+uint32_t IntermediateBuffer::descriptors_in_frame() const
+{
+    return m_buffer->descriptors_in_buffer(m_transfer_size);
 }
 
-Expected<uint16_t> ExternalDescIntermediateBuffer::program_ddr()
+uint16_t IntermediateBuffer::desc_page_size() const
 {
-    return m_desc_list.program_descs_for_ddr_transfers(m_desc_list.desc_page_size(), false, 1, 
-        static_cast<uint32_t>(m_desc_list.count()), 0, true);
+    return m_buffer->desc_page_size();
 }
 
-Expected<uint16_t> ExternalDescIntermediateBuffer::program_host_managed_ddr(uint16_t row_size, uint32_t buffered_rows,
-    uint16_t initial_desc_offset)
+uint32_t IntermediateBuffer::descs_count() const
 {
-    return m_desc_list.program_descs_for_ddr_transfers(row_size, true, DDR_NUMBER_OF_ROWS_PER_INTERRUPT,
-        buffered_rows, initial_desc_offset, true);
+    return m_buffer->descs_count();
+}
+
+uint8_t IntermediateBuffer::depth()
+{
+    // TODO HRT-6763: remove this function, use desc count instead
+    auto count = m_buffer->descs_count();
+
+    uint32_t depth = 0;
+    while (count >>= 1) {
+        ++depth;
+    }
+    assert(IS_FIT_IN_UINT8(depth));
+    return static_cast<uint8_t>(depth);
 }
 
-Expected<Buffer> ExternalDescIntermediateBuffer::read()
+Expected<Buffer> IntermediateBuffer::read()
 {
-    const auto size = m_transfer_size * m_transfers_count;
-    assert(size <= m_buffer.size());
+    const auto size = m_transfer_size * m_dynamic_batch_size;
+    assert(size <= m_buffer->size());
 
     auto res = Buffer::create(size);
     CHECK_EXPECTED(res);
 
-    auto status = m_buffer.read(res->data(), size, 0);
+    auto status = m_buffer->read(res->data(), size, 0);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
     return res.release();
 }
 
+CONTROL_PROTOCOL__host_buffer_info_t IntermediateBuffer::get_host_buffer_info() const
+{
+    CONTROL_PROTOCOL__host_buffer_info_t buffer_info = {};
+
+    buffer_info.buffer_type = static_cast<uint8_t>((m_buffer->type() == vdma::VdmaBuffer::Type::SCATTER_GATHER) ?
+        CONTROL_PROTOCOL__HOST_BUFFER_TYPE_EXTERNAL_DESC : 
+        CONTROL_PROTOCOL__HOST_BUFFER_TYPE_CCB);
+    buffer_info.dma_address = dma_address();
+    buffer_info.desc_page_size = desc_page_size();
+    buffer_info.total_desc_count = descs_count();
+    buffer_info.bytes_in_pattern = m_transfer_size;
+
+    return buffer_info;
+}
+
+Expected<std::unique_ptr<vdma::VdmaBuffer>> IntermediateBuffer::create_sg_buffer(HailoRTDriver &driver,
+    const uint32_t transfer_size, const uint16_t batch_size)
+{
+    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(driver,
+        batch_size, batch_size, transfer_size);
+    CHECK_EXPECTED(desc_sizes_pair);
+    auto desc_page_size = desc_sizes_pair->first;
+    auto descs_count = desc_sizes_pair->second;
+
+    // On dram-dma all descriptors should have channel index, until we implement CCB,
+    // we use some fake channel index. Currently the channel_index is not in used by
+    // the hw. TODO HRT-5835: remove channel_index. 
+    const uint8_t channel_index = 0;
+    auto buffer = vdma::SgBuffer::create(driver, descs_count, desc_page_size,
+        HailoRTDriver::DmaDirection::BOTH, channel_index);
+    CHECK_EXPECTED(buffer);
+
+    auto buffer_ptr = make_unique_nothrow<vdma::SgBuffer>(buffer.release());
+    CHECK_NOT_NULL_AS_EXPECTED(buffer_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    return std::unique_ptr<vdma::VdmaBuffer>(std::move(buffer_ptr));
+}
+
+IntermediateBuffer::IntermediateBuffer(std::unique_ptr<vdma::VdmaBuffer> &&buffer, uint32_t transfer_size,
+                                       uint16_t batch_size) :
+    m_buffer(std::move(buffer)),
+    m_transfer_size(transfer_size),
+    m_max_batch_size(batch_size),
+    m_dynamic_batch_size(batch_size)
+{}
+
+hailo_status IntermediateBuffer::set_dynamic_batch_size(uint16_t batch_size)
+{
+    if (CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == batch_size) {
+        LOGGER__TRACE("Received CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == batch_size; "
+                      "Leaving previously set value of {}", m_dynamic_batch_size);
+    } else {
+        CHECK(batch_size <= m_max_batch_size, HAILO_INVALID_ARGUMENT,
+            "batch_size ({}) must be <= than m_max_batch_size ({})",
+            batch_size, m_max_batch_size);
+
+        LOGGER__TRACE("Setting intermediate buffer's batch_size to {}", batch_size);
+        m_dynamic_batch_size = batch_size;
+    }
+
+    return HAILO_SUCCESS;
+}
+
+Expected<std::unique_ptr<vdma::VdmaBuffer>> IntermediateBuffer::create_ccb_buffer(HailoRTDriver &driver,
+    const uint32_t transfer_size, const uint16_t batch_size)
+{
+    // The first 12 channels in D2H CCB ("regular channels") requires that the amount of descriptors will be a power
+    // of 2. Altough the 4 last channels ("enhanced channels") don't have this requirements, we keep the code the same.
+    auto buffer_size = vdma::ContinuousBuffer::get_buffer_size_desc_power2(transfer_size * batch_size);
+    auto buffer = vdma::ContinuousBuffer::create(buffer_size, driver);
+    CHECK_EXPECTED(buffer);
+
+    auto buffer_ptr = make_unique_nothrow<vdma::ContinuousBuffer>(buffer.release());
+    CHECK_NOT_NULL_AS_EXPECTED(buffer_ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    return std::unique_ptr<vdma::VdmaBuffer>(std::move(buffer_ptr));
+}
+
+bool IntermediateBuffer::should_use_ccb(HailoRTDriver &driver, ChannelType channel_type)
+{
+    if (ChannelType::DDR == channel_type) {
+        // TODO HRT-6645: remove this if
+        return false;
+    }
+
+    switch (driver.dma_type()) {
+    case HailoRTDriver::DmaType::PCIE:
+        return false;
+    case HailoRTDriver::DmaType::DRAM:
+        return true;
+    default:
+        assert(true);
+        return false;
+    }
+}
+
 } /* namespace hailort */
index 2020242c95fa3d53510a8fdeec920e87a47833ff..647733d9a4e56ef10472f0258b2df0186de9205a 100644 (file)
 #define _HAILO_INTERMEDIATE_BUFFER_HPP_
 
 #include "os/hailort_driver.hpp"
-#include "vdma_buffer.hpp"
-#include "vdma_descriptor_list.hpp"
+#include "vdma/vdma_buffer.hpp"
 #include "hailo/expected.hpp"
 #include "hailo/buffer.hpp"
+#include "control_protocol.h"
 
 
 namespace hailort
 {
 
-class IntermediateBuffer {
+class IntermediateBuffer final {
 public:
-
-    enum class Type {
-        EXTERNAL_DESC
+    enum class ChannelType {
+        INTER_CONTEXT,
+        DDR
     };
 
-    static Expected<std::unique_ptr<IntermediateBuffer>> create(Type type, HailoRTDriver &driver,
-        const uint32_t transfer_size, const uint16_t batch_size);
-
-    virtual ~IntermediateBuffer() = default;
-    IntermediateBuffer(const IntermediateBuffer &) = delete;
-    IntermediateBuffer& operator=(const IntermediateBuffer &) = delete;
-    IntermediateBuffer(IntermediateBuffer &&) = default;
-    IntermediateBuffer& operator=(IntermediateBuffer &&) = delete;
-
-
-    virtual hailo_status program_inter_context() = 0;
-
-    // Returns the amount of programed descriptors
-    virtual Expected<uint16_t> program_ddr() = 0;
-    virtual Expected<uint16_t> program_host_managed_ddr(uint16_t row_size, uint32_t buffered_rows,
-        uint16_t initial_desc_offset) = 0;
-
-    virtual uint64_t dma_address() const = 0;
-    virtual uint16_t descriptors_in_frame() const = 0;
-    virtual uint16_t desc_page_size() const = 0;
-    virtual uint16_t descs_count() const = 0;
-    virtual uint8_t depth() const = 0;
-
-    // Should be only used for host managed ddr buffer, in the future this function may return nullptr (on CCB
-    // case where there is no descriptors list)
-    virtual VdmaDescriptorList* get_desc_list() = 0;
-
-    virtual Expected<Buffer> read() = 0;
-
-protected:
-    IntermediateBuffer() = default;
-};
-
-class ExternalDescIntermediateBuffer : public IntermediateBuffer
-{
-public:
-
-    static Expected<std::unique_ptr<IntermediateBuffer>> create(HailoRTDriver &driver, const uint32_t transfer_size,
-        const uint16_t batch_size);
-
-    ExternalDescIntermediateBuffer(VdmaBuffer &&buffer, VdmaDescriptorList &&desc_list,
-        const uint32_t transfer_size, const uint32_t transfers_count) :
-           m_buffer(std::move(buffer)), m_desc_list(std::move(desc_list)),
-           m_transfer_size(transfer_size), m_transfers_count(transfers_count) {};
-
-    hailo_status program_inter_context() override;
+    static Expected<IntermediateBuffer> create(HailoRTDriver &driver,
+        ChannelType channel_type, const uint32_t transfer_size, const uint16_t batch_size);
+    // TODO: create two subclasses - one for ddr buffers and one for intercontext buffers (HRT-6784)
 
+    hailo_status program_inter_context();
+    // This is to be called after program_inter_context
+    hailo_status reprogram_inter_context(uint16_t batch_size);
     // Returns the amount of programed descriptors
-    Expected<uint16_t> program_ddr() override;
-    Expected<uint16_t> program_host_managed_ddr(uint16_t row_size, uint32_t buffered_rows,
-        uint16_t initial_desc_offset) override;
-
-    uint64_t dma_address() const override
-    {
-        return m_desc_list.dma_address();
-    }
-
-    uint16_t descriptors_in_frame() const override
-    {
-        return static_cast<uint16_t>(m_desc_list.descriptors_in_buffer(m_transfer_size));
-    }
+    Expected<uint16_t> program_ddr();
+    uint64_t dma_address() const;
+    uint32_t descriptors_in_frame() const;
+    uint16_t desc_page_size() const;
+    uint32_t descs_count() const;
+    uint8_t depth();
+    Expected<Buffer> read();
 
-    uint16_t desc_page_size() const override
-    {
-        return m_desc_list.desc_page_size();
-    }
+    CONTROL_PROTOCOL__host_buffer_info_t get_host_buffer_info() const;
 
-    uint16_t descs_count() const override
-    {
-        return static_cast<uint16_t>(m_desc_list.count());
-    }
-
-    uint8_t depth() const override
-    {
-        return m_desc_list.depth();
-    }
-
-    // Should be only used for host managed ddr buffer, in the future this function may return nullptr (on CCB
-    // case where there is no descriptors list)
-    VdmaDescriptorList* get_desc_list() override
-    {
-        return &m_desc_list;
-    }
+private:
+    IntermediateBuffer(std::unique_ptr<vdma::VdmaBuffer> &&buffer, uint32_t transfer_size, uint16_t batch_size);
+    hailo_status set_dynamic_batch_size(uint16_t batch_size);
 
-    Expected<Buffer> read() override;
+    static Expected<std::unique_ptr<vdma::VdmaBuffer>> create_sg_buffer(HailoRTDriver &driver,
+        const uint32_t transfer_size, const uint16_t batch_size);
+    static Expected<std::unique_ptr<vdma::VdmaBuffer>> create_ccb_buffer(HailoRTDriver &driver,
+        const uint32_t transfer_size, const uint16_t batch_size);
 
-private:
+    static bool should_use_ccb(HailoRTDriver &driver, ChannelType channel_type);
 
-    VdmaBuffer m_buffer;
-    VdmaDescriptorList m_desc_list;
+    std::unique_ptr<vdma::VdmaBuffer> m_buffer;
     const uint32_t m_transfer_size;
-    const uint32_t m_transfers_count;
+    const uint16_t m_max_batch_size;
+    uint16_t m_dynamic_batch_size;
 };
 
 } /* namespace hailort */
index 3027463d61aa7728b87947bec4443dbd91455a51..82628e9ea6db3a93e0c93b5169fbad0db7415ef6 100644 (file)
@@ -43,9 +43,7 @@ struct LayerInfo {
     hailo_nms_info_t nms_info;
     uint32_t height_gcd;
     std::vector<uint32_t> height_ratios;
-    // Note - network name as seen by the user is build in the following way - "network_group_name / partial_network name"
-    // In layer info scope - we would use the partial network name only. 
-    std::string partial_network_name;
+    std::string network_name;
 
     // Simulation Info
     BufferIndices buffer_indices;
@@ -96,24 +94,24 @@ public:
         return false;
     }
 
-    static std::vector<hailo_vstream_info_t> get_vstream_infos_from_layer_info(const LayerInfo &layer_info, const std::string &network_group_name)
+    static std::vector<hailo_vstream_info_t> get_vstream_infos_from_layer_info(const LayerInfo &layer_info)
     {
         std::vector<hailo_vstream_info_t> res = {};
         if (layer_info.is_mux) {
             for (auto &pred : layer_info.predecessor) {
-                auto vstream_infos = get_vstream_infos_from_layer_info(pred, network_group_name);
+                auto vstream_infos = get_vstream_infos_from_layer_info(pred);
                 res.insert(res.end(), vstream_infos.begin(), vstream_infos.end());
             }
         } else if (layer_info.is_defused_nms) {
             for (auto &fused_nms : layer_info.fused_nms_layer) {
                 // In case of fused nms layers, several LayerInfos will contain data about the same fused layer
                 if (!vstream_info_already_in_vector(res, fused_nms.name)) {
-                    auto vstream_info = get_vstream_info_from_layer_info_impl(fused_nms, network_group_name);
+                    auto vstream_info = get_vstream_info_from_layer_info_impl(fused_nms);
                     res.push_back(vstream_info);
                 }
             }
         } else {
-            auto vstream_info = get_vstream_info_from_layer_info_impl(layer_info, network_group_name);
+            auto vstream_info = get_vstream_info_from_layer_info_impl(layer_info);
             res.push_back(vstream_info);
         }
 
@@ -121,7 +119,7 @@ public:
     }
 
 private:
-    static hailo_vstream_info_t get_vstream_info_from_layer_info_impl(const LayerInfo &layer_info, const std::string &network_group_name)
+    static hailo_vstream_info_t get_vstream_info_from_layer_info_impl(const LayerInfo &layer_info)
     {
         hailo_vstream_info_t res = {};
         res.format.type = layer_info.format.type;
@@ -138,9 +136,8 @@ private:
         res.direction = layer_info.direction;
         assert(layer_info.name.length() < HAILO_MAX_STREAM_NAME_SIZE);
         strncpy(res.name, layer_info.name.c_str(), layer_info.name.length() + 1);
-        auto network_name = network_group_name + HAILO_DEFAULT_NETWORK_NAME_QUALIFIER + layer_info.partial_network_name;
-        assert(network_name.length() < HAILO_MAX_NETWORK_NAME_SIZE);
-        strncpy(res.network_name, network_name.c_str(), network_name.length() + 1);
+        assert(layer_info.network_name.length() < HAILO_MAX_NETWORK_NAME_SIZE);
+        strncpy(res.network_name, layer_info.network_name.c_str(), layer_info.network_name.length() + 1);
         res.quant_info = layer_info.quant_info;
 
         return res;
index 59cb243af8b38b05d0d2e6303b65a5d05f49d2a2..4a9115c0e146b86c44b382b7e1c3fff502de5afb 100644 (file)
@@ -100,7 +100,8 @@ CONTROL_PROTOCOL__mipi_input_config_params_t MipiInputStream::hailo_mipi_params_
     return control_mipi_params;
 }
 
-hailo_status MipiInputStream::activate_stream()
+// Note: Mipi streams don't work with dynamic batch sizes
+hailo_status MipiInputStream::activate_stream(uint16_t /* dynamic_batch_size */)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     CONTROL_PROTOCOL__config_stream_params_t params = {};
index dfc62330af1e811cec6c2d16ff40dc572c6d3685..3ca6e43a844ca8191ecfeb99287a3b403286b98d 100644 (file)
@@ -51,7 +51,7 @@ public:
 
     virtual ~MipiInputStream();
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_MIPI; }
     virtual std::chrono::milliseconds get_timeout() const override;
diff --git a/hailort/libhailort/src/network_group_scheduler.cpp b/hailort/libhailort/src/network_group_scheduler.cpp
new file mode 100644 (file)
index 0000000..164d232
--- /dev/null
@@ -0,0 +1,640 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file network_group_scheduler.cpp
+ * @brief: Network scheduler
+ **/
+
+#include "network_group_scheduler.hpp"
+#include "context_switch/network_group_internal.hpp"
+#include "hef_internal.hpp"
+#include "vdevice_stream.hpp"
+#include "vdma_stream.hpp"
+
+namespace hailort
+{
+
+Expected<NetworkGroupSchedulerPtr> NetworkGroupScheduler::create_shared(hailo_scheduling_algorithm_t algorithm)
+{
+    auto ptr = make_shared_nothrow<NetworkGroupScheduler>(algorithm);
+    CHECK_AS_EXPECTED(nullptr != ptr, HAILO_OUT_OF_HOST_MEMORY);
+
+    return ptr;
+}
+
+hailo_status NetworkGroupScheduler::SchedulerIdleGuard::set_scheduler(std::shared_ptr<NetworkGroupScheduler> scheduler)
+{
+    CHECK(nullptr != scheduler, HAILO_INTERNAL_FAILURE);
+    m_scheduler = scheduler;
+    m_scheduler->force_idle_state();
+    return HAILO_SUCCESS;
+}
+
+NetworkGroupScheduler::SchedulerIdleGuard::~SchedulerIdleGuard()
+{
+    if (m_scheduler) {
+        m_scheduler->resume_from_idle_state();
+    }
+}
+
+void NetworkGroupScheduler::force_idle_state()
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        m_write_read_cv.wait(lock, [this] {
+            return has_current_ng_finished();
+        });
+        deactivate_network_group();
+        m_forced_idle_state = true;
+    }
+    m_write_read_cv.notify_all();
+}
+
+void NetworkGroupScheduler::resume_from_idle_state()
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        m_forced_idle_state = false;
+    }
+    m_write_read_cv.notify_all();
+}
+
+Expected<network_group_handle_t> NetworkGroupScheduler::add_network_group(std::weak_ptr<ConfiguredNetworkGroup> added_cng)
+{
+    network_group_handle_t network_group_handle = INVALID_NETWORK_GROUP_HANDLE;
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        network_group_handle = static_cast<uint32_t>(m_cngs.size());
+
+        m_cngs.emplace_back(added_cng);
+        m_timeout_per_network_group[network_group_handle] = DEFAULT_SCHEDULER_TIMEOUT;
+        m_last_run_time_stamp[network_group_handle] = {}; // Default c'tor to mark this network_group didn't run yet
+
+        auto added_cng_ptr = added_cng.lock();
+        CHECK_AS_EXPECTED(added_cng_ptr, HAILO_INTERNAL_FAILURE);
+
+        auto stream_infos = added_cng_ptr->get_all_stream_infos();
+        CHECK_EXPECTED(stream_infos);
+
+        // Prepare empty counters for the added cng
+        for (const auto &stream_info : stream_infos.value()) {
+            m_should_ng_stop[network_group_handle][stream_info.name] = false;
+            m_min_threshold_per_stream[network_group_handle][stream_info.name] = DEFAULT_SCHEDULER_MIN_THRESHOLD;
+            if (HAILO_H2D_STREAM == stream_info.direction) {
+                m_requested_write[network_group_handle][stream_info.name] = 0;
+                m_written_buffer[network_group_handle][stream_info.name] = 0;
+                m_sent_pending_buffer[network_group_handle][stream_info.name] = 0;
+                m_finished_sent_pending_buffer[network_group_handle][stream_info.name] = 0;
+
+                auto event = Event::create_shared(Event::State::signalled);
+                CHECK_AS_EXPECTED(nullptr != event, HAILO_OUT_OF_HOST_MEMORY);
+
+                m_write_buffer_events[network_group_handle][stream_info.name] = event;
+            } else {
+                m_allowed_read[network_group_handle][stream_info.name] = 0;
+                m_finished_read[network_group_handle][stream_info.name] = 0;
+            }
+        }
+    }
+    m_write_read_cv.notify_all();
+    return network_group_handle;
+}
+
+hailo_status NetworkGroupScheduler::wait_for_write(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        assert(contains(m_requested_write, network_group_handle));
+        assert(contains(m_write_buffer_events, network_group_handle));
+        if ((nullptr != m_ang) && m_switching_network_group &&
+            (m_requested_write[network_group_handle][stream_name] == get_max_value_of_unordered_map(m_requested_write[network_group_handle]))) {
+            auto status = m_write_buffer_events[network_group_handle][stream_name]->reset();
+            CHECK_SUCCESS(status);
+        }
+    }
+
+    auto status = m_write_buffer_events[network_group_handle][stream_name]->wait(std::chrono::milliseconds(HAILO_INFINITE));
+    CHECK_SUCCESS(status);
+
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+
+        assert(contains(m_should_ng_stop, network_group_handle));
+        if (m_should_ng_stop[network_group_handle][stream_name]) {
+            return HAILO_STREAM_INTERNAL_ABORT;
+        }
+
+        m_requested_write[network_group_handle][stream_name]++;
+
+        if ((nullptr != m_ang) && (m_current_network_group == network_group_handle)) {
+            m_has_current_ng_finished = false;
+        }
+
+        status = allow_writes_for_other_inputs_if_needed(network_group_handle);
+        CHECK_SUCCESS(status);
+    }
+
+    m_write_read_cv.notify_all();
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::allow_writes_for_other_inputs_if_needed(const network_group_handle_t &network_group_handle)
+{
+    if (!m_has_current_ng_finished && m_switching_network_group) {
+        auto max_write = get_max_value_of_unordered_map(m_requested_write[network_group_handle]);
+        for (auto &name_event_pair : m_write_buffer_events[network_group_handle]) {
+            if (m_requested_write[network_group_handle][name_event_pair.first] < max_write) {
+                auto status = name_event_pair.second->signal();
+                CHECK_SUCCESS(status);
+            }
+        }
+    }
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::signal_write_finish(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+
+        assert(contains(m_should_ng_stop, network_group_handle));
+        if (m_should_ng_stop[network_group_handle][stream_name]) {
+            return HAILO_STREAM_INTERNAL_ABORT;
+        }
+        
+        assert(contains(m_written_buffer, network_group_handle));
+        assert(contains(m_written_buffer[network_group_handle], stream_name));
+        m_written_buffer[network_group_handle][stream_name]++;
+
+        auto status = switch_network_group_if_idle(network_group_handle, lock);
+        CHECK_SUCCESS(status);
+
+        status = switch_network_group_if_should_be_next(network_group_handle, lock);
+        CHECK_SUCCESS(status);
+
+        status = send_all_pending_buffers(network_group_handle, lock);
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            LOGGER__INFO("send_all_pending_buffers has failed with status=HAILO_STREAM_INTERNAL_ABORT");
+            return status;
+        }
+        CHECK_SUCCESS(status);
+    }
+    m_write_read_cv.notify_all();
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::switch_network_group_if_idle(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock)
+{
+    if (!m_forced_idle_state && !m_switching_network_group && m_has_current_ng_finished &&
+        ((nullptr == m_ang) || (network_group_handle != m_current_network_group)) && is_network_group_ready(network_group_handle)) {
+        auto status = activate_network_group(network_group_handle, read_write_lock);
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            return status;
+        }
+        CHECK_SUCCESS(status);
+    }
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::activate_network_group(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock)
+{
+    deactivate_network_group();
+
+    m_switching_network_group = false;
+    auto status = allow_all_writes();
+    CHECK_SUCCESS(status);
+
+    assert(m_cngs.size() > network_group_handle);
+    auto cng = m_cngs[network_group_handle].lock();
+    CHECK(cng, HAILO_INTERNAL_FAILURE);
+
+    auto cng_base = std::dynamic_pointer_cast<ConfiguredNetworkGroupBase>(cng);
+    auto expected_ang = cng_base->force_activate();
+    CHECK_EXPECTED_AS_STATUS(expected_ang);
+    m_last_run_time_stamp[network_group_handle] = std::chrono::steady_clock::now(); // Mark last timestamp on activation
+
+    m_ang = expected_ang.release();
+
+    m_current_network_group = network_group_handle;
+    m_has_current_ng_finished = false;
+
+    status = send_all_pending_buffers(network_group_handle, read_write_lock);
+    if (HAILO_STREAM_INTERNAL_ABORT == status) {
+        LOGGER__INFO("send_all_pending_buffers has failed with status=HAILO_STREAM_INTERNAL_ABORT");
+        return status;
+    }
+    CHECK_SUCCESS(status);
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::allow_all_writes()
+{
+    for (auto &name_dict_pair : m_write_buffer_events) {
+        for (auto &name_event_pair : name_dict_pair.second) {
+            auto status = name_event_pair.second->signal();
+            CHECK_SUCCESS(status);
+        }
+    }
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::send_all_pending_buffers(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock)
+{
+    if ((nullptr == m_ang) || (m_current_network_group != network_group_handle)) {
+        return HAILO_SUCCESS;
+    }
+
+    while (true) {
+        uint32_t finished_sending_count = 0;
+        for (auto &name_counter_pair : m_written_buffer[network_group_handle]) {
+            if (m_sent_pending_buffer[network_group_handle][name_counter_pair.first] < name_counter_pair.second) {
+                auto status = send_pending_buffer(network_group_handle, name_counter_pair.first, read_write_lock);
+                if (HAILO_STREAM_INTERNAL_ABORT == status) {
+                    LOGGER__INFO("send_pending_buffer has failed with status=HAILO_STREAM_INTERNAL_ABORT");
+                    return status;
+                }
+                CHECK_SUCCESS(status);
+            } else {
+                finished_sending_count++;
+            }
+        }
+        if (finished_sending_count == m_written_buffer[network_group_handle].size()) {
+            break;
+        }
+    }
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::send_pending_buffer(const network_group_handle_t &network_group_handle, const std::string &stream_name,
+    std::unique_lock<std::mutex> &read_write_lock)
+{
+    assert(m_cngs.size() > network_group_handle);
+    auto current_cng = m_cngs[network_group_handle].lock();
+    CHECK(current_cng, HAILO_INTERNAL_FAILURE);
+
+    auto input_stream = current_cng->get_input_stream_by_name(stream_name);
+    CHECK_EXPECTED_AS_STATUS(input_stream);
+
+    m_has_current_ng_finished = false;
+
+    VDeviceInputStream &vdevice_input = dynamic_cast<VDeviceInputStream&>(input_stream->get());
+    auto pending_buffer_state = vdevice_input.send_pending_buffer();
+    CHECK_EXPECTED_AS_STATUS(pending_buffer_state);
+
+    assert(contains(m_sent_pending_buffer, network_group_handle));
+    m_sent_pending_buffer[network_group_handle][stream_name]++;
+
+    auto status = pending_buffer_state->finish(vdevice_input.get_timeout(), read_write_lock);
+    if (HAILO_STREAM_INTERNAL_ABORT == status) {
+        LOGGER__INFO("finish has failed with status=HAILO_STREAM_INTERNAL_ABORT");
+        return status;
+    }
+    CHECK_SUCCESS(status);
+    
+    assert(contains(m_finished_sent_pending_buffer, network_group_handle));
+    m_finished_sent_pending_buffer[network_group_handle][stream_name]++;
+
+    // Update m_has_current_ng_finished here because after finishing send pending buffer the network group can actually be finished
+    m_has_current_ng_finished = has_current_ng_finished();
+
+    return HAILO_SUCCESS;
+}
+
+void NetworkGroupScheduler::deactivate_network_group()
+{
+    if (m_ang) {
+        reset_current_ng_counters();
+        m_ang.reset();
+        m_last_run_time_stamp[m_current_network_group] = std::chrono::steady_clock::now(); // Mark last timestamp on deactivation
+    }
+}
+
+hailo_status NetworkGroupScheduler::switch_network_group_if_should_be_next(const network_group_handle_t &network_group_handle,
+    std::unique_lock<std::mutex> &read_write_lock)
+{
+    // Checking (nullptr == m_ang) for activating the first time the scheduler is running
+    if (!m_forced_idle_state && m_switching_network_group && m_has_current_ng_finished && is_network_group_ready(network_group_handle) &&
+        ((nullptr == m_ang) || (m_next_network_group == network_group_handle))) {
+        auto status = activate_network_group(network_group_handle, read_write_lock);
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            return status;
+        }
+    }
+
+    return HAILO_SUCCESS;
+}
+
+bool NetworkGroupScheduler::is_network_group_ready(const network_group_handle_t &network_group_handle)
+{
+    assert(contains(m_written_buffer, network_group_handle));
+    assert(contains(m_timeout_per_network_group, network_group_handle));
+    assert(contains(m_min_threshold_per_stream, network_group_handle));
+
+    // TODO: move inside the for-loop when timeout-per-network will be supported
+    bool timeout_passed = (m_timeout_per_network_group[network_group_handle] <
+        (std::chrono::steady_clock::now() - m_last_run_time_stamp[network_group_handle]));
+
+    for (auto &name_counter_pair : m_written_buffer[network_group_handle]) {
+        // Check if there arent any write requests
+        if (0 == name_counter_pair.second) {
+            return false;
+        }
+
+        // Check if there arent enough write requests and timeout didnt passed
+        if ((name_counter_pair.second < m_min_threshold_per_stream[network_group_handle][name_counter_pair.first]) && (!timeout_passed)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+hailo_status NetworkGroupScheduler::wait_for_read(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        assert(contains(m_allowed_read, network_group_handle));
+        assert(contains(m_allowed_read[network_group_handle], stream_name));
+
+        hailo_status status = HAILO_UNINITIALIZED;
+        m_write_read_cv.wait(lock, [this, network_group_handle, stream_name, &status, &lock] {
+            assert(contains(m_should_ng_stop, network_group_handle));
+            if (m_should_ng_stop[network_group_handle][stream_name]) {
+                status = HAILO_STREAM_INTERNAL_ABORT;
+                return true; // return true so that the wait will finish
+            }
+
+            status = switch_network_group_if_idle(network_group_handle, lock);
+            if (HAILO_SUCCESS != status) {
+                return true; // return true so that the wait will finish
+            }
+
+            status = switch_network_group_if_should_be_next(network_group_handle, lock);
+            if (HAILO_SUCCESS != status) {
+                return true; // return true so that the wait will finish
+            }
+
+            return can_stream_read(network_group_handle, stream_name);
+        });
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            return status;
+        }
+        CHECK_SUCCESS(status);
+
+        assert(contains(m_allowed_read, network_group_handle));
+        m_allowed_read[network_group_handle][stream_name]++;
+    }
+    m_write_read_cv.notify_all();
+
+    return HAILO_SUCCESS;
+}
+
+bool NetworkGroupScheduler::can_stream_read(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    if (nullptr == m_ang) {
+        return false;
+    }
+
+    if (m_current_network_group != network_group_handle) {
+        return false;
+    }
+
+    if (m_has_current_ng_finished) {
+        return false;
+    }
+
+    assert(contains(m_allowed_read, network_group_handle));
+    assert(contains(m_sent_pending_buffer, network_group_handle));
+    return m_allowed_read[network_group_handle][stream_name].load() < get_max_value_of_unordered_map(m_sent_pending_buffer[network_group_handle]);
+}
+
+hailo_status NetworkGroupScheduler::signal_read_finish(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+        assert(contains(m_finished_read, network_group_handle));
+        assert(contains(m_finished_read[network_group_handle], stream_name));
+
+        m_finished_read[network_group_handle][stream_name]++;
+        hailo_status status = mark_switching_ng_if_ready();
+        CHECK_SUCCESS(status);
+    }
+    m_write_read_cv.notify_all();
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::mark_switching_ng_if_ready()
+{
+    if (!m_switching_network_group) {
+        for (uint32_t i = 0; i < m_cngs.size() - 1; i++) {
+            network_group_handle_t handle = m_current_network_group + i + 1;
+            handle %= static_cast<uint32_t>(m_cngs.size());
+
+            if (is_network_group_ready(handle)) {
+                m_switching_network_group = true;
+                m_next_network_group = handle;
+                break;
+            }
+        }
+    }
+    m_has_current_ng_finished = has_current_ng_finished();
+
+    // Prevents integer overflow of the counters
+    decrease_current_ng_counters();
+    
+    return HAILO_SUCCESS;
+}
+
+bool NetworkGroupScheduler::has_current_ng_finished()
+{
+    uint32_t written_frames = get_max_value_of_unordered_map(m_requested_write[m_current_network_group]);
+    for (auto &name_counter_pair : m_finished_read[m_current_network_group]) {
+        if (name_counter_pair.second < written_frames) {
+            return false;
+        }
+    }
+    for (auto &name_counter_pair : m_finished_sent_pending_buffer[m_current_network_group]) {
+        if (name_counter_pair.second < written_frames) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void NetworkGroupScheduler::reset_current_ng_counters()
+{
+    uint32_t written_frames = get_max_value_of_unordered_map(m_sent_pending_buffer[m_current_network_group]);
+
+    for (auto &name_counter_pair : m_requested_write[m_current_network_group]) {
+        name_counter_pair.second -= written_frames;
+    }
+    for (auto &name_counter_pair : m_written_buffer[m_current_network_group]) {
+        assert(name_counter_pair.second == written_frames);
+        name_counter_pair.second = 0;
+    }
+    for (auto &name_counter_pair : m_sent_pending_buffer[m_current_network_group]) {
+        assert(name_counter_pair.second == written_frames);
+        name_counter_pair.second = 0;
+    }
+    for (auto &name_counter_pair : m_finished_sent_pending_buffer[m_current_network_group]) {
+        assert(name_counter_pair.second == written_frames);
+        name_counter_pair.second = 0;
+    }
+    for (auto &name_counter_pair : m_allowed_read[m_current_network_group]) {
+        // TODO (HRT-6811): Recover from timeout, verify counters
+        name_counter_pair.second = 0;
+    }
+    for (auto &name_counter_pair : m_finished_read[m_current_network_group]) {
+        // TODO (HRT-6811): Recover from timeout, verify counters
+        name_counter_pair.second = 0;
+    }
+}
+
+void NetworkGroupScheduler::decrease_current_ng_counters()
+{
+    if (nullptr == m_ang) {
+        return;
+    }
+
+    // Decrease only if counter is 2 or bigger because reaching 0 can cause states to change
+    for (auto &name_counter_pair : m_requested_write[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+    for (auto &name_counter_pair : m_written_buffer[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+    for (auto &name_counter_pair : m_sent_pending_buffer[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+    for (auto &name_counter_pair : m_finished_sent_pending_buffer[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+    for (auto &name_counter_pair : m_allowed_read[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+    for (auto &name_counter_pair : m_finished_read[m_current_network_group]) {
+        if (name_counter_pair.second <= 1) {
+            return;
+        }
+    }
+
+    for (auto &name_counter_pair : m_requested_write[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+    for (auto &name_counter_pair : m_written_buffer[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+    for (auto &name_counter_pair : m_sent_pending_buffer[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+    for (auto &name_counter_pair : m_finished_sent_pending_buffer[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+    for (auto &name_counter_pair : m_allowed_read[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+    for (auto &name_counter_pair : m_finished_read[m_current_network_group]) {
+        name_counter_pair.second--;
+    }
+}
+
+hailo_status NetworkGroupScheduler::enable_stream(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+
+        assert(contains(m_should_ng_stop, network_group_handle));
+        if (!m_should_ng_stop[network_group_handle][stream_name]) {
+            return HAILO_SUCCESS;
+        }
+
+        m_should_ng_stop[network_group_handle][stream_name] = false;
+    }
+    m_write_read_cv.notify_all();
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::disable_stream(const network_group_handle_t &network_group_handle, const std::string &stream_name)
+{
+    {
+        std::unique_lock<std::mutex> lock(m_before_read_write_mutex);
+
+        assert(contains(m_should_ng_stop, network_group_handle));
+        if (m_should_ng_stop[network_group_handle][stream_name]) {
+            return HAILO_SUCCESS;
+        }
+
+        m_should_ng_stop[network_group_handle][stream_name] = true;
+
+        // Signal event to exit infinite timeout on wait_for_write if actually an input stream
+        assert(contains(m_write_buffer_events, network_group_handle));
+        if (contains(m_write_buffer_events[network_group_handle], stream_name)) {
+            auto status = m_write_buffer_events[network_group_handle][stream_name]->signal();
+            CHECK_SUCCESS(status);
+        }
+    }
+    m_write_read_cv.notify_all();
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::set_timeout(const network_group_handle_t &network_group_handle, const std::chrono::milliseconds &timeout, const std::string &network_name)
+{
+    (void)network_name;
+
+    assert(contains(m_timeout_per_network_group, network_group_handle));
+    assert(contains(m_last_run_time_stamp, network_group_handle));
+    CHECK((std::chrono::time_point<std::chrono::steady_clock>() == m_last_run_time_stamp[network_group_handle]), HAILO_INVALID_OPERATION,
+        "Setting scheduler timeout is allowed only before sending / receiving frames on the network group.");
+    m_timeout_per_network_group[network_group_handle] = timeout;
+
+    assert(m_cngs.size() > network_group_handle);
+    auto cng = m_cngs[network_group_handle].lock();
+    CHECK(cng, HAILO_INTERNAL_FAILURE);
+
+    auto name = (network_name.empty()) ? cng->get_network_group_name() : network_name;
+    LOGGER__INFO("Setting scheduler timeout of {} to {}ms", name, timeout.count());
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status NetworkGroupScheduler::set_threshold(const network_group_handle_t &network_group_handle, uint32_t threshold, const std::string &network_name)
+{
+    (void)network_name;
+
+    assert(contains(m_min_threshold_per_stream, network_group_handle));
+    assert(contains(m_last_run_time_stamp, network_group_handle));
+    CHECK((std::chrono::time_point<std::chrono::steady_clock>() == m_last_run_time_stamp[network_group_handle]), HAILO_INVALID_OPERATION,
+        "Setting scheduler threshold is allowed only before sending / receiving frames on the network group.");
+    for (auto &threshold_per_stream_pair : m_min_threshold_per_stream[network_group_handle]) {
+        threshold_per_stream_pair.second = threshold;
+    }
+
+    assert(m_cngs.size() > network_group_handle);
+    auto cng = m_cngs[network_group_handle].lock();
+    CHECK(cng, HAILO_INTERNAL_FAILURE);
+
+    auto name = (network_name.empty()) ? cng->get_network_group_name() : network_name;
+    LOGGER__INFO("Setting scheduler threshold of {} to {} frames", name, threshold);
+
+    return HAILO_SUCCESS;
+}
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/src/network_group_scheduler.hpp b/hailort/libhailort/src/network_group_scheduler.hpp
new file mode 100644 (file)
index 0000000..c262ebb
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file network_group_scheduler.hpp
+ * @brief Class declaration for NetworkGroupScheduler that schedules network groups to be active depending on the scheduling algorithm.
+ **/
+
+#ifndef _HAILO_NETWORK_GROUP_SCHEDULER_HPP_
+#define _HAILO_NETWORK_GROUP_SCHEDULER_HPP_
+
+#include "hailo/hailort.h"
+#include "hailo/expected.hpp"
+#include "common/utils.hpp"
+#include "hailo/network_group.hpp"
+
+#include <condition_variable>
+
+#define DEFAULT_SCHEDULER_TIMEOUT (std::chrono::milliseconds(0))
+#define DEFAULT_SCHEDULER_MIN_THRESHOLD (1)
+
+namespace hailort
+{
+
+#define INVALID_NETWORK_GROUP_HANDLE (UINT32_MAX)
+using network_group_handle_t = uint32_t;
+
+const auto SCHEDULER_REFRESH_INTERVAL = std::chrono::milliseconds(500);
+
+class NetworkGroupScheduler;
+using NetworkGroupSchedulerPtr = std::shared_ptr<NetworkGroupScheduler>;
+
+// We use mostly weak pointer for the scheduler to prevent circular dependency of the pointers
+using NetworkGroupSchedulerWeakPtr = std::weak_ptr<NetworkGroupScheduler>;
+
+using stream_name_t = std::string;
+class NetworkGroupScheduler final {
+public:
+    static Expected<NetworkGroupSchedulerPtr> create_shared(hailo_scheduling_algorithm_t algorithm);
+    NetworkGroupScheduler(hailo_scheduling_algorithm_t algorithm)
+        : m_algorithm(algorithm), m_before_read_write_mutex(), m_write_read_cv(), m_current_network_group(0),
+            m_switching_network_group(true), m_has_current_ng_finished(true), m_next_network_group(0), m_forced_idle_state(false)
+        {
+            // Temp solution until we'll implement timeout as timers
+            m_thread = std::thread([this] () {
+                while (!m_should_stop.load()) {
+                    m_write_read_cv.notify_all();
+                    std::this_thread::sleep_for(SCHEDULER_REFRESH_INTERVAL);
+                }
+          });
+        }
+
+    ~NetworkGroupScheduler()
+    {
+        m_should_stop = true;
+        m_thread.join();
+    }
+
+    hailo_scheduling_algorithm_t algorithm()
+    {
+        return m_algorithm;
+    }
+
+    Expected<network_group_handle_t> add_network_group(std::weak_ptr<ConfiguredNetworkGroup> added_cng);
+
+    hailo_status wait_for_write(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+    hailo_status signal_write_finish(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+    hailo_status wait_for_read(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+    hailo_status signal_read_finish(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+
+    hailo_status enable_stream(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+    hailo_status disable_stream(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+
+    hailo_status set_timeout(const network_group_handle_t &network_group_handle, const std::chrono::milliseconds &timeout, const std::string &network_name);
+    hailo_status set_threshold(const network_group_handle_t &network_group_handle, uint32_t threshold, const std::string &network_name);
+
+    class SchedulerIdleGuard final {
+        /* After 'set_scheduler()' is called, the idle guard will guarantee nothing is running on the device.
+        Relevant for state and configs changes */
+    public:
+        SchedulerIdleGuard() = default;
+        ~SchedulerIdleGuard();
+        hailo_status set_scheduler(std::shared_ptr<NetworkGroupScheduler> scheduler);
+    private:
+        std::shared_ptr<NetworkGroupScheduler> m_scheduler;
+    };
+
+    static std::unique_ptr<SchedulerIdleGuard> create_scheduler_idle_guard()
+    {
+        auto guard = make_unique_nothrow<SchedulerIdleGuard>();
+        return guard;
+    }
+
+private:
+    hailo_status switch_network_group_if_idle(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock);
+    hailo_status activate_network_group(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock);
+    hailo_status send_all_pending_buffers(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock);
+    hailo_status send_pending_buffer(const network_group_handle_t &network_group_handle, const std::string &stream_name, std::unique_lock<std::mutex> &read_write_lock);
+    hailo_status switch_network_group_if_should_be_next(const network_group_handle_t &network_group_handle, std::unique_lock<std::mutex> &read_write_lock);
+    void deactivate_network_group();
+    bool is_network_group_ready(const network_group_handle_t &network_group_handle);
+    hailo_status mark_switching_ng_if_ready();
+    bool can_stream_read(const network_group_handle_t &network_group_handle, const std::string &stream_name);
+    bool has_current_ng_finished();
+    void reset_current_ng_counters();
+    void decrease_current_ng_counters();
+    hailo_status allow_all_writes();
+    hailo_status allow_writes_for_other_inputs_if_needed(const network_group_handle_t &network_group_handle);
+
+    void force_idle_state();
+    void resume_from_idle_state();
+
+    hailo_scheduling_algorithm_t m_algorithm;
+    std::mutex m_before_read_write_mutex;
+    std::condition_variable m_write_read_cv;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_bool>> m_should_ng_stop;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_requested_write;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_written_buffer;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, EventPtr>> m_write_buffer_events;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_sent_pending_buffer;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_finished_sent_pending_buffer;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_allowed_read;
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_finished_read;
+    network_group_handle_t m_current_network_group;
+    std::vector<std::weak_ptr<ConfiguredNetworkGroup>> m_cngs;
+    std::unique_ptr<ActivatedNetworkGroup> m_ang;
+    std::atomic_bool m_switching_network_group;
+    std::atomic_bool m_has_current_ng_finished;
+    network_group_handle_t m_next_network_group;
+    std::atomic_bool m_forced_idle_state;
+
+    std::thread m_thread;
+    std::atomic_bool m_should_stop;
+
+    std::unordered_map<network_group_handle_t, std::unordered_map<stream_name_t, std::atomic_uint32_t>> m_min_threshold_per_stream;
+    std::unordered_map<network_group_handle_t, std::chrono::milliseconds> m_timeout_per_network_group;
+    std::unordered_map<network_group_handle_t, std::chrono::time_point<std::chrono::steady_clock>> m_last_run_time_stamp;
+};
+
+} /* namespace hailort */
+
+#endif /* _HAILO_NETWORK_GROUP_SCHEDULER_HPP_ */
index 5e4ab74934d08403d65bc121c0638c48f28e3f40..1f866a62717adcdb0fda6c828aa2081dded1120e 100644 (file)
@@ -27,10 +27,15 @@ set(files
     ${HAILO_FULL_OS_DIR}/event.cpp
 )
 
-if(UNIX)
+if(CMAKE_SYSTEM_NAME STREQUAL QNX)
+    # QNX only modules
+    set(files ${files}
+        ${HAILO_OS_DIR}/qnx/pcie_driver_scan.cpp
+    )
+elseif(UNIX)
     # Unix only modules
     set(files ${files}
-        ${HAILO_OS_DIR}/pcie_driver_sysfs.cpp
+        ${HAILO_OS_DIR}/unix/pcie_driver_scan.cpp
     )
 endif()
 
index a3db6c8c584dcfb82e20189f2f4d688a3e039a95..817a0f72bec57f6b014ffd15e9705a215a6b3885 100755 (executable)
@@ -37,6 +37,8 @@ static_assert((0 == ((PENDING_BUFFERS_SIZE - 1) &  PENDING_BUFFERS_SIZE)), "PEND
 // When measuring latency, each channel is capable of PENDING_BUFFERS_SIZE active transfers, each transfer raises max of 2 timestamps
 #define MAX_IRQ_TIMESTAMPS_SIZE (PENDING_BUFFERS_SIZE * 2)
 
+#define DESCRIPTORS_IN_BUFFER(buffer_size, desc_page_size) (((buffer_size) + (desc_page_size) - 1) / (desc_page_size))
+
 #define PCIE_EXPECTED_MD5_LENGTH (16)
 
 enum class PciBar {
@@ -166,9 +168,6 @@ public:
      * Frees a vdma descriptors buffer allocated by 'create_descriptors_buffer'.
      */
     hailo_status descriptors_list_release(uintptr_t desc_handle);
-    Expected<uintptr_t> vdma_low_memory_buffer_alloc(size_t size);
-    hailo_status vdma_low_memory_buffer_free(uintptr_t buffer_handle);
 
     /**
      * Configure vdma channel descriptors to point to the given user address.
@@ -176,6 +175,22 @@ public:
     hailo_status descriptors_list_bind_vdma_buffer(uintptr_t desc_handle, VdmaBufferHandle buffer_handle,
         uint16_t desc_page_size, uint8_t channel_index);
 
+    Expected<uintptr_t> vdma_low_memory_buffer_alloc(size_t size);
+    hailo_status vdma_low_memory_buffer_free(uintptr_t buffer_handle);
+
+    /**
+     * Allocate continuous vdma buffer.
+     *
+     * @param[in] size - Buffer size
+     * @return pair <buffer_handle, dma_address>.
+     */
+    Expected<std::pair<uintptr_t, uint64_t>> vdma_continuous_buffer_alloc(size_t size);
+
+    /**
+     * Frees a vdma continuous buffer allocated by 'vdma_continuous_buffer_alloc'.
+     */
+    hailo_status vdma_continuous_buffer_free(uintptr_t buffer_handle);
+
     /**
      * The actual desc page size might be smaller than the once requested, depends on the host capabilities.
      */
index 86828138cc2758b6b025ff6933837f344529436f..acffa8e00956728b90a30aff860c44a946231004 100755 (executable)
@@ -1,5 +1,5 @@
 #include "os/hailort_driver.hpp"
-#include "os/posix/pcie_driver_sysfs.hpp"
+#include "os/posix/pcie_driver_scan.hpp"
 #include "hailo_ioctl_common.h"
 #include "common/logger_macros.hpp"
 #include "common/utils.hpp"
@@ -182,9 +182,10 @@ hailo_status HailoRTDriver::disable_notifications()
     return HAILO_SUCCESS;
 }
 
+#if defined(__linux__)
 Expected<std::vector<HailoRTDriver::DeviceInfo>> HailoRTDriver::scan_pci()
 {
-    auto device_names = list_sysfs_pcie_devices();
+    auto device_names = list_pcie_devices();
     CHECK_EXPECTED(device_names, "Failed listing pcie devices");
 
     std::vector<HailoRTDriver::DeviceInfo> devices_info;
@@ -195,6 +196,26 @@ Expected<std::vector<HailoRTDriver::DeviceInfo>> HailoRTDriver::scan_pci()
     }
     return devices_info;
 }
+#elif defined(__QNX__)
+Expected<std::vector<HailoRTDriver::DeviceInfo>> HailoRTDriver::scan_pci()
+{
+    auto device_names = list_pcie_devices();
+    CHECK_EXPECTED(device_names, "Failed listing pcie devices");
+
+    // TODO: HRT-6785 - support multiple devices - currently device_names is vector of one device - in future will be multiple
+    std::vector<HailoRTDriver::DeviceInfo> devices_info;
+    uint32_t index = 0;
+    for (const auto &device_name : device_names.value()) {
+        auto device_info = query_device_info(device_name, index);
+        CHECK_EXPECTED(device_info, "failed parsing device info for {}", device_name);
+        devices_info.push_back(device_info.release());
+        index++;
+    }
+    return devices_info;
+}
+#else
+static_assert(true, "Error, Unsupported Platform");
+#endif //defined (__linux__)
 
 Expected<uint32_t> HailoRTDriver::read_vdma_channel_registers(off_t offset, size_t size)
 {
@@ -247,14 +268,21 @@ hailo_status HailoRTDriver::read_bar(PciBar bar, off_t offset, size_t size, void
         .bar_index = static_cast<uint32_t>(bar),
         .offset = offset,
         .count = size,
-        .buffer = buf
+        .buffer = {0}
     };
 
+    if (size > sizeof(transfer.buffer)) {
+        LOGGER__ERROR("Invalid size to read, size given {} is larger than max size {}", size, sizeof(transfer.buffer));
+        return HAILO_INVALID_ARGUMENT;
+    }
+
     if (0 > ioctl(this->m_fd, HAILO_BAR_TRANSFER, &transfer)) {
         LOGGER__ERROR("HailoRTDriver::read_bar failed with errno:{}", errno);
         return HAILO_PCIE_DRIVER_FAIL;
     }
 
+    memcpy(buf, transfer.buffer, transfer.count);
+
     return HAILO_SUCCESS;
 }
 
@@ -275,9 +303,16 @@ hailo_status HailoRTDriver::write_bar(PciBar bar, off_t offset, size_t size, con
         .bar_index = static_cast<uint32_t>(bar),
         .offset = offset,
         .count = size,
-        .buffer = (void*)buf
+        .buffer = {0}
     };
 
+    if (size > sizeof(transfer.buffer)) {
+        LOGGER__ERROR("Invalid size to read, size given {} is larger than max size {}", size, sizeof(transfer.buffer));
+        return HAILO_INVALID_ARGUMENT;
+    }
+
+    memcpy(transfer.buffer, buf, transfer.count);
+
     if (0 > ioctl(this->m_fd, HAILO_BAR_TRANSFER, &transfer)) {
         LOGGER__ERROR("HailoRTDriver::write_bar failed with errno:{}", errno);
         return HAILO_PCIE_DRIVER_FAIL;
@@ -419,16 +454,23 @@ hailo_status HailoRTDriver::read_log(uint8_t *buffer, size_t buffer_size, size_t
 
     hailo_read_log_params params {
         .cpu_id = translate_cpu_id(cpu_id),
-        .buffer = buffer,
+        .buffer = {0},
         .buffer_size = buffer_size,
         .read_bytes = 0
     };
 
+    CHECK(buffer_size <= sizeof(params.buffer), HAILO_PCIE_DRIVER_FAIL,
+        "Given buffer size {} is bigger than buffer size used to read logs {}", buffer_size, sizeof(params.buffer));
+
     if (0 > ioctl(this->m_fd, HAILO_READ_LOG, &params)) {
         LOGGER__ERROR("Failed to read log with errno:{}", errno);
         return HAILO_PCIE_DRIVER_FAIL;
     }
 
+    CHECK(params.read_bytes <= sizeof(params.buffer), HAILO_PCIE_DRIVER_FAIL,
+        "Amount of bytes read from log {} is bigger than size of buffer {}", params.read_bytes, sizeof(params.buffer));
+
+    memcpy(buffer, params.buffer, params.read_bytes);
     *read_bytes = params.read_bytes;
 
     return HAILO_SUCCESS;
@@ -561,7 +603,7 @@ Expected<uintptr_t> HailoRTDriver::vdma_low_memory_buffer_alloc(size_t size)
     CHECK_AS_EXPECTED(m_allocate_driver_buffer, HAILO_INVALID_OPERATION,
         "Tried to allocate buffer from driver even though operation is not supported");
 
-    hailo_allocate_buffer_params allocate_params = {
+    hailo_allocate_low_memory_buffer_params allocate_params = {
         .buffer_size    = size,
         .buffer_handle  = 0
     };
@@ -587,6 +629,28 @@ hailo_status HailoRTDriver::vdma_low_memory_buffer_free(uintptr_t buffer_handle)
     return HAILO_SUCCESS; 
 }
 
+Expected<std::pair<uintptr_t, uint64_t>> HailoRTDriver::vdma_continuous_buffer_alloc(size_t size)
+{
+    hailo_allocate_continuous_buffer_params params { .buffer_size = size, .buffer_handle = 0, .dma_address = 0 };
+
+    if (0 > ioctl(this->m_fd, HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC, &params)) {
+        LOGGER__ERROR("Failed allocate continuous buffer with errno:{}", errno);
+        return make_unexpected(HAILO_PCIE_DRIVER_FAIL);
+    }
+
+    return std::make_pair(params.buffer_handle, params.dma_address);
+}
+
+hailo_status HailoRTDriver::vdma_continuous_buffer_free(uintptr_t buffer_handle)
+{
+    if (0 > ioctl(this->m_fd, HAILO_VDMA_CONTINUOUS_BUFFER_FREE, buffer_handle)) {
+        LOGGER__ERROR("Failed to free continuous buffer with errno: {}", errno);
+        return HAILO_PCIE_DRIVER_FAIL;
+    }
+
+    return HAILO_SUCCESS;
+}
+
 hailo_status HailoRTDriver::mark_as_used()
 {
     hailo_mark_as_in_use_params params = {
index 1fdd3bf246929cefd6606ebf5db055ad743c39b8..fbf798817f203557bab10c14f64a98fef2df2fca 100644 (file)
@@ -12,7 +12,7 @@
 #include <sys/mman.h>
 #include <errno.h>
 
-#if defined(__unix__)
+#if defined(__linux__)
 #include <linux/mman.h>
 #endif
 
diff --git a/hailort/libhailort/src/os/posix/pcie_driver_scan.hpp b/hailort/libhailort/src/os/posix/pcie_driver_scan.hpp
new file mode 100644 (file)
index 0000000..4536cfe
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file pcie_driver_scan.hpp
+ * @brief Get list and parse pcie driver info
+ **/
+
+#include "os/hailort_driver.hpp"
+
+namespace hailort
+{
+
+Expected<std::vector<std::string>> list_pcie_devices();
+#if defined(__linux__)
+Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name);
+#elif defined(__QNX__)
+Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name, uint32_t index);
+#endif // defined(__linux__)
+
+} /* namespace hailort */
diff --git a/hailort/libhailort/src/os/posix/pcie_driver_sysfs.cpp b/hailort/libhailort/src/os/posix/pcie_driver_sysfs.cpp
deleted file mode 100644 (file)
index ddfe4c4..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @file pcie_driver_sysfs.cpp
- * @brief Parse pcie driver sysfs
- **/
-
-#include "os/posix/pcie_driver_sysfs.hpp"
-#include <stdarg.h>
-#include <dirent.h>
-
-namespace hailort
-{
-
-#define HAILO_PCIE_CLASS_PATH ("/sys/class/hailo_chardev")
-#define HAILO_BOARD_LOCATION_FILENAME ("board_location")
-#define HAILO_DEVICE_ID_FILENAME ("device_id")
-
-
-Expected<std::vector<std::string>> list_sysfs_pcie_devices()
-{
-    DIR *dir_iter = opendir(HAILO_PCIE_CLASS_PATH);
-    if (!dir_iter) {
-        if (ENOENT == errno) {
-            LOGGER__ERROR("Can't find hailo pcie class, this may happen if the driver is not installed (this may happen"
-            " if the kernel was updated), or if there is no connected Hailo board");
-            return make_unexpected(HAILO_PCIE_DRIVER_NOT_INSTALLED);
-        }
-        else {
-            LOGGER__ERROR("Failed to open hailo pcie class ({}), errno {}", HAILO_PCIE_CLASS_PATH, errno);
-            return make_unexpected(HAILO_PCIE_DRIVER_FAIL);
-        }
-    }
-
-    std::vector<std::string> devices;
-    struct dirent *dir = nullptr;
-    while ((dir = readdir(dir_iter)) != nullptr) {
-        std::string device_name(dir->d_name);
-        if (device_name == "." || device_name == "..") {
-            continue;
-        }
-        devices.push_back(device_name);
-    }
-
-    closedir(dir_iter);
-    return devices;
-}
-
-/**
- * Parses hailo driver sysfs entry using scanf format string
- * @param device_name - name of the specific device (inside hailo class sysfs directory)
- * @param sysfs_file_name - file name inside the device sysfs directory
- * @param expected_count - expected amount of scanf variable
- * @param fscanf_format - scanf format of the file
- * @param ... - external arguments, filled by the scanf
- */
-__attribute__((__format__ (__scanf__, 4, 5)))
-static hailo_status parse_device_sysfs_file(const std::string &device_name, const std::string &sysfs_file_name, uint32_t expected_count,
-    const char *fscanf_format, ...)
-{
-    std::string sysfs_file_path = std::string(HAILO_PCIE_CLASS_PATH) + "/" +
-        device_name + "/" + sysfs_file_name;
-    FILE *file_obj = fopen(sysfs_file_path.c_str(), "r");
-    if (!file_obj) {
-        LOGGER__ERROR("Failed opening sysfs file {}, errno {}", sysfs_file_path, errno);
-        return HAILO_FILE_OPERATION_FAILURE;
-    }
-
-    va_list args;
-    va_start(args, fscanf_format);
-    auto items_count = vfscanf(file_obj, fscanf_format, args);
-    va_end(args);
-    fclose(file_obj);
-
-    if (static_cast<uint32_t>(items_count) != expected_count) {
-        LOGGER__ERROR("Invalid sysfs file format {}", sysfs_file_path);
-        return HAILO_PCIE_DRIVER_FAIL;
-    }
-
-    return HAILO_SUCCESS;
-}
-
-Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name)
-{
-    HailoRTDriver::DeviceInfo device_info = {};
-    device_info.dev_path = std::string("/dev/") + device_name;
-
-    auto status = parse_device_sysfs_file(device_name, HAILO_BOARD_LOCATION_FILENAME, 4, "%04x:%02x:%02x.%d",
-        &device_info.domain, &device_info.bus, &device_info.device, &device_info.func);
-    CHECK_SUCCESS_AS_EXPECTED(status, "Failed reading {} file", HAILO_BOARD_LOCATION_FILENAME);
-
-    status = parse_device_sysfs_file(device_name, HAILO_DEVICE_ID_FILENAME, 2, "%x:%x",
-        &device_info.vendor_id, &device_info.device_id);
-    CHECK_SUCCESS_AS_EXPECTED(status, "Failed reading {} file", HAILO_DEVICE_ID_FILENAME);
-
-    return device_info;
-}
-
-} /* namespace hailort */
diff --git a/hailort/libhailort/src/os/posix/pcie_driver_sysfs.hpp b/hailort/libhailort/src/os/posix/pcie_driver_sysfs.hpp
deleted file mode 100644 (file)
index 32b60af..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @file pcie_driver_sysfs.hpp
- * @brief Parse pcie driver sysfs
- **/
-
-#include "os/hailort_driver.hpp"
-
-namespace hailort
-{
-
-Expected<std::vector<std::string>> list_sysfs_pcie_devices();
-Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name);
-
-} /* namespace hailort */
index 6109676a0a10c09e3ae2da55985d95d1c74d1124..d205f0c8bbbf38de0ebfaf207c0e9c6ad65b9aa3 100644 (file)
@@ -6,7 +6,8 @@
  * @file event.cpp
  * @brief Event & Semaphore wrapper for QNX
  *
- * TODO: doc
+ * This class implements our Events API over the neosmart pevents events. It also implement the Semaphore behavior and API
+ * Using the pevents events. For more information check out the implementation of pevents https://github.com/neosmart/pevents
  **/
 #include "hailo/event.hpp"
 #include "hailo/hailort.h"
 #include <poll.h>
 #include <utility>
 
-#define INVALID_FD (-1)
+#define WFMO
+#include "pevents.h"
+#undef WFMO
+
+#define INVALID_EVENT_HANDLE    (nullptr)
+#define WAIT_OBJECT_0           (0)
 
 namespace hailort
 {
 
-Waitable::Waitable(underlying_handle_t handle) :
+Waitable::Waitable(underlying_waitable_handle_t handle) :
     m_handle(handle)
 {}
 
 Waitable::~Waitable()
 {
-    if (-1 != m_handle) {
-        (void) close(m_handle);
+    if (INVALID_EVENT_HANDLE != m_handle) {
+        int err = 0;
+        if (0 != (err = neosmart::DestroyEvent(m_handle))) {
+            LOGGER__ERROR("Error destroying event handle, returned error={}", err);
+        }
     }
 }
 
 Waitable::Waitable(Waitable&& other) :
-    m_handle(std::exchange(other.m_handle, INVALID_FD))
+    m_handle(std::exchange(other.m_handle, INVALID_EVENT_HANDLE))
 {}
 
-underlying_handle_t Waitable::get_underlying_handle()
+underlying_waitable_handle_t Waitable::get_underlying_handle()
 {
     return m_handle;
 }
 
-hailo_status Waitable::eventfd_poll(underlying_handle_t fd, std::chrono::milliseconds timeout)
-{
-    (void) fd;
-    (void) timeout;
-    return HAILO_NOT_IMPLEMENTED;
-}
-
-hailo_status Waitable::eventfd_read(underlying_handle_t fd)
+hailo_status Waitable::wait_for_single_object(underlying_waitable_handle_t handle, std::chrono::milliseconds timeout)
 {
-    (void) fd;
-    return HAILO_NOT_IMPLEMENTED;
-}
-
-hailo_status Waitable::eventfd_write(underlying_handle_t fd)
-{
-    (void) fd;
-    return HAILO_NOT_IMPLEMENTED;
+    const size_t timeout_ms = (timeout.count() > INT_MAX) ? INT_MAX : static_cast<size_t>(timeout.count());
+    const auto wait_result = neosmart::WaitForEvent(handle, timeout_ms);
+    switch (wait_result) {
+        case WAIT_OBJECT_0:
+            return HAILO_SUCCESS;
+        case ETIMEDOUT:
+            return HAILO_TIMEOUT;
+        default:
+            LOGGER__ERROR("WaitForEvent failed, returned error={}", wait_result);
+            return HAILO_INTERNAL_FAILURE;
+    }
 }
 
 Expected<Event> Event::create(const State& initial_state)
 {
-    (void) initial_state;
-    return make_unexpected(HAILO_NOT_IMPLEMENTED);
+    const auto handle = open_event_handle(initial_state);
+    if (INVALID_EVENT_HANDLE == handle) {
+        return make_unexpected(HAILO_INTERNAL_FAILURE);
+    }
+    return std::move(Event(handle));
 }
 
 EventPtr Event::create_shared(const State& initial_state)
 {
-    (void) initial_state;
-    return make_shared_nothrow<Event>(INVALID_FD);
+    const auto handle = open_event_handle(initial_state);
+    if (INVALID_EVENT_HANDLE == handle) {
+        return nullptr;
+    }
+
+    return make_shared_nothrow<Event>(handle);
 }
 
 hailo_status Event::wait(std::chrono::milliseconds timeout)
 {
-    (void) timeout;
-    return HAILO_NOT_IMPLEMENTED;
+    return wait_for_single_object(m_handle, timeout);
 }
 
 hailo_status Event::signal()
 {
-    return HAILO_NOT_IMPLEMENTED;
+    const auto result = neosmart::SetEvent(m_handle);
+    CHECK(0 != result, HAILO_INTERNAL_FAILURE, "SetEvent failed with error {}" , result);
+
+    return HAILO_SUCCESS;
 }
 
 bool Event::is_auto_reset()
@@ -90,36 +104,76 @@ bool Event::is_auto_reset()
 
 hailo_status Event::reset()
 {
-    return HAILO_NOT_IMPLEMENTED;
+    const auto result = neosmart::ResetEvent(m_handle);
+    CHECK(0 != result, HAILO_INTERNAL_FAILURE, "ResetEvent failed with error {}", result);
+    
+    return HAILO_SUCCESS;
 }
 
-underlying_handle_t Event::open_event_handle(const State& initial_state)
+underlying_waitable_handle_t Event::open_event_handle(const State& initial_state)
 {
-    (void) initial_state;
-    return INVALID_FD;
+    static const auto manual_reset = true;
+    const bool state = (initial_state == State::signalled ? true : false);
+    auto event = neosmart::CreateEvent(manual_reset, state);
+    if (INVALID_EVENT_HANDLE == event) {
+        LOGGER__ERROR("Call to CreateEvent failed");
+    }
+    return event;
 }
 
 Expected<Semaphore> Semaphore::create(uint32_t initial_count)
 {
-    (void) initial_count;
-    return make_unexpected(HAILO_NOT_IMPLEMENTED);
+    const auto handle = open_semaphore_handle(initial_count);
+    if (INVALID_EVENT_HANDLE == handle) {
+        return make_unexpected(HAILO_INTERNAL_FAILURE);
+    }
+    return std::move(Semaphore(handle, initial_count));
 }
 
 SemaphorePtr Semaphore::create_shared(uint32_t initial_count)
 {
-    (void) initial_count;
-    return make_shared_nothrow<Semaphore>(INVALID_FD);
+    const auto handle = open_semaphore_handle(initial_count);
+    if (INVALID_EVENT_HANDLE == handle) {
+        return nullptr;
+    }
+
+    return make_shared_nothrow<Semaphore>(handle, initial_count);
 }
 
 hailo_status Semaphore::wait(std::chrono::milliseconds timeout)
 {
-    (void) timeout;
-    return HAILO_NOT_IMPLEMENTED;
+    auto wait_result = wait_for_single_object(m_handle, timeout);
+    if (HAILO_SUCCESS == wait_result) {
+        m_sem_mutex.lock();
+        if (0 == m_count.load()) {
+            LOGGER__ERROR("Waiting on semaphore with 0 value");
+        }
+        if (m_count > 0) {
+            m_count--;
+        }
+        // After decrementing the value of the semaphore - check if the new value is bigger than 0 and if it is signal the event
+        if (m_count > 0) {
+            neosmart::SetEvent(m_handle);
+        }
+        m_sem_mutex.unlock();
+    }
+    
+    return wait_result;
 }
 
 hailo_status Semaphore::signal()
 {
-    return HAILO_NOT_IMPLEMENTED;
+    m_sem_mutex.lock();
+    const auto result = neosmart::SetEvent(m_handle);
+    if (0 != result) {
+        LOGGER__ERROR("SetEvent failed with error {}", result);
+        m_sem_mutex.unlock();
+        return HAILO_INTERNAL_FAILURE;
+    }
+    m_count++;
+    m_sem_mutex.unlock();
+    
+    return HAILO_SUCCESS;
 }
 
 bool Semaphore::is_auto_reset()
@@ -127,39 +181,94 @@ bool Semaphore::is_auto_reset()
     return true;
 }
 
-underlying_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
+underlying_waitable_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
 {
-    (void) initial_count;
-    return INVALID_FD;
+    static const auto manual_reset = false;
+    static const auto state = (initial_count > 0 ? true : false);
+    auto event = neosmart::CreateEvent(manual_reset, state);
+    if (INVALID_EVENT_HANDLE == event) {
+        LOGGER__ERROR("Call to CreateEvent failed");
+    }
+    return event;
 }
 
-WaitOrShutdown::WaitOrShutdown(WaitablePtr waitable, EventPtr shutdown_event)
+Semaphore::Semaphore(underlying_waitable_handle_t handle, uint32_t initial_count) :
+    Waitable(handle), m_count(initial_count)
+{}
+
+Semaphore::Semaphore(Semaphore&& other) :
+    Waitable(std::move(other))
 {
-    (void) waitable;
-    (void) shutdown_event;
+    other.m_sem_mutex.lock();
+    m_count.store(other.m_count.load());
+    other.m_sem_mutex.unlock();
+}
+
+WaitOrShutdown::WaitOrShutdown(WaitablePtr waitable, EventPtr shutdown_event) :
+    m_waitable(waitable),
+    m_shutdown_event(shutdown_event),
+    m_wait_handle_array(create_wait_handle_array(waitable, shutdown_event))
+{}
+
+void Event::post_wait()
+{}
+
+void Semaphore::post_wait(){
+    m_sem_mutex.lock();
+    if (0 == m_count.load()) {
+        LOGGER__ERROR("Wait Returned on semaphore with 0 value");
+    }
+    if (m_count > 0) {
+        m_count--;
+    }
+    // After decrementing the value of the semaphore - check if the new value is bigger than 0 and if it is signal the event
+    if (m_count > 0) {
+        neosmart::SetEvent(m_handle);
+    }
+    m_sem_mutex.unlock();
 }
 
 hailo_status WaitOrShutdown::wait(std::chrono::milliseconds timeout)
 {
-    (void) timeout;
-    return HAILO_NOT_IMPLEMENTED;
+    int wait_index = -1;
+    const uint64_t timeout_ms = (timeout.count() > INT_MAX) ? INT_MAX : static_cast<uint64_t>(timeout.count());
+    const auto wait_result = neosmart::WaitForMultipleEvents(m_wait_handle_array.data(), static_cast<int>(m_wait_handle_array.size()),
+        false, timeout_ms, wait_index);
+    // If semaphore need to subtract from counter
+    if (0 != wait_result) {
+        if (ETIMEDOUT == wait_result) {
+            return HAILO_TIMEOUT;
+        } else {
+            LOGGER__ERROR("WaitForMultipleEvents Failed, error: {}", wait_result);
+            return HAILO_INTERNAL_FAILURE;
+        }
+    }
+    
+    if (WAITABLE_INDEX == wait_index) {
+        // Meaning it can be a semaphore object
+        m_waitable->post_wait();
+        return HAILO_SUCCESS;
+    } else if (SHUTDOWN_INDEX == wait_index) {
+        return HAILO_SHUTDOWN_EVENT_SIGNALED;
+    } else {
+        LOGGER__ERROR("Invalid event index signalled in WaitForMultipleEventsFailed, index: {}", wait_index);
+        return HAILO_INTERNAL_FAILURE;
+    }
 }
 
 hailo_status WaitOrShutdown::signal()
 {
-    return HAILO_NOT_IMPLEMENTED;
+    return m_waitable->signal();
 }
 
 WaitOrShutdown::WaitHandleArray WaitOrShutdown::create_wait_handle_array(WaitablePtr waitable, EventPtr shutdown_event)
 {
-    (void) waitable;
-    (void) shutdown_event;
     // Note the order!
-    WaitHandleArray pfds{{
-        {INVALID_FD, POLLIN, 0},
-        {INVALID_FD, POLLIN, 0}
-    }};
-    return pfds;
+    WaitHandleArray handles{
+        shutdown_event->get_underlying_handle(),
+        waitable->get_underlying_handle()
+    };
+    return handles;
 }
 
 } /* namespace hailort */
diff --git a/hailort/libhailort/src/os/posix/qnx/pcie_driver_scan.cpp b/hailort/libhailort/src/os/posix/qnx/pcie_driver_scan.cpp
new file mode 100644 (file)
index 0000000..05b5de3
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file pcie_driver_scan.cpp
+ * @brief Get list and parse pcie driver info
+ **/
+
+#include "os/posix/pcie_driver_scan.hpp"
+#include <dirent.h>
+extern "C" {
+#include <pci/pci.h>
+}
+
+namespace hailort
+{
+
+#define HAILO_VENDOR_ID (0x1e60)
+#define HAILO_PCIE_CLASS_PATH ("/dev/")
+// Every device name will start with "hailo"
+#define HAILO_PCIE_DEVICE_NAME_PREFIX ("hailo")
+
+Expected<std::vector<std::string>> list_pcie_devices()
+{
+    DIR *dir_iter = opendir(HAILO_PCIE_CLASS_PATH);
+    if (!dir_iter) {
+        if (ENOENT == errno) {
+            LOGGER__ERROR("Can't find hailo pcie class, this may happen if the driver is not installed (this may happen"
+            " if the kernel was updated), or if there is no connected Hailo board");
+            return make_unexpected(HAILO_PCIE_DRIVER_NOT_INSTALLED);
+        }
+        else {
+            LOGGER__ERROR("Failed to open hailo pcie class ({}), errno {}", HAILO_PCIE_CLASS_PATH, errno);
+            return make_unexpected(HAILO_PCIE_DRIVER_FAIL);
+        }
+    }
+
+    std::vector<std::string> devices;
+    struct dirent *dir = nullptr;
+    while ((dir = readdir(dir_iter)) != nullptr) {
+        std::string device_name(dir->d_name);
+        if (device_name == "." || device_name == "..") {
+            continue;
+        }
+        // Check that it is hailo device
+        if (std::string::npos == device_name.find(HAILO_PCIE_DEVICE_NAME_PREFIX)) {
+            continue;
+        }
+        devices.push_back(device_name);
+    }
+
+    closedir(dir_iter);
+    return devices;
+}
+
+Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name, uint32_t index)
+{
+    HailoRTDriver::DeviceInfo dev_info = {};
+    pci_err_t err;
+
+    // pci_device_find finds all relevant devices - find specific using index
+    pci_bdf_t pci_dev = pci_device_find(index, HAILO_VENDOR_ID, PCI_DID_ANY, PCI_CCODE_ANY);
+    if (PCI_BDF_NONE == pci_dev) {
+        LOGGER__ERROR("Error finding relevant device");
+        make_unexpected(HAILO_INVALID_ARGUMENT);
+    }
+
+    pci_did_t device_id;
+    if (PCI_ERR_OK != (err = pci_device_read_did(pci_dev, &device_id))) {
+        LOGGER__ERROR("Failed reading Device ID, error {}", err);
+        make_unexpected(HAILO_INTERNAL_FAILURE);
+    }
+
+    dev_info.dev_path = std::move(std::string(HAILO_PCIE_CLASS_PATH) + device_name);
+    dev_info.vendor_id = HAILO_VENDOR_ID;
+    dev_info.device_id = device_id;
+    dev_info.domain = 0;
+    dev_info.bus = PCI_BUS(pci_dev);
+    dev_info.device = PCI_DEV(pci_dev);
+    dev_info.func = PCI_FUNC(pci_dev);
+
+    return dev_info;
+}
+
+} /* namespace hailort */
index 2e7a898abc975ffbe8b800eb0c72e329050f9259..465b4c8e36ee52bdf2f111e3e511ee7e236f2e22 100644 (file)
@@ -20,7 +20,7 @@
 namespace hailort
 {
 
-Waitable::Waitable(underlying_handle_t handle) :
+Waitable::Waitable(underlying_waitable_handle_t handle) :
     m_handle(handle)
 {}
 
@@ -35,12 +35,12 @@ Waitable::Waitable(Waitable&& other) :
     m_handle(std::exchange(other.m_handle, -1))
 {}
 
-underlying_handle_t Waitable::get_underlying_handle()
+underlying_waitable_handle_t Waitable::get_underlying_handle()
 {
     return m_handle;
 }
 
-hailo_status Waitable::eventfd_poll(underlying_handle_t fd, std::chrono::milliseconds timeout)
+hailo_status Waitable::eventfd_poll(underlying_waitable_handle_t fd, std::chrono::milliseconds timeout)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     struct pollfd pfd{};
@@ -84,7 +84,7 @@ l_exit:
     return status;
 }
 
-hailo_status Waitable::eventfd_read(underlying_handle_t fd)
+hailo_status Waitable::eventfd_read(underlying_waitable_handle_t fd)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     ssize_t read_ret = -1;
@@ -104,7 +104,7 @@ l_exit:
     return status;
 }
 
-hailo_status Waitable::eventfd_write(underlying_handle_t fd)
+hailo_status Waitable::eventfd_write(underlying_waitable_handle_t fd)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     ssize_t write_ret = -1;
@@ -167,7 +167,7 @@ hailo_status Event::reset()
     return eventfd_read(m_handle);
 }
 
-underlying_handle_t Event::open_event_handle(const State& initial_state)
+underlying_waitable_handle_t Event::open_event_handle(const State& initial_state)
 {
     static const int NO_FLAGS = 0;
     const int state = initial_state == State::signalled ? 1 : 0;
@@ -223,7 +223,7 @@ bool Semaphore::is_auto_reset()
     return true;
 }
 
-underlying_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
+underlying_waitable_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
 {
     static const int SEMAPHORE = EFD_SEMAPHORE;
     const auto handle = eventfd(initial_count, SEMAPHORE);
diff --git a/hailort/libhailort/src/os/posix/unix/pcie_driver_scan.cpp b/hailort/libhailort/src/os/posix/unix/pcie_driver_scan.cpp
new file mode 100644 (file)
index 0000000..531778a
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file pcie_driver_scan.cpp
+ * @brief Parse pcie driver sysfs
+ **/
+
+#include "os/posix/pcie_driver_scan.hpp"
+#include <stdarg.h>
+#include <dirent.h>
+
+namespace hailort
+{
+
+#define HAILO_PCIE_CLASS_PATH ("/sys/class/hailo_chardev")
+#define HAILO_BOARD_LOCATION_FILENAME ("board_location")
+#define HAILO_DEVICE_ID_FILENAME ("device_id")
+
+
+Expected<std::vector<std::string>> list_pcie_devices()
+{
+    DIR *dir_iter = opendir(HAILO_PCIE_CLASS_PATH);
+    if (!dir_iter) {
+        if (ENOENT == errno) {
+            LOGGER__ERROR("Can't find hailo pcie class, this may happen if the driver is not installed (this may happen"
+            " if the kernel was updated), or if there is no connected Hailo board");
+            return make_unexpected(HAILO_PCIE_DRIVER_NOT_INSTALLED);
+        }
+        else {
+            LOGGER__ERROR("Failed to open hailo pcie class ({}), errno {}", HAILO_PCIE_CLASS_PATH, errno);
+            return make_unexpected(HAILO_PCIE_DRIVER_FAIL);
+        }
+    }
+
+    std::vector<std::string> devices;
+    struct dirent *dir = nullptr;
+    while ((dir = readdir(dir_iter)) != nullptr) {
+        std::string device_name(dir->d_name);
+        if (device_name == "." || device_name == "..") {
+            continue;
+        }
+        devices.push_back(device_name);
+    }
+
+    closedir(dir_iter);
+    return devices;
+}
+
+/**
+ * Parses hailo driver sysfs entry using scanf format string
+ * @param device_name - name of the specific device (inside hailo class sysfs directory)
+ * @param sysfs_file_name - file name inside the device sysfs directory
+ * @param expected_count - expected amount of scanf variable
+ * @param fscanf_format - scanf format of the file
+ * @param ... - external arguments, filled by the scanf
+ */
+__attribute__((__format__ (__scanf__, 4, 5)))
+static hailo_status parse_device_sysfs_file(const std::string &device_name, const std::string &sysfs_file_name, uint32_t expected_count,
+    const char *fscanf_format, ...)
+{
+    std::string sysfs_file_path = std::string(HAILO_PCIE_CLASS_PATH) + "/" +
+        device_name + "/" + sysfs_file_name;
+    FILE *file_obj = fopen(sysfs_file_path.c_str(), "r");
+    if (!file_obj) {
+        LOGGER__ERROR("Failed opening sysfs file {}, errno {}", sysfs_file_path, errno);
+        return HAILO_FILE_OPERATION_FAILURE;
+    }
+
+    va_list args;
+    va_start(args, fscanf_format);
+    auto items_count = vfscanf(file_obj, fscanf_format, args);
+    va_end(args);
+    fclose(file_obj);
+
+    if (static_cast<uint32_t>(items_count) != expected_count) {
+        LOGGER__ERROR("Invalid sysfs file format {}", sysfs_file_path);
+        return HAILO_PCIE_DRIVER_FAIL;
+    }
+
+    return HAILO_SUCCESS;
+}
+
+Expected<HailoRTDriver::DeviceInfo> query_device_info(const std::string &device_name)
+{
+    HailoRTDriver::DeviceInfo device_info = {};
+    device_info.dev_path = std::string("/dev/") + device_name;
+
+    auto status = parse_device_sysfs_file(device_name, HAILO_BOARD_LOCATION_FILENAME, 4, "%04x:%02x:%02x.%d",
+        &device_info.domain, &device_info.bus, &device_info.device, &device_info.func);
+    CHECK_SUCCESS_AS_EXPECTED(status, "Failed reading {} file", HAILO_BOARD_LOCATION_FILENAME);
+
+    status = parse_device_sysfs_file(device_name, HAILO_DEVICE_ID_FILENAME, 2, "%x:%x",
+        &device_info.vendor_id, &device_info.device_id);
+    CHECK_SUCCESS_AS_EXPECTED(status, "Failed reading {} file", HAILO_DEVICE_ID_FILENAME);
+
+    return device_info;
+}
+
+} /* namespace hailort */
index fd019c94956a728a69dde8ea3d76a2721c794c1a..dd053ac3c2de364353daab77613f0b4ff555e992 100644 (file)
@@ -17,7 +17,7 @@
 namespace hailort
 {
 
-Waitable::Waitable(underlying_handle_t handle) :
+Waitable::Waitable(underlying_waitable_handle_t handle) :
     m_handle(handle)
 {}
 
@@ -32,7 +32,7 @@ Waitable::Waitable(Waitable&& other) :
     m_handle(std::exchange(other.m_handle, nullptr))
 {}
 
-underlying_handle_t Waitable::get_underlying_handle()
+underlying_waitable_handle_t Waitable::get_underlying_handle()
 {
     return m_handle;
 }
@@ -46,7 +46,7 @@ static DWORD timeout_millies(long long value)
     return millies;
 }
 
-hailo_status Waitable::wait_for_single_object(underlying_handle_t handle, std::chrono::milliseconds timeout)
+hailo_status Waitable::wait_for_single_object(underlying_waitable_handle_t handle, std::chrono::milliseconds timeout)
 {
     DWORD wait_millies = timeout_millies(timeout.count());
     assert(nullptr != handle);
@@ -117,7 +117,7 @@ hailo_status Event::reset()
     return HAILO_SUCCESS;
 }
 
-underlying_handle_t Event::open_event_handle(const State& initial_state)
+underlying_waitable_handle_t Event::open_event_handle(const State& initial_state)
 {
     static const LPSECURITY_ATTRIBUTES NO_INHERITANCE = nullptr;
     static const BOOL                  MANUAL_RESET = true;
@@ -172,7 +172,7 @@ bool Semaphore::is_auto_reset()
     return true;
 }
 
-underlying_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
+underlying_waitable_handle_t Semaphore::open_semaphore_handle(uint32_t initial_count)
 {
     static const LPSECURITY_ATTRIBUTES NO_INHERITANCE = nullptr;
     static const LONG                  MAX_SIZE = std::numeric_limits<long>::max();
index a8854d155c507515610a905de74a9194d8510ba9..92e1ce65a1d9d7d5a05f94686c1c34f10b61d96a 100644 (file)
@@ -603,13 +603,18 @@ hailo_status HailoRTDriver::read_bar(PciBar bar, off_t offset, size_t size, void
     transfer.bar_index = static_cast<uint32_t>(bar);
     transfer.offset = offset;
     transfer.count = size;
-    transfer.buffer = buf;
+    memset(transfer.buffer, 0, sizeof(transfer.buffer));
+
+    CHECK(size <= sizeof(transfer.buffer), HAILO_INVALID_ARGUMENT,
+        "Invalid size to read, size given {} is larger than max size {}", size, sizeof(transfer.buffer));
 
     if (0 > ioctl(m_fd, HAILO_BAR_TRANSFER, &data)) {
         LOGGER__ERROR("HailoRTDriver::read_bar failed with errno:{}", errno);
         return HAILO_PCIE_DRIVER_FAIL;
     }
 
+    memcpy(buf, transfer.buffer, transfer.count);
+
     return HAILO_SUCCESS;
 }
 
@@ -631,7 +636,12 @@ hailo_status HailoRTDriver::write_bar(PciBar bar, off_t offset, size_t size, con
     transfer.bar_index = static_cast<uint32_t>(bar);
     transfer.offset = offset;
     transfer.count = size;
-    transfer.buffer = (void*)buf;
+    memset(transfer.buffer, 0, sizeof(transfer.buffer));
+
+    CHECK(size <= sizeof(transfer.buffer), HAILO_INVALID_ARGUMENT,
+        "Invalid size to write, size given {} is larger than max size {}", size, sizeof(transfer.buffer));
+
+    memcpy(transfer.buffer, buf, transfer.count);
 
     if (0 > ioctl(this->m_fd, HAILO_BAR_TRANSFER, &data)) {
         LOGGER__ERROR("HailoRTDriver::write_bar failed with errno: {}", errno);
@@ -965,6 +975,18 @@ hailo_status HailoRTDriver::vdma_low_memory_buffer_free(uintptr_t buffer_handle)
     return HAILO_INVALID_OPERATION;
 }
 
+Expected<std::pair<uintptr_t, uint64_t>> HailoRTDriver::vdma_continuous_buffer_alloc(size_t size)
+{
+    (void) size;
+    return make_unexpected(HAILO_INVALID_OPERATION);
+}
+
+hailo_status HailoRTDriver::vdma_continuous_buffer_free(uintptr_t buffer_handle)
+{
+    (void) buffer_handle;
+    return HAILO_INVALID_OPERATION;
+}
+
 hailo_status HailoRTDriver::mark_as_used()
 {
     tCompatibleHailoIoctlData data = {};
index 9e51d252bb4b1c47cfda31e282a2d56f24b008fc..c7f46e886c941d2048bfb3e1ff02ced58b07f617 100644 (file)
@@ -13,27 +13,26 @@ namespace hailort
 
 PcieInputStream::PcieInputStream(
     PcieDevice &device,
-    uint8_t channel_index,
+    std::shared_ptr<VdmaChannel> channel,
     const LayerInfo &edge_layer,
     EventPtr network_group_activated_event,
     uint16_t batch_size,
-    LatencyMeterPtr latency_meter,
     const std::chrono::milliseconds &transfer_timeout,
     hailo_status &status) :
-        VdmaInputStream(device, channel_index, edge_layer, network_group_activated_event,
-            batch_size, latency_meter, transfer_timeout, HAILO_STREAM_INTERFACE_PCIE, status)
+        VdmaInputStream(device, std::move(channel), edge_layer, network_group_activated_event,
+            batch_size, transfer_timeout, HAILO_STREAM_INTERFACE_PCIE, status)
     {}
 
 Expected<std::unique_ptr<PcieInputStream>> PcieInputStream::create(Device &device,
-    uint8_t channel_index, const LayerInfo &edge_layer, uint16_t batch_size,
-    EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, 
+    uint16_t batch_size, EventPtr network_group_activated_event)
 {
     hailo_status status = HAILO_UNINITIALIZED;
 
     PcieDevice *pcie_device = reinterpret_cast<PcieDevice*>(&device);
     std::unique_ptr<PcieInputStream> local_stream(new (std::nothrow) PcieInputStream(*pcie_device,
-        channel_index, edge_layer, std::move(network_group_activated_event), batch_size,
-        latency_meter, DEFAULT_TRANSFER_TIMEOUT, status));
+        std::move(channel), edge_layer, std::move(network_group_activated_event), batch_size,
+        DEFAULT_TRANSFER_TIMEOUT, status));
     CHECK((nullptr != local_stream), make_unexpected(HAILO_OUT_OF_HOST_MEMORY));
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -41,15 +40,15 @@ Expected<std::unique_ptr<PcieInputStream>> PcieInputStream::create(Device &devic
 }
 
 Expected<std::unique_ptr<PcieOutputStream>> PcieOutputStream::create(Device &device,
-    uint8_t channel_index, const LayerInfo &edge_layer, uint16_t batch_size,
-    EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, uint16_t batch_size,
+    EventPtr network_group_activated_event)
 {
     hailo_status status = HAILO_UNINITIALIZED;
     PcieDevice *pcie_device = reinterpret_cast<PcieDevice*>(&device);
 
     std::unique_ptr<PcieOutputStream> local_stream(new (std::nothrow) PcieOutputStream(*pcie_device,
-        channel_index, edge_layer, std::move(network_group_activated_event),
-        batch_size, latency_meter, DEFAULT_TRANSFER_TIMEOUT, status));
+        std::move(channel), edge_layer, std::move(network_group_activated_event),
+        batch_size, DEFAULT_TRANSFER_TIMEOUT, status));
     CHECK((nullptr != local_stream), make_unexpected(HAILO_OUT_OF_HOST_MEMORY));
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -58,15 +57,14 @@ Expected<std::unique_ptr<PcieOutputStream>> PcieOutputStream::create(Device &dev
 
 PcieOutputStream::PcieOutputStream(
     PcieDevice &device,
-    uint8_t channel_index,
+    std::shared_ptr<VdmaChannel> channel,
     const LayerInfo &edge_layer,
     EventPtr network_group_activated_event,
     uint16_t batch_size,
-    LatencyMeterPtr latency_meter,
     const std::chrono::milliseconds &transfer_timeout,
     hailo_status &status) :
-        VdmaOutputStream(device, channel_index, edge_layer,
-            network_group_activated_event, batch_size, latency_meter, transfer_timeout, status)
+        VdmaOutputStream(device, std::move(channel), edge_layer,
+            network_group_activated_event, batch_size, transfer_timeout, status)
     {}
 
 } /* namespace hailort */
index 314537cf15f7ba3dded934e6a98111214ba519fc..40a331b3f1a6836c63a7aeb0fc0035cceea29273 100644 (file)
@@ -21,20 +21,19 @@ public:
     PcieInputStream(PcieInputStream &&other) = default;
     virtual ~PcieInputStream() = default;
 
-    static Expected<std::unique_ptr<PcieInputStream>> create(Device &device, uint8_t channel_index,
-        const LayerInfo &edge_layer, uint16_t batch_size, EventPtr network_group_activated_event,
-        LatencyMeterPtr latency_meter = nullptr);
+    static Expected<std::unique_ptr<PcieInputStream>> create(Device &device,
+        std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, uint16_t batch_size, 
+        EventPtr network_group_activated_event);
 
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_PCIE; }
 
 private:
     PcieInputStream(
         PcieDevice &device,
-        uint8_t channel_index,
+        std::shared_ptr<VdmaChannel> channel,
         const LayerInfo &edge_layer,
         EventPtr network_group_activated_event,
         uint16_t batch_size,
-        LatencyMeterPtr latency_meter,
         const std::chrono::milliseconds &transfer_timeout,
         hailo_status &status);
 
@@ -46,9 +45,9 @@ public:
     PcieOutputStream(PcieOutputStream &&other) = default;
     virtual ~PcieOutputStream() = default;
 
-    static Expected<std::unique_ptr<PcieOutputStream>> create(Device &device, uint8_t channel_index,
-        const LayerInfo &edge_layer, uint16_t batch_size, EventPtr network_group_activated_event
-        LatencyMeterPtr latency_meter);
+    static Expected<std::unique_ptr<PcieOutputStream>> create(Device &device,
+        std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer, uint16_t batch_size
+        EventPtr network_group_activated_event);
 
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_PCIE; }
 
@@ -57,11 +56,10 @@ public:
 private:
     explicit PcieOutputStream(
         PcieDevice &device,
-        uint8_t channel_index,
+        std::shared_ptr<VdmaChannel> channel,
         const LayerInfo &edge_layer,
         EventPtr network_group_activated_event,
         uint16_t batch_size,
-        LatencyMeterPtr latency_meter,
         const std::chrono::milliseconds &transfer_timeout,
         hailo_status &status);
 };
index c65122e244e2c24b1a4aa04741269ed31235478a..de3ae91de076d3d4bba5863baed5e9f17225dc0e 100644 (file)
@@ -10,6 +10,7 @@
 #include "pipeline.hpp"
 #include "common/utils.hpp"
 #include "common/runtime_statistics_internal.hpp"
+#include "microprofile.h"
 
 namespace hailort
 {
@@ -629,6 +630,11 @@ BaseQueueElement::BaseQueueElement(SpscQueue<PipelineBuffer> &&queue, EventPtr s
 void BaseQueueElement::start_thread()
 {
     m_thread = std::thread([this] () {
+        // Microprofile the thread
+        MicroProfileOnThreadCreate(name().c_str());
+        MicroProfileSetEnableAllGroups(true);
+        MicroProfileSetForceMetaCounters(true);
+
         while (m_is_thread_running.load()) {
             auto status = m_activation_event.wait(INIFINITE_TIMEOUT());
 
@@ -669,6 +675,8 @@ void BaseQueueElement::start_thread()
                 }
             }
         }
+        // TODO: Should we use MicroProfileShutdown?
+        MicroProfileOnThreadExit();
     });
 }
 
@@ -846,14 +854,13 @@ hailo_status PushQueueElement::deactivate()
     if (HAILO_SUCCESS != status) {
         // We want to deactivate source even if enqueue failed
         auto deactivation_status = next_pad().deactivate();
-        if (HAILO_SUCCESS != deactivation_status) {
-            LOGGER__ERROR("Deactivate of source in {} has failed with status {}", name(), status);
-            // TODO (HRT-4156): return error status?
-        }
+        CHECK_SUCCESS(deactivation_status);
         if ((HAILO_STREAM_INTERNAL_ABORT == status) || (HAILO_SHUTDOWN_EVENT_SIGNALED == status)) {
             LOGGER__INFO("enqueue() in element {} was aborted, got status = {}", name(), status);
-        } else {
-            LOGGER__ERROR("enqueue() in element {} failed, got status = {}", name(), status);
+        }
+        else {
+             LOGGER__ERROR("enqueue() in element {} failed, got status = {}", name(), status);
+             return status;
         }
     }
 
@@ -980,14 +987,9 @@ Expected<PipelineBuffer> PullQueueElement::run_pull(PipelineBuffer &&optional, c
 hailo_status PullQueueElement::deactivate()
 {
     hailo_status status = next_pad().deactivate();
-    if (HAILO_SUCCESS != status) {
-        LOGGER__ERROR("deactivate of source in {} has failed with status {}", name(), status);
-    }
-
-    status = m_shutdown_event->signal();
-    if (HAILO_SUCCESS != status) {
-        LOGGER__CRITICAL("Signaling shutdown event has failed with status = {}", status);
-    }
+    auto shutdown_event_status = m_shutdown_event->signal();
+    CHECK_SUCCESS(status);
+    CHECK_SUCCESS(shutdown_event_status);
 
     return HAILO_SUCCESS;
 }
@@ -1349,9 +1351,6 @@ hailo_status BaseDemuxElement::deactivate()
     // deactivate should be called before mutex acquire and notify_all because it is possible that all queues are waiting on
     // the run_pull of the source (HwRead) and the mutex is already acquired so this would prevent a timeout error
     hailo_status status = next_pad().deactivate();
-    if (HAILO_SUCCESS != status) {
-        LOGGER__ERROR("deactivate of source in {} has failed with status {}", name(), status);
-    }
 
     {
         // There is a case where the other thread is halted (via context switch) before the wait_for() function,
@@ -1361,6 +1360,8 @@ hailo_status BaseDemuxElement::deactivate()
     }
     m_cv.notify_all();
 
+    CHECK_SUCCESS(status);
+
     return HAILO_SUCCESS;
 }
 
index 07ee85bdc481a8ba37545f675e64e061bbdaa4ee..039e81b51ef151df04ad889ebc42247895725591 100644 (file)
@@ -13,6 +13,7 @@
 #include "hailo/transform.hpp"
 #include "common/utils.hpp"
 #include "hef_internal.hpp"
+#include "microprofile.h"
 
 #include <sstream>
 
@@ -26,13 +27,16 @@ hailo_status InputStream::flush()
 
 hailo_status InputStream::write(const MemoryView &buffer)
 {
+    MICROPROFILE_SCOPEI("Stream", "Write", 0);
     CHECK((buffer.size() % m_stream_info.hw_frame_size) == 0, HAILO_INVALID_ARGUMENT,
         "write size {} must be a multiple of hw size {}", buffer.size(), m_stream_info.hw_frame_size);
 
     CHECK(((buffer.size() % HailoRTCommon::HW_DATA_ALIGNMENT) == 0), HAILO_INVALID_ARGUMENT,
         "Input must be aligned to {} (got {})", HailoRTCommon::HW_DATA_ALIGNMENT, buffer.size());
     
-    return sync_write_all_raw_buffer_no_transform_impl(const_cast<uint8_t*>(buffer.data()), 0, buffer.size());
+    auto status = sync_write_all_raw_buffer_no_transform_impl(const_cast<uint8_t*>(buffer.data()), 0, buffer.size());
+    MicroProfileFlip(nullptr);
+    return status;
 }
 
 std::string InputStream::to_string() const
@@ -78,6 +82,10 @@ hailo_status OutputStream::read_nms(void *buffer, size_t offset, size_t size)
                 CHECK(transfer_size == bbox_size, HAILO_INTERNAL_FAILURE,
                     "Data read from the device was size {}, should be bbox size {}", transfer_size, bbox_size);
 
+                if (HailoRTCommon::NMS_DUMMY_DELIMITER == *(uint64_t*)((uint8_t*)buffer + offset)) {
+                    continue;
+                }
+
                 if (HailoRTCommon::NMS_DELIMITER == *(uint64_t*)((uint8_t*)buffer + offset)) {
                     break;
                 }
@@ -96,6 +104,7 @@ hailo_status OutputStream::read_nms(void *buffer, size_t offset, size_t size)
 
 hailo_status OutputStream::read(MemoryView buffer)
 {
+    MICROPROFILE_SCOPEI("Stream", "Read", 0);
     CHECK((buffer.size() % m_stream_info.hw_frame_size) == 0, HAILO_INVALID_ARGUMENT,
         "When read size {} must be a multiple of hw size {}", buffer.size(), m_stream_info.hw_frame_size);
 
index 0b80c01f101f70335e1e1413f2fc2157ae6d1314..652b326b976d8e8840092fa399abf1f4b01648a3 100644 (file)
@@ -22,9 +22,19 @@ EventPtr &InputStreamBase::get_network_group_activated_event()
     return m_network_group_activated_event;
 }
 
+bool InputStreamBase::is_scheduled()
+{
+    return false;
+}
+
 EventPtr &OutputStreamBase::get_network_group_activated_event()
 {
     return m_network_group_activated_event;
 }
 
+bool OutputStreamBase::is_scheduled()
+{
+    return false;
+}
+
 } /* namespace hailort */
index 4ba44671c46d06386612eb6f60a2979d8014cb34..85ce20e7ebab21f26853094c67dc5f57a8422f77 100644 (file)
@@ -83,6 +83,7 @@ protected:
     }
 
     virtual EventPtr &get_network_group_activated_event() override;
+    virtual bool is_scheduled() override;
 
 private:
     EventPtr m_network_group_activated_event;
@@ -124,6 +125,7 @@ protected:
     }
 
     virtual EventPtr &get_network_group_activated_event() override;
+    virtual bool is_scheduled() override;
 
     LayerInfo m_layer_info;
 
index 65ffe22b6d864671d344b361ee23c92b4e7e5fb2..509c1981762fc0ac271dcb86c193c81a64931c50 100644 (file)
@@ -17,6 +17,7 @@
 #include "common/logger_macros.hpp"
 #include "common/utils.hpp"
 #include "transform_internal.hpp"
+#include "microprofile.h"
 
 #include <type_traits>
 #include <sstream>
@@ -829,7 +830,7 @@ hailo_status reorder_input_stream(const void *src_ptr, hailo_3d_image_shape_t sr
         return HAILO_SUCCESS;
     }
 
-    if ((HAILO_FORMAT_ORDER_FCR == src_format.order) &&
+    if (((HAILO_FORMAT_ORDER_FCR == src_format.order) || (HAILO_FORMAT_ORDER_NHWC == src_format.order)) &&
         (HAILO_FORMAT_ORDER_FCR == dst_format.order)) {
         assert(0 == (dst_image_shape.features % 8));
         switch (dst_format.type) {
@@ -846,7 +847,7 @@ hailo_status reorder_input_stream(const void *src_ptr, hailo_3d_image_shape_t sr
         return HAILO_SUCCESS;
     }
 
-    if ((HAILO_FORMAT_ORDER_F8CR == src_format.order) &&
+    if (((HAILO_FORMAT_ORDER_F8CR == src_format.order) || (HAILO_FORMAT_ORDER_NHWC == src_format.order)) &&
         (HAILO_FORMAT_ORDER_F8CR == dst_format.order)) {
         switch (dst_format.type) {
             case HAILO_FORMAT_TYPE_UINT8:
@@ -993,7 +994,7 @@ hailo_status reorder_output_stream(const void *src_ptr, hailo_3d_image_shape_t s
             }
     }
     else if ((HAILO_FORMAT_ORDER_FCR == src_format.order) &&
-        (HAILO_FORMAT_ORDER_FCR == dst_format.order)) {
+        ((HAILO_FORMAT_ORDER_FCR == dst_format.order) || (HAILO_FORMAT_ORDER_NHWC == dst_format.order))) {
             switch (src_format.type) {
                 case HAILO_FORMAT_TYPE_UINT8:
                     transform__d2h_NHWC_to_NHWC<uint8_t>((uint8_t*)src_ptr, &src_image_shape, (uint8_t*)dst_ptr, &dst_image_shape);
@@ -1007,7 +1008,7 @@ hailo_status reorder_output_stream(const void *src_ptr, hailo_3d_image_shape_t s
             }
     }
     else if ((HAILO_FORMAT_ORDER_F8CR == src_format.order) &&
-        (HAILO_FORMAT_ORDER_F8CR == dst_format.order)) {
+        ((HAILO_FORMAT_ORDER_F8CR == dst_format.order) || (HAILO_FORMAT_ORDER_NHWC == dst_format.order))) {
             switch (src_format.type) {
                 case HAILO_FORMAT_TYPE_UINT8:
                     transform__d2h_F8CR<uint8_t>((uint8_t*)src_ptr, &src_image_shape, (uint8_t*)dst_ptr, &dst_image_shape);
@@ -1230,6 +1231,7 @@ hailo_status FrameOutputTransformContext::transform_inner(const void *src_ptr, v
 hailo_status transform_demux_raw_frame(const void *src, uint32_t offset,
     hailo_mux_info_t *mux_info, uint32_t mux_row_count)
 {
+    MICROPROFILE_SCOPEI("Transformations", "Demux", 0);
     // This is a recursive function with a maximum depth of HailoRTCommon::MUX_INFO_COUNT.
     hailo_status status = HAILO_UNINITIALIZED;
     struct hailo_mux_info_t *predecessor = NULL;
@@ -1470,6 +1472,7 @@ InputTransformContext::InputTransformContext(size_t src_frame_size, const hailo_
 
 hailo_status InputTransformContext::transform(const MemoryView src, MemoryView dst)
 {
+    MICROPROFILE_SCOPEI("Transformations", "H2D transform", 0);
     /* Check sizes */
     CHECK(src.size() == m_src_frame_size, HAILO_INVALID_ARGUMENT,
         "src size must be {}. passed size - {}", m_src_frame_size, src.size());
@@ -1636,6 +1639,7 @@ Expected<std::unique_ptr<OutputTransformContext>> NMSOutputTransformContext::cre
 
 hailo_status FrameOutputTransformContext::transform(const MemoryView src, MemoryView dst)
 {
+    MICROPROFILE_SCOPEI("Transformations", "D2H transform", 0);
     /* Check sizes */
     CHECK(src.size() == m_src_frame_size, HAILO_INVALID_ARGUMENT,
         "src size must be {}. passed size - {}", m_src_frame_size, src.size());
@@ -1650,6 +1654,7 @@ hailo_status FrameOutputTransformContext::transform(const MemoryView src, Memory
 
 hailo_status NMSOutputTransformContext::transform(const MemoryView src, MemoryView dst)
 {
+    MICROPROFILE_SCOPEI("Transformations", "D2H NMS transform", 0);
     /* Check sizes */
     CHECK(src.size() == m_src_frame_size, HAILO_INVALID_ARGUMENT,
         "src size must be {}. passed size - {}", m_src_frame_size, src.size());
@@ -1826,6 +1831,7 @@ hailo_status OutputDemuxerBase::get_mux_info_from_layer_info_impl(hailo_mux_info
 hailo_status fuse_buffers(const std::vector<MemoryView> &buffers,
     const std::vector<hailo_nms_info_t> &infos_of_buffers, MemoryView dst)
 {
+    MICROPROFILE_SCOPEI("Transformations", "Fuse NMS", 0);
     CHECK_ARG_NOT_NULL(dst.data());
     CHECK(buffers.size() == infos_of_buffers.size(), HAILO_INVALID_ARGUMENT,
         "Vectors of buffers and NMS infos does not match!");
index aa8712469f9dc5487ea4719510809a4d9decc36a..5fdf5e07a1b18c2216c816f9cb12187d478dd82d 100644 (file)
@@ -22,6 +22,9 @@ Expected<std::unique_ptr<VDevice>> VDevice::create(const hailo_vdevice_params_t
 {
     CHECK_AS_EXPECTED(0 != params.device_count, HAILO_INVALID_ARGUMENT,
         "VDevice creation failed. invalid device_count ({}).", params.device_count);
+    
+    CHECK_AS_EXPECTED((HAILO_SCHEDULING_ALGORITHM_NONE == params.scheduling_algorithm) || (1 == params.device_count), HAILO_INVALID_ARGUMENT,
+        "Network group scheduler can be active only when using one device in the vDevice!");
 
     auto vdevice = VDeviceBase::create(params);
     CHECK_EXPECTED(vdevice);
@@ -38,6 +41,13 @@ Expected<std::unique_ptr<VDevice>> VDevice::create()
 
 Expected<std::unique_ptr<VDeviceBase>> VDeviceBase::create(const hailo_vdevice_params_t &params)
 {
+    NetworkGroupSchedulerPtr scheduler_ptr;
+    if (HAILO_SCHEDULING_ALGORITHM_NONE != params.scheduling_algorithm) {
+        auto network_group_scheduler = NetworkGroupScheduler::create_shared(params.scheduling_algorithm);
+        CHECK_EXPECTED(network_group_scheduler);
+        scheduler_ptr = network_group_scheduler.release();
+    }
+
     auto scan_res = PcieDevice::scan();
     CHECK_EXPECTED(scan_res);
 
@@ -70,25 +80,36 @@ Expected<std::unique_ptr<VDeviceBase>> VDeviceBase::create(const hailo_vdevice_p
     CHECK_AS_EXPECTED(params.device_count == devices.size(), HAILO_OUT_OF_PHYSICAL_DEVICES,
         "Failed to create vdevice. there are not enough free devices. requested: {}, found: {}",
             params.device_count, devices.size());
-    auto vdevice = std::unique_ptr<VDeviceBase>(new (std::nothrow) VDeviceBase(std::move(devices)));
+
+    std::string vdevice_infos = "VDevice Infos:";
+    for (const auto &device : devices) {
+        auto info_str = PcieDevice::pcie_device_info_to_string(device->get_device_info());
+        CHECK_EXPECTED(info_str);
+
+        vdevice_infos += " " + info_str.value();
+    }
+    LOGGER__INFO("{}", vdevice_infos);
+
+    auto vdevice = std::unique_ptr<VDeviceBase>(new (std::nothrow) VDeviceBase(std::move(devices), scheduler_ptr));
     CHECK_AS_EXPECTED(nullptr != vdevice, HAILO_OUT_OF_HOST_MEMORY);
 
     return vdevice;
 }
 
+// TODO - make this function thread-safe.
 Expected<ConfiguredNetworkGroupVector> VDeviceBase::configure(Hef &hef,
     const NetworkGroupsParamsMap &configure_params)
 {
     auto start_time = std::chrono::steady_clock::now();
     if (!m_context_switch_manager) {
-
         auto local_context_switch_manager = VdmaConfigManager::create(*this);
         CHECK_EXPECTED(local_context_switch_manager);
         m_context_switch_manager = make_unique_nothrow<VdmaConfigManager>(local_context_switch_manager.release());
         CHECK_AS_EXPECTED(nullptr != m_context_switch_manager, HAILO_OUT_OF_HOST_MEMORY);
     }
 
-    auto network_groups = m_context_switch_manager->add_hef(hef, configure_params);
+    bool is_scheduler_used = (m_network_group_scheduler != nullptr);
+    auto network_groups = m_context_switch_manager->add_hef(hef, configure_params, is_scheduler_used);
     CHECK_EXPECTED(network_groups);
 
     auto elapsed_time_ms = std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - start_time).count();
index abf263254b8f8c3e7a0ca94c1c7cae036bf9d2da..d9735265ab8cf57a77762ac3c0167dbefd6a09d2 100644 (file)
@@ -20,6 +20,7 @@
 #include "hailo/vdevice.hpp"
 #include "pcie_device.hpp"
 #include "context_switch/multi_context/vdma_config_manager.hpp"
+#include "network_group_scheduler.hpp"
 
 
 namespace hailort
@@ -59,13 +60,19 @@ public:
         return devices_infos;
     }
 
+    const NetworkGroupSchedulerPtr &network_group_scheduler()
+    {
+        return m_network_group_scheduler;
+    }
+
 private:
-    VDeviceBase(std::vector<std::unique_ptr<PcieDevice>> &&devices) : m_devices(std::move(devices))
+    VDeviceBase(std::vector<std::unique_ptr<PcieDevice>> &&devices, NetworkGroupSchedulerPtr network_group_scheduler) :
+        m_devices(std::move(devices)), m_network_group_scheduler(network_group_scheduler)
         {}
 
     std::vector<std::unique_ptr<PcieDevice>> m_devices;
     std::unique_ptr<VdmaConfigManager> m_context_switch_manager;
-
+    NetworkGroupSchedulerPtr m_network_group_scheduler;
 };
 
 } /* namespace hailort */
index c3cb113e66e7fac81e90ca01f9c89aac211d8031..79eab93ceb447e51405e22ee02631f818d0d2298 100644 (file)
@@ -48,10 +48,10 @@ VDeviceInputStream::~VDeviceInputStream()
     }
 }
 
-hailo_status VDeviceInputStream::activate_stream()
+hailo_status VDeviceInputStream::activate_stream(uint16_t dynamic_batch_size)
 {
     for (auto &stream : m_streams) {
-        auto status = stream->activate_stream();
+        auto status = stream->activate_stream(dynamic_batch_size);
         if (HAILO_SUCCESS != status) {
             LOGGER__ERROR("Failed to activate input stream. (device: {})", stream->get_dev_id());
             deactivate_stream();
@@ -64,18 +64,44 @@ hailo_status VDeviceInputStream::activate_stream()
 
 Expected<size_t> VDeviceInputStream::sync_write_raw_buffer(const MemoryView &buffer)
 {
-    auto written_bytes = m_streams[m_next_transfer_stream_index]->sync_write_raw_buffer(buffer);
-    if (HAILO_SUCCESS != written_bytes.status()) {
-        LOGGER__INFO("Write to stream has failed! status = {}", written_bytes.status());
-        return make_unexpected(written_bytes.status());
+    size_t written_bytes = 0;
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto status = network_group_scheduler->wait_for_write(m_network_group_handle, name());
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            LOGGER__INFO("Write to stream was aborted.");
+            return make_unexpected(status);
+        }
+        CHECK_SUCCESS_AS_EXPECTED(status);
+
+        status = m_streams[m_next_transfer_stream_index]->write_buffer_only(buffer);
+        if (HAILO_SUCCESS != status) {
+            LOGGER__INFO("Write to stream has failed! status = {}", status);
+            return make_unexpected(status);
+        }
+
+        status = network_group_scheduler->signal_write_finish(m_network_group_handle, name());
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            return make_unexpected(status);
+        }
+        CHECK_SUCCESS_AS_EXPECTED(status);
+
+        written_bytes = buffer.size();
+    } else {
+        auto expected_written_bytes = m_streams[m_next_transfer_stream_index]->sync_write_raw_buffer(buffer);
+        if (HAILO_SUCCESS != expected_written_bytes.status()) {
+            LOGGER__INFO("Write to stream has failed! status = {}", expected_written_bytes.status());
+            return make_unexpected(expected_written_bytes.status());
+        }
+        written_bytes = expected_written_bytes.value();
     }
 
     // Update m_next_transfer_stream_index only if 'batch' frames has been transferred
-    if (0 == (++m_acc_frames % m_streams[0]->get_batch_size())) {
+    if (0 == (++m_acc_frames % m_streams[0]->get_dynamic_batch_size())) {
         m_next_transfer_stream_index = static_cast<uint32_t>((m_next_transfer_stream_index + 1) % m_streams.size());
         m_acc_frames = 0;
     }
-    return written_bytes.release();
+    return written_bytes;
 }
 
 hailo_status VDeviceInputStream::sync_write_all_raw_buffer_no_transform_impl(void *buffer, size_t offset, size_t size)
@@ -85,30 +111,35 @@ hailo_status VDeviceInputStream::sync_write_all_raw_buffer_no_transform_impl(voi
     return sync_write_raw_buffer(MemoryView(static_cast<uint8_t*>(buffer) + offset, size)).status();
 }
 
+Expected<PendingBufferState> VDeviceInputStream::send_pending_buffer()
+{
+    assert(1 == m_streams.size());
+    VdmaInputStream &vdma_input = dynamic_cast<VdmaInputStream&>(*m_streams[m_next_transfer_stream_index].get());
+    return vdma_input.send_pending_buffer();
+}
+
+// TODO - HRT-6830 - make create_input/output_stream_from_net_group as virutal function
 Expected<std::unique_ptr<VDeviceInputStream>> VDeviceInputStream::create_input_stream_from_net_group(
     std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-    const LayerInfo &edge_layer, const std::string &stream_name,
-    EventPtr &&network_group_activated_event, LatencyMeterPtr latency_meter)
+    const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle,
+    EventPtr &&network_group_activated_event, NetworkGroupSchedulerWeakPtr network_group_scheduler)
 {
     hailo_status status = HAILO_UNINITIALIZED;
 
-    const auto stream_index = edge_layer.index;
-    // Channel index is the same through all resources_managers
-    const auto channel_index = resources_managers[0]->get_boundary_channel_index(stream_index, HAILO_H2D_STREAM, stream_name);
-    CHECK_EXPECTED(channel_index, "Failed to get channel index for input stream {}", stream_index);
-
     std::vector<PcieDevice*> devices;
     std::vector<std::unique_ptr<PcieInputStream>> streams;
-    auto partial_network_name = edge_layer.partial_network_name;
 
     for (auto &resources_manager : resources_managers) {
         CHECK_AS_EXPECTED(Device::Type::PCIE == resources_manager->get_device().get_type(), HAILO_INTERNAL_FAILURE,
             "vDevice stream is supported only with PCIe devices");
         PcieDevice &pcie_device = reinterpret_cast<PcieDevice&>(resources_manager->get_device());
 
-        auto batch_size = resources_manager->get_network_batch_size_from_partial_name(partial_network_name);
-        auto local_stream = PcieInputStream::create(pcie_device, channel_index.value(),
-            edge_layer, batch_size.value(), network_group_activated_event, latency_meter);
+        auto vdma_channel_ptr = resources_manager->get_boundary_vdma_channel_by_stream_name(stream_name);
+        CHECK_EXPECTED(vdma_channel_ptr);
+
+        auto batch_size = resources_manager->get_network_batch_size(edge_layer.network_name);
+        auto local_stream = PcieInputStream::create(pcie_device,
+            vdma_channel_ptr.release(), edge_layer, batch_size.value(), network_group_activated_event);
         CHECK_EXPECTED(local_stream);
 
         devices.push_back(&pcie_device);
@@ -116,7 +147,7 @@ Expected<std::unique_ptr<VDeviceInputStream>> VDeviceInputStream::create_input_s
     }
 
     std::unique_ptr<VDeviceInputStream> local_vdevice_stream(new (std::nothrow) VDeviceInputStream(devices,
-        std::move(streams), std::move(network_group_activated_event), edge_layer, status));
+        std::move(streams), network_group_handle, std::move(network_group_activated_event), edge_layer, network_group_scheduler, status));
     CHECK_AS_EXPECTED((nullptr != local_vdevice_stream), HAILO_OUT_OF_HOST_MEMORY);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -124,12 +155,13 @@ Expected<std::unique_ptr<VDeviceInputStream>> VDeviceInputStream::create_input_s
 }
 
 Expected<std::unique_ptr<VDeviceInputStream>> VDeviceInputStream::create(std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-    const LayerInfo &edge_layer, const std::string &stream_name, EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle, EventPtr network_group_activated_event,
+    NetworkGroupSchedulerWeakPtr network_group_scheduler)
 {
     assert(0 < resources_managers.size());
 
     auto input_stream = create_input_stream_from_net_group(resources_managers, edge_layer,
-        stream_name, std::move(network_group_activated_event), latency_meter);
+        stream_name, network_group_handle, std::move(network_group_activated_event), network_group_scheduler);
     CHECK_EXPECTED(input_stream);
 
     return input_stream.release();
@@ -173,6 +205,16 @@ hailo_status VDeviceInputStream::abort()
             status = abort_status;
         }
     }
+
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto disable_status = network_group_scheduler->disable_stream(m_network_group_handle, name());
+        if (HAILO_SUCCESS != disable_status) {
+            LOGGER__ERROR("Failed to disable stream in the network group scheduler. (status: {})", disable_status);
+            status = disable_status;
+        }
+    }
+
     return status;
 }
 
@@ -181,14 +223,33 @@ hailo_status VDeviceInputStream::clear_abort()
     auto status = HAILO_SUCCESS; // Best effort
     for (auto &stream : m_streams) {
         auto clear_abort_status = stream->clear_abort();
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed to clear abort input stream. (status: {} device: {})", status, stream->get_dev_id());
+        if ((HAILO_SUCCESS != clear_abort_status) && (HAILO_STREAM_NOT_ACTIVATED != clear_abort_status)) {
+            LOGGER__ERROR("Failed to clear abort input stream. (status: {} device: {})", clear_abort_status, stream->get_dev_id());
             status = clear_abort_status;
         }
     }
+
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto enable_status = network_group_scheduler->enable_stream(m_network_group_handle, name());
+        if (HAILO_SUCCESS != enable_status) {
+            LOGGER__ERROR("Failed to enable stream in the network group scheduler. (status: {})", enable_status);
+            status = enable_status;
+        }
+    }
+
     return status;
 }
 
+bool VDeviceInputStream::is_scheduled()
+{
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (!network_group_scheduler) {
+        return false;
+    }
+    return (HAILO_SCHEDULING_ALGORITHM_NONE != network_group_scheduler->algorithm());
+}
+
 /** Output stream **/
 hailo_status VDeviceOutputStream::deactivate_stream()
 {
@@ -213,10 +274,10 @@ VDeviceOutputStream::~VDeviceOutputStream()
     }
 }
 
-hailo_status VDeviceOutputStream::activate_stream()
+hailo_status VDeviceOutputStream::activate_stream(uint16_t dynamic_batch_size)
 {
     for (auto &stream : m_streams) {
-        auto status = stream->activate_stream();
+        auto status = stream->activate_stream(dynamic_batch_size);
         if (HAILO_SUCCESS != status) {
             LOGGER__ERROR("Failed to activate output stream. (device: {})", stream->get_dev_id());
             deactivate_stream();
@@ -241,6 +302,16 @@ Expected<size_t> VDeviceOutputStream::sync_read_raw_buffer(MemoryView &/*buffer*
 
 hailo_status VDeviceOutputStream::read(MemoryView buffer)
 {
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto status = network_group_scheduler->wait_for_read(m_network_group_handle, name());
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            LOGGER__INFO("Read from stream was aborted.");
+            return status;
+        }
+        CHECK_SUCCESS(status);
+    }
+
     auto status = m_streams[m_next_transfer_stream_index]->read(buffer);
     if (HAILO_SUCCESS != status) {
         LOGGER__INFO("Read from stream has failed! status = {}", status);
@@ -248,46 +319,52 @@ hailo_status VDeviceOutputStream::read(MemoryView buffer)
     }
 
     // Update m_next_transfer_stream_index only if 'batch' frames has been transferred
-    if (0 == (++m_acc_frames % m_streams[0]->get_batch_size())) {
+    if (0 == (++m_acc_frames % m_streams[0]->get_dynamic_batch_size())) {
         m_next_transfer_stream_index = static_cast<uint32_t>((m_next_transfer_stream_index + 1) % m_streams.size());
         m_acc_frames = 0;
     }
+
+    if (network_group_scheduler) {
+        status = network_group_scheduler->signal_read_finish(m_network_group_handle, name());
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            return status;
+        }
+        CHECK_SUCCESS(status);
+    }
+
     return HAILO_SUCCESS;
 }
 
+// TODO - HRT-6830 - make create_input/output_stream_from_net_group as virutal function
 Expected<std::unique_ptr<VDeviceOutputStream>> VDeviceOutputStream::create_output_stream_from_net_group(
     std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-    const LayerInfo &edge_layer, const std::string &stream_name,
-    EventPtr &&network_group_activated_event, LatencyMeterPtr latency_meter)
+    const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle,
+    EventPtr &&network_group_activated_event, NetworkGroupSchedulerWeakPtr network_group_scheduler)
 {
     hailo_status status = HAILO_UNINITIALIZED;
 
-    const auto stream_index = edge_layer.index;
-
-    // Channel index is the same through all resources_managers
-    const auto channel_index = resources_managers[0]->get_boundary_channel_index(stream_index, HAILO_D2H_STREAM, stream_name);
-    CHECK_EXPECTED(channel_index, "Failed to get channel index for output stream {}", stream_index);
-
     std::vector<PcieDevice*> devices;
     std::vector<std::unique_ptr<PcieOutputStream>> streams;
-    auto partial_network_name = edge_layer.partial_network_name;
 
     for (auto &resources_manager : resources_managers) {
         CHECK_AS_EXPECTED(Device::Type::PCIE == resources_manager->get_device().get_type(), HAILO_INTERNAL_FAILURE,
             "vDevice stream is supported only with PCIe devices");
         PcieDevice &pcie_device = reinterpret_cast<PcieDevice&>(resources_manager->get_device());
 
-        auto batch_size = resources_manager->get_network_batch_size_from_partial_name(partial_network_name);
-        auto local_stream = PcieOutputStream::create(pcie_device, channel_index.value(),
-            edge_layer, batch_size.value(), network_group_activated_event, latency_meter);
+        auto vdma_channel_ptr = resources_manager->get_boundary_vdma_channel_by_stream_name(stream_name);
+        CHECK_EXPECTED(vdma_channel_ptr);
+
+        auto batch_size = resources_manager->get_network_batch_size(edge_layer.network_name);
+        auto local_stream = PcieOutputStream::create(pcie_device,
+            vdma_channel_ptr.release(), edge_layer, batch_size.value(), network_group_activated_event);
         CHECK_EXPECTED(local_stream);
 
         devices.push_back(&pcie_device);
         streams.emplace_back(local_stream.release());
     }
 
-    std::unique_ptr<VDeviceOutputStream> local_vdevice_stream(new (std::nothrow) VDeviceOutputStream(devices, std::move(streams),
-        edge_layer, std::move(network_group_activated_event), status));
+    std::unique_ptr<VDeviceOutputStream> local_vdevice_stream(new (std::nothrow) VDeviceOutputStream(devices, std::move(streams), network_group_handle,
+        edge_layer, std::move(network_group_activated_event), network_group_scheduler, status));
     CHECK_AS_EXPECTED((nullptr != local_vdevice_stream), HAILO_OUT_OF_HOST_MEMORY);
     CHECK_SUCCESS_AS_EXPECTED(status);
 
@@ -295,12 +372,13 @@ Expected<std::unique_ptr<VDeviceOutputStream>> VDeviceOutputStream::create_outpu
 }
 
 Expected<std::unique_ptr<VDeviceOutputStream>> VDeviceOutputStream::create(std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-    const LayerInfo &edge_layer, const std::string &stream_name, EventPtr network_group_activated_event, LatencyMeterPtr latency_meter)
+    const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle, EventPtr network_group_activated_event,
+    NetworkGroupSchedulerWeakPtr network_group_scheduler)
 {
     assert(0 < resources_managers.size());
 
     auto output_stream = create_output_stream_from_net_group(resources_managers, edge_layer,
-        stream_name, std::move(network_group_activated_event), latency_meter);
+        stream_name, network_group_handle, std::move(network_group_activated_event), network_group_scheduler);
     CHECK_EXPECTED(output_stream);
 
     return output_stream.release();
@@ -331,6 +409,16 @@ hailo_status VDeviceOutputStream::abort()
             status = abort_status;
         }
     }
+
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto disable_status = network_group_scheduler->disable_stream(m_network_group_handle, name());
+        if (HAILO_SUCCESS != disable_status) {
+            LOGGER__ERROR("Failed to disable stream in the network group scheduler. (status: {})", disable_status);
+            status = disable_status;
+        }
+    }
+
     return status;
 }
 
@@ -339,12 +427,31 @@ hailo_status VDeviceOutputStream::clear_abort()
     auto status = HAILO_SUCCESS; // Best effort
     for (auto &stream : m_streams) {
         auto clear_abort_status = stream->clear_abort();
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed to clear abort output stream. (status: {} device: {})", status, stream->get_dev_id());
+        if ((HAILO_SUCCESS != clear_abort_status) && (HAILO_STREAM_NOT_ACTIVATED != clear_abort_status)) {
+            LOGGER__ERROR("Failed to clear abort output stream. (status: {} device: {})", clear_abort_status, stream->get_dev_id());
             status = clear_abort_status;
         }
     }
+
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (network_group_scheduler) {
+        auto enable_status = network_group_scheduler->enable_stream(m_network_group_handle, name());
+        if (HAILO_SUCCESS != enable_status) {
+            LOGGER__ERROR("Failed to enable stream in the network group scheduler. (status: {})", enable_status);
+            status = enable_status;
+        }
+    }
+
     return status;
 }
 
+bool VDeviceOutputStream::is_scheduled()
+{
+    auto network_group_scheduler = m_network_group_scheduler.lock();
+    if (!network_group_scheduler) {
+        return false;
+    }
+    return (HAILO_SCHEDULING_ALGORITHM_NONE != network_group_scheduler->algorithm());
+}
+
 } /* namespace hailort */
index 4b8d8170da62d1700f82a1bedde42a43ac31fdcd..44475ffe17ff615df716c2755bf0a336285c1c04 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "stream_internal.hpp"
 #include "hailo/hailort.h"
+#include "vdevice_internal.hpp"
 #include "pcie_device.hpp"
 #include "pcie_stream.hpp"
 #include "hailo/expected.hpp"
@@ -25,6 +26,8 @@ class VDeviceInputStream : public InputStreamBase {
 public:
     VDeviceInputStream(VDeviceInputStream &&other) :
         InputStreamBase(std::move(other)),
+        m_network_group_handle(std::move(other.m_network_group_handle)),
+        m_network_group_scheduler(std::move(other.m_network_group_scheduler)),
         m_devices(std::move(other.m_devices)),
         m_streams(std::move(other.m_streams)),
         m_is_stream_activated(std::exchange(other.m_is_stream_activated, false)),
@@ -35,15 +38,18 @@ public:
     virtual ~VDeviceInputStream();
 
     static Expected<std::unique_ptr<VDeviceInputStream>> create(std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-        const LayerInfo &edge_layer, const std::string &stream_name, EventPtr network_group_activated_event,
-        LatencyMeterPtr latency_meter = nullptr);
+        const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle, EventPtr network_group_activated_event,
+        NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_PCIE; }
     virtual std::chrono::milliseconds get_timeout() const override;
     virtual hailo_status abort() override;
     virtual hailo_status clear_abort() override;
+    virtual bool is_scheduled() override;
+
+    Expected<PendingBufferState> send_pending_buffer();
 
 protected:
     virtual Expected<size_t> sync_write_raw_buffer(const MemoryView &buffer) override;
@@ -53,10 +59,14 @@ private:
     explicit VDeviceInputStream(
         std::vector<PcieDevice*> devices,
         std::vector<std::unique_ptr<PcieInputStream>> &&streams,
+        const network_group_handle_t &network_group_handle,
         EventPtr &&network_group_activated_event,
         const LayerInfo &layer_info,
+        NetworkGroupSchedulerWeakPtr network_group_scheduler,
         hailo_status &status) :
             InputStreamBase(layer_info, HAILO_STREAM_INTERFACE_PCIE, std::move(network_group_activated_event), status),
+            m_network_group_handle(network_group_handle),
+            m_network_group_scheduler(network_group_scheduler),
             m_devices(devices),
             m_streams(std::move(streams)),
             m_is_stream_activated(false),
@@ -69,9 +79,11 @@ private:
 
     static Expected<std::unique_ptr<VDeviceInputStream>> create_input_stream_from_net_group(
         std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-        const LayerInfo &edge_layer, const std::string &stream_name,
-        EventPtr &&network_group_activated_event, LatencyMeterPtr latency_meter);
+        const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle,
+        EventPtr &&network_group_activated_event, NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
+    network_group_handle_t m_network_group_handle;
+    NetworkGroupSchedulerWeakPtr m_network_group_scheduler;
     std::vector<PcieDevice*> m_devices;
     std::vector<std::unique_ptr<PcieInputStream>> m_streams;
     bool m_is_stream_activated;
@@ -83,6 +95,8 @@ class VDeviceOutputStream : public OutputStreamBase {
 public:
     VDeviceOutputStream(VDeviceOutputStream &&other) :
         OutputStreamBase(std::move(other)),
+        m_network_group_handle(std::move(other.m_network_group_handle)),
+        m_network_group_scheduler(std::move(other.m_network_group_scheduler)),
         m_devices(std::move(other.m_devices)),
         m_streams(std::move(other.m_streams)),
         m_is_stream_activated(std::exchange(other.m_is_stream_activated, false)),
@@ -93,15 +107,16 @@ public:
     virtual ~VDeviceOutputStream();
 
     static Expected<std::unique_ptr<VDeviceOutputStream>> create(std::vector<std::shared_ptr<ResourcesManager>> &resources_managers,
-        const LayerInfo &edge_layer, const std::string &stream_name,
-        EventPtr network_group_activated_event, LatencyMeterPtr latency_meter = nullptr);
+        const LayerInfo &edge_layer, const std::string &stream_name, const network_group_handle_t &network_group_handle,
+        EventPtr network_group_activated_event, NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual hailo_stream_interface_t get_interface() const override { return HAILO_STREAM_INTERFACE_PCIE; }
     virtual std::chrono::milliseconds get_timeout() const override;
     virtual hailo_status abort() override;
     virtual hailo_status clear_abort() override;
+    virtual bool is_scheduled() override;
 
 protected:
     virtual Expected<size_t> sync_read_raw_buffer(MemoryView &buffer) override;
@@ -110,10 +125,14 @@ private:
     explicit VDeviceOutputStream(
         std::vector<PcieDevice*> devices,
         std::vector<std::unique_ptr<PcieOutputStream>> &&streams,
+        const network_group_handle_t &network_group_handle,
         const LayerInfo &layer_info,
         EventPtr &&network_group_activated_event,
+        NetworkGroupSchedulerWeakPtr network_group_scheduler,
         hailo_status &status) :
             OutputStreamBase(layer_info, std::move(network_group_activated_event), status),
+            m_network_group_handle(network_group_handle),
+            m_network_group_scheduler(network_group_scheduler),
             m_devices(devices),
             m_streams(std::move(streams)),
             m_is_stream_activated(false),
@@ -127,8 +146,11 @@ private:
     
     static Expected<std::unique_ptr<VDeviceOutputStream>> create_output_stream_from_net_group(
         std::vector<std::shared_ptr<ResourcesManager>> &resources_managers, const LayerInfo &edge_layer,
-        const std::string &stream_name, EventPtr &&network_group_activated_event, LatencyMeterPtr latency_meter);
+        const std::string &stream_name, const network_group_handle_t &network_group_handle, EventPtr &&network_group_activated_event,
+        NetworkGroupSchedulerWeakPtr network_group_scheduler);
 
+    network_group_handle_t m_network_group_handle;
+    NetworkGroupSchedulerWeakPtr m_network_group_scheduler;
     std::vector<PcieDevice*> m_devices;
     std::vector<std::unique_ptr<PcieOutputStream>> m_streams;
     bool m_is_stream_activated;
diff --git a/hailort/libhailort/src/vdma/continuous_buffer.cpp b/hailort/libhailort/src/vdma/continuous_buffer.cpp
new file mode 100644 (file)
index 0000000..562cdcc
--- /dev/null
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file continuous_buffer.hpp
+ * @brief Continuous physical vdma buffer. 
+ **/
+
+#include "continuous_buffer.hpp"
+
+namespace hailort {
+namespace vdma {
+
+// Minimum size of ccb buffers in descriptors, taken from the CCB spec.
+#define MIN_CCB_DESCRIPTORS_COUNT (16)
+
+static uint32_t align(uint32_t size, uint32_t align)
+{
+    assert(is_powerof2(align));
+    const uint32_t mask = align - 1;
+    return (size + mask) & ~mask;
+}
+
+Expected<ContinuousBuffer> ContinuousBuffer::create(size_t size, HailoRTDriver &driver)
+{
+    auto result = driver.vdma_continuous_buffer_alloc(size);
+    CHECK_EXPECTED(result, "Failed allocating continuous buffer, size {}", size);
+
+    uintptr_t handle = 0;
+    uint64_t dma_address = 0;
+    std::tie(handle, dma_address) = result.release();
+
+    auto mmap = MmapBuffer<void>::create_file_map(size, driver.fd(), handle);
+    if (!mmap) {
+        LOGGER__ERROR("Failed mmap continuous buffer");
+        driver.vdma_continuous_buffer_free(handle);
+        return make_unexpected(mmap.status());
+    }
+
+    return ContinuousBuffer(size, driver, handle, dma_address, mmap.release());
+}
+
+uint32_t ContinuousBuffer::get_buffer_size(uint32_t buffer_size)
+{
+    const uint16_t page_size = DEFAULT_DESC_PAGE_SIZE;
+    const auto aligned_buffer_size = align(buffer_size, page_size);
+
+    const uint32_t min_buffer_size = page_size * MIN_CCB_DESCRIPTORS_COUNT;
+    return std::max(aligned_buffer_size, min_buffer_size);
+}
+
+uint32_t ContinuousBuffer::get_buffer_size_desc_power2(uint32_t buffer_size)
+{
+    const uint16_t page_size = DEFAULT_DESC_PAGE_SIZE;
+    const auto descriptors_in_buffer = DESCRIPTORS_IN_BUFFER(buffer_size, page_size);
+    const auto actual_descriptors_count = get_nearest_powerof_2(descriptors_in_buffer, MIN_CCB_DESCRIPTORS_COUNT);
+    return actual_descriptors_count * page_size;
+}
+
+ContinuousBuffer::~ContinuousBuffer()
+{
+    if (0 != m_handle) {
+        auto status = m_mmap.unmap();
+        if (HAILO_SUCCESS != status) {
+            LOGGER__ERROR("Failed unmap mmap buffer {}", status);
+        }
+
+        status = m_driver.vdma_continuous_buffer_free(m_handle);
+        if (HAILO_SUCCESS != status) {
+            LOGGER__ERROR("Failed free continuous buffer, {}", status);
+        }
+
+        m_handle = 0;
+    }
+}
+
+size_t ContinuousBuffer::size() const
+{
+    return m_size;
+}
+
+uint64_t ContinuousBuffer::dma_address() const
+{
+    return m_dma_address;
+}
+
+uint16_t ContinuousBuffer::desc_page_size() const
+{
+    // Currently we support only the default desc page size, TODO: HRT-5381 support more desc page size?
+    return DEFAULT_DESC_PAGE_SIZE;
+}
+
+uint32_t ContinuousBuffer::descs_count() const
+{
+    return descriptors_in_buffer(m_size);
+}
+
+hailo_status ContinuousBuffer::read(void *buf_dst, size_t count, size_t offset)
+{
+    CHECK((count + offset) <= m_size, HAILO_INSUFFICIENT_BUFFER,
+        "Requested size {} from offset {} is more than the buffer size {}", count, offset, m_size);
+    // We use dma coherent mmap, so no need to sync the buffer after the memcpy.
+    const auto src_address = reinterpret_cast<uint8_t*>(m_mmap.get()) + offset;
+    memcpy(buf_dst, src_address, count);
+    return HAILO_SUCCESS;
+}
+
+hailo_status ContinuousBuffer::write(const void *buf_src, size_t count, size_t offset)
+{
+    CHECK((count + offset) <= m_size, HAILO_INSUFFICIENT_BUFFER,
+        "Requested size {} from offset {} is more than the buffer size {}", count, offset, m_size);
+    // We use dma coherent mmap, so no need to sync the buffer after the memcpy.
+    const auto dst_address = reinterpret_cast<uint8_t*>(m_mmap.get()) + offset;
+    memcpy(dst_address, buf_src, count);
+    return HAILO_SUCCESS;
+}
+
+Expected<uint32_t> ContinuousBuffer::program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
+    VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular)
+{
+    (void)first_desc_interrupts_domain;
+    (void)last_desc_interrupts_domain;
+    (void)desc_offset;
+    (void)is_circular;
+
+    // The descriptors in continuous mode are programmed by the hw, nothing to do here.
+    return descriptors_in_buffer(transfer_size);
+}
+
+hailo_status ContinuousBuffer::reprogram_device_interrupts_for_end_of_batch(size_t transfer_size, uint16_t batch_size,
+        VdmaInterruptsDomain new_interrupts_domain)
+{
+    (void)transfer_size;
+    (void)batch_size;
+    (void)new_interrupts_domain;
+
+    // The descriptors in continuous mode are programmed by the hw, nothing to do here.
+    return HAILO_SUCCESS;
+}
+
+ContinuousBuffer::ContinuousBuffer(size_t size, HailoRTDriver &driver, uintptr_t handle, uint64_t dma_address,
+    MmapBuffer<void> &&mmap) :
+    m_size(size),
+    m_driver(driver),
+    m_handle(handle),
+    m_dma_address(dma_address),
+    m_mmap(std::move(mmap))
+{}
+
+}; /* namespace vdma */
+}; /* namespace hailort */
diff --git a/hailort/libhailort/src/vdma/continuous_buffer.hpp b/hailort/libhailort/src/vdma/continuous_buffer.hpp
new file mode 100644 (file)
index 0000000..fcaec99
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file continuous_buffer.hpp
+ * @brief Continuous physical vdma buffer. 
+ **/
+
+#ifndef _HAILO_VDMA_CONTINUOUS_BUFFER_HPP_
+#define _HAILO_VDMA_CONTINUOUS_BUFFER_HPP_
+
+#include "os/hailort_driver.hpp"
+#include "os/mmap_buffer.hpp"
+#include "vdma/vdma_buffer.hpp"
+
+namespace hailort {
+namespace vdma {
+
+class ContinuousBuffer final : public VdmaBuffer {
+public:
+    static Expected<ContinuousBuffer> create(size_t size, HailoRTDriver &driver);
+
+    static uint32_t get_buffer_size(uint32_t buffer_size);
+    // Get buffer size with the requirment that the amount of descriptors is a power of 2.
+    static uint32_t get_buffer_size_desc_power2(uint32_t buffer_size);
+
+    ContinuousBuffer(const ContinuousBuffer &) = delete;
+    ContinuousBuffer& operator=(const ContinuousBuffer &) = delete;
+    ContinuousBuffer& operator=(ContinuousBuffer &&) = delete;
+
+    virtual ~ContinuousBuffer();
+
+    ContinuousBuffer(ContinuousBuffer &&other) noexcept :
+        VdmaBuffer(std::move(other)),
+        m_size(other.m_size),
+        m_driver(other.m_driver),
+        m_handle(std::exchange(other.m_handle, 0)),
+        m_dma_address(std::exchange(other.m_dma_address, 0)),
+        m_mmap(std::move(other.m_mmap))
+    {}
+
+    virtual Type type() const override
+    {
+        return Type::CONTINUOUS;
+    }
+
+    virtual size_t size() const override;
+    virtual uint64_t dma_address() const override;
+    virtual uint16_t desc_page_size() const override;
+    virtual uint32_t descs_count() const override;
+
+    // Not used in this flow
+    virtual ExpectedRef<VdmaDescriptorList> get_desc_list() override
+    {
+        LOGGER__ERROR("Can't get descriptor list on continuous buffer");
+        return make_unexpected(HAILO_INVALID_OPERATION);
+    }
+
+    virtual hailo_status read(void *buf_dst, size_t count, size_t offset) override;
+    virtual hailo_status write(const void *buf_src, size_t count, size_t offset) override;
+
+    virtual Expected<uint32_t> program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
+        VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular) override;
+    virtual hailo_status reprogram_device_interrupts_for_end_of_batch(size_t transfer_size, uint16_t batch_size,
+        VdmaInterruptsDomain new_interrupts_domain) override;
+
+private:
+    ContinuousBuffer(size_t size, HailoRTDriver &driver, uintptr_t handle, uint64_t dma_address,
+        MmapBuffer<void> &&mmap);
+
+    const size_t m_size;
+    HailoRTDriver &m_driver;
+    uintptr_t m_handle;
+    uint64_t m_dma_address;
+    MmapBuffer<void> m_mmap;
+};
+
+}; /* namespace vdma */
+}; /* namespace hailort */
+
+#endif /* _HAILO_VDMA_CONTINUOUS_BUFFER_HPP_ */
diff --git a/hailort/libhailort/src/vdma/mapped_buffer.cpp b/hailort/libhailort/src/vdma/mapped_buffer.cpp
new file mode 100644 (file)
index 0000000..9195178
--- /dev/null
@@ -0,0 +1,164 @@
+#include "mapped_buffer.hpp"
+#include "microprofile.h"
+
+namespace hailort {
+namespace vdma {
+
+Expected<MappedBuffer> MappedBuffer::create(size_t required_size, HailoRTDriver::DmaDirection data_direction,
+    HailoRTDriver &driver)
+{
+    hailo_status status = HAILO_UNINITIALIZED;
+    MappedBuffer object(required_size, data_direction, driver, status);
+    if (HAILO_SUCCESS != status) {
+        return make_unexpected(status);
+    }
+
+    return object;
+}
+
+MappedBuffer::MappedBuffer(
+    size_t required_size, HailoRTDriver::DmaDirection data_direction, HailoRTDriver &driver, hailo_status &status)
+    : m_user_address(), m_size(required_size), m_driver(driver),
+      m_driver_buff_handle(HailoRTDriver::INVALID_DRIVER_BUFFER_HANDLE_VALUE)
+{
+    auto buffer = allocate_vdma_buffer(driver, required_size, m_driver_buff_handle);
+    if (! buffer) {
+        status = buffer.status();
+        return;
+    }
+
+    auto expected_handle = m_driver.vdma_buffer_map(buffer->get(), required_size, data_direction, m_driver_buff_handle);
+    if (!expected_handle) {
+        status = expected_handle.status();
+        return;
+    }
+    
+    m_handle = expected_handle.release();
+    m_user_address = buffer.release();
+    status = HAILO_SUCCESS;
+}
+
+MappedBuffer::~MappedBuffer()
+{
+    if (m_user_address) {
+        m_driver.vdma_buffer_unmap(m_handle);
+
+        if (HailoRTDriver::INVALID_DRIVER_BUFFER_HANDLE_VALUE != m_driver_buff_handle) {
+            m_driver.vdma_low_memory_buffer_free(m_driver_buff_handle);
+        }
+    }
+}
+
+hailo_status MappedBuffer::write(const void *buf_src, size_t count, size_t offset)
+{
+    if ((count + offset) > m_size) {
+        LOGGER__ERROR("Requested size {} from offset {} is more than the MappedBuffer size {}", count, offset, m_size);
+        return HAILO_INSUFFICIENT_BUFFER;
+    }
+
+    if (count > 0) {
+        auto dst_vdma_address = (uint8_t*)m_user_address.get() + offset;
+        memcpy(dst_vdma_address, buf_src, count);
+
+        auto status = m_driver.vdma_buffer_sync(m_handle, HailoRTDriver::DmaDirection::H2D, dst_vdma_address, count);
+        if (HAILO_SUCCESS != status) {
+            LOGGER__ERROR("Failed synching vdma buffer on write");
+            return status;
+        }
+    }
+    
+    return HAILO_SUCCESS;
+}
+
+hailo_status MappedBuffer::read(void *buf_dst, size_t count, size_t offset)
+{
+    if ((count + offset) > m_size) {
+        LOGGER__ERROR("Requested size {} from offset {} is more than the MappedBuffer size {}", count, offset, m_size);
+        return HAILO_INSUFFICIENT_BUFFER;
+    }
+
+    if (count > 0) {
+        auto dst_vdma_address = (uint8_t*)m_user_address.get() + offset;
+        auto status = m_driver.vdma_buffer_sync(m_handle, HailoRTDriver::DmaDirection::D2H, dst_vdma_address, count);
+        if (HAILO_SUCCESS != status) {
+            LOGGER__ERROR("Failed synching vdma buffer on read");
+            return status;
+        }
+
+        memcpy(buf_dst, dst_vdma_address, count);
+    }
+    
+    return HAILO_SUCCESS;
+}
+
+hailo_status MappedBuffer::write_cyclic(const void *buf_src, size_t count, size_t offset)
+{
+    MICROPROFILE_SCOPEI("vDMA", "Write buffer", 0);
+    if (count > m_size) {
+        LOGGER__ERROR("Requested size({}) is more than the MappedBuffer size {}", count, m_size);
+        return HAILO_INSUFFICIENT_BUFFER;
+    }
+
+    auto size_to_end = m_size - offset;
+    auto copy_size = std::min(size_to_end, count);
+    auto status = write(buf_src, copy_size, offset);
+    if (HAILO_SUCCESS != status) {
+        return status;
+    }
+
+    auto remaining_size = count - copy_size;
+    if (remaining_size > 0) {
+        status = write((uint8_t*)buf_src + copy_size, remaining_size, 0);
+        if (HAILO_SUCCESS != status) {
+            return status;
+        }
+    }
+
+    return HAILO_SUCCESS;
+}
+
+hailo_status MappedBuffer::read_cyclic(void *buf_dst, size_t count, size_t offset)
+{
+    MICROPROFILE_SCOPEI("vDMA", "Read buffer", 0);
+    if (count > m_size) {
+        LOGGER__ERROR("Requested size({}) is more than the MappedBuffer size {}", count, m_size);
+        return HAILO_INSUFFICIENT_BUFFER;
+    }
+
+    auto size_to_end = m_size - offset;
+    auto copy_size = std::min(size_to_end, count);
+    auto status = read(buf_dst, copy_size, offset);
+    if (HAILO_SUCCESS != status) {
+        return status;
+    }
+
+    auto remaining_size = count - copy_size;
+    if (remaining_size > 0) {
+        status = read((uint8_t*)buf_dst + copy_size, remaining_size, 0);
+        if (HAILO_SUCCESS != status) {
+            return status;
+        }
+    }
+
+    return HAILO_SUCCESS;
+}
+
+Expected<MmapBuffer<void>> MappedBuffer::allocate_vdma_buffer(HailoRTDriver &driver, size_t required_size,
+    uintptr_t &driver_buff_handle)
+{
+    // Check if driver should be allocated from driver or from user
+    if (driver.allocate_driver_buffer()) {
+        auto driver_buffer_handle = driver.vdma_low_memory_buffer_alloc(required_size);
+        CHECK_EXPECTED(driver_buffer_handle);
+
+        driver_buff_handle = driver_buffer_handle.release();
+
+        return MmapBuffer<void>::create_file_map(required_size, driver.fd(), driver_buff_handle);
+    }
+    else {
+        return MmapBuffer<void>::create_shared_memory(required_size);
+    }
+}
+
+} /* namespace vdma */
+} /* namespace hailort */
diff --git a/hailort/libhailort/src/vdma/mapped_buffer.hpp b/hailort/libhailort/src/vdma/mapped_buffer.hpp
new file mode 100644 (file)
index 0000000..2fc2d68
--- /dev/null
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file mapped_buffer.hpp
+ * @brief The mapped buffer that is continuous in virtual memory, but not on physical memory.
+ *        We map the buffer to the IOMMU.
+ * 
+ * The buffer can be used only with the help of a descriptors list that contains pointers to a physical
+ * continuous "dma pages".
+ * 
+ * There are 2 options to allocated the buffer:
+ *      1. User mode allocation - the user mode calls `malloc` or `mmap` to allocate the buffer, then
+ *         using HailoRTDriver we map the driver to the IOMMU (and pin the pages to avoid pagigs).
+ *         This is the default option
+ *      2. Kernel mode allocation - on some systems, the user mode doesn't allocate the memory in a "dma-able" address,
+ *         so we need to allocate the pages in driver.
+ **/
+
+#ifndef _HAILO_VDMA_MAPPED_BUFFER_HPP_
+#define _HAILO_VDMA_MAPPED_BUFFER_HPP_
+
+#include "os/mmap_buffer.hpp"
+#include "os/hailort_driver.hpp"
+#include "hailo/expected.hpp"
+
+namespace hailort {
+namespace vdma {
+
+class MappedBuffer final
+{
+public:
+    static Expected<MappedBuffer> create(size_t required_size, HailoRTDriver::DmaDirection data_direction,
+        HailoRTDriver &driver);
+
+    MappedBuffer(size_t required_size, HailoRTDriver::DmaDirection data_direction,
+        HailoRTDriver &driver, hailo_status &status);
+    ~MappedBuffer();
+
+    MappedBuffer(const MappedBuffer &other) = delete;
+    MappedBuffer &operator=(const MappedBuffer &other) = delete;
+    MappedBuffer(MappedBuffer &&other) noexcept = default;
+    MappedBuffer &operator=(MappedBuffer &&other) = delete;
+
+    void *user_address() { return m_user_address.get(); }
+    size_t handle() { return m_handle; }
+    size_t size() const { return m_size; }
+
+    /**
+     * Copy data from buf_src parameter to this MappedBuffer.
+     *
+     * @note (offset + count) MUST be smaller than this MappedBuffer size
+     *
+     * @param[in] buf_src The buffer to copy the data from
+     * @param[in] count Number of bytes to copy from buf_src
+     * @param[in] offset The offset relative to this MappedBuffer to copy the data to
+     */
+    hailo_status write(const void *buf_src, size_t count, size_t offset);
+
+    /**
+     * Copy data from this MappedBuffer to buf_dst.
+     *
+     * @note (offset + count) MUST be smaller than this MappedBuffer size
+     *
+     * @param[out] buf_dst The buffer to copy the data to
+     * @param[in] count Number of bytes to copy to buf_dst
+     * @param[in] offset The offset relative to this MappedBuffer to copy the data from
+     */
+    hailo_status read(void *buf_dst, size_t count, size_t offset);
+
+    /**
+     * Copy data from buf_src parameter to this MappedBuffer.
+     * 
+     * Similar to 'write' but if (offset + count) is larger than the MappedBuffer size, the copy continues
+     * from the start of the MappedBuffer.
+     *
+     * @note count MUST be smaller than this MappedBuffer size
+     *
+     * @param[in] buf_src The buffer to copy the data from
+     * @param[in] count Number of bytes to copy from buf_src
+     * @param[in] offset The offset relative to this MappedBuffer to copy the data to
+     */
+    hailo_status write_cyclic(const void *buf_src, size_t count, size_t offset);
+
+    /**
+     * Copy data from this MappedBuffer to buf_dst.
+     *
+     * Similar to 'read' but if (offset + count) is larger than the MappedBuffer size, the copy continues
+     * from the start of the MappedBuffer.
+     *
+     * @note count MUST be smaller than this MappedBuffer size
+     *
+     * @param[out] buf_dst The buffer to copy the data to
+     * @param[in] count Number of bytes to copy to buf_dst
+     * @param[in] offset The offset relative to this MappedBuffer to copy the data from
+     */
+    hailo_status read_cyclic(void *buf_dst, size_t count, size_t offset);
+
+private:
+
+    static Expected<MmapBuffer<void>> allocate_vdma_buffer(HailoRTDriver &driver, size_t required_size,
+        uintptr_t &driver_buff_handle);
+
+    MmapBuffer<void> m_user_address;
+    HailoRTDriver::VdmaBufferHandle m_handle;
+    size_t m_size;
+    HailoRTDriver &m_driver;
+    uintptr_t m_driver_buff_handle;
+};
+
+} /* namespace vdma */
+} /* namespace hailort */
+
+#endif /* _HAILO_VDMA_MAPPED_BUFFER_HPP_ */
\ No newline at end of file
diff --git a/hailort/libhailort/src/vdma/sg_buffer.cpp b/hailort/libhailort/src/vdma/sg_buffer.cpp
new file mode 100644 (file)
index 0000000..01c3583
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file vdma_sg_buffer.cpp
+ * @brief Scatter-gather vdma buffer.
+ **/
+
+#include "sg_buffer.hpp"
+
+namespace hailort {
+namespace vdma {
+
+Expected<SgBuffer> SgBuffer::create(HailoRTDriver &driver, uint32_t desc_count, uint16_t desc_page_size,
+    HailoRTDriver::DmaDirection data_direction, uint8_t channel_index)
+{
+    auto desc_list = VdmaDescriptorList::create(desc_count, desc_page_size, driver);
+    CHECK_EXPECTED(desc_list);
+
+    assert((desc_count * desc_page_size) <= std::numeric_limits<uint32_t>::max());
+    auto mapped_buffer = MappedBuffer::create(desc_count * desc_page_size, data_direction, driver);
+    CHECK_EXPECTED(mapped_buffer);
+
+    auto status = desc_list->configure_to_use_buffer(mapped_buffer.value(), channel_index);
+    CHECK_SUCCESS_AS_EXPECTED(status);
+
+    return SgBuffer(desc_list.release(), mapped_buffer.release());
+}
+
+size_t SgBuffer::size() const
+{
+    return m_mapped_buffer.size();
+}
+
+uint64_t SgBuffer::dma_address() const
+{
+    return m_desc_list.dma_address();
+}
+
+uint16_t SgBuffer::desc_page_size() const
+{
+    return m_desc_list.desc_page_size();
+}
+
+uint32_t SgBuffer::descs_count() const
+{
+    return (uint32_t)m_desc_list.count();
+}
+
+uint8_t SgBuffer::depth() const
+{
+    return m_desc_list.depth();
+}
+
+ExpectedRef<VdmaDescriptorList> SgBuffer::get_desc_list()
+{
+    return std::ref(m_desc_list);
+}
+
+hailo_status SgBuffer::read(void *buf_dst, size_t count, size_t offset)
+{
+    return m_mapped_buffer.read(buf_dst, count, offset);
+}
+
+hailo_status SgBuffer::write(const void *buf_src, size_t count, size_t offset)
+{
+    return m_mapped_buffer.write(buf_src, count, offset);
+}
+
+Expected<uint32_t> SgBuffer::program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
+    VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular)
+{
+    return m_desc_list.program_descriptors(transfer_size, first_desc_interrupts_domain, last_desc_interrupts_domain,
+        desc_offset, is_circular);
+}
+
+hailo_status SgBuffer::reprogram_device_interrupts_for_end_of_batch(size_t transfer_size, uint16_t batch_size,
+        VdmaInterruptsDomain new_interrupts_domain)
+{
+    const auto desc_per_transfer = m_desc_list.descriptors_in_buffer(transfer_size);
+    const auto num_desc_in_batch = desc_per_transfer * batch_size;
+    const auto last_desc_index_in_batch = num_desc_in_batch - 1;
+    return m_desc_list.reprogram_descriptor_interrupts_domain(last_desc_index_in_batch, new_interrupts_domain);
+}
+
+}
+}
\ No newline at end of file
diff --git a/hailort/libhailort/src/vdma/sg_buffer.hpp b/hailort/libhailort/src/vdma/sg_buffer.hpp
new file mode 100644 (file)
index 0000000..c1472a1
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)
+ **/
+/**
+ * @file sg_buffer.hpp
+ * @brief Scatter-gather vdma buffer, from the user-mode point of view the buffer is continuous,
+ *        but not from the physical-memory point of view.
+ *        The sg buffer contains 2 parts:
+ *              - MappedBuffer - the actual buffer stores the data.
+ *              - Descriptors list - each descritpor points to a single "dma page" in the MappedBuffer.
+ *        The hw accept the descriptors list address and parses it to get the actual data.
+ **/
+
+#ifndef _HAILO_VDMA_SG_BUFFER_HPP_
+#define _HAILO_VDMA_SG_BUFFER_HPP_
+
+#include "os/hailort_driver.hpp"
+#include "vdma/vdma_buffer.hpp"
+#include "vdma_descriptor_list.hpp"
+#include "vdma/mapped_buffer.hpp"
+
+namespace hailort {
+namespace vdma {
+
+class SgBuffer final : public VdmaBuffer {
+public:
+    static Expected<SgBuffer> create(HailoRTDriver &driver, uint32_t desc_count, uint16_t desc_page_size,
+        HailoRTDriver::DmaDirection data_direction, uint8_t channel_index = 0);
+
+    virtual ~SgBuffer() = default;
+
+    SgBuffer(const SgBuffer &) = delete;
+    SgBuffer(SgBuffer &&) = default;
+    SgBuffer& operator=(const SgBuffer &) = delete;
+    SgBuffer& operator=(SgBuffer &&) = delete;
+
+    virtual Type type() const override
+    {
+        return Type::SCATTER_GATHER;
+    }
+
+    virtual size_t size() const override;
+    virtual uint64_t dma_address() const override;
+    virtual uint16_t desc_page_size() const override;
+    virtual uint32_t descs_count() const override;
+    uint8_t depth() const;
+
+    // Should be only used for host managed ddr buffer, in the future this function may return nullptr (on CCB
+    // case where there is no descriptors list)
+    virtual ExpectedRef<VdmaDescriptorList> get_desc_list() override;
+
+    virtual hailo_status read(void *buf_dst, size_t count, size_t offset) override;
+    virtual hailo_status write(const void *buf_src, size_t count, size_t offset) override;
+
+    virtual Expected<uint32_t> program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
+        VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular) override;
+    virtual hailo_status reprogram_device_interrupts_for_end_of_batch(size_t transfer_size, uint16_t batch_size,
+        VdmaInterruptsDomain new_interrupts_domain) override;
+
+private:
+    SgBuffer(VdmaDescriptorList &&desc_list, MappedBuffer &&mapped_buffer) :
+        m_desc_list(std::move(desc_list)),
+        m_mapped_buffer(std::move(mapped_buffer))
+    {}
+
+    VdmaDescriptorList m_desc_list;
+    MappedBuffer m_mapped_buffer;
+};
+
+} /* vdma */
+} /* hailort */
+
+#endif /* _HAILO_VDMA_SG_BUFFER_HPP_ */
diff --git a/hailort/libhailort/src/vdma/vdma_buffer.hpp b/hailort/libhailort/src/vdma/vdma_buffer.hpp
new file mode 100644 (file)
index 0000000..e28187f
--- /dev/null
@@ -0,0 +1,65 @@
+/**\r
+ * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.\r
+ * Distributed under the MIT license (https://opensource.org/licenses/MIT)\r
+ **/\r
+/**\r
+ * @file vdma_buffer.hpp\r
+ * @brief Abstract layer representing a vdma buffer (buffer that can be read/written to the device over vdma.)\r
+ *        The buffer can be either non-continuous with attach descriptors list (SgBuffer) or continuous buffer.\r
+ **/\r
+\r
+#ifndef _HAILO_VDMA_VDMA_BUFFER_HPP_\r
+#define _HAILO_VDMA_VDMA_BUFFER_HPP_\r
+\r
+#include "os/hailort_driver.hpp"\r
+#include "vdma_descriptor_list.hpp"\r
+\r
+namespace hailort {\r
+namespace vdma {\r
+\r
+class VdmaBuffer {\r
+public:\r
+\r
+    enum class Type {\r
+        SCATTER_GATHER,\r
+        CONTINUOUS\r
+    };\r
+\r
+    virtual ~VdmaBuffer() = default;\r
+\r
+    VdmaBuffer() = default;\r
+    VdmaBuffer(const VdmaBuffer &) = delete;\r
+    VdmaBuffer(VdmaBuffer &&) = default;\r
+    VdmaBuffer& operator=(const VdmaBuffer &) = delete;\r
+    VdmaBuffer& operator=(VdmaBuffer &&) = delete;\r
+\r
+    virtual Type type() const = 0;\r
+    virtual size_t size() const = 0;\r
+    virtual uint64_t dma_address() const = 0;\r
+    virtual uint16_t desc_page_size() const = 0;\r
+    virtual uint32_t descs_count() const = 0;\r
+\r
+    uint32_t descriptors_in_buffer(size_t buffer_size) const\r
+    {\r
+        assert(buffer_size < std::numeric_limits<uint32_t>::max());\r
+        const auto page_size = desc_page_size();\r
+        return static_cast<uint32_t>(DESCRIPTORS_IN_BUFFER(buffer_size, page_size));\r
+    }\r
+\r
+    // If there's no descriptor list then Unexpected(HAILO_INVALID_OPERATION) will be returned\r
+    // (E.g. for CCB, where there is no descriptors list)\r
+    virtual ExpectedRef<VdmaDescriptorList> get_desc_list() = 0;\r
+\r
+    virtual hailo_status read(void *buf_dst, size_t count, size_t offset) = 0;\r
+    virtual hailo_status write(const void *buf_src, size_t count, size_t offset) = 0;\r
+\r
+    virtual Expected<uint32_t> program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,\r
+        VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular) = 0;\r
+    virtual hailo_status reprogram_device_interrupts_for_end_of_batch(size_t transfer_size, uint16_t batch_size,\r
+        VdmaInterruptsDomain new_interrupts_domain) = 0;\r
+};\r
+\r
+} /* vdma */\r
+} /* hailort */\r
+\r
+#endif /* _HAILO_VDMA_VDMA_BUFFER_HPP_ */\r
diff --git a/hailort/libhailort/src/vdma_buffer.cpp b/hailort/libhailort/src/vdma_buffer.cpp
deleted file mode 100644 (file)
index 6dd9565..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "vdma_buffer.hpp"
-
-namespace hailort
-{
-
-Expected<VdmaBuffer> VdmaBuffer::create(size_t required_size, HailoRTDriver::DmaDirection data_direction,
-    HailoRTDriver &driver)
-{
-    hailo_status status = HAILO_UNINITIALIZED;
-    VdmaBuffer object(required_size, data_direction, driver, status);
-    if (HAILO_SUCCESS != status) {
-        return make_unexpected(status);
-    }
-
-    return object;
-}
-
-VdmaBuffer::VdmaBuffer(
-    size_t required_size, HailoRTDriver::DmaDirection data_direction, HailoRTDriver &driver, hailo_status &status)
-    : m_user_address(), m_size(required_size), m_driver(driver),
-      m_driver_buff_handle(HailoRTDriver::INVALID_DRIVER_BUFFER_HANDLE_VALUE)
-{
-    auto buffer = allocate_vdma_buffer(driver, required_size, m_driver_buff_handle);
-    if (! buffer) {
-        status = buffer.status();
-        return;
-    }
-
-    auto expected_handle = m_driver.vdma_buffer_map(buffer->get(), required_size, data_direction, m_driver_buff_handle);
-    if (!expected_handle) {
-        status = expected_handle.status();
-        return;
-    }
-    
-    m_handle = expected_handle.release();
-    m_user_address = buffer.release();
-    status = HAILO_SUCCESS;
-}
-
-VdmaBuffer::~VdmaBuffer()
-{
-    if (m_user_address) {
-        m_driver.vdma_buffer_unmap(m_handle);
-
-        if (HailoRTDriver::INVALID_DRIVER_BUFFER_HANDLE_VALUE != m_driver_buff_handle) {
-            m_driver.vdma_low_memory_buffer_free(m_driver_buff_handle);
-        }
-    }
-}
-
-hailo_status VdmaBuffer::write(const void *buf_src, size_t count, size_t offset)
-{
-    if ((count + offset) > m_size) {
-        LOGGER__ERROR("Requested size {} from offset {} is more than the VdmaBuffer size {}", count, offset, m_size);
-        return HAILO_INSUFFICIENT_BUFFER;
-    }
-
-    if (count > 0) {
-        auto dst_vdma_address = (uint8_t*)m_user_address.get() + offset;
-        memcpy(dst_vdma_address, buf_src, count);
-
-        auto status = m_driver.vdma_buffer_sync(m_handle, HailoRTDriver::DmaDirection::H2D, dst_vdma_address, count);
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed synching vdma buffer on write");
-            return status;
-        }
-    }
-    
-    return HAILO_SUCCESS;
-}
-
-hailo_status VdmaBuffer::read(void *buf_dst, size_t count, size_t offset)
-{
-    if ((count + offset) > m_size) {
-        LOGGER__ERROR("Requested size {} from offset {} is more than the VdmaBuffer size {}", count, offset, m_size);
-        return HAILO_INSUFFICIENT_BUFFER;
-    }
-
-    if (count > 0) {
-        auto dst_vdma_address = (uint8_t*)m_user_address.get() + offset;
-        auto status = m_driver.vdma_buffer_sync(m_handle, HailoRTDriver::DmaDirection::D2H, dst_vdma_address, count);
-        if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Failed synching vdma buffer on read");
-            return status;
-        }
-
-        memcpy(buf_dst, dst_vdma_address, count);
-    }
-    
-    return HAILO_SUCCESS;
-}
-
-hailo_status VdmaBuffer::write_cyclic(const void *buf_src, size_t count, size_t offset)
-{
-    if (count > m_size) {
-        LOGGER__ERROR("Requested size({}) is more than the VdmaBuffer size {}", count, m_size);
-        return HAILO_INSUFFICIENT_BUFFER;
-    }
-
-    auto size_to_end = m_size - offset;
-    auto copy_size = std::min(size_to_end, count);
-    auto status = write(buf_src, copy_size, offset);
-    if (HAILO_SUCCESS != status) {
-        return status;
-    }
-
-    auto remaining_size = count - copy_size;
-    if (remaining_size > 0) {
-        status = write((uint8_t*)buf_src + copy_size, remaining_size, 0);
-        if (HAILO_SUCCESS != status) {
-            return status;
-        }
-    }
-
-    return HAILO_SUCCESS;
-}
-
-hailo_status VdmaBuffer::read_cyclic(void *buf_dst, size_t count, size_t offset)
-{
-    if (count > m_size) {
-        LOGGER__ERROR("Requested size({}) is more than the VdmaBuffer size {}", count, m_size);
-        return HAILO_INSUFFICIENT_BUFFER;
-    }
-
-    auto size_to_end = m_size - offset;
-    auto copy_size = std::min(size_to_end, count);
-    auto status = read(buf_dst, copy_size, offset);
-    if (HAILO_SUCCESS != status) {
-        return status;
-    }
-
-    auto remaining_size = count - copy_size;
-    if (remaining_size > 0) {
-        status = read((uint8_t*)buf_dst + copy_size, remaining_size, 0);
-        if (HAILO_SUCCESS != status) {
-            return status;
-        }
-    }
-
-    return HAILO_SUCCESS;
-}
-
-Expected<MmapBuffer<void>> VdmaBuffer::allocate_vdma_buffer(HailoRTDriver &driver, size_t required_size,
-    uintptr_t &driver_buff_handle)
-{
-    // Check if driver should be allocated from driver or from user
-    if (driver.allocate_driver_buffer()) {
-        auto driver_buffer_handle = driver.vdma_low_memory_buffer_alloc(required_size);
-        CHECK_EXPECTED(driver_buffer_handle);
-
-        driver_buff_handle = driver_buffer_handle.release();
-
-        return MmapBuffer<void>::create_file_map(required_size, driver.fd(), driver_buff_handle);
-    }
-    else {
-        return MmapBuffer<void>::create_shared_memory(required_size);
-    }
-}
-
-} /* namespace hailort */
diff --git a/hailort/libhailort/src/vdma_buffer.hpp b/hailort/libhailort/src/vdma_buffer.hpp
deleted file mode 100644 (file)
index b11d4e6..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
- * Distributed under the MIT license (https://opensource.org/licenses/MIT)
- **/
-/**
- * @file vdma_buffer.hpp
- * @brief Provides a buffer that can be used for VDMA
- *
- **/
-
-#ifndef _HAILO_VDMA_BUFFER_HPP_
-#define _HAILO_VDMA_BUFFER_HPP_
-
-#include "os/mmap_buffer.hpp"
-#include "os/hailort_driver.hpp"
-#include "hailo/expected.hpp"
-
-namespace hailort
-{
-
-class VdmaBuffer final
-{
-public:
-    static Expected<VdmaBuffer> create(size_t required_size, HailoRTDriver::DmaDirection data_direction,
-        HailoRTDriver &driver);
-
-    VdmaBuffer(size_t required_size, HailoRTDriver::DmaDirection data_direction,
-        HailoRTDriver &driver, hailo_status &status);
-    ~VdmaBuffer();
-
-    VdmaBuffer(const VdmaBuffer &other) = delete;
-    VdmaBuffer &operator=(const VdmaBuffer &other) = delete;
-    VdmaBuffer(VdmaBuffer &&other) noexcept = default;
-    VdmaBuffer &operator=(VdmaBuffer &&other) = delete;
-
-    void *user_address() { return m_user_address.get(); }
-    size_t handle() { return m_handle; }
-    size_t size() const { return m_size; }
-
-    /**
-     * Copy data from buf_src parameter to this VdmaBuffer.
-     *
-     * @note (offset + count) MUST be smaller than this VdmaBuffer size
-     *
-     * @param[in] buf_src The buffer to copy the data from
-     * @param[in] count Number of bytes to copy from buf_src
-     * @param[in] offset The offset relative to this VdmaBuffer to copy the data to
-     */
-    hailo_status write(const void *buf_src, size_t count, size_t offset);
-
-    /**
-     * Copy data from this VdmaBuffer to buf_dst.
-     *
-     * @note (offset + count) MUST be smaller than this VdmaBuffer size
-     *
-     * @param[out] buf_dst The buffer to copy the data to
-     * @param[in] count Number of bytes to copy to buf_dst
-     * @param[in] offset The offset relative to this VdmaBuffer to copy the data from
-     */
-    hailo_status read(void *buf_dst, size_t count, size_t offset);
-
-    /**
-     * Copy data from buf_src parameter to this VdmaBuffer.
-     * 
-     * Similar to 'write' but if (offset + count) is larger than the VdmaBuffer size, the copy continues
-     * from the start of the VdmaBuffer.
-     *
-     * @note count MUST be smaller than this VdmaBuffer size
-     *
-     * @param[in] buf_src The buffer to copy the data from
-     * @param[in] count Number of bytes to copy from buf_src
-     * @param[in] offset The offset relative to this VdmaBuffer to copy the data to
-     */
-    hailo_status write_cyclic(const void *buf_src, size_t count, size_t offset);
-
-    /**
-     * Copy data from this VdmaBuffer to buf_dst.
-     *
-     * Similar to 'read' but if (offset + count) is larger than the VdmaBuffer size, the copy continues
-     * from the start of the VdmaBuffer.
-     *
-     * @note count MUST be smaller than this VdmaBuffer size
-     *
-     * @param[out] buf_dst The buffer to copy the data to
-     * @param[in] count Number of bytes to copy to buf_dst
-     * @param[in] offset The offset relative to this VdmaBuffer to copy the data from
-     */
-    hailo_status read_cyclic(void *buf_dst, size_t count, size_t offset);
-
-private:
-
-    static Expected<MmapBuffer<void>> allocate_vdma_buffer(HailoRTDriver &driver, size_t required_size,
-        uintptr_t &driver_buff_handle);
-
-    MmapBuffer<void> m_user_address;
-    HailoRTDriver::VdmaBufferHandle m_handle;
-    size_t m_size;
-    HailoRTDriver &m_driver;
-    uintptr_t m_driver_buff_handle;
-};
-
-} /* namespace hailort */
-
-#endif /* _HAILO_VDMA_BUFFER_HPP_ */
\ No newline at end of file
index cfbe70d71a5cf4eff12ba43e15e205972ef375fe..79f4fbf8064d9a7db9f19dcda6abfa5660ccddb5 100644 (file)
@@ -3,6 +3,7 @@
 #include "hw_consts.hpp"
 #include "common/logger_macros.hpp"
 #include "common/utils.hpp"
+#include "microprofile.h"
 
 #include <list>
 #include <chrono>
@@ -73,11 +74,12 @@ Expected<VdmaChannel> VdmaChannel::create(uint8_t channel_index, Direction direc
 VdmaChannel::VdmaChannel(uint8_t channel_index, Direction direction, HailoRTDriver &driver, 
     uint32_t stream_index, LatencyMeterPtr latency_meter, uint16_t desc_page_size, uint16_t transfers_per_axi_intr, 
     hailo_status &status)
-    : channel_index(channel_index), m_direction(direction), m_driver(driver),
+    : m_channel_index(channel_index), m_direction(direction), m_driver(driver),
       m_host_registers(driver, channel_index, direction),
       m_device_registers(driver, channel_index, other_direction(direction)), m_desc_page_size(desc_page_size),
       m_stream_index(stream_index), m_latency_meter(latency_meter), m_channel_enabled(false), 
-      m_transfers_per_axi_intr(transfers_per_axi_intr)
+      m_transfers_per_axi_intr(transfers_per_axi_intr), m_pending_buffers_sizes(0), m_pending_num_avail_offset(0), m_is_waiting_for_channel_completion(false),
+      m_is_aborted(false)
 {
     // channel index invalid
     if (channel_index >= MAX_HOST_CHANNELS_COUNT) {
@@ -128,7 +130,7 @@ VdmaChannel::~VdmaChannel()
 }
 
 VdmaChannel::VdmaChannel(VdmaChannel &&other) noexcept:
-channel_index(other.channel_index),
+m_channel_index(other.m_channel_index),
  m_direction(other.m_direction),
  m_driver(other.m_driver),
  m_host_registers(std::move(other.m_host_registers)),
@@ -141,7 +143,11 @@ channel_index(other.channel_index),
  m_state(std::move(other.m_state)),
  m_channel_handle(std::move(other.m_channel_handle)),
  m_channel_enabled(std::exchange(other.m_channel_enabled, false)),
- m_transfers_per_axi_intr(std::move(other.m_transfers_per_axi_intr))
+ m_transfers_per_axi_intr(std::move(other.m_transfers_per_axi_intr)),
+ m_pending_buffers_sizes(std::move(other.m_pending_buffers_sizes)),
+ m_pending_num_avail_offset(std::move(other.m_pending_num_avail_offset)),
+ m_is_waiting_for_channel_completion(other.m_is_waiting_for_channel_completion.load()),
+ m_is_aborted(std::move(other.m_is_aborted))
 {}
 
 hailo_status VdmaChannel::stop_channel()
@@ -150,7 +156,12 @@ hailo_status VdmaChannel::stop_channel()
     if (HailoRTDriver::INVALID_VDMA_CHANNEL_HANDLE != *m_channel_handle) {
         // The driver also stops the channels
         const auto status = unregister_fw_controlled_channel();
-        CHECK_SUCCESS(status, "Failed to disable channel {}", channel_index);
+        CHECK_SUCCESS(status, "Failed to disable channel {}", m_channel_index);
+    }
+
+    if (m_state) {
+        std::lock_guard<State> state_guard(*m_state);
+        reset_internal_counters();
     }
     
     return HAILO_SUCCESS;
@@ -164,12 +175,15 @@ uint16_t VdmaChannel::get_page_size()
 
 hailo_status VdmaChannel::abort()
 {
-    return m_driver.vdma_channel_abort(channel_index, *m_channel_handle);
+    m_is_aborted = true;
+    m_can_write_buffer_cv.notify_one();
+    return m_driver.vdma_channel_abort(m_channel_index, *m_channel_handle);
 }
 
 hailo_status VdmaChannel::clear_abort()
 {
-    return m_driver.vdma_channel_clear_abort(channel_index, *m_channel_handle);
+    m_is_aborted = false;
+    return m_driver.vdma_channel_clear_abort(m_channel_index, *m_channel_handle);
 }
 
 hailo_status VdmaChannel::prepare_d2h_pending_descriptors(uint32_t descs_count, uint32_t transfer_size)
@@ -183,7 +197,7 @@ hailo_status VdmaChannel::prepare_d2h_pending_descriptors(uint32_t descs_count,
     for (uint32_t i = 0; i < transfers_count; i++) {
         /* Provide FW interrupt only in the end of the last transfer in the batch */
         auto last_desc_interrutps_domain = 
-            (static_cast<uint32_t>(m_transfers_per_axi_intr -1) == (i % m_transfers_per_axi_intr)) ? 
+            (static_cast<uint32_t>(m_transfers_per_axi_intr - 1) == (i % m_transfers_per_axi_intr)) ? 
                 VdmaInterruptsDomain::BOTH : VdmaInterruptsDomain::HOST;
         auto status = prepare_descriptors(transfer_size, first_desc_interrupts_domain, last_desc_interrutps_domain);
         CHECK_SUCCESS(status, "Failed prepare desc status={}", status);
@@ -225,6 +239,7 @@ hailo_status VdmaChannel::allocate_resources(uint32_t descs_count)
 #endif
 
     m_state = state.release();
+    m_pending_buffers_sizes = CircularArray<size_t>(descs_count);
 
     // If measuring latency, max_active_transfer is limited to 16 (see hailort_driver.hpp doc for further information)
     int pending_buffers_size = (nullptr == m_latency_meter) ? static_cast<int>(m_state->m_pending_buffers.size()) :
@@ -262,13 +277,11 @@ hailo_status VdmaChannel::start_allocated_channel(uint32_t transfer_size)
     /* descriptor buffer must be allocated */
     assert(m_descriptors_buffer);
     assert(m_state);
-
     std::lock_guard<State> state_guard(*m_state);
-
     reset_internal_counters();
 
     auto status = start_channel(*m_descriptors_buffer);
-    CHECK_SUCCESS(status, "failed to start channel {}", channel_index);
+    CHECK_SUCCESS(status, "failed to start channel {}", m_channel_index);
 
     if ((Direction::D2H == m_direction) && (transfer_size != 0)) {
         auto descs_count = CB_SIZE(m_state->m_descs);
@@ -278,6 +291,7 @@ hailo_status VdmaChannel::start_allocated_channel(uint32_t transfer_size)
         }
         return status;
     }
+
     return HAILO_SUCCESS;
 }
 
@@ -305,14 +319,8 @@ hailo_status VdmaChannel::wait(size_t buffer_size, const std::chrono::millisecon
 
 hailo_status VdmaChannel::transfer(void *buf, size_t count)
 {
-    if ((nullptr == buf) || (0 == count)) {
-        return HAILO_INVALID_ARGUMENT;
-    }
-
-    if (!m_mapped_user_buffer) {
-        LOGGER__ERROR("Transfer called without allocating buffers");
-        return HAILO_INVALID_OPERATION;
-    }
+    CHECK((nullptr != buf) && (0 < count), HAILO_INVALID_ARGUMENT);
+    CHECK(nullptr != m_mapped_user_buffer, HAILO_INVALID_OPERATION, "Transfer called without allocating buffers");
 
     hailo_status status = HAILO_UNINITIALIZED;
     assert(m_state);
@@ -321,14 +329,14 @@ hailo_status VdmaChannel::transfer(void *buf, size_t count)
     if (Direction::H2D == m_direction) {
         status = transfer_h2d(buf, count);
         if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Transfer failed for channel {}", channel_index);
+            LOGGER__ERROR("Transfer failed for channel {}", m_channel_index);
             return status;
         }
         return HAILO_SUCCESS;
     } else {
         status = transfer_d2h(buf, count);
         if (HAILO_SUCCESS != status) {
-            LOGGER__ERROR("Transfer failed for channel {} status {}", channel_index, status);
+            LOGGER__ERROR("Transfer failed for channel {} status {}", m_channel_index, status);
             return status;
         }
         return HAILO_SUCCESS;
@@ -337,62 +345,155 @@ hailo_status VdmaChannel::transfer(void *buf, size_t count)
     return HAILO_SUCCESS;
 }
 
-hailo_status VdmaChannel::flush(const std::chrono::milliseconds &timeout)
+hailo_status VdmaChannel::write_buffer_impl(const MemoryView &buffer)
+{
+    CHECK(nullptr != m_mapped_user_buffer, HAILO_INVALID_OPERATION, "Transfer called without allocating buffers");
+
+    size_t desired_desc_num = m_descriptors_buffer->descriptors_in_buffer(buffer.size());
+    uint32_t desc_avail = (get_num_available() + m_pending_num_avail_offset) & m_state->m_descs.size_mask;
+
+    assert(CB_AVAIL(m_state->m_descs, desc_avail, CB_TAIL(m_state->m_descs)) >= static_cast<uint16_t>(desired_desc_num));
+
+    /* Copy buffer into the PLDA data struct */
+    auto offset = desc_avail * m_desc_page_size;
+    auto status = m_mapped_user_buffer->write_cyclic(buffer.data(), buffer.size(), offset);
+    CHECK_SUCCESS(status);
+
+    m_pending_num_avail_offset = static_cast<uint16_t>(m_pending_num_avail_offset + desired_desc_num);
+
+    CHECK(!m_pending_buffers_sizes.full(), HAILO_INVALID_OPERATION, "Cannot add more pending buffers!");
+    m_pending_buffers_sizes.push_back(buffer.size());
+    return HAILO_SUCCESS;
+}
+
+hailo_status VdmaChannel::write_buffer(const MemoryView &buffer, std::chrono::milliseconds timeout)
 {
     assert(m_state);
+    std::unique_lock<State> state_guard(*m_state);
 
-    if (Direction::D2H == m_direction) {
-        // We are not buffering user data
-        return HAILO_SUCCESS;
-    }
+    hailo_status status = HAILO_UNINITIALIZED;
+    size_t desired_desc_num = m_descriptors_buffer->descriptors_in_buffer(buffer.size());
+    bool was_successful = m_can_write_buffer_cv.wait_for(state_guard, timeout, [this, &status, desired_desc_num] () {
+        if ((!m_channel_enabled) || (m_is_aborted)) {
+            status = HAILO_STREAM_INTERNAL_ABORT;
+            return true;
+        }
 
-    if (!m_mapped_user_buffer) {
-        LOGGER__ERROR("VdmaChannel::flush is called on a channel without allocated resources");
-        return HAILO_INVALID_OPERATION;
+        uint32_t desc_avail = (get_num_available() + m_pending_num_avail_offset) & m_state->m_descs.size_mask;
+        int num_free = CB_AVAIL(m_state->m_descs, desc_avail, CB_TAIL(m_state->m_descs));
+        return (num_free >= static_cast<uint16_t>(desired_desc_num));
+    });
+    if (HAILO_STREAM_INTERNAL_ABORT == status) {
+        LOGGER__INFO("wait_for in write_buffer was aborted!");
+        return status;
     }
+    CHECK(was_successful, HAILO_TIMEOUT, "Waiting for descriptors in write_buffer has reached a timeout!");
 
-    return wait_for_condition([this] { return CB_HEAD(m_state->m_buffers) == CB_TAIL(m_state->m_buffers); }, timeout);
+    return write_buffer_impl(buffer);
 }
 
-hailo_status VdmaChannel::transfer_h2d(void *buf, size_t count)
+hailo_status VdmaChannel::send_pending_buffer_impl()
 {
-    uint16_t descNum = 0;
-    const uint16_t pageSize = m_desc_page_size;
-    uint32_t desc_avail = 0;
-    hailo_status status = HAILO_UNINITIALIZED;
+    CHECK(!m_pending_buffers_sizes.empty(), HAILO_INVALID_OPERATION, "There are no pending buffers to send!");
+
     // For h2d, only the host need to get transfer done interrupts
     VdmaInterruptsDomain last_desc_interrupts_domain = VdmaInterruptsDomain::HOST;
-    // If we measure latecy, we need interrupt on the first descriptor
+    // If we measure latency, we need interrupt on the first descriptor
     VdmaInterruptsDomain first_desc_interrupts_domain = (m_latency_meter != nullptr) ?
         VdmaInterruptsDomain::HOST : VdmaInterruptsDomain::NONE;
 
-    assert(buf != nullptr);
-    assert(m_state);
+    auto status = prepare_descriptors(m_pending_buffers_sizes.front(), first_desc_interrupts_domain, last_desc_interrupts_domain);
+    CHECK_SUCCESS(status);
 
-    desc_avail = get_num_available();
+    m_state->m_accumulated_transfers = (m_state->m_accumulated_transfers + 1) % m_transfers_per_axi_intr;
 
-    /* calculate desired descriptors for the buffer */
-    size_t desiredDescNum = ((count + pageSize - 1) / pageSize);
-    if (desiredDescNum > UINT16_MAX) {
-        return HAILO_OUT_OF_DESCRIPTORS;
+    size_t desired_desc_num = m_descriptors_buffer->descriptors_in_buffer(m_pending_buffers_sizes.front());
+    m_pending_num_avail_offset = static_cast<uint16_t>(m_pending_num_avail_offset - desired_desc_num);
+
+    m_pending_buffers_sizes.pop_front();
+
+    return HAILO_SUCCESS;
+}
+
+Expected<PendingBufferState> VdmaChannel::send_pending_buffer()
+{
+    size_t next_buffer_desc_num = 0;
+    {
+        assert(m_state);
+        std::lock_guard<State> state_guard(*m_state);
+
+        // Save before calling send_pending_buffer_impl because we pop from m_pending_buffers_sizes there
+        next_buffer_desc_num = m_descriptors_buffer->descriptors_in_buffer(m_pending_buffers_sizes.front());
+
+        auto status = send_pending_buffer_impl();
+        CHECK_SUCCESS_AS_EXPECTED(status);
     }
-    descNum = (uint16_t)(desiredDescNum);
-    int num_available = desc_avail;
-    int num_processed = CB_TAIL(m_state->m_descs);
-    int num_free = CB_AVAIL(m_state->m_descs, num_available, num_processed);
-    if (num_free < descNum) {
-        return HAILO_OUT_OF_DESCRIPTORS;
+    m_can_write_buffer_cv.notify_one();
+
+    return PendingBufferState(*this, next_buffer_desc_num);
+}
+
+hailo_status PendingBufferState::finish(std::chrono::milliseconds timeout, std::unique_lock<std::mutex> &lock)
+{
+    unlock_guard<std::unique_lock<std::mutex>> unlock(lock);
+
+    while (true) {
+        {
+            std::lock_guard<VdmaChannel::State> state_guard(*m_vdma_channel.m_state);
+
+            // Make sure that only one thread is waiting for channel completion
+            if (m_vdma_channel.m_is_waiting_for_channel_completion) {
+                break;
+            }
+
+            // When all pending buffers have been sent but no buffers were processed yet (there are no free descriptors) we want to wait
+            // for channel completion to make free room to the next buffers
+            // TODO: This assumes the next buffer is the same size as the current one, so consider moving this to the write_buffer function
+            int num_free = CB_AVAIL(m_vdma_channel.m_state->m_descs, m_vdma_channel.get_num_available(), CB_TAIL(m_vdma_channel.m_state->m_descs));
+
+            // We use m_next_buffer_desc_num to check if the next buffer has enough descriptors
+            bool should_free_descs = (0 == m_vdma_channel.m_pending_num_avail_offset) && (num_free < static_cast<uint16_t>(m_next_buffer_desc_num));
+            m_vdma_channel.m_is_waiting_for_channel_completion = should_free_descs;
+            if (!should_free_descs) {
+                break;
+            }
+        }
+
+        auto status = m_vdma_channel.wait_for_channel_completion(timeout);
+        if (HAILO_STREAM_INTERNAL_ABORT == status) {
+            LOGGER__INFO("wait_for_channel_completion has failed with status=HAILO_STREAM_INTERNAL_ABORT");
+            return status;
+        }
+        CHECK_SUCCESS(status);
     }
 
-    /* Copy buffer into the PLDA data struct */
-    auto offset = desc_avail * pageSize;
-    status = m_mapped_user_buffer->write_cyclic(buf, count, offset);
-    CHECK_SUCCESS(status);
+    return HAILO_SUCCESS;
+}
 
-    status = prepare_descriptors(count, first_desc_interrupts_domain, last_desc_interrupts_domain);
+hailo_status VdmaChannel::flush(const std::chrono::milliseconds &timeout)
+{
+    assert(m_state);
+
+    if (Direction::D2H == m_direction) {
+        // We are not buffering user data
+        return HAILO_SUCCESS;
+    }
+
+    if (!m_mapped_user_buffer) {
+        LOGGER__ERROR("VdmaChannel::flush is called on a channel without allocated resources");
+        return HAILO_INVALID_OPERATION;
+    }
+
+    return wait_for_condition([this] { return CB_HEAD(m_state->m_buffers) == CB_TAIL(m_state->m_buffers); }, timeout);
+}
+
+hailo_status VdmaChannel::transfer_h2d(void *buf, size_t count)
+{
+    auto status = write_buffer_impl(MemoryView(buf, count));
     CHECK_SUCCESS(status);
 
-    m_state->m_accumulated_transfers = (m_state->m_accumulated_transfers + 1) % m_transfers_per_axi_intr;
+    status = send_pending_buffer_impl();
+    CHECK_SUCCESS(status);
 
     return HAILO_SUCCESS;
 }
@@ -432,7 +533,6 @@ hailo_status VdmaChannel::transfer_d2h(void *buf, size_t count)
     m_state->m_accumulated_transfers = (m_state->m_accumulated_transfers + 1) % m_transfers_per_axi_intr;
 
     return HAILO_SUCCESS;
-
 }
 
 uint16_t VdmaChannel::get_num_available()
@@ -446,7 +546,13 @@ uint16_t VdmaChannel::get_num_available()
     auto hw_num_avail = m_host_registers.get_num_available();
     assert(hw_num_avail);
     // On case of channel aborted, the num_available is set to 0 (so we don't accept sync)
-    assert((hw_num_avail.value() == num_available) || is_aborted().value());
+
+    auto is_aborted_exp = is_aborted();
+    assert(is_aborted_exp);
+
+    if ((HailoRTDriver::INVALID_VDMA_CHANNEL_HANDLE != *m_channel_handle) && !is_aborted_exp.value()) {
+         assert(hw_num_avail.value() == num_available);
+    }
 #endif
     return num_available;
 }
@@ -465,24 +571,6 @@ Expected<uint16_t> VdmaChannel::get_hw_num_processed()
     return static_cast<uint16_t>(hw_num_processed.value() & m_state->m_descs.size_mask);
 }
 
-Expected<uint16_t> VdmaChannel::get_hw_num_processed_ddr(uint32_t size_mask)
-{
-    auto hw_num_processed = m_host_registers.get_num_processed();
-    CHECK_EXPECTED(hw_num_processed, "Fail to read vdma num processed register");
-
-    // Although the hw_num_processed should be a number between 0 and m_descs.size-1, if
-    // m_desc.size < 0x10000 (the maximum desc size), the actual hw_num_processed is a number
-    // between 1 and m_descs.size. Therefore the value can be m_descs.size, in this case we change it
-    // to zero.
-    return static_cast<uint16_t>(hw_num_processed.value() & size_mask);
-}
-
-hailo_status VdmaChannel::wait_channel_interrupts_for_ddr(const std::chrono::milliseconds &timeout)
-{
-    auto irq_data = m_driver.wait_channel_interrupts(channel_index, *m_channel_handle, timeout);
-    return irq_data.status();
-}
-
 hailo_status VdmaChannel::set_num_avail_value(uint16_t new_value)
 {
     auto status = m_host_registers.set_num_available(new_value);
@@ -494,18 +582,14 @@ hailo_status VdmaChannel::set_num_avail_value(uint16_t new_value)
     assert(hw_num_avail);
     assert(hw_num_avail.value() == new_value);
 #endif
-
     return HAILO_SUCCESS;
 }
 
-hailo_status VdmaChannel::inc_num_available_for_ddr(uint16_t value, uint32_t size_mask)
+hailo_status VdmaChannel::set_transfers_per_axi_intr(uint16_t transfers_per_axi_intr)
 {
-    //TODO: validate that count is added.
-    auto num_available = m_host_registers.get_num_available();
-    CHECK_EXPECTED_AS_STATUS(num_available, "Fail to read vdma num available register");
-
-    uint16_t new_value =  static_cast<uint16_t>((num_available.value() + value) & size_mask);
-    return set_num_avail_value(new_value);
+    CHECK(0 != transfers_per_axi_intr, HAILO_INVALID_ARGUMENT, "Invalid transfers per axi interrupt");
+    m_transfers_per_axi_intr = transfers_per_axi_intr;
+    return HAILO_SUCCESS;
 }
 
 hailo_status VdmaChannel::inc_num_available(uint16_t value)
@@ -516,9 +600,6 @@ hailo_status VdmaChannel::inc_num_available(uint16_t value)
     int num_available = get_num_available();
     int num_processed = CB_TAIL(m_state->m_descs);
     int num_free = CB_AVAIL(m_state->m_descs, num_available, num_processed);
-    uint16_t hw_num_avail = 0;
-    
-    (void) hw_num_avail;
     if (value > num_free) {
         return HAILO_OUT_OF_DESCRIPTORS;
     }
@@ -549,9 +630,9 @@ VdmaChannel::Direction VdmaChannel::other_direction(Direction direction)
 
 hailo_status VdmaChannel::unregister_fw_controlled_channel()
 {
-    auto status = m_driver.vdma_channel_disable(channel_index, *m_channel_handle);
+    auto status = m_driver.vdma_channel_disable(m_channel_index, *m_channel_handle);
     *m_channel_handle = HailoRTDriver::INVALID_VDMA_CHANNEL_HANDLE;
-    CHECK_SUCCESS(status, "Failed to disable channel {}", channel_index);
+    CHECK_SUCCESS(status, "Failed to disable channel {}", m_channel_index);
 
     return HAILO_SUCCESS;
 }
@@ -560,8 +641,8 @@ hailo_status VdmaChannel::register_channel_to_driver(uintptr_t desc_list_handle)
 {
     const bool measure_latency = (nullptr != m_latency_meter);
     const uintptr_t desc_handle = desc_list_handle;
-    auto channel_handle = m_driver.vdma_channel_enable(channel_index, m_direction, desc_handle, measure_latency);
-    CHECK_EXPECTED_AS_STATUS(channel_handle, "Failed to enable channel {}", channel_index);
+    auto channel_handle = m_driver.vdma_channel_enable(m_channel_index, m_direction, desc_handle, measure_latency);
+    CHECK_EXPECTED_AS_STATUS(channel_handle, "Failed to enable channel {}", m_channel_index);
 
     *m_channel_handle = channel_handle.release();
     return HAILO_SUCCESS;
@@ -572,7 +653,7 @@ hailo_status VdmaChannel::start_channel(VdmaDescriptorList &desc_list)
     assert(is_aborted());
 
     auto status = register_channel_to_driver(desc_list.handle());
-    CHECK_SUCCESS(status, "Failed to enable channel {}", channel_index);
+    CHECK_SUCCESS(status, "Failed to enable channel {}", m_channel_index);
 
     return HAILO_SUCCESS;
 }
@@ -592,17 +673,17 @@ void VdmaChannel::clear_descriptor_list()
     }
 }
 
-hailo_status VdmaChannel::allocate_buffer(const size_t buffer_size)
+hailo_status VdmaChannel::allocate_buffer(const uint32_t buffer_size)
 {
     assert((buffer_size % m_desc_page_size) == 0);
-    size_t desc_count = buffer_size / m_desc_page_size;
+    uint32_t desc_count = buffer_size / m_desc_page_size;
 
     if (m_mapped_user_buffer) {
         LOGGER__ERROR("m_mapped_user_buffer is not NULL");
         return HAILO_INVALID_OPERATION;
     }
 
-    auto mapped_buffer = VdmaBuffer::create(buffer_size, m_direction, m_driver);
+    auto mapped_buffer = vdma::MappedBuffer::create(buffer_size, m_direction, m_driver);
     if(!mapped_buffer) {
         LOGGER__ERROR("create mapped buffer failed");
         return mapped_buffer.status();
@@ -614,13 +695,13 @@ hailo_status VdmaChannel::allocate_buffer(const size_t buffer_size)
         return descriptors.status();
     }
 
-    auto status = descriptors->configure_to_use_buffer(mapped_buffer.value(), channel_index);
+    auto status = descriptors->configure_to_use_buffer(mapped_buffer.value(), m_channel_index);
     if (status != HAILO_SUCCESS) {
         LOGGER__ERROR("connect descriptor list to buffer failed");
         return status;
     }
 
-    m_mapped_user_buffer = make_unique_nothrow<VdmaBuffer>(mapped_buffer.release());
+    m_mapped_user_buffer = make_unique_nothrow<vdma::MappedBuffer>(mapped_buffer.release());
     CHECK_NOT_NULL(m_mapped_user_buffer, HAILO_OUT_OF_HOST_MEMORY);
 
     m_descriptors_buffer = make_unique_nothrow<VdmaDescriptorList>(descriptors.release());
@@ -655,6 +736,7 @@ hailo_status VdmaChannel::trigger_channel_completion(uint16_t hw_num_processed)
     // situation correctly.
 
     assert(m_state);
+    std::lock_guard<State> state_guard(*m_state);
 
     int processed_no = 0;
     int head = CB_HEAD(m_state->m_buffers);
@@ -664,7 +746,7 @@ hailo_status VdmaChannel::trigger_channel_completion(uint16_t hw_num_processed)
 
     auto channel_error = m_host_registers.get_channel_error();
     CHECK_EXPECTED_AS_STATUS(channel_error, "Fail to read vdma channel error register");
-    CHECK(0 == channel_error.value(), HAILO_INTERNAL_FAILURE, "Vdma channel {} in error state {}", channel_index, channel_error.value());
+    CHECK(0 == channel_error.value(), HAILO_INTERNAL_FAILURE, "Vdma channel {} in error state {}", m_channel_index, channel_error.value());
 
     uint16_t last_num_processed = static_cast<uint16_t>(CB_TAIL(m_state->m_descs));
 
@@ -672,14 +754,13 @@ hailo_status VdmaChannel::trigger_channel_completion(uint16_t hw_num_processed)
         uint16_t last_desc_index = static_cast<uint16_t>(m_state->m_pending_buffers[tail].last_desc);
         // Transfer is complete if its last descriptor is in [last_num_processed, hw_num_processed) or
         // the the buffer is empty (hw_num_processed == get_num_available())
-        bool is_complete = (is_desc_between(last_num_processed, hw_num_processed, last_desc_index) ||
-                            hw_num_processed == get_num_available());
+        bool is_complete = is_desc_between(last_num_processed, hw_num_processed, last_desc_index) || (hw_num_processed == get_num_available());
 
 #ifndef NDEBUG
         auto status = (*m_descriptors_buffer)[last_desc_index].RemainingPageSize_Status & 0xFF;
         // Verify if a DMA Descriptor error occurred.
         if (status & 0x2) {
-            LOGGER__ERROR("Error while processing descriptor {} of DMA {} on board {}.", last_desc_index, channel_index,
+            LOGGER__ERROR("Error while processing descriptor {} of DMA {} on board {}.", last_desc_index, m_channel_index,
                 m_driver.dev_path());
             return HAILO_INTERNAL_FAILURE;
         }
@@ -701,8 +782,13 @@ hailo_status VdmaChannel::trigger_channel_completion(uint16_t hw_num_processed)
         // TODO: use a different macro instead?
         _CB_SET(m_state->m_descs.tail, (m_state->m_pending_buffers[last_tail].last_desc + 1) & m_state->m_descs.size_mask);
         CB_DEQUEUE(m_state->m_buffers, processed_no);
+
+        if (Direction::H2D == m_direction) {
+            m_can_write_buffer_cv.notify_one();
+        }
     }
 
+    m_is_waiting_for_channel_completion = false;
     return HAILO_SUCCESS;
 }
 
@@ -762,6 +848,8 @@ bool VdmaChannel::is_ready_for_transfer_d2h(size_t buffer_size)
 hailo_status VdmaChannel::prepare_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
     VdmaInterruptsDomain last_desc_interrupts_domain)
 {
+    MICROPROFILE_SCOPEI("vDMA Channel", "Trigger vDMA", 0);
+
     assert(m_descriptors_buffer);
     assert(m_state);
     auto &desc_info = *m_descriptors_buffer;
@@ -781,7 +869,7 @@ hailo_status VdmaChannel::prepare_descriptors(size_t transfer_size, VdmaInterrup
     auto actual_desc_count = desc_info.program_descriptors(transfer_size, first_desc_interrupts_domain,
         last_desc_interrupts_domain, num_available, true);
     if (!actual_desc_count) {
-        LOGGER__ERROR("Failed to program desc_list for channel {}", channel_index);
+        LOGGER__ERROR("Failed to program desc_list for channel {}", m_channel_index);
         return actual_desc_count.status();
     }
     assert (actual_desc_count.value() == desc_num);
@@ -834,7 +922,6 @@ Expected<bool> VdmaChannel::is_aborted()
 
 hailo_status VdmaChannel::wait_for_condition(std::function<bool()> condition, std::chrono::milliseconds timeout)
 {
-    hailo_status status = HAILO_UNINITIALIZED;
     auto start_time = std::chrono::steady_clock::now();
     std::chrono::milliseconds time_elapsed(0);
     while (timeout > time_elapsed) {
@@ -842,28 +929,10 @@ hailo_status VdmaChannel::wait_for_condition(std::function<bool()> condition, st
             return HAILO_SUCCESS;
         }
 
-        auto hw_num_processed = wait_interrupts(timeout);
-        if ((hw_num_processed.status() == HAILO_TIMEOUT) ||
-            (hw_num_processed &&  hw_num_processed.value() == 0)) {
-            // We need to check for channel abort in this 2 cases:
-            //  1. TIMEOUT - maybe the timeout is a result of channel aborted.
-            //  2. hw_num_processed == 0 - In this case we receive an interrupt, but the channel may be
-            //     aborted. When the channel is aborted, num processed is set to 0.
-            auto is_aborted_exp = is_aborted();
-            CHECK_EXPECTED_AS_STATUS(is_aborted_exp);
-            if (is_aborted_exp.value()) {
-                LOGGER__CRITICAL("Channel {} was aborted by an external source!", channel_index);
-                return HAILO_STREAM_ABORTED;
-            }
-        }
-        if ((HAILO_STREAM_INTERNAL_ABORT == hw_num_processed.status()) ||
-            (HAILO_STREAM_NOT_ACTIVATED == hw_num_processed.status())) {
-            return hw_num_processed.status();
+        auto status = wait_for_channel_completion(timeout);
+        if (HAILO_SUCCESS != status) {
+            return status;
         }
-        CHECK_EXPECTED_AS_STATUS(hw_num_processed);
-
-        status = trigger_channel_completion(hw_num_processed.value());
-        CHECK_SUCCESS(status);
 
         time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time);
     }
@@ -871,11 +940,39 @@ hailo_status VdmaChannel::wait_for_condition(std::function<bool()> condition, st
     return condition() ? HAILO_SUCCESS : HAILO_TIMEOUT;
 }
 
+hailo_status VdmaChannel::wait_for_channel_completion(std::chrono::milliseconds timeout)
+{
+    auto hw_num_processed = wait_interrupts(timeout);
+    if ((hw_num_processed.status() == HAILO_TIMEOUT) ||
+        (hw_num_processed &&  hw_num_processed.value() == 0)) {
+        // We need to check for channel abort in this 2 cases:
+        //  1. TIMEOUT - maybe the timeout is a result of channel aborted.
+        //  2. hw_num_processed == 0 - In this case we receive an interrupt, but the channel may be
+        //     aborted. When the channel is aborted, num processed is set to 0.
+        auto is_aborted_exp = is_aborted();
+        CHECK_EXPECTED_AS_STATUS(is_aborted_exp);
+        if (is_aborted_exp.value()) {
+            LOGGER__CRITICAL("Channel {} was aborted by an external source!", m_channel_index);
+            return HAILO_STREAM_ABORTED;
+        }
+    }
+    if ((HAILO_STREAM_INTERNAL_ABORT == hw_num_processed.status()) ||
+        (HAILO_STREAM_NOT_ACTIVATED == hw_num_processed.status())) {
+        return hw_num_processed.status();
+    }
+    CHECK_EXPECTED_AS_STATUS(hw_num_processed);
+
+    auto status = trigger_channel_completion(hw_num_processed.value());
+    CHECK_SUCCESS(status);
+
+    return HAILO_SUCCESS;
+}
+
 Expected<uint16_t> VdmaChannel::wait_interrupts(std::chrono::milliseconds timeout)
 {
     assert(m_state);
 
-    auto irq_data = m_driver.wait_channel_interrupts(channel_index, *m_channel_handle, timeout);
+    auto irq_data = m_driver.wait_channel_interrupts(m_channel_index, *m_channel_handle, timeout);
     if ((HAILO_STREAM_INTERNAL_ABORT == irq_data.status()) ||
         (HAILO_STREAM_NOT_ACTIVATED == irq_data.status())) {
         LOGGER__INFO("Wait channel interrupts was aborted!");
index d2a9f921a56ae3f3a0ccb0942e22613708b59a2f..0ceb03f37eeb6f004da2f7260a4b12eb29eaf816 100644 (file)
 #include "vdma_channel_regs.hpp"
 #include "hailo/expected.hpp"
 #include "os/hailort_driver.hpp"
-#include "vdma_buffer.hpp"
+#include "vdma/mapped_buffer.hpp"
 #include "vdma_descriptor_list.hpp"
+#include "hailo/buffer.hpp"
 
 #include <mutex>
 #include <array>
+#include <condition_variable>
 
 namespace hailort
 {
 
+class VdmaChannel;
+class PendingBufferState final
+{
+public:
+    PendingBufferState(VdmaChannel &vdma_channel, size_t next_buffer_desc_num) : m_vdma_channel(vdma_channel),
+        m_next_buffer_desc_num(next_buffer_desc_num) {}
+    hailo_status finish(std::chrono::milliseconds timeout, std::unique_lock<std::mutex> &lock);
+
+private:
+    VdmaChannel &m_vdma_channel;
+    size_t m_next_buffer_desc_num;
+};
+
 class VdmaChannel final
 {
 public:
@@ -48,6 +63,8 @@ public:
     hailo_status wait(size_t buffer_size, const std::chrono::milliseconds &timeout);
 
     hailo_status transfer(void *buf, size_t count);
+    hailo_status write_buffer(const MemoryView &buffer, std::chrono::milliseconds timeout);
+    Expected<PendingBufferState> send_pending_buffer();
     hailo_status trigger_channel_completion(uint16_t hw_num_processed);
     hailo_status allocate_resources(uint32_t descs_count);
     /* For channels controlled by the HailoRT, the HailoRT needs to use this function to start the channel (it registers the channel to driver 
@@ -57,8 +74,8 @@ public:
     hailo_status unregister_fw_controlled_channel();
     hailo_status flush(const std::chrono::milliseconds &timeout);
     hailo_status set_num_avail_value(uint16_t new_value);
+    hailo_status set_transfers_per_axi_intr(uint16_t transfers_per_axi_intr);
     hailo_status inc_num_available_for_ddr(uint16_t value, uint32_t size_mask);
-    hailo_status wait_channel_interrupts_for_ddr(const std::chrono::milliseconds &timeout);
     Expected<uint16_t> get_hw_num_processed_ddr(uint32_t size_mask);
     /*Used for DDR channels only. TODO - remove */
     hailo_status start_channel(VdmaDescriptorList &desc_list);
@@ -71,6 +88,11 @@ public:
     hailo_status abort();
     hailo_status clear_abort();
 
+    uint8_t get_channel_index()
+    {
+        return m_channel_index;
+    }
+
     VdmaChannel(const VdmaChannel &other) = delete;
     VdmaChannel &operator=(const VdmaChannel &other) = delete;
     VdmaChannel(VdmaChannel &&other) noexcept;
@@ -80,7 +102,9 @@ public:
         uint16_t requested_desc_page_size);
 
 
-    const uint8_t channel_index;
+    const uint8_t m_channel_index;
+
+    friend class PendingBufferState;
 
 private:
     struct PendingBuffer {
@@ -115,11 +139,13 @@ private:
     VdmaChannel(uint8_t channel_index, Direction direction, HailoRTDriver &driver, uint32_t stream_index,
         LatencyMeterPtr latency_meter, uint16_t desc_page_size, uint16_t transfers_per_axi_intr, hailo_status &status);
 
-    hailo_status allocate_buffer(const size_t buffer_size);
+    hailo_status allocate_buffer(const uint32_t buffer_size);
     void clear_descriptor_list();
     hailo_status release_buffer();
     static Direction other_direction(const Direction direction);
     hailo_status transfer_h2d(void *buf, size_t count);
+    hailo_status write_buffer_impl(const MemoryView &buffer);
+    hailo_status send_pending_buffer_impl();
     uint16_t get_num_available();
     Expected<uint16_t> get_hw_num_processed();
     void add_pending_buffer(uint32_t first_desc, uint32_t last_desc);
@@ -131,6 +157,7 @@ private:
         VdmaInterruptsDomain last_desc_interrupts_domain);
     hailo_status prepare_d2h_pending_descriptors(uint32_t descs_count, uint32_t transfer_size);
     void reset_internal_counters();
+    hailo_status wait_for_channel_completion(std::chrono::milliseconds timeout);
 
     uint32_t calculate_descriptors_count(uint32_t buffer_size);
 
@@ -158,7 +185,7 @@ private:
 
     // TODO: remove the unique_ptr, instead allocate the buffer in the ctor (needs to move ddr channel to
     // other class)
-    std::unique_ptr<VdmaBuffer> m_mapped_user_buffer;
+    std::unique_ptr<vdma::MappedBuffer> m_mapped_user_buffer;
     std::unique_ptr<VdmaDescriptorList> m_descriptors_buffer;
     uint32_t m_stream_index;
     LatencyMeterPtr m_latency_meter;
@@ -171,6 +198,12 @@ private:
     bool m_channel_enabled;
     
     uint16_t m_transfers_per_axi_intr;
+    // Using CircularArray because it won't allocate or free memory wile pushing and poping. The fact that it is circural is not relevant here
+    CircularArray<size_t> m_pending_buffers_sizes;
+    uint16_t m_pending_num_avail_offset;
+    std::condition_variable_any m_can_write_buffer_cv;
+    std::atomic_bool m_is_waiting_for_channel_completion;
+    bool m_is_aborted;
 };
 
 } /* namespace hailort */
index 6d023683d1e633d8a647017c95462e43123b9bda..a74133ee8a37ba3d73eec3874589156cfaf70a20 100644 (file)
 
 #define DESC_PAGE_SIZE_SHIFT                  (8)
 #define DESC_PAGE_SIZE_MASK                   (0xFFFFFF00)
+#define DESC_IRQ_MASK                         (0x0000003C)
 
 namespace hailort
 {
 
-Expected<VdmaDescriptorList> VdmaDescriptorList::create(size_t desc_count, uint16_t requested_desc_page_size,
+Expected<VdmaDescriptorList> VdmaDescriptorList::create(uint32_t desc_count, uint16_t requested_desc_page_size,
     HailoRTDriver &driver)
 {
     hailo_status status = HAILO_UNINITIALIZED;
@@ -30,7 +31,7 @@ Expected<VdmaDescriptorList> VdmaDescriptorList::create(size_t desc_count, uint1
     return object;
 }
 
-VdmaDescriptorList::VdmaDescriptorList(size_t desc_count, HailoRTDriver &driver, uint16_t desc_page_size,
+VdmaDescriptorList::VdmaDescriptorList(uint32_t desc_count, HailoRTDriver &driver, uint16_t desc_page_size,
                                        hailo_status &status) :
     m_mapped_list(),
     m_count(desc_count),
@@ -107,13 +108,13 @@ Expected<uint8_t> VdmaDescriptorList::calculate_desc_list_depth(size_t count)
     return static_cast<uint8_t>(depth);
 }
 
-hailo_status VdmaDescriptorList::configure_to_use_buffer(VdmaBuffer& buffer, uint8_t channel_index)
+hailo_status VdmaDescriptorList::configure_to_use_buffer(vdma::MappedBuffer& buffer, uint8_t channel_index)
 {
     return m_driver.descriptors_list_bind_vdma_buffer(m_desc_handle, buffer.handle(), m_desc_page_size,
         channel_index);
 }
 
-hailo_status VdmaDescriptorList::configure_to_use_buffer(VdmaBuffer& buffer)
+hailo_status VdmaDescriptorList::configure_to_use_buffer(vdma::MappedBuffer& buffer)
 {
     return configure_to_use_buffer(buffer, HailoRTDriver::INVALID_VDMA_CHANNEL_INDEX);
 }
@@ -125,7 +126,7 @@ Expected<uint16_t> VdmaDescriptorList::program_descriptors(size_t transfer_size,
     const auto required_descriptors = descriptors_in_buffer(transfer_size);
     // Required_descriptors + desc_offset can't reach m_count. We need to keep at least 1 free desc at all time.
     if ((!is_circular) && ((required_descriptors + desc_offset) >= m_count)){
-        LOGGER__ERROR("Requested transfer size ({}) result in more descrptors than available ({})", transfer_size, m_count);
+        LOGGER__ERROR("Requested transfer size ({}) result in more descriptors than available ({})", transfer_size, m_count);
         return make_unexpected(HAILO_OUT_OF_DESCRIPTORS);
     }
 
@@ -144,23 +145,15 @@ Expected<uint16_t> VdmaDescriptorList::program_descriptors(size_t transfer_size,
     return std::move(static_cast<uint16_t>(required_descriptors));
 }
 
-Expected<uint16_t> VdmaDescriptorList::program_descs_for_ddr_transfers(uint32_t row_size, bool should_raise_interrupt,
-    uint32_t number_of_rows_per_intrpt, uint32_t buffered_rows, uint16_t initial_descs_offset, bool is_circular)
+hailo_status VdmaDescriptorList::reprogram_descriptor_interrupts_domain(size_t desc_index,
+    VdmaInterruptsDomain interrupts_domain)
 {
-    uint16_t programmed_descs = 0;
-    size_t offset = initial_descs_offset;
-    assert(0 == (buffered_rows % number_of_rows_per_intrpt));
-
-    auto first_desc_interrupts_mask = VdmaInterruptsDomain::NONE;
-    auto last_desc_interrupts_mask = (should_raise_interrupt) ? VdmaInterruptsDomain::HOST : VdmaInterruptsDomain::NONE;
-    for (uint32_t rows_count = 0; rows_count < buffered_rows; rows_count += number_of_rows_per_intrpt) {
-        auto desc_count_local = program_descriptors((row_size * number_of_rows_per_intrpt),
-            first_desc_interrupts_mask, last_desc_interrupts_mask, offset, is_circular);
-        CHECK_EXPECTED(desc_count_local);
-        offset = (offset + desc_count_local.value()) & (m_count - 1);
-        programmed_descs = static_cast<uint16_t>(programmed_descs + desc_count_local.value());
+    if (desc_index >= m_count){
+        LOGGER__ERROR("Requested desc (index={}) exceeds the number of descriptors in the list ({})", desc_index, m_count);
+        return HAILO_OUT_OF_DESCRIPTORS;
     }
-    return programmed_descs;
+    reprogram_single_descriptor_interrupts_domain((*this)[desc_index], interrupts_domain);
+    return HAILO_SUCCESS;
 }
 
 uint32_t VdmaDescriptorList::descriptors_in_buffer(size_t buffer_size) const
@@ -171,7 +164,7 @@ uint32_t VdmaDescriptorList::descriptors_in_buffer(size_t buffer_size) const
 uint32_t VdmaDescriptorList::descriptors_in_buffer(size_t buffer_size, uint16_t desc_page_size)
 {
     assert(buffer_size < std::numeric_limits<uint32_t>::max());
-    return static_cast<uint32_t>(((buffer_size) + desc_page_size - 1) / desc_page_size);
+    return static_cast<uint32_t>(DESCRIPTORS_IN_BUFFER(buffer_size, desc_page_size));
 }
 
 uint32_t VdmaDescriptorList::calculate_descriptors_count(uint32_t buffer_size, uint16_t batch_size, uint16_t desc_page_size)
@@ -257,8 +250,9 @@ Expected<std::pair<uint16_t, uint32_t>> VdmaDescriptorList::get_desc_buffer_size
 
         CHECK_AS_EXPECTED(local_desc_page_size <= max_desc_page_size, HAILO_OUT_OF_DESCRIPTORS,
             "Network shapes and batch size exceeds driver descriptors capabilities. "
-            "Required descriptors count: {}, max allowed on the driver: {}.",
-            (batch_size * acc_desc_count), MAX_DESCS_COUNT);
+            "Required descriptors count: {}, max allowed on the driver: {}. (A common cause for this error could be the"
+            "Batch size - which is {}).",
+            (batch_size * acc_desc_count), MAX_DESCS_COUNT, batch_size);
 
         CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(local_desc_page_size), HAILO_INTERNAL_FAILURE,
             "Descriptor page size needs to fit in 16B");
@@ -322,16 +316,31 @@ void VdmaDescriptorList::program_single_descriptor(VdmaDescriptor &descriptor, u
         (uint32_t)(page_size << DESC_PAGE_SIZE_SHIFT) & (uint32_t)DESC_PAGE_SIZE_MASK;
 
     if (VdmaInterruptsDomain::NONE != interrupts_domain) {
-        // update the desc_control
-        descriptor.PageSize_DescControl |= (DESC_REQUREST_IRQ_PROCESSED | DESC_REQUREST_IRQ_ERR);
+        // Update the desc_control
+        descriptor.PageSize_DescControl |= (DESC_REQUREST_IRQ_PROCESSED | DESC_REQUREST_IRQ_ERR |
+            get_interrupts_bitmask(interrupts_domain));
 #ifndef NDEBUG
         descriptor.PageSize_DescControl |= (DESC_STATUS_REQ | DESC_STATUS_REQ_ERR);
 #endif
-        descriptor.PageSize_DescControl |= get_interrupts_bitmask(interrupts_domain);
     }
 
     // Clear status
     descriptor.RemainingPageSize_Status = 0;
 }
 
+void VdmaDescriptorList::reprogram_single_descriptor_interrupts_domain(VdmaDescriptor &descriptor,
+    VdmaInterruptsDomain interrupts_domain)
+{
+    // Set the IRQ control bits to zero
+    descriptor.PageSize_DescControl &= ~DESC_IRQ_MASK;
+    
+    if (VdmaInterruptsDomain::NONE == interrupts_domain) {
+        // Nothing else to do
+        return;
+    }
+
+    descriptor.PageSize_DescControl |= (DESC_REQUREST_IRQ_PROCESSED | DESC_REQUREST_IRQ_ERR |
+        get_interrupts_bitmask(interrupts_domain));
+}
+
 } /* namespace hailort */
index f09a3a3305865e97de347a75b5d7d68f55c6d257..28cd03d385a300d2223eb9db8af29f9ade693e71 100644 (file)
@@ -14,7 +14,7 @@
 #include "os/hailort_driver.hpp"
 #include "hailo/expected.hpp"
 #include "os/mmap_buffer.hpp"
-#include "vdma_buffer.hpp"
+#include "vdma/mapped_buffer.hpp"
 #include "common/utils.hpp"
 
 namespace hailort
@@ -81,7 +81,7 @@ inline bool device_interuptes_enabled(VdmaInterruptsDomain interrupts_domain)
 class VdmaDescriptorList
 {
 public:
-    static Expected<VdmaDescriptorList> create(size_t desc_count, uint16_t requested_desc_page_size,
+    static Expected<VdmaDescriptorList> create(uint32_t desc_count, uint16_t requested_desc_page_size,
         HailoRTDriver &driver);
 
     ~VdmaDescriptorList();
@@ -96,7 +96,7 @@ public:
         return m_depth;
     }
 
-    size_t count() const
+    uint32_t count() const
     {
         return m_count;
     }
@@ -122,15 +122,13 @@ public:
         return m_desc_handle;
     }
 
-    hailo_status configure_to_use_buffer(VdmaBuffer& buffer, uint8_t channel_index);
+    hailo_status configure_to_use_buffer(vdma::MappedBuffer& buffer, uint8_t channel_index);
     // On hailo8, we allow configuring buffer without specific channel index.
-    hailo_status configure_to_use_buffer(VdmaBuffer& buffer);
+    hailo_status configure_to_use_buffer(vdma::MappedBuffer& buffer);
 
     Expected<uint16_t> program_descriptors(size_t transfer_size, VdmaInterruptsDomain first_desc_interrupts_domain,
         VdmaInterruptsDomain last_desc_interrupts_domain, size_t desc_offset, bool is_circular);
-
-    Expected<uint16_t> program_descs_for_ddr_transfers(uint32_t row_size, bool should_raise_interrupt, 
-        uint32_t number_of_rows_per_intrpt, uint32_t buffered_rows, uint16_t initial_descs_offset, bool is_circular);
+    hailo_status reprogram_descriptor_interrupts_domain(size_t desc_index, VdmaInterruptsDomain interrupts_domain);
 
     uint32_t descriptors_in_buffer(size_t buffer_size) const;
     static uint32_t descriptors_in_buffer(size_t buffer_size, uint16_t desc_page_size);
@@ -141,10 +139,11 @@ public:
         uint16_t batch_size, const std::vector<uint32_t> &transfer_sizes);
 
 private:
-    VdmaDescriptorList(size_t desc_count, HailoRTDriver &driver, uint16_t desc_page_size, hailo_status &status);
+    VdmaDescriptorList(uint32_t desc_count, HailoRTDriver &driver, uint16_t desc_page_size, hailo_status &status);
     uint32_t get_interrupts_bitmask(VdmaInterruptsDomain interrupts_domain);
     void program_single_descriptor(VdmaDescriptor &descriptor, uint16_t page_size,
         VdmaInterruptsDomain interrupts_domain);
+    void reprogram_single_descriptor_interrupts_domain(VdmaDescriptor &descriptor, VdmaInterruptsDomain interrupts_domain);
     static Expected<uint8_t> calculate_desc_list_depth(size_t count);
     // Note: initial_desc_page_size should be the optimal descriptor page size.
     static Expected<std::pair<uint16_t, uint32_t>> get_desc_buffer_sizes_for_single_transfer_impl(
@@ -155,7 +154,7 @@ private:
         uint16_t initial_desc_page_size);
 
     MmapBuffer<VdmaDescriptor> m_mapped_list;
-    size_t m_count;
+    uint32_t m_count;
     uint8_t m_depth;
     uintptr_t m_desc_handle;
     uint64_t m_dma_address;
index e1aa94dc9824dd6bc38ba7afa8587123ed8eb115..60af9460ae46af2e547cd9cdd213b06ac3c52e92 100644 (file)
 namespace hailort
 {
 
-VdmaInputStream::VdmaInputStream(VdmaDevice &device, uint8_t channel_index, const LayerInfo &edge_layer,
-                                 EventPtr network_group_activated_event, uint16_t batch_size,
-                                 LatencyMeterPtr latency_meter, std::chrono::milliseconds transfer_timeout,
+VdmaInputStream::VdmaInputStream(VdmaDevice &device, std::shared_ptr<VdmaChannel> channel,
+                                 const LayerInfo &edge_layer, EventPtr network_group_activated_event, uint16_t batch_size,
+                                 std::chrono::milliseconds transfer_timeout,
                                  hailo_stream_interface_t stream_interface, hailo_status &status) :
     InputStreamBase(edge_layer, stream_interface, std::move(network_group_activated_event), status),
     m_device(&device),
-    m_channel_index(channel_index),
+    m_channel(std::move(channel)),
     is_stream_activated(false),
     m_channel_timeout(transfer_timeout),
-    m_latency_meter(latency_meter),
-    m_batch_size(batch_size)
+    m_max_batch_size(batch_size),
+    m_dynamic_batch_size(batch_size)
 {
     // Checking status for base class c'tor
     if (HAILO_SUCCESS != status) {
         return;
     }
 
-    status = config_stream();
-    if (HAILO_SUCCESS != status) {
-        return;
-    }
-
     status = HAILO_SUCCESS;
 }
 
@@ -52,12 +47,11 @@ VdmaInputStream::~VdmaInputStream()
 VdmaInputStream::VdmaInputStream(VdmaInputStream &&other) :
     InputStreamBase(std::move(other)),
     m_device(std::move(other.m_device)),
-    m_channel_index(std::move(other.m_channel_index)),
     m_channel(std::move(other.m_channel)),
     is_stream_activated(std::exchange(other.is_stream_activated, false)),
     m_channel_timeout(std::move(other.m_channel_timeout)),
-    m_latency_meter(std::move(other.m_latency_meter)),
-    m_batch_size(other.m_batch_size)
+    m_max_batch_size(other.m_max_batch_size),
+    m_dynamic_batch_size(other.m_dynamic_batch_size)
 {}
 
 std::chrono::milliseconds VdmaInputStream::get_timeout() const
@@ -83,12 +77,15 @@ hailo_status VdmaInputStream::clear_abort()
 
 hailo_status VdmaInputStream::flush()
 {
-    return m_channel->flush((m_channel_timeout * m_batch_size));
+    return m_channel->flush((m_channel_timeout * m_dynamic_batch_size));
 }
 
-hailo_status VdmaInputStream::activate_stream()
+hailo_status VdmaInputStream::activate_stream(uint16_t dynamic_batch_size)
 {
-    auto status = m_channel->start_allocated_channel(0);
+    auto status = set_dynamic_batch_size(dynamic_batch_size);
+    CHECK_SUCCESS(status);
+
+    status = m_channel->start_allocated_channel(0);
     CHECK_SUCCESS(status);
 
     this->is_stream_activated = true;
@@ -104,10 +101,10 @@ hailo_status VdmaInputStream::deactivate_stream()
     /* Flush is best effort */
     auto status = m_channel->flush(VDMA_FLUSH_TIMEOUT);
     if (HAILO_STREAM_INTERNAL_ABORT == status) {
-        LOGGER__INFO("Flush input_channel is not needed because channel was aborted. (channel {})", m_channel_index);
+        LOGGER__INFO("Flush input_channel is not needed because channel was aborted. (channel {})", m_channel->get_channel_index());
         status = HAILO_SUCCESS;
     } else if (HAILO_SUCCESS != status) {
-        LOGGER__ERROR("Failed to flush input_channel. (status {} channel {})", status, m_channel_index);
+        LOGGER__ERROR("Failed to flush input_channel. (status {} channel {})", status, m_channel->get_channel_index());
     }
 
     /* Close channel is best effort. */
@@ -137,59 +134,70 @@ Expected<size_t> VdmaInputStream::sync_write_raw_buffer(const MemoryView &buffer
     return buffer.size();
 }
 
-hailo_status VdmaInputStream::sync_write_all_raw_buffer_no_transform_impl(void *buffer, size_t offset, size_t size)
+hailo_status VdmaInputStream::write_buffer_only(const MemoryView &buffer)
 {
-    ASSERT(NULL != buffer);
-
-    return sync_write_raw_buffer(MemoryView(static_cast<uint8_t*>(buffer) + offset, size)).status();
+    return m_channel->write_buffer(buffer, m_channel_timeout);
 }
 
-hailo_status VdmaInputStream::config_stream()
+Expected<PendingBufferState> VdmaInputStream::send_pending_buffer()
 {
-    hailo_status status = HAILO_UNINITIALIZED;
-    uint32_t descs_count = 0;
-    uint16_t page_size = 0;
-    uint32_t min_active_trans = MIN_ACTIVE_TRANSFERS_SCALE * m_batch_size;
-    uint32_t max_active_trans = MAX_ACTIVE_TRANSFERS_SCALE * m_batch_size;
-    assert(min_active_trans <= max_active_trans);
-
-    CHECK(IS_FIT_IN_UINT16(min_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
+    hailo_status status = m_channel->wait(get_frame_size(), m_channel_timeout);
+    if ((HAILO_STREAM_INTERNAL_ABORT == status) || (HAILO_STREAM_NOT_ACTIVATED == status)) {
+        return make_unexpected(status);
+    }
+    CHECK_SUCCESS_AS_EXPECTED(status);
 
-    CHECK(IS_FIT_IN_UINT16(max_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
+    return m_channel->send_pending_buffer();
+}
 
-    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(m_device->get_driver(),
-        static_cast<uint16_t>(min_active_trans), static_cast<uint16_t>(max_active_trans), m_stream_info.hw_frame_size);
-    CHECK_EXPECTED_AS_STATUS(desc_sizes_pair);
+uint16_t VdmaInputStream::get_dynamic_batch_size() const
+{
+    return m_dynamic_batch_size;
+}
 
-    page_size = desc_sizes_pair->first;
-    descs_count = desc_sizes_pair->second;
+const char* VdmaInputStream::get_dev_id() const
+{
+    return m_device->get_dev_id();
+}
 
-    auto channel = VdmaChannel::create(m_channel_index, VdmaChannel::Direction::H2D, m_device->get_driver(), page_size,
-        m_stream_info.index, m_latency_meter, m_batch_size);
+hailo_status VdmaInputStream::sync_write_all_raw_buffer_no_transform_impl(void *buffer, size_t offset, size_t size)
+{
+    ASSERT(NULL != buffer);
 
-    m_channel = make_unique_nothrow<VdmaChannel>(channel.release());
-    CHECK(nullptr != m_channel, HAILO_OUT_OF_HOST_MEMORY);
+    return sync_write_raw_buffer(MemoryView(static_cast<uint8_t*>(buffer) + offset, size)).status();
+}
 
-    status = m_channel->allocate_resources(descs_count);
-    CHECK_SUCCESS(status);
+hailo_status VdmaInputStream::set_dynamic_batch_size(uint16_t dynamic_batch_size)
+{
+    CHECK(dynamic_batch_size <= m_max_batch_size, HAILO_INVALID_ARGUMENT,
+        "Dynamic batch size ({}) must be <= than the configured batch size ({})",
+        dynamic_batch_size, m_max_batch_size);
+    
+    if (CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == dynamic_batch_size) {
+        LOGGER__TRACE("Received CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == dynamic_batch_size; "
+                      "Leaving previously set value of {}", m_dynamic_batch_size);
+    } else {
+        LOGGER__TRACE("Setting stream's dynamic_batch_size to {}", dynamic_batch_size);
+        m_dynamic_batch_size = dynamic_batch_size;
+
+        const auto status = m_channel->set_transfers_per_axi_intr(m_dynamic_batch_size);
+        CHECK_SUCCESS(status);
+    }
 
     return HAILO_SUCCESS;
 }
 
 /** Output stream **/
-VdmaOutputStream::VdmaOutputStream(VdmaDevice &device, uint8_t channel_index, const LayerInfo &edge_layer,
-                                   EventPtr network_group_activated_event, uint16_t batch_size,
-                                   LatencyMeterPtr latency_meter, std::chrono::milliseconds transfer_timeout,
-                                   hailo_status &status) :
+VdmaOutputStream::VdmaOutputStream(VdmaDevice &device, std::shared_ptr<VdmaChannel> channel,
+                                   const LayerInfo &edge_layer, EventPtr network_group_activated_event, uint16_t batch_size,
+                                   std::chrono::milliseconds transfer_timeout, hailo_status &status) :
     OutputStreamBase(edge_layer, std::move(network_group_activated_event), status),
     m_device(&device),
-    m_channel_index(channel_index),
+    m_channel(std::move(channel)),
     is_stream_activated(false),
     m_transfer_timeout(transfer_timeout),
-    m_latency_meter(latency_meter),
-    m_batch_size(batch_size),
+    m_max_batch_size(batch_size),
+    m_dynamic_batch_size(batch_size),
     m_transfer_size(get_transfer_size(m_stream_info))
 {
     // Check status for base class c'tor
@@ -197,23 +205,17 @@ VdmaOutputStream::VdmaOutputStream(VdmaDevice &device, uint8_t channel_index, co
         return;
     }
 
-    status = config_stream();
-    if (HAILO_SUCCESS != status) {
-        return;
-    }
-
     status = HAILO_SUCCESS;
 }
 
 VdmaOutputStream::VdmaOutputStream(VdmaOutputStream &&other) :
     OutputStreamBase(std::move(other)),
     m_device(std::move(other.m_device)),
-    m_channel_index(std::move(other.m_channel_index)),
     m_channel(std::move(other.m_channel)),
     is_stream_activated(std::exchange(other.is_stream_activated, false)),
     m_transfer_timeout(std::move(other.m_transfer_timeout)),
-    m_latency_meter(std::move(other.m_latency_meter)),
-    m_batch_size(other.m_batch_size),
+    m_max_batch_size(other.m_max_batch_size),
+    m_dynamic_batch_size(other.m_dynamic_batch_size),
     m_transfer_size(other.m_transfer_size)
 {}
 
@@ -252,9 +254,22 @@ hailo_status VdmaOutputStream::clear_abort()
     return m_channel->clear_abort();
 }
 
-hailo_status VdmaOutputStream::activate_stream()
+uint16_t VdmaOutputStream::get_dynamic_batch_size() const
+{
+    return m_dynamic_batch_size;
+}
+
+const char* VdmaOutputStream::get_dev_id() const
 {
-    auto status = m_channel->start_allocated_channel(m_transfer_size);
+    return m_device->get_dev_id();
+}
+
+hailo_status VdmaOutputStream::activate_stream(uint16_t dynamic_batch_size)
+{
+    auto status = set_dynamic_batch_size(dynamic_batch_size);
+    CHECK_SUCCESS(status);
+    
+    status = m_channel->start_allocated_channel(m_transfer_size);
     CHECK_SUCCESS(status);
 
     this->is_stream_activated = true;
@@ -291,36 +306,6 @@ Expected<size_t> VdmaOutputStream::sync_read_raw_buffer(MemoryView &buffer)
     return buffer.size();
 }
 
-hailo_status VdmaOutputStream::config_stream()
-{
-    const uint32_t min_active_trans = MIN_ACTIVE_TRANSFERS_SCALE * m_batch_size;
-    const uint32_t max_active_trans = MAX_ACTIVE_TRANSFERS_SCALE * m_batch_size;
-    assert(min_active_trans <= max_active_trans);
-
-    CHECK(IS_FIT_IN_UINT16(min_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
-
-    CHECK(IS_FIT_IN_UINT16(max_active_trans), HAILO_INVALID_ARGUMENT, 
-        "calculated min_active_trans for vdma descriptor list is out of UINT16 range");
-
-    auto desc_sizes_pair = VdmaDescriptorList::get_desc_buffer_sizes_for_single_transfer(m_device->get_driver(),
-        static_cast<uint16_t>(min_active_trans), static_cast<uint16_t>(max_active_trans), m_transfer_size);
-    CHECK_EXPECTED_AS_STATUS(desc_sizes_pair);
-    
-    const auto page_size = desc_sizes_pair->first;
-    auto channel = VdmaChannel::create(m_channel_index, VdmaChannel::Direction::D2H, m_device->get_driver(), page_size,
-        m_stream_info.index, m_latency_meter, m_batch_size);
-
-    m_channel = make_unique_nothrow<VdmaChannel>(channel.release());
-    CHECK(nullptr != m_channel, HAILO_OUT_OF_HOST_MEMORY);
-
-    const auto descs_count = desc_sizes_pair->second;
-    const auto status = m_channel->allocate_resources(descs_count);
-    CHECK_SUCCESS(status);
-
-    return HAILO_SUCCESS;
-}
-
 hailo_status VdmaOutputStream::read_all(MemoryView &buffer)
 {
     CHECK((buffer.size() % HailoRTCommon::HW_DATA_ALIGNMENT) == 0, HAILO_INVALID_ARGUMENT, 
@@ -336,4 +321,24 @@ uint32_t VdmaOutputStream::get_transfer_size(const hailo_stream_info_t &stream_i
         stream_info.nms_info.bbox_size : stream_info.hw_frame_size;
 }
 
+hailo_status VdmaOutputStream::set_dynamic_batch_size(uint16_t dynamic_batch_size)
+{
+    CHECK(dynamic_batch_size <= m_max_batch_size, HAILO_INVALID_ARGUMENT,
+        "Dynamic batch size ({}) must be <= than the configured batch size ({})",
+        dynamic_batch_size, m_max_batch_size);
+    
+    if (CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == dynamic_batch_size) {
+        LOGGER__TRACE("Received CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE == dynamic_batch_size; "
+                      "Leaving previously set value of {}", m_dynamic_batch_size);
+    } else {
+        LOGGER__TRACE("Setting stream's dynamic_batch_size to {}", dynamic_batch_size);
+        m_dynamic_batch_size = dynamic_batch_size;
+
+        const auto status = m_channel->set_transfers_per_axi_intr(m_dynamic_batch_size);
+        CHECK_SUCCESS(status);
+    }
+
+    return HAILO_SUCCESS;
+}
+
 } /* namespace hailort */
index 4f07b2260cb672e12fdea26503d84967d64000f4..8eb9faffb62c9cf1321d795550e1a19836bd3460 100644 (file)
@@ -30,39 +30,32 @@ public:
     virtual hailo_status abort() override;
     virtual hailo_status clear_abort() override;
     virtual hailo_status flush() override;
-
-    uint16_t get_batch_size() const
-    {
-        return m_batch_size;
-    }
-
-    const char* get_dev_id() const
-    {
-        return m_device->get_dev_id();
-    }
+    hailo_status write_buffer_only(const MemoryView &buffer);
+    Expected<PendingBufferState> send_pending_buffer();
+    uint16_t get_dynamic_batch_size() const;
+    const char* get_dev_id() const;
 
 protected:
-    VdmaInputStream(VdmaDevice &device, uint8_t channel_index, const LayerInfo &edge_layer,
-                    EventPtr network_group_activated_event, uint16_t batch_size, LatencyMeterPtr latency_meter,
+    VdmaInputStream(VdmaDevice &device, std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer,
+                    EventPtr network_group_activated_event, uint16_t batch_size,
                     std::chrono::milliseconds transfer_timeout, hailo_stream_interface_t stream_interface,
                     hailo_status &status);
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual Expected<size_t> sync_write_raw_buffer(const MemoryView &buffer) override;
     virtual hailo_status sync_write_all_raw_buffer_no_transform_impl(void *buffer, size_t offset, size_t size) override;
 
     VdmaDevice *m_device;
-    const uint8_t m_channel_index;
-    std::unique_ptr<VdmaChannel> m_channel;
+    std::shared_ptr<VdmaChannel> m_channel;
 
 private:
-    hailo_status config_stream();
+    hailo_status set_dynamic_batch_size(uint16_t dynamic_batch_size);
 
     bool is_stream_activated;
     std::chrono::milliseconds m_channel_timeout;
-    LatencyMeterPtr m_latency_meter;
-    uint16_t m_batch_size;
+    const uint16_t m_max_batch_size;
+    uint16_t m_dynamic_batch_size;
 };
 
 class VdmaOutputStream : public OutputStreamBase {
@@ -74,39 +67,30 @@ public:
     virtual hailo_status set_timeout(std::chrono::milliseconds timeout) override;
     virtual hailo_status abort() override;
     virtual hailo_status clear_abort() override;
-
-    uint16_t get_batch_size() const
-    {
-        return m_batch_size;
-    }
-
-    const char* get_dev_id() const
-    {
-        return m_device->get_dev_id();
-    }
+    uint16_t get_dynamic_batch_size() const;
+    const char* get_dev_id() const;
 
 protected:
-    VdmaOutputStream(VdmaDevice &device, uint8_t channel_index, const LayerInfo &edge_layer,
-                     EventPtr network_group_activated_event, uint16_t batch_size, LatencyMeterPtr latency_meter,
+    VdmaOutputStream(VdmaDevice &device, std::shared_ptr<VdmaChannel> channel, const LayerInfo &edge_layer,
+                     EventPtr network_group_activated_event, uint16_t batch_size,
                      std::chrono::milliseconds transfer_timeout, hailo_status &status);
 
-    virtual hailo_status activate_stream() override;
+    virtual hailo_status activate_stream(uint16_t dynamic_batch_size) override;
     virtual hailo_status deactivate_stream() override;
     virtual Expected<size_t> sync_read_raw_buffer(MemoryView &buffer);
 
     VdmaDevice *m_device;
-    const uint8_t m_channel_index;
-    std::unique_ptr<VdmaChannel> m_channel;
+    std::shared_ptr<VdmaChannel> m_channel;
 
 private:
-    hailo_status config_stream();
     hailo_status read_all(MemoryView &buffer) override;
     static uint32_t get_transfer_size(const hailo_stream_info_t &stream_info);
+    hailo_status set_dynamic_batch_size(uint16_t dynamic_batch_size);
 
     bool is_stream_activated;
     std::chrono::milliseconds m_transfer_timeout;
-    LatencyMeterPtr m_latency_meter;
-    uint16_t m_batch_size;
+    const uint16_t m_max_batch_size;
+    uint16_t m_dynamic_batch_size;
     const uint32_t m_transfer_size;
 };
 
index 080c20c6634470d2031d2a237820432b75df7ae4..ffd14e5c3f1a0943c14ae058c8948cdac0fb8e2f 100644 (file)
@@ -348,8 +348,9 @@ Expected<std::vector<PipelineBuffer>> TransformDemuxElement::action(PipelineBuff
 
 BaseVStream::BaseVStream(const hailo_vstream_info_t &vstream_info, const hailo_vstream_params_t &vstream_params,
                          std::shared_ptr<PipelineElement> pipeline_entry, std::vector<std::shared_ptr<PipelineElement>> &&pipeline,
-                         std::shared_ptr<std::atomic<hailo_status>> &&pipeline_status, EventPtr shutdown_event,
-                         AccumulatorPtr pipeline_latency_accumulator, EventPtr &&network_group_activated_event, hailo_status &output_status) :
+                         std::shared_ptr<std::atomic<hailo_status>> &&pipeline_status,
+                         EventPtr shutdown_event, AccumulatorPtr pipeline_latency_accumulator, EventPtr &&network_group_activated_event,
+                         hailo_status &output_status) :
     m_vstream_info(vstream_info),
     m_vstream_params(vstream_params),
     m_measure_pipeline_latency((vstream_params.vstream_stats_flags & HAILO_VSTREAM_STATS_MEASURE_LATENCY) != 0),
@@ -443,13 +444,13 @@ hailo_status BaseVStream::stop_vstream()
 
 hailo_status BaseVStream::stop_and_clear()
 {
-     auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
-     CHECK(HAILO_TIMEOUT == status, HAILO_INVALID_OPERATION,
+    auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
+    CHECK(HAILO_TIMEOUT == status, HAILO_INVALID_OPERATION,
         "Trying to clear {} vstream before its network group is deactivated", name());
-     status = stop_vstream();
-     CHECK_SUCCESS(status);
-    
+
+    status = stop_vstream();
+    CHECK_SUCCESS(status);
+
     status = m_entry_element->clear();
     CHECK_SUCCESS(status, "Failed clearing vstream {}", name());
     
@@ -584,8 +585,8 @@ InputVStream::InputVStream(const hailo_vstream_info_t &vstream_info, const hailo
                            std::shared_ptr<std::atomic<hailo_status>> &&pipeline_status, EventPtr shutdown_event,
                            AccumulatorPtr pipeline_latency_accumulator,
                            EventPtr network_group_activated_event, hailo_status &output_status) :
-    BaseVStream(vstream_info, vstream_params, pipeline_entry, std::move(pipeline), std::move(pipeline_status), shutdown_event,
-                pipeline_latency_accumulator, std::move(network_group_activated_event), output_status)
+    BaseVStream(vstream_info, vstream_params, pipeline_entry, std::move(pipeline), std::move(pipeline_status),
+                shutdown_event, pipeline_latency_accumulator, std::move(network_group_activated_event), output_status)
 {
     if (HAILO_SUCCESS != output_status) {
         return;
@@ -595,11 +596,14 @@ InputVStream::InputVStream(const hailo_vstream_info_t &vstream_info, const hailo
 
 hailo_status InputVStream::write(const MemoryView &buffer)
 {
-    CHECK(m_is_activated, HAILO_VSTREAM_PIPELINE_NOT_ACTIVATED, "Failed to write buffer! Virtual stream {} is not activated!", name());
-    auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
-    CHECK(HAILO_TIMEOUT != status, HAILO_NETWORK_GROUP_NOT_ACTIVATED,
-        "Trying to write to vstream {} before its network group is activated", name());
-    status = m_entry_element->run_push(PipelineBuffer(buffer, m_measure_pipeline_latency));
+    if (nullptr != m_network_group_activated_event) {
+        CHECK(m_is_activated, HAILO_VSTREAM_PIPELINE_NOT_ACTIVATED, "Failed to write buffer! Virtual stream {} is not activated!", name());
+        auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
+        CHECK(HAILO_TIMEOUT != status, HAILO_NETWORK_GROUP_NOT_ACTIVATED,
+            "Trying to write to vstream {} before its network group is activated", name());
+    }
+
+    auto status = m_entry_element->run_push(PipelineBuffer(buffer, m_measure_pipeline_latency));
     if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
         LOGGER__INFO("Sending to VStream was shutdown!");
         status = m_pipeline_status->load();
@@ -665,7 +669,6 @@ Expected<OutputVStream> OutputVStream::create(const hailo_vstream_info_t &vstrea
     std::shared_ptr<PipelineElement> pipeline_entry, std::vector<std::shared_ptr<PipelineElement>> &&pipeline,
     std::shared_ptr<std::atomic<hailo_status>> &&pipeline_status, EventPtr shutdown_event,
     EventPtr network_group_activated_event, AccumulatorPtr pipeline_latency_accumulator)
-
 {
     hailo_status status = HAILO_UNINITIALIZED;
 
@@ -693,8 +696,8 @@ OutputVStream::OutputVStream(const hailo_vstream_info_t &vstream_info, const hai
                              std::shared_ptr<std::atomic<hailo_status>> &&pipeline_status, EventPtr shutdown_event,
                              AccumulatorPtr pipeline_latency_accumulator,
                              EventPtr network_group_activated_event, hailo_status &output_status) :
-    BaseVStream(vstream_info, vstream_params, pipeline_entry, std::move(pipeline), std::move(pipeline_status), shutdown_event,
-                pipeline_latency_accumulator, std::move(network_group_activated_event), output_status)
+    BaseVStream(vstream_info, vstream_params, pipeline_entry, std::move(pipeline), std::move(pipeline_status),
+                shutdown_event, pipeline_latency_accumulator, std::move(network_group_activated_event), output_status)
 {
     if (HAILO_SUCCESS != output_status) {
         return;
@@ -705,17 +708,19 @@ OutputVStream::OutputVStream(const hailo_vstream_info_t &vstream_info, const hai
 
 hailo_status OutputVStream::read(MemoryView buffer)
 {
-    CHECK(m_is_activated, HAILO_VSTREAM_PIPELINE_NOT_ACTIVATED, "read() failed! Virtual stream {} is not activated!", name());
-    auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
-    if (HAILO_TIMEOUT == status) {
-        LOGGER__INFO("Trying to read from vstream {} before its network_group is activated", name());
-        return HAILO_NETWORK_GROUP_NOT_ACTIVATED;
+    if (nullptr != m_network_group_activated_event) {
+        CHECK(m_is_activated, HAILO_VSTREAM_PIPELINE_NOT_ACTIVATED, "read() failed! Virtual stream {} is not activated!", name());
+        auto status = m_network_group_activated_event->wait(std::chrono::milliseconds(0));
+        if (HAILO_TIMEOUT == status) {
+            LOGGER__INFO("Trying to read from vstream {} before its network_group is activated", name());
+            return HAILO_NETWORK_GROUP_NOT_ACTIVATED;
+        }
+        CHECK_SUCCESS(status);
     }
-    CHECK_SUCCESS(status);
 
     assert(1 == m_entry_element->sources().size());
     auto recv_buffer = m_entry_element->sources()[0].run_pull(PipelineBuffer(buffer, m_measure_pipeline_latency));
-    status = recv_buffer.status();
+    auto status = recv_buffer.status();
     if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
         LOGGER__INFO("Receiving to VStream was shutdown!");
         status = m_pipeline_status->load();
@@ -850,18 +855,25 @@ Expected<PipelineBuffer> HwReadElement::run_pull(PipelineBuffer &&optional, cons
     CHECK_EXPECTED(buffer);
 
     while (true) {
-        auto status = m_activation_wait_or_shutdown.wait(m_timeout);
-        if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
-            return make_unexpected(HAILO_SHUTDOWN_EVENT_SIGNALED);
-        }
-        if (HAILO_TIMEOUT == status) {
-            return make_unexpected(HAILO_NETWORK_GROUP_NOT_ACTIVATED);
+        if (!m_stream.is_scheduled()) {
+            auto status = m_activation_wait_or_shutdown.wait(m_timeout);
+            if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
+                return make_unexpected(HAILO_SHUTDOWN_EVENT_SIGNALED);
+            }
+            if (HAILO_TIMEOUT == status) {
+                return make_unexpected(HAILO_NETWORK_GROUP_NOT_ACTIVATED);
+            }
+            CHECK_SUCCESS_AS_EXPECTED(status);
+        } else {
+            auto status = m_activation_wait_or_shutdown.wait(std::chrono::milliseconds(0));
+            if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
+                return make_unexpected(HAILO_SHUTDOWN_EVENT_SIGNALED);
+            }
         }
-        CHECK_SUCCESS_AS_EXPECTED(status);
 
         MemoryView buffer_view(buffer.value().as_view());
         m_duration_collector.start_measurement();
-        status = m_stream.read(buffer_view);
+        auto status = m_stream.read(buffer_view);
         m_duration_collector.complete_measurement();
         if (HAILO_INVALID_FRAME == status) {
             m_stream.increase_invalid_frames_count(1);
@@ -992,7 +1004,7 @@ hailo_status HwWriteElement::clear()
 
 hailo_status HwWriteElement::flush()
 {
-    hailo_status status = m_got_flush_event->wait(std::chrono::milliseconds(HAILO_DEFAULT_VSTREAM_TIMEOUT_MS));
+    hailo_status status = m_got_flush_event->wait(m_stream.get_timeout());
     CHECK_SUCCESS(status);
 
     status = m_got_flush_event->reset();
@@ -1195,7 +1207,10 @@ Expected<std::vector<InputVStream>> VStreamsBuilderUtils::create_inputs(InputStr
     std::vector<std::shared_ptr<PipelineElement>> elements;
     std::vector<InputVStream> vstreams;
 
-    auto network_group_activated_event = input_stream.get_network_group_activated_event();
+    EventPtr network_group_activated_event = nullptr;
+    if (!input_stream.is_scheduled()) {
+        network_group_activated_event = input_stream.get_network_group_activated_event();
+    }
 
     auto shutdown_event = Event::create_shared(Event::State::not_signalled);
     CHECK_AS_EXPECTED(nullptr != shutdown_event, HAILO_OUT_OF_HOST_MEMORY);
@@ -1261,7 +1276,10 @@ Expected<std::vector<OutputVStream>> VStreamsBuilderUtils::create_outputs(Output
     std::vector<std::shared_ptr<PipelineElement>> elements;
     std::vector<OutputVStream> vstreams;
 
-    auto network_group_activated_event = output_stream.get_network_group_activated_event();
+    EventPtr network_group_activated_event = nullptr;
+    if (!output_stream.is_scheduled()) {
+        network_group_activated_event = output_stream.get_network_group_activated_event();
+    }
 
     auto shutdown_event = Event::create_shared(Event::State::not_signalled);
     CHECK_AS_EXPECTED(nullptr != shutdown_event, HAILO_OUT_OF_HOST_MEMORY);
@@ -1336,8 +1354,8 @@ Expected<std::vector<OutputVStream>> VStreamsBuilderUtils::create_outputs(Output
 
             output_stream.set_timeout(std::chrono::milliseconds(HAILO_INFINITE));
             hw_read_queue_elem->get()->set_timeout(std::chrono::milliseconds(HAILO_INFINITE));
-            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, post_infer_queue_elem.release(),
-                std::move(elements), std::move(pipeline_status), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
+            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, post_infer_queue_elem.release(), std::move(elements),
+                std::move(pipeline_status), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
             CHECK_EXPECTED(vstream);
             vstreams.emplace_back(vstream.release());
         } else {
@@ -1421,7 +1439,10 @@ hailo_status VStreamsBuilderUtils::add_demux(OutputStream &output_stream, NameTo
     base_elements.push_back(demux_elem.value());
     CHECK_SUCCESS(PipelinePad::link_pads(hw_read_elem, demux_elem.value()));
 
-    auto network_group_activated_event = output_stream.get_network_group_activated_event();
+    EventPtr network_group_activated_event = nullptr;
+    if (!output_stream.is_scheduled()) {
+        network_group_activated_event = output_stream.get_network_group_activated_event();
+    }
 
     uint32_t i = 0;
     for (auto &edge_info : demuxer_ptr->get_edges_stream_info()) {
@@ -1471,9 +1492,8 @@ hailo_status VStreamsBuilderUtils::add_demux(OutputStream &output_stream, NameTo
             current_vstream_elements.push_back(post_infer_queue_elem.value());
             CHECK_SUCCESS(PipelinePad::link_pads(post_infer_elem.value(), post_infer_queue_elem.value()));
 
-            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, post_infer_queue_elem.release(),
-                std::move(current_vstream_elements), std::move(pipeline_status_copy), shutdown_event, network_group_activated_event,
-                pipeline_latency_accumulator.release());
+            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, post_infer_queue_elem.release(), std::move(current_vstream_elements),
+                std::move(pipeline_status_copy), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
             CHECK_EXPECTED_AS_STATUS(vstream);
             vstreams.emplace_back(vstream.release());
         } else {
@@ -1485,9 +1505,8 @@ hailo_status VStreamsBuilderUtils::add_demux(OutputStream &output_stream, NameTo
             current_vstream_elements.push_back(user_copy_elem.value());
             CHECK_SUCCESS(PipelinePad::link_pads(demux_queue_elem.value(), user_copy_elem.value()));
 
-            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, user_copy_elem.release(),
-                std::move(current_vstream_elements), std::move(pipeline_status_copy), shutdown_event, network_group_activated_event,
-                pipeline_latency_accumulator.release());
+            auto vstream = OutputVStream::create(vstream_info->second, vstream_params, user_copy_elem.release(), std::move(current_vstream_elements),
+                std::move(pipeline_status_copy), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
             CHECK_EXPECTED_AS_STATUS(vstream);
             vstreams.emplace_back(vstream.release());
         }
@@ -1550,6 +1569,11 @@ hailo_status VStreamsBuilderUtils::add_nms_fuse(OutputStreamRefVector &output_st
 
     auto should_transform = OutputTransformContext::is_transformation_required({}, src_stream_format, {},
         vstreams_params.user_buffer_format, vstream_info->second.quant_info);
+    
+    EventPtr network_group_activated_event = nullptr;
+    if (!output_streams[0].get().is_scheduled()) {
+        network_group_activated_event = output_streams[0].get().get_network_group_activated_event();
+    }
 
     if (should_transform) {
         auto nms_queue_elem = PullQueueElement::create(
@@ -1574,15 +1598,13 @@ hailo_status VStreamsBuilderUtils::add_nms_fuse(OutputStreamRefVector &output_st
         elements.push_back(post_infer_queue_elem.value());
         CHECK_SUCCESS(PipelinePad::link_pads(post_infer_elem.value(), post_infer_queue_elem.value()));
 
-        auto vstream = OutputVStream::create(vstream_info->second, vstreams_params, post_infer_queue_elem.release(),
-                std::move(elements), std::move(pipeline_status), shutdown_event, output_streams[0].get().get_network_group_activated_event(),
-                pipeline_latency_accumulator.release());
+        auto vstream = OutputVStream::create(vstream_info->second, vstreams_params, post_infer_queue_elem.release(), std::move(elements),
+            std::move(pipeline_status), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
         CHECK_EXPECTED_AS_STATUS(vstream);
         vstreams.emplace_back(vstream.release());
     } else {
-        auto vstream = OutputVStream::create(vstream_info->second, vstreams_params, nms_elem.release(),
-                std::move(elements), std::move(pipeline_status), shutdown_event, output_streams[0].get().get_network_group_activated_event(),
-                pipeline_latency_accumulator.release());
+        auto vstream = OutputVStream::create(vstream_info->second, vstreams_params, nms_elem.release(), std::move(elements),
+            std::move(pipeline_status), shutdown_event, network_group_activated_event, pipeline_latency_accumulator.release());
         CHECK_EXPECTED_AS_STATUS(vstream);
         vstreams.emplace_back(vstream.release());
     }
index 6eb22763c95aa5dc23ab569e5bc874986fa0c64b..47a43c53d189a05bd2a7cc240777a8f0c46b0a24 100644 (file)
@@ -1,14 +1,18 @@
 cmake_minimum_required(VERSION 3.0.0)
 project(hailort_prebuild)
 
-set(HAILO_PRE_BUILD_EXTERNAL_DIR ${CMAKE_CURRENT_LIST_DIR}/external)
-include(../libhailort/cmake/execute_cmake.cmake)
-message("Downloading dependencies to ${HAILO_EXTERNAL_DIR} ...")
-execute_cmake(
-    SOURCE_DIR "${HAILO_PRE_BUILD_EXTERNAL_DIR}"
-    BUILD_DIR "${HAILO_PRE_BUILD_EXTERNAL_DIR}/build"
-    CONFIGURE_ARGS "-DHAILO_EXTERNAL_DIR=${HAILO_EXTERNAL_DIR}"
-)
-message("Finished downloading dependencies")
+if(NOT HAILO_OFFLINE_COMPILATION)
+    set(HAILO_PRE_BUILD_EXTERNAL_DIR ${CMAKE_CURRENT_LIST_DIR}/external)
+    include(../libhailort/cmake/execute_cmake.cmake)
+    message("Downloading dependencies to ${HAILO_EXTERNAL_DIR} ...")
+    execute_cmake(
+        SOURCE_DIR "${HAILO_PRE_BUILD_EXTERNAL_DIR}"
+        BUILD_DIR "${HAILO_PRE_BUILD_EXTERNAL_DIR}/build"
+        CONFIGURE_ARGS "-DHAILO_EXTERNAL_DIR=${HAILO_EXTERNAL_DIR}"
+    )
+    message("Finished downloading dependencies")
+else()
+    message("Offline compilation, skipped dependencies download")
+endif()
 
 add_subdirectory(tools)
\ No newline at end of file
index 11c34b0796723db1b8a0033c2718045aedceb9a1..c807e11bdf7e079fad867713a226ced3877a08e9 100644 (file)
@@ -16,7 +16,7 @@ function(git_clone proj repo tag)
     )
 endfunction()
 
-git_clone(pybind11          https://github.com/pybind/pybind11.git                                  502ffe50a9f22c04637bbc8ec0019488458ba948)
+git_clone(pybind11          https://github.com/pybind/pybind11.git                                  8de7772cc72daca8e947b79b83fea46214931604)
 git_clone(Catch2            https://github.com/catchorg/Catch2.git                                  c4e3767e265808590986d5db6ca1b5532a7f3d13)
 git_clone(CLI11             https://github.com/CLIUtils/CLI11.git                                   706b14fb14444e68ace232eb9a0ef106bf99343b)
 git_clone(spdlog            https://github.com/gabime/spdlog.git                                    e2789531912a5c6ab28a90387f97c52963eec08a)
@@ -24,4 +24,6 @@ git_clone(protobuf          https://github.com/protocolbuffers/protobuf.git
 git_clone(readerwriterqueue https://github.com/cameron314/readerwriterqueue.git                     435e36540e306cac40fcfeab8cc0a22d48464509)
 git_clone(json              https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git  391786c6c3abdd3eeb993a3154f1f2a4cfe137a0)
 git_clone(DotWriter         https://github.com/hailo-ai/DotWriter.git                               e5fa8f281adca10dd342b1d32e981499b8681daf)
-git_clone(benchmark         https://github.com/google/benchmark.git                                 f91b6b42b1b9854772a90ae9501464a161707d1e)
\ No newline at end of file
+git_clone(benchmark         https://github.com/google/benchmark.git                                 f91b6b42b1b9854772a90ae9501464a161707d1e)
+git_clone(pevents           https://github.com/neosmart/pevents.git                                 1209b1fd1bd2e75daab4380cf43d280b90b45366)
+git_clone(microprofile      https://github.com/jonasmr/microprofile                                 03c34f96840defe0f4c196309628815d02b98059)
index aea8c589546787bc9bc3022d830732350d5b0ca9..98c8fb61b1e3d733185b49a4b4cc5d4f6ca5bf6e 100644 (file)
@@ -1,7 +1,7 @@
 :: cmd
 @ECHO OFF
 set BASE_URI=https://hailo-hailort.s3.eu-west-2.amazonaws.com
-set HRT_VERSION=4.6.0
+set HRT_VERSION=4.8.0
 set REMOTE_HEF_DIR=Hailo8/%HRT_VERSION%/HEFS
 set LOCAL_EXAMPLES_HEF_DIR=..\libhailort\examples\hefs
 set LOCAL_TUTORIALS_HEF_DIR=..\libhailort\bindings\python\platform\tutorials\hefs
index 94312188b9c3ddd5ebe66599b151b5cede6a275c..28d847912393dd756eb4c84aebe8e624ee0cac18 100755 (executable)
@@ -2,7 +2,7 @@
 set -e
 
 readonly BASE_URI="https://hailo-hailort.s3.eu-west-2.amazonaws.com"
-readonly HRT_VERSION=4.6.0
+readonly HRT_VERSION=4.8.0
 readonly REMOTE_HEF_DIR="Hailo8/${HRT_VERSION}/HEFS"
 readonly LOCAL_EXAMPLES_HEF_DIR="../libhailort/examples/hefs"
 readonly LOCAL_TUTORIALS_HEF_DIR="../libhailort/bindings/python/platform/tutorials/hefs/"