├── .github └── workflows │ └── workflow.yaml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── sources ├── ade │ ├── CMakeLists.txt │ ├── cmake │ │ └── adeConfig.cmake.in │ ├── doc │ │ └── Doxyfile.in │ ├── include │ │ └── ade │ │ │ ├── communication │ │ │ ├── callback_connector.hpp │ │ │ ├── comm_buffer.hpp │ │ │ └── comm_interface.hpp │ │ │ ├── edge.hpp │ │ │ ├── execution_engine │ │ │ ├── backend.hpp │ │ │ ├── executable.hpp │ │ │ └── execution_engine.hpp │ │ │ ├── graph.hpp │ │ │ ├── graph_listener.hpp │ │ │ ├── handle.hpp │ │ │ ├── helpers │ │ │ ├── search.hpp │ │ │ └── subgraphs.hpp │ │ │ ├── memory │ │ │ ├── alloc.hpp │ │ │ ├── memory_access_listener.hpp │ │ │ ├── memory_accessor.hpp │ │ │ ├── memory_descriptor.hpp │ │ │ ├── memory_descriptor_ref.hpp │ │ │ ├── memory_descriptor_view.hpp │ │ │ └── memory_types.hpp │ │ │ ├── metatypes │ │ │ └── metatypes.hpp │ │ │ ├── node.hpp │ │ │ ├── passes │ │ │ ├── check_cycles.hpp │ │ │ ├── communications.hpp │ │ │ ├── pass_base.hpp │ │ │ └── topological_sort.hpp │ │ │ ├── passmanager.hpp │ │ │ ├── typed_graph.hpp │ │ │ ├── typed_metadata.hpp │ │ │ └── util │ │ │ ├── algorithm.hpp │ │ │ ├── assert.hpp │ │ │ ├── chain_range.hpp │ │ │ ├── checked_cast.hpp │ │ │ ├── container_helper.hpp │ │ │ ├── filter_range.hpp │ │ │ ├── func_ref.hpp │ │ │ ├── hash.hpp │ │ │ ├── intrusive_list.hpp │ │ │ ├── iota_range.hpp │ │ │ ├── map_range.hpp │ │ │ ├── math.hpp │ │ │ ├── md_cast.hpp │ │ │ ├── md_io.hpp │ │ │ ├── md_size.hpp │ │ │ ├── md_span.hpp │ │ │ ├── md_view.hpp │ │ │ ├── memory_range.hpp │ │ │ ├── range.hpp │ │ │ ├── range_iterator.hpp │ │ │ ├── tuple.hpp │ │ │ ├── type_traits.hpp │ │ │ └── zip_range.hpp │ ├── manifest.cmake │ └── source │ │ ├── alloc.cpp │ │ ├── assert.cpp │ │ ├── check_cycles.cpp │ │ ├── edge.cpp │ │ ├── execution_engine.cpp │ │ ├── graph.cpp │ │ ├── memory_accessor.cpp │ │ ├── memory_descriptor.cpp │ │ ├── memory_descriptor_ref.cpp │ │ ├── memory_descriptor_view.cpp │ │ ├── metadata.cpp │ │ ├── metatypes.cpp │ │ ├── node.cpp │ │ ├── passes │ │ └── communications.cpp │ │ ├── search.cpp │ │ ├── subgraphs.cpp │ │ └── topological_sort.cpp └── tests │ ├── CMakeLists.txt │ ├── ade │ ├── CMakeLists.txt │ ├── check_cycles_pass.cpp │ ├── comm_buffer.cpp │ ├── communications.cpp │ ├── communications_pass.cpp │ ├── execution_engine.cpp │ ├── execution_engine_backend.cpp │ ├── graph.cpp │ ├── node.cpp │ ├── passmanager.cpp │ ├── search.cpp │ ├── subgraphs.cpp │ ├── topological_sort_pass.cpp │ └── typed_graph.cpp │ └── common │ ├── CMakeLists.txt │ ├── algo_tests.cpp │ ├── chain_range_tests.cpp │ ├── checkedcast_test.cpp │ ├── filter_range_tests.cpp │ ├── func_ref_tests.cpp │ ├── intrusive_list_tests.cpp │ ├── map_range_tests.cpp │ ├── md_view_tests.cpp │ ├── range_tests.cpp │ ├── tuple_tests.cpp │ └── zip_range_tests.cpp └── tutorial ├── 01_hello.cpp ├── 02_add_link_remove.cpp ├── 03_meta.cpp ├── 04_passes.cpp ├── 05_backend.cpp ├── 06_hierarchy.cpp ├── CMakeLists.txt └── README.md /.github/workflows/workflow.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | env: 6 | repo_name: ${{ github.repository }} 7 | sha_git: ${{ github.sha }} 8 | 9 | jobs: 10 | Basic_Workflow: 11 | strategy: 12 | matrix: 13 | version: [11, 14, 17, 20, 23] 14 | os: [ 15 | ubuntu-22.04, 16 | ubuntu-24.04, 17 | windows-2022, 18 | ] 19 | 20 | runs-on: ${{ matrix.os }} 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Build Stage 25 | shell: bash 26 | run: | 27 | mkdir build && cd build 28 | 29 | if [ "$RUNNER_OS" == "Windows" ]; then 30 | cmake -DENABLE_ADE_TESTING=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=${{ matrix.version }} .. 31 | cmake --build . --target GTest --config Release 32 | cmake --build . --config Release 33 | 34 | elif [ "$RUNNER_OS" == "Linux" ]; then 35 | cmake -DENABLE_ADE_TESTING=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=${{ matrix.version }} .. 36 | make -j2 37 | 38 | else 39 | echo "$RUNNER_OS not supported" 40 | exit 1 41 | fi 42 | 43 | - name: Test Stage 44 | shell: bash 45 | run: cd build && ctest -C Release 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.user 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: cpp 3 | 4 | compiler: 5 | - gcc 6 | 7 | addons: 8 | apt: 9 | sources: 10 | - ubuntu-toolchain-r-test 11 | packages: 12 | - gcc-5 13 | - g++-5 14 | - ninja-build 15 | 16 | install: 17 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then export CC="gcc-5"; export CXX="g++-5"; fi 18 | - cmake --version 19 | - ninja --version 20 | 21 | script: 22 | - mkdir build 23 | - cd build 24 | # TODO: fix ninja build 25 | # - cmake -G Ninja -DENABLE_ADE_TESTING=ON -DBUILD_ADE_TUTORIAL=ON -DCMAKE_BUILD_TYPE=Release .. 26 | # - ninja 27 | - cmake -DENABLE_ADE_TESTING=ON -DBUILD_ADE_TUTORIAL=ON -DCMAKE_BUILD_TYPE=Release .. 28 | - make 29 | - ctest 30 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.5) 8 | 9 | project(ade) 10 | 11 | if(POLICY CMP0063) 12 | cmake_policy(SET CMP0063 NEW) 13 | endif() 14 | 15 | option(ENABLE_ADE_TESTING "Build tests, require google test" OFF) 16 | option(BUILD_ADE_TUTORIAL "Build tutorial samples" OFF) 17 | option(FORCE_ADE_ASSERTS "Always enable ADE_ASSERT" OFF) 18 | option(BUILD_ADE_DOCUMENTATION "Build doxygen documentation" OFF) 19 | option(BUILD_WITH_STATIC_CRT "Build with static multi-threaded C Runtime (MS Windows/Visual Studio only)" OFF) 20 | 21 | if(NOT DEFINED CMAKE_CXX_STANDARD) 22 | set(CMAKE_CXX_STANDARD 11) 23 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 24 | endif() 25 | 26 | # TODO: this is horrible hack, we must follow cmake 27 | # build/install policy 28 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 29 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 30 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 31 | 32 | function(add_security_flags target) 33 | if(UNIX) 34 | target_compile_definitions( ${target} PRIVATE _FORTIFY_SOURCE=2 ) 35 | if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") 36 | if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) 37 | target_compile_options( ${target} PRIVATE -fstack-protector) 38 | else() 39 | target_compile_options( ${target} PRIVATE -fstack-protector-strong) 40 | endif() 41 | elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel") 42 | target_compile_options( ${target} PRIVATE -fstack-protector-strong) 43 | endif() 44 | elseif(WIN32) 45 | if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") 46 | target_compile_options( ${target} PRIVATE /GS /DynamicBase) 47 | if(BUILD_WITH_STATIC_CRT) 48 | target_compile_options( ${target} PRIVATE "/MT") 49 | endif() 50 | if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") 51 | # These options for 32 bit builds only 52 | target_compile_options( ${target} PRIVATE /SAFESEH /NXCOMPAT ) 53 | endif() 54 | elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") 55 | target_compile_definitions( ${target} PRIVATE _FORTIFY_SOURCE=2 ) 56 | target_compile_options( ${target} PRIVATE -fstack-protector-strong ) 57 | endif() 58 | endif() 59 | endfunction() 60 | 61 | if (MSVC) 62 | add_definitions(-D_SCL_SECURE_NO_WARNINGS) 63 | endif(MSVC) 64 | 65 | add_subdirectory(sources/ade/) 66 | 67 | if(ENABLE_ADE_TESTING) 68 | enable_testing() 69 | add_subdirectory(sources/tests) 70 | endif() 71 | 72 | if(BUILD_ADE_TUTORIAL) 73 | add_subdirectory(tutorial) 74 | endif() 75 | 76 | # cpack 77 | 78 | if(CMAKE_BUILD_TYPE STREQUAL "Release") 79 | set(CPACK_STRIP_FILES ON) 80 | endif() 81 | set(CPACK_PACKAGE_VERSION ${THE_PROJECT_VERSION}) 82 | set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) 83 | set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) 84 | set(CPACK_GENERATOR "ZIP") 85 | 86 | include(CPack) 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ADE Framework 2 | 3 | [![Build Status](https://github.com/opencv/ade/actions/workflows/workflow.yaml/badge.svg)](https://github.com/opencv/ade/actions/workflows/workflow.yaml) 4 | 5 | ## Intro 6 | 7 | ADE Framework is a graph construction, manipulation, and processing 8 | framework. ADE Framework is suitable for organizing data flow 9 | processing and execution. 10 | 11 | ## Prerequisites and building 12 | 13 | The only prerequisites for library are CMake 3.5+ and a C++11 14 | compiler. 15 | 16 | Building: 17 | 18 | $ mkdir build 19 | $ cd build 20 | $ cmake /path/to/ade/repository 21 | $ make -j 22 | 23 | After a successfull compilation binaries should reside in `./lib` and 24 | `./bin` directories. Use 25 | 26 | $ make test 27 | 28 | to run ADE Framework test suite (ADE Framework tests + utility tests). 29 | 30 | If you want to build tutorial samples set `-DBUILD_ADE_TUTORIAL=ON` to 31 | cmake. 32 | 33 | Building with tutorial: 34 | 35 | $ cmake -DBUILD_ADE_TUTORIAL=ON /path/to/ade/repository 36 | $ make -j 37 | 38 | Additional information on tutorial samples can be found in 39 | `./tutorial/README.md`. 40 | 41 | If you want to build library tests set `-DENABLE_ADE_TESTING=ON` to cmake. 42 | Tests require gtest (https://github.com/google/googletest/releases). 43 | 44 | Building gtest: 45 | 46 | $ cmake -DCMAKE_INSTALL_PREFIX=/gtest/install/path /path/to/gtest 47 | $ make && make install 48 | 49 | Building with tests: 50 | 51 | $ cmake -DENABLE_ADE_TESTING=ON -DGTEST_ROOT=/gtest/install/path /path/to/ade/repository 52 | $ make -j 53 | 54 | You can build library with hardened asserts via 55 | `-DFORCE_ADE_ASSERTS=ON` option, forcing `ADE_ASSERT` to be present 56 | even in release builds. 57 | 58 | This library only does error checking in debug or `FORCE_ADE_ASSERTS=ON` 59 | builds due to performance reasons. Library doesn't process any user 60 | input directly and doesn't read any files or sockets. If you want to 61 | use this library to process any input from external source you must 62 | validate it before doing any library calls. 63 | 64 | To build documentation set `-DBUILD_ADE_DOCUMENTATION=ON`. Documentation 65 | can be found in `./doc` directory. Doxygen is required. 66 | 67 | ## Support 68 | 69 | Current ADE Framework support model is: 70 | * ADE Framework is mainly used as a building block for other projects. 71 | * ADE Framework major version are synchronized with that other 72 | projects releases. 73 | * ADE Framework accepts pull requests but is stabilized prior to a 74 | major parent project release only. 75 | 76 | ## Branches 77 | 78 | * `master` -- a default development branch. All further PRs are merged 79 | there by default. Projects which use ADE pull code from other 80 | (stable) branches by default. 81 | - `master` is not guaranteed to be stable (some tests may be failing 82 | on some platforms). 83 | - `master` is stabilized before other components major release. 84 | * `release_XX.YY` -- a release branch for version XX.YY where XX is a 85 | major release and YY is an update number. Mostly used by other 86 | projects as "frozen versions", support is limited (by request). 87 | 88 | ## License 89 | 90 | ADE Framework is distributed under terms of Apache License v2.0 (see 91 | `LICENSE`). 92 | -------------------------------------------------------------------------------- /sources/ade/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | include(manifest.cmake) 8 | project(${THE_PROJECT_NAME} VERSION ${THE_PROJECT_VERSION} LANGUAGES CXX) 9 | 10 | file( GLOB_RECURSE sources source/*.cpp ) 11 | file( GLOB_RECURSE include *.hpp ) 12 | 13 | if (CMAKE_CXX_COMPILER_ID STREQUAL GNU) 14 | set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Wconversion -Wshadow -Wno-error=cpp -Wformat -Wformat-security" ) 15 | endif() 16 | 17 | add_library( ${PROJECT_NAME} STATIC ${include} ${sources} ) 18 | target_include_directories(${PROJECT_NAME} PUBLIC $) 19 | set_target_properties( ${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE True) 20 | 21 | add_security_flags( ${PROJECT_NAME} ) 22 | 23 | if(FORCE_ADE_ASSERTS) 24 | target_compile_definitions( ${PROJECT_NAME} PUBLIC FORCE_ADE_ASSERTS ) 25 | endif() 26 | 27 | if(BUILD_ADE_DOCUMENTATION) 28 | find_package(Doxygen REQUIRED) 29 | 30 | set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 31 | 32 | set(DOXYGEN_PROJECT_NAME ${THE_PROJECT_NAME}) 33 | set(DOXYGEN_PROJECT_VERSION ${THE_PROJECT_VERSION}) 34 | set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/doc) 35 | set(DOXYGEN_INPUT "${CMAKE_SOURCE_DIR}/README.md ${CMAKE_CURRENT_SOURCE_DIR}/include") 36 | set(DOXYGEN_EXCLUDE_SYMBOLS "detail details") 37 | set(DOXYGEN_README_PATH ${CMAKE_SOURCE_DIR}/README.md) 38 | set(DOXYGEN_STRIP_FROM_PATH ${CMAKE_SOURCE_DIR}) 39 | 40 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in 41 | ${doxyfile} @ONLY) 42 | 43 | add_custom_target(doc ALL 44 | COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} 45 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc 46 | COMMENT "Generating API documentation with Doxygen" 47 | VERBATIM) 48 | endif() 49 | 50 | include(GNUInstallDirs) 51 | 52 | install(TARGETS ade COMPONENT dev 53 | EXPORT adeTargets 54 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 55 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 56 | RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} 57 | INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 58 | 59 | install(EXPORT adeTargets 60 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/ade" 61 | COMPONENT dev) 62 | 63 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" 64 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev 65 | FILES_MATCHING PATTERN "*.hpp") 66 | 67 | include(CMakePackageConfigHelpers) 68 | 69 | write_basic_package_version_file( 70 | "${CMAKE_BINARY_DIR}/adeConfigVersion.cmake" 71 | VERSION ${PROJECT_VERSION} 72 | COMPATIBILITY ExactVersion) 73 | 74 | configure_package_config_file( 75 | "${CMAKE_CURRENT_LIST_DIR}/cmake/adeConfig.cmake.in" 76 | "${CMAKE_BINARY_DIR}/adeConfig.cmake" 77 | INSTALL_DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/ade" 78 | NO_SET_AND_CHECK_MACRO 79 | NO_CHECK_REQUIRED_COMPONENTS_MACRO) 80 | 81 | export(TARGETS ade FILE "${CMAKE_BINARY_DIR}/adeTargets.cmake") 82 | 83 | install(FILES "${CMAKE_BINARY_DIR}/adeConfig.cmake" 84 | "${CMAKE_BINARY_DIR}/adeConfigVersion.cmake" 85 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/ade" COMPONENT dev) 86 | -------------------------------------------------------------------------------- /sources/ade/cmake/adeConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | include("${CMAKE_CURRENT_LIST_DIR}/adeTargets.cmake") 3 | -------------------------------------------------------------------------------- /sources/ade/include/ade/communication/comm_interface.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file comm_interface.hpp 8 | 9 | #ifndef ADE_COMM_INTERFACE_HPP 10 | #define ADE_COMM_INTERFACE_HPP 11 | 12 | #include 13 | 14 | #include "ade/memory/memory_types.hpp" 15 | 16 | #include "ade/memory/memory_descriptor_ref.hpp" 17 | 18 | namespace ade 19 | { 20 | 21 | class IDataBuffer; 22 | class DataBufferView; 23 | 24 | /// Data communication interface between different implementataions 25 | class ICommChannel 26 | { 27 | public: 28 | virtual ~ICommChannel() = default; 29 | 30 | using Size = memory::DynMdSize; 31 | using View = memory::DynMdView; 32 | using Span = memory::DynMdSpan; 33 | 34 | struct BufferDesc 35 | { 36 | /// Writers count for this buffer 37 | /// always greater than 0 38 | int writersCount = 0; 39 | 40 | /// Readers count for this buffer 41 | /// always greater than 0 42 | int readersCount = 0; 43 | 44 | /// Reference to memory descriptor 45 | /// Will never be null 46 | MemoryDescriptorRef memoryRef; 47 | }; 48 | 49 | struct BufferPrefs 50 | { 51 | /// Preferred alignment for buffer data 52 | /// dimensions count must be equal to buffer dimensions count 53 | /// Each element must be power of two 54 | /// Implementation can set elements to 1 if it doesn't care about alignment 55 | Size preferredAlignment; 56 | }; 57 | 58 | /// Implementation must return buffer memory preferences 59 | /// 60 | /// @param desc Buffer description 61 | /// 62 | /// @returns Buffer memory preferences 63 | virtual BufferPrefs getBufferPrefs(const BufferDesc& desc) = 0; 64 | 65 | /// Implementation can return buffer object if it supports efficient implementation or null 66 | /// If all participants returned nulls buffer will be allocated by framework 67 | /// Caller takes ownership of this buffer 68 | /// 69 | /// @param desc Buffer description 70 | /// @param prefs Buffer memory preferences 71 | /// 72 | /// @returns Buffer object instance or null, caller will take ownership of this object 73 | virtual std::unique_ptr getBuffer(const BufferDesc& desc, const BufferPrefs& prefs) = 0; 74 | 75 | /// Framework will call the method for all participant after appropriate buffer was allocated 76 | /// (either by one of participants or by framework itself) 77 | /// Participant must store buffer object to be able to access its data during execution 78 | /// 79 | /// @param buffer Buffer object wrapper 80 | /// @param desc Buffer description 81 | virtual void setBuffer(const DataBufferView& buffer, const BufferDesc& desc) = 0; 82 | }; 83 | } 84 | 85 | #endif // ADE_COMM_INTERFACE_HPP 86 | -------------------------------------------------------------------------------- /sources/ade/include/ade/edge.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file edge.hpp 8 | 9 | #ifndef ADE_EDGE_HPP 10 | #define ADE_EDGE_HPP 11 | 12 | #include 13 | 14 | #include "handle.hpp" 15 | 16 | namespace ade 17 | { 18 | 19 | class Graph; 20 | class Node; 21 | class Edge; 22 | using EdgeHandle = Handle; 23 | using NodeHandle = Handle; 24 | 25 | class Edge final : public std::enable_shared_from_this 26 | { 27 | public: 28 | NodeHandle srcNode() const; 29 | NodeHandle dstNode() const; 30 | private: 31 | friend class Graph; 32 | friend class Node; 33 | 34 | Edge(Node* prev, Node* next); 35 | ~Edge(); 36 | Edge(const Edge&) = delete; 37 | Edge& operator=(const Edge&) = delete; 38 | 39 | Graph* getParent() const; 40 | 41 | void unlink(); 42 | void resetPrevNode(Node* newNode); 43 | void resetNextNode(Node* newNode); 44 | 45 | Node* m_prevNode = nullptr; 46 | Node* m_nextNode = nullptr; 47 | }; 48 | 49 | } 50 | 51 | #endif // ADE_EDGE_HPP 52 | -------------------------------------------------------------------------------- /sources/ade/include/ade/execution_engine/backend.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file backend.hpp 8 | 9 | #ifndef ADE_BACKEND_HPP 10 | #define ADE_BACKEND_HPP 11 | 12 | #include 13 | 14 | namespace ade 15 | { 16 | 17 | class Graph; 18 | class Executable; 19 | class ExecutionEngineSetupContext; 20 | 21 | class BackendExecutable; 22 | 23 | class ExecutionBackend 24 | { 25 | public: 26 | virtual ~ExecutionBackend() = default; 27 | 28 | virtual void setupExecutionEngine(ExecutionEngineSetupContext& engine) = 0; 29 | virtual std::unique_ptr createExecutable(const Graph& graph) = 0; 30 | }; 31 | 32 | class BackendExecutable 33 | { 34 | protected: 35 | // Backward-compatibility stubs 36 | virtual void run() {}; // called by run(void*) 37 | virtual void runAsync() {}; // called by runAsync(void*) 38 | 39 | public: 40 | virtual ~BackendExecutable() = default; 41 | 42 | virtual void run(void *opaque); // Triggered by ADE engine 43 | virtual void runAsync(void *opaque); // Triggered by ADE engine 44 | 45 | virtual void wait() = 0; 46 | virtual void cancel() = 0; 47 | }; 48 | } 49 | 50 | #endif // ADE_BACKEND_HPP 51 | -------------------------------------------------------------------------------- /sources/ade/include/ade/execution_engine/executable.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file executable.hpp 8 | 9 | #ifndef ADE_EXECUTABLE_HPP 10 | #define ADE_EXECUTABLE_HPP 11 | 12 | namespace ade 13 | { 14 | class Executable 15 | { 16 | public: 17 | virtual ~Executable() = default; 18 | virtual void run() = 0; 19 | virtual void run(void *opaque) = 0; // WARNING: opaque may be accessed from various threads. 20 | 21 | virtual void runAsync() = 0; 22 | virtual void runAsync(void *opaque) = 0; // WARNING: opaque may be accessed from various threads. 23 | 24 | virtual void wait() = 0; 25 | }; 26 | } 27 | 28 | #endif // ADE_EXECUTABLE_HPP 29 | -------------------------------------------------------------------------------- /sources/ade/include/ade/graph.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file graph.hpp 8 | 9 | #ifndef ADE_GRAPH_HPP 10 | #define ADE_GRAPH_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "util/assert.hpp" 19 | #include "util/range.hpp" 20 | #include "util/map_range.hpp" 21 | 22 | #include "handle.hpp" 23 | #include "edge.hpp" 24 | #include "node.hpp" 25 | 26 | namespace ade 27 | { 28 | 29 | template 30 | class TypedGraph; 31 | 32 | template 33 | class ConstTypedGraph; 34 | 35 | namespace details 36 | { 37 | class MetadataId; 38 | class Metadata; 39 | 40 | template 41 | struct InitIdsArray; 42 | } 43 | 44 | class Node; 45 | class Edge; 46 | class IGraphListener; 47 | 48 | class Graph final 49 | { 50 | public: 51 | template 52 | friend class TypedGraph; 53 | 54 | template 55 | friend class ConstTypedGraph; 56 | 57 | template 58 | friend struct details::InitIdsArray; 59 | 60 | struct HandleMapper 61 | { 62 | template 63 | Handle operator()(T* obj) const 64 | { 65 | ADE_ASSERT(nullptr != obj); 66 | return Handle(obj->shared_from_this()); 67 | } 68 | 69 | template 70 | Handle operator()(const std::shared_ptr& obj) const 71 | { 72 | ADE_ASSERT(nullptr != obj); 73 | return Handle(obj); 74 | } 75 | }; 76 | 77 | using EdgePtr = std::shared_ptr; 78 | using EdgeList = std::vector; 79 | 80 | using NodePtr = std::shared_ptr; 81 | using NodesList = std::vector; 82 | using NodesListRange = util::MapRange, HandleMapper>; 83 | using NodesListCRange = util::MapRange, HandleMapper>; 84 | 85 | Graph(); 86 | ~Graph(); 87 | 88 | /// Create new node 89 | NodeHandle createNode(); 90 | 91 | /// Delete node and all connected edges from graph and null all handles pointing to it 92 | void erase(const NodeHandle& node); 93 | 94 | /// Delete all edges, connected to this node 95 | void unlink(const NodeHandle& node); 96 | 97 | /// Delete edge from graph and null all handles pointing to it 98 | void erase(const EdgeHandle& edge); 99 | 100 | 101 | /// Create new edge between src_node and dst_node 102 | EdgeHandle link(const NodeHandle& src_node, const NodeHandle& dst_node); 103 | 104 | /// Change src_edge destination node to dst_node 105 | /// noop if src_edge destination node is already dst_node 106 | /// returns src_edge 107 | EdgeHandle link(const EdgeHandle& src_edge, const NodeHandle& dst_node); 108 | 109 | /// Change dst_edge source node to src_node 110 | /// noop if dst_edge source node is already src_node 111 | /// returns dst_edge 112 | EdgeHandle link(const NodeHandle& src_node, const EdgeHandle& dst_edge); 113 | 114 | NodesListRange nodes(); 115 | NodesListCRange nodes() const; 116 | 117 | void setListener(IGraphListener* listener); 118 | IGraphListener* getListener() const; 119 | private: 120 | friend class Node; 121 | friend class Edge; 122 | 123 | struct ElemDeleter final 124 | { 125 | void operator()(Node* node) const; 126 | void operator()(Edge* edge) const; 127 | }; 128 | 129 | Graph(const Graph&) = delete; 130 | Graph& operator=(const Graph&) = delete; 131 | 132 | EdgeHandle createEdge(Node* src_node, Node* dst_node); 133 | 134 | void removeNode(Node* node); 135 | void removeEdge(Edge* edge); 136 | 137 | details::Metadata& geMetadataImpl(void* handle) const; 138 | 139 | NodesList m_nodes; 140 | EdgeList m_edges; 141 | 142 | struct Id 143 | { 144 | std::unique_ptr p; 145 | 146 | Id():p(new char) {} // enforce identity 147 | Id(const Id&) = delete; 148 | Id& operator=(const Id&) = delete; 149 | Id(Id&&) = default; 150 | Id& operator=(Id&&) = default; 151 | }; 152 | 153 | // To make getMetadataId() const 154 | mutable std::unordered_map m_ids; 155 | 156 | // We will create metadata lazily 157 | // Stores node/edge metadata per object ptr 158 | // Stores graph metadata per nullptr 159 | mutable std::unordered_map> m_metadata; 160 | 161 | IGraphListener* m_listener = nullptr; 162 | 163 | details::MetadataId getMetadataId(const std::string& name) const; 164 | 165 | details::Metadata& metadata(); 166 | const details::Metadata& metadata() const; 167 | 168 | details::Metadata& metadata(const NodeHandle handle); 169 | const details::Metadata& metadata(const NodeHandle handle) const; 170 | 171 | details::Metadata& metadata(const EdgeHandle handle); 172 | const details::Metadata& metadata(const EdgeHandle handle) const; 173 | }; 174 | 175 | } 176 | 177 | #endif // ADE_GRAPH_HPP 178 | -------------------------------------------------------------------------------- /sources/ade/include/ade/graph_listener.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file graph_listener.hpp 8 | 9 | #ifndef ADE_GRAPH_LISTENER_HPP 10 | #define ADE_GRAPH_LISTENER_HPP 11 | 12 | #include "handle.hpp" 13 | 14 | namespace ade 15 | { 16 | 17 | class Graph; 18 | class Node; 19 | class Edge; 20 | using EdgeHandle = Handle; 21 | using NodeHandle = Handle; 22 | 23 | class IGraphListener 24 | { 25 | public: 26 | virtual ~IGraphListener() = default; 27 | 28 | virtual void nodeCreated(const Graph& graph, const NodeHandle& node) = 0; 29 | virtual void nodeAboutToBeDestroyed(const Graph& graph, const NodeHandle& node) = 0; 30 | 31 | virtual void edgeCreated(const Graph&, const EdgeHandle& edge) = 0; 32 | virtual void edgeAboutToBeDestroyed(const Graph& graph, const EdgeHandle& edge) = 0; 33 | virtual void edgeAboutToBeRelinked(const Graph& graph, 34 | const EdgeHandle& edge, 35 | const NodeHandle& newSrcNode, 36 | const NodeHandle& newDstNode) = 0; 37 | }; 38 | 39 | } 40 | 41 | #endif // ADE_GRAPH_LISTENER_HPP 42 | -------------------------------------------------------------------------------- /sources/ade/include/ade/handle.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file handle.hpp 8 | 9 | #ifndef ADE_HANDLE_HPP 10 | #define ADE_HANDLE_HPP 11 | 12 | #include 13 | #include 14 | #include //std::hash 15 | 16 | #include "util/assert.hpp" 17 | 18 | namespace ade 19 | { 20 | 21 | // Non owning graph elements pointer 22 | // Elements owned by graph 23 | template 24 | class Handle final 25 | { 26 | friend class Graph; 27 | 28 | std::weak_ptr m_ptr; 29 | 30 | Handle(const std::shared_ptr& obj): 31 | m_ptr(obj) 32 | { 33 | ADE_ASSERT(nullptr != obj); 34 | } 35 | 36 | static T* check(T* val) 37 | { 38 | ADE_ASSERT_STRONG(nullptr != val); 39 | return val; 40 | } 41 | 42 | public: 43 | Handle() = default; 44 | Handle(std::nullptr_t) {} 45 | Handle(const Handle&) = default; 46 | Handle& operator=(const Handle&) = default; 47 | Handle& operator=(std::nullptr_t) { m_ptr.reset(); return *this; } 48 | Handle(Handle&&) = default; 49 | Handle& operator=(Handle&&) = default; 50 | 51 | // Graphs not intended for multithreaded modification so this should be safe 52 | T* get() const { return m_ptr.lock().get(); } 53 | 54 | T& operator*() const { return *check(get()); } 55 | 56 | T* operator->() const { return check(get()); } 57 | 58 | bool operator==(const Handle& other) const 59 | { 60 | return get() == other.get(); 61 | } 62 | 63 | bool operator!=(const Handle& other) const 64 | { 65 | return get() != other.get(); 66 | } 67 | 68 | friend bool operator==(std::nullptr_t, const Handle& other) 69 | { 70 | return nullptr == other.get(); 71 | } 72 | 73 | friend bool operator==(const Handle& other, std::nullptr_t) 74 | { 75 | return nullptr == other.get(); 76 | } 77 | 78 | friend bool operator!=(std::nullptr_t, const Handle& other) 79 | { 80 | return nullptr != other.get(); 81 | } 82 | 83 | friend bool operator!=(const Handle& other, std::nullptr_t) 84 | { 85 | return nullptr != other.get(); 86 | } 87 | }; 88 | 89 | template 90 | inline std::ostream& operator<<(std::ostream& os, const Handle& arg) 91 | { 92 | os << arg.get(); 93 | return os; 94 | } 95 | 96 | /// Generally it is not safe to use handles as keys so we dont provide default 97 | /// hash, user must use this hasher explicitly if he really want to 98 | template 99 | struct HandleHasher final 100 | { 101 | std::size_t operator()(const ade::Handle& handle) const 102 | { 103 | ADE_ASSERT(nullptr != handle); 104 | return std::hash()(handle.get()); 105 | } 106 | }; 107 | 108 | 109 | } 110 | 111 | #endif // ADE_HANDLE_HPP 112 | -------------------------------------------------------------------------------- /sources/ade/include/ade/helpers/search.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file search.hpp 8 | 9 | #ifndef ADE_SEARCH_HPP 10 | #define ADE_SEARCH_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/node.hpp" 16 | 17 | #include "ade/util/algorithm.hpp" 18 | #include "ade/util/assert.hpp" 19 | #include "ade/util/func_ref.hpp" 20 | 21 | namespace ade 22 | { 23 | namespace traverse 24 | { 25 | using traverse_func_type 26 | = util::func_ref)>; 28 | inline void forward(const Node& node, 29 | util::func_ref visitor) 30 | { 31 | for (auto&& next : node.outNodes()) 32 | { 33 | visitor(next); 34 | } 35 | } 36 | inline void backward(const Node& node, 37 | util::func_ref visitor) 38 | { 39 | for (auto&& next : node.inNodes()) 40 | { 41 | visitor(next); 42 | } 43 | } 44 | } // namespace ade::traverse 45 | 46 | /// Depth first search through nodes 47 | /// 48 | /// @param node - Start node, must not be null 49 | /// @param visitor - Functor called for each found node, 50 | /// must return true to continue search 51 | /// @param direction - Traverse direction, this functor will be called for 52 | /// current node and it must call its argument for each node we want to 53 | /// visit next. 54 | void dfs(const NodeHandle& node, 55 | util::func_ref visitor, 56 | traverse::traverse_func_type direction = traverse::forward); 57 | 58 | namespace details 59 | { 60 | struct TransitiveClosureHelper 61 | { 62 | using CacheT = 63 | std::unordered_map>, 65 | HandleHasher>; 66 | void operator()(CacheT& cache, 67 | const NodeHandle& node, 68 | traverse::traverse_func_type direction) const; 69 | }; 70 | } 71 | 72 | /// Computes transitive closure for graph 73 | /// https://en.wikipedia.org/wiki/Transitive_closure#In_graph_theory 74 | /// 75 | /// @param nodes - List of nodes to check 76 | /// @param visitor - functor which will be called for pairs of nodes, 77 | /// first parameted is source node from provided list and 78 | /// second parameter is node reachable from this source node 79 | /// @param direction - Traverse direction, this functor will be called for 80 | /// current node and it must call its argument for each node we want to 81 | /// visit next. 82 | template 83 | void transitiveClosure( 84 | Nodes&& nodes, 85 | Visitor&& visitor, 86 | traverse::traverse_func_type direction = traverse::forward) 87 | { 88 | using Helper = details::TransitiveClosureHelper; 89 | Helper::CacheT visited; 90 | for (auto node : nodes) 91 | { 92 | ADE_ASSERT(nullptr != node); 93 | if (!util::contains(visited, node)) 94 | { 95 | Helper()(visited, node, direction); 96 | } 97 | ADE_ASSERT(util::contains(visited, node)); 98 | for (auto nextNode : visited[node]) 99 | { 100 | visitor(node, nextNode); 101 | } 102 | } 103 | } 104 | 105 | } 106 | 107 | #endif // ADE_SEARCH_HPP 108 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/alloc.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file alloc.hpp 8 | 9 | #ifndef ADE_ALLOC_HPP 10 | #define ADE_ALLOC_HPP 11 | 12 | #include //size_t 13 | 14 | namespace ade 15 | { 16 | void* aligned_alloc(std::size_t size, std::size_t alignment); 17 | void aligned_free(void* ptr); 18 | 19 | } 20 | 21 | #endif // ADE_ALLOC_HPP 22 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/memory_access_listener.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file memory_access_listener.hpp 8 | 9 | #ifndef ADE_MEMORYACCESSLISTENER_HPP 10 | #define ADE_MEMORYACCESSLISTENER_HPP 11 | 12 | #include 13 | 14 | #include "ade/util/assert.hpp" 15 | 16 | #include "ade/memory/memory_types.hpp" 17 | 18 | namespace ade 19 | { 20 | 21 | class MemoryDescriptor; 22 | 23 | enum class MemoryAccessType 24 | { 25 | NoAccess, 26 | Read, 27 | Write, 28 | ReadWrite, 29 | }; 30 | 31 | /// Listener used to notify internal objects 32 | /// when graph managed data is being accessed extenally 33 | class IMemoryAccessListener 34 | { 35 | public: 36 | virtual ~IMemoryAccessListener() {} 37 | 38 | using AccessHandle = void*; 39 | 40 | struct AccessHandleDeleter 41 | { 42 | IMemoryAccessListener* listener; 43 | void operator()(AccessHandle handle) 44 | { 45 | ADE_ASSERT(nullptr != listener); 46 | listener->commitImpl(handle); 47 | } 48 | }; 49 | 50 | using AccessHandlePtr = std::unique_ptr; 51 | 52 | /// This method is called just before external user will be able to access data 53 | /// so listener can do required preparations (e.g. do OpenCL map or copy data from device) 54 | /// Listener can report errors via exceptions 55 | /// 56 | /// @param desc The memory descriptor to be accessed 57 | /// @param span Span that represents a ROI of current view to be accessed 58 | /// @param accessType Access type for this view, it can be Read, Write or ReadWrite 59 | /// @returns Listener specific handle which later will be passed to commitImpl 60 | /// Framework doesn't check this return value in any way 61 | virtual AccessHandle accessImpl(const MemoryDescriptor& desc, const memory::DynMdSpan& span, MemoryAccessType accessType) = 0; 62 | 63 | /// This method is called immediately after external user finished access to data 64 | /// This method must never throw 65 | /// 66 | /// @param handle Handle returned from successuful accessImpl call 67 | virtual void commitImpl(AccessHandle handle) = 0; 68 | 69 | /// This method called when externally accessible data view is about to change 70 | /// Listener must drop all references to old data and use new 71 | /// Listener can report errors via exceptions 72 | /// 73 | /// @param old_view Previous data, can be null if data wasn't externally accessible previously 74 | /// @param new_view New data, can be null 75 | virtual void memoryViewChangedImpl(const memory::DynMdView& old_view, 76 | const memory::DynMdView& new_view) = 0; 77 | 78 | /// This method is called when external memory descriptor is destroyed, 79 | /// so the listener can remove any objects created for it (OpenCL buffers, etc.) 80 | virtual void memoryDescriptorDestroyedImpl() = 0; 81 | 82 | AccessHandlePtr access(const MemoryDescriptor& desc, const memory::DynMdSpan& span, MemoryAccessType accessType) 83 | { 84 | return AccessHandlePtr(accessImpl(desc, span, accessType), 85 | AccessHandleDeleter{this}); 86 | } 87 | }; 88 | 89 | } 90 | 91 | #endif // ADE_MEMORYACCESSLISTENER_HPP 92 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/memory_accessor.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file memory_accessor.hpp 8 | 9 | #ifndef ADE_MEMORYACCESSOR_HPP 10 | #define ADE_MEMORYACCESSOR_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "ade/memory/memory_types.hpp" 17 | 18 | #include "ade/memory/memory_access_listener.hpp" 19 | 20 | namespace ade 21 | { 22 | 23 | /// This class is used to notify listeners about externally accessible 24 | /// data state changes 25 | class MemoryAccessor final 26 | { 27 | struct SavedHandles; 28 | public: 29 | MemoryAccessor(); 30 | MemoryAccessor(const MemoryAccessor&) = delete; 31 | MemoryAccessor& operator=(const MemoryAccessor&) = delete; 32 | ~MemoryAccessor(); 33 | 34 | /// Add events listener 35 | /// 36 | /// @param listener Listener to be added, must not be null 37 | /// Same listener must not be added twice 38 | void addListener(IMemoryAccessListener* listener); 39 | 40 | /// Remove events listener 41 | /// 42 | /// @param listener Listener to be removed, must not be null 43 | /// Listener must be previously added via addListener call 44 | void removeListener(IMemoryAccessListener* listener); 45 | 46 | using AccessHandle = std::list::iterator; 47 | 48 | /// Notify all listeners about memory access 49 | /// 50 | /// @param desc The memory descriptor to be accessed 51 | /// @param span Span that represents a ROI of current view to be accessed 52 | /// @param accessType Access type for this view, it must be Read, Write or ReadWrite 53 | /// @returns Handle which later will be passed to commit 54 | AccessHandle access(const MemoryDescriptor& desc, const memory::DynMdSpan& span, MemoryAccessType accessType); 55 | 56 | /// Notify all listeners about memory commit 57 | /// 58 | /// @param handle Handle returned from successuful access call 59 | void commit(AccessHandle handle); 60 | 61 | /// Update memory view and notify all listeners 62 | /// 63 | /// @param mem New memory view 64 | void setNewView(const memory::DynMdView& mem); 65 | 66 | /// Set MemoryAccessor usage errors listener 67 | /// 68 | /// @param listener Errors listener with signature void(const char*) 69 | template 70 | void setErrorListener(F&& listener) 71 | { 72 | m_errorListener = std::forward(listener); 73 | } 74 | 75 | private: 76 | std::vector m_accessListeners; 77 | 78 | memory::DynMdView m_memory; 79 | 80 | struct SavedHandles 81 | { 82 | SavedHandles(MemoryAccessor* parent, 83 | const MemoryDescriptor& desc, 84 | const memory::DynMdSpan& span, 85 | MemoryAccessType accessType); 86 | ~SavedHandles(); 87 | SavedHandles(const SavedHandles&) = delete; 88 | SavedHandles& operator=(const SavedHandles&) = delete; 89 | SavedHandles(SavedHandles&&) = default; 90 | SavedHandles& operator=(SavedHandles&&) = default; 91 | 92 | // optimization to reduce heap allocation for common case 93 | IMemoryAccessListener::AccessHandlePtr handle; 94 | std::vector handles; 95 | 96 | void abandon(IMemoryAccessListener* listener); 97 | void abandon(); 98 | }; 99 | 100 | std::list m_activeHandles; 101 | 102 | std::function m_errorListener; 103 | 104 | void abandonListenerHandles(IMemoryAccessListener* listener); 105 | void abandonAllHandles(); 106 | void onError(const char* str); 107 | }; 108 | 109 | } 110 | 111 | #endif // ADE_MEMORYACCESSOR_HPP 112 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/memory_descriptor.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file memory_descriptor.hpp 8 | 9 | #ifndef ADE_MEMORY_DESCRIPTOR_HPP 10 | #define ADE_MEMORY_DESCRIPTOR_HPP 11 | 12 | #include "ade/util/memory_range.hpp" 13 | 14 | #include "ade/memory/memory_types.hpp" 15 | #include "ade/memory/memory_accessor.hpp" 16 | 17 | namespace ade 18 | { 19 | 20 | class MemoryDescriptorRef; 21 | class MemoryDescriptorView; 22 | 23 | /// This class represents continuous buffer used in graph 24 | /// It can have optional memory view, accessible to external users 25 | class MemoryDescriptor final 26 | { 27 | public: 28 | /// MemoryDescriptor constructor 29 | /// 30 | /// @param element_size Data element size in bytes 31 | /// @param dims Memory dimensions in elements 32 | explicit MemoryDescriptor(size_t element_size, 33 | const memory::DynMdSize& dims); 34 | MemoryDescriptor(const MemoryDescriptor&) = delete; 35 | MemoryDescriptor& operator=(const MemoryDescriptor&) = delete; 36 | ~MemoryDescriptor(); 37 | 38 | /// Add events listener 39 | /// 40 | /// @param listener Listener to be added, must not be null 41 | /// Same listener must not be added twice 42 | void addListener(IMemoryAccessListener* listener); 43 | 44 | /// Remove events listener 45 | /// 46 | /// @param listener Listener to be removed, must not be null 47 | /// Listener must be previously added via addListener call 48 | void removeListener(IMemoryAccessListener* listener); 49 | 50 | using AccessHandle = MemoryAccessor::AccessHandle; 51 | 52 | /// Notify all listeners about memory access 53 | /// 54 | /// @param span Span that represents a ROI of current view to be accessed 55 | /// @param accessType Access type for this view, it must be Read, Write or ReadWrite 56 | /// @returns Handle which later will be passed to commit 57 | AccessHandle access(const memory::DynMdSpan& span, MemoryAccessType accessType); 58 | 59 | /// Notify all listeners about memory commit 60 | /// 61 | /// @param handle Handle returned from successuful access call 62 | void commit(AccessHandle handle); 63 | 64 | /// Get memory dimensions 65 | /// 66 | /// @returns Dimensions 67 | const memory::DynMdSize& dimensions() const; 68 | 69 | /// Get buffer element size 70 | /// 71 | /// @returns Size in bytes, always greater than 0 72 | std::size_t elementSize() const; 73 | 74 | /// Update externally accessible memory view and notify all listeners 75 | /// 76 | /// @param view New memory view 77 | void setExternalView(const memory::DynMdView& view); 78 | 79 | /// Returns externally accessible memory view if any 80 | /// 81 | /// @returns View into externally accessible memory or null view 82 | memory::DynMdView getExternalView() const; 83 | 84 | private: 85 | friend class MemoryDescriptorView; 86 | 87 | const size_t m_elementSize; 88 | const memory::DynMdSize m_dims; 89 | memory::DynMdView m_externalView; 90 | 91 | MemoryAccessor m_accessor; 92 | }; 93 | 94 | } 95 | 96 | #endif // ADE_MEMORY_DESCRIPTOR_HPP 97 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/memory_descriptor_ref.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file memory_descriptor_ref.hpp 8 | 9 | #ifndef ADE_MEMORY_DESCRIPTOR_REF_HPP 10 | #define ADE_MEMORY_DESCRIPTOR_REF_HPP 11 | 12 | #include 13 | 14 | #include "ade/memory/memory_types.hpp" 15 | 16 | namespace ade 17 | { 18 | 19 | class MemoryDescriptor; 20 | class MemoryDescriptorView; 21 | 22 | /// Lghtweight reference into MemoryDescriptorView 23 | /// It can reference to a part of MemoryDescriptorView 24 | class MemoryDescriptorRef final 25 | { 26 | public: 27 | /// Constructs empty MemoryDescriptorRef 28 | MemoryDescriptorRef(); 29 | 30 | /// Consructs MemoryDescriptorRef covering entire view 31 | /// 32 | /// @param view Source view 33 | MemoryDescriptorRef(MemoryDescriptorView& view); 34 | 35 | /// Consructs MemoryDescriptorRef covering part view 36 | /// 37 | /// @param view Source view 38 | /// @param span Span into descriptor view, must be inside view dimensions 39 | MemoryDescriptorRef(MemoryDescriptorView& view_, 40 | const memory::DynMdSpan& span_); 41 | ~MemoryDescriptorRef(); 42 | 43 | MemoryDescriptorRef(const MemoryDescriptorRef&) = default; 44 | MemoryDescriptorRef(MemoryDescriptorRef&&) = default; 45 | MemoryDescriptorRef& operator=(const MemoryDescriptorRef&) = default; 46 | MemoryDescriptorRef& operator=(MemoryDescriptorRef&&) = default; 47 | 48 | /// Get source view 49 | /// 50 | /// @returns Source view 51 | MemoryDescriptorView* getView(); 52 | 53 | /// Get source view 54 | /// 55 | /// @returns Source view 56 | const MemoryDescriptorView* getView() const; 57 | 58 | /// Get source descriptor 59 | /// 60 | /// @returns Source descriptor 61 | MemoryDescriptor* getDescriptor(); 62 | 63 | /// Get source descriptor 64 | /// 65 | /// @returns Source descriptor 66 | const MemoryDescriptor* getDescriptor() const; 67 | 68 | /// Get span into current view 69 | /// 70 | /// @returns span 71 | const memory::DynMdSpan& span() const; 72 | 73 | /// Get span size 74 | /// 75 | /// @returns size 76 | memory::DynMdSize size() const; 77 | 78 | /// Get buffer element size 79 | /// 80 | /// @returns Size in bytes 81 | std::size_t elementSize() const; 82 | 83 | /// Get span into parent ref 84 | /// 85 | /// @returns span 86 | memory::DynMdSpan originSpan() const; 87 | 88 | /// Returns externally accessible memory view if any 89 | /// 90 | /// @returns View into externally accessible memory or null view 91 | memory::DynMdView getExternalView() const; 92 | 93 | /// Check whether this object is null 94 | friend bool operator==(std::nullptr_t, const MemoryDescriptorRef& ref); 95 | 96 | /// Check whether this object is null 97 | friend bool operator==(const MemoryDescriptorRef& ref, std::nullptr_t); 98 | 99 | /// Check whether this object is null 100 | friend bool operator!=(std::nullptr_t, const MemoryDescriptorRef& ref); 101 | 102 | /// Check whether this object is null 103 | friend bool operator!=(const MemoryDescriptorRef& ref, std::nullptr_t); 104 | private: 105 | MemoryDescriptorView* m_parent = nullptr; 106 | memory::DynMdSpan m_span; 107 | }; 108 | 109 | std::ostream& operator<<(std::ostream& os, const MemoryDescriptorRef& ref); 110 | 111 | } 112 | 113 | #endif // ADE_MEMORY_DESCRIPTOR_REF_HPP 114 | -------------------------------------------------------------------------------- /sources/ade/include/ade/memory/memory_types.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file memory_types.hpp 8 | 9 | #ifndef ADE_MEMORY_TYPES_HPP 10 | #define ADE_MEMORY_TYPES_HPP 11 | 12 | #include "ade/util/md_size.hpp" 13 | #include "ade/util/md_span.hpp" 14 | #include "ade/util/md_view.hpp" 15 | 16 | namespace ade 17 | { 18 | namespace memory 19 | { 20 | static const constexpr std::size_t MaxDimensions = 6; 21 | using DynMdSize = util::DynMdSize; 22 | using DynMdSpan = util::DynMdSpan; 23 | 24 | template 25 | using DynMdView = util::DynMdView; 26 | 27 | } 28 | } 29 | 30 | #endif // ADE_MEMORY_TYPES_HPP 31 | -------------------------------------------------------------------------------- /sources/ade/include/ade/metatypes/metatypes.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file metatypes.hpp 8 | 9 | #ifndef ADE_METATYPES_HPP 10 | #define ADE_METATYPES_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "ade/memory/memory_descriptor_ref.hpp" 18 | 19 | namespace ade 20 | { 21 | class ICommChannel; 22 | class IDataBuffer; 23 | 24 | namespace meta 25 | { 26 | struct NodeInfo final 27 | { 28 | std::string kernel_name; 29 | std::string target_name; 30 | 31 | using NodeId = void*; 32 | 33 | NodeInfo() = default; 34 | NodeInfo(const std::string& kernel, 35 | const std::string& target); 36 | NodeInfo(const NodeInfo&) = default; 37 | NodeInfo& operator=(const NodeInfo&) = default; 38 | NodeInfo(NodeInfo&&) = default; 39 | NodeInfo& operator=(NodeInfo&&) = default; 40 | 41 | NodeId getId() const; 42 | 43 | void link(NodeInfo& node); 44 | 45 | static const char* name(); 46 | private: 47 | struct IdStruct final 48 | { 49 | // Nothing 50 | }; 51 | 52 | using IdPtr = std::shared_ptr; 53 | 54 | // mutable to allocate id lazily 55 | mutable IdPtr m_id; 56 | 57 | IdPtr getIdInternal() const; 58 | }; 59 | 60 | struct DataObject final 61 | { 62 | ade::MemoryDescriptorRef dataRef; 63 | 64 | std::string originalFormat; /// Original format of composite object 65 | 66 | static const char* name(); 67 | }; 68 | 69 | struct CommNode final 70 | { 71 | CommNode(int producersCount_); 72 | CommNode(const CommNode&) = default; 73 | CommNode& operator=(const CommNode&) = default; 74 | 75 | int producersCount() const { return m_producersCount; } 76 | 77 | void addDataBuffer(const std::shared_ptr& buff); 78 | 79 | static const char* name(); 80 | private: 81 | int m_producersCount = 0; 82 | std::vector> m_buffers; 83 | }; 84 | 85 | struct CommChannel final 86 | { 87 | std::shared_ptr channel; 88 | 89 | static const char* name(); 90 | }; 91 | 92 | /// Backends must set this metadata to their consumer nodes in heterogeneous case. 93 | struct CommConsumerCallback final 94 | { 95 | using Callback = std::function; 96 | 97 | Callback callback; 98 | 99 | static const char* name(); 100 | }; 101 | 102 | /// The framework will set this metadata to producers nodes in heterogeneous case. 103 | /// Backends must use it in their executable representation. 104 | struct CommProducerCallback final 105 | { 106 | using Callback = std::function; 107 | 108 | Callback callback; 109 | 110 | static const char* name(); 111 | }; 112 | 113 | /// Store various finalizers which should run after graph execution completion 114 | struct Finalizers final 115 | { 116 | std::vector> finalizers; 117 | 118 | static const char* name(); 119 | }; 120 | 121 | std::ostream& operator<<(std::ostream& os, const ade::meta::NodeInfo& obj); 122 | 123 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommNode& obj); 124 | 125 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommConsumerCallback& obj); 126 | 127 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommProducerCallback& obj); 128 | 129 | std::ostream& operator<<(std::ostream& os, const ade::meta::DataObject& obj); 130 | 131 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommChannel& obj); 132 | 133 | std::ostream& operator<<(std::ostream& os, const ade::meta::Finalizers& obj); 134 | 135 | } 136 | } 137 | 138 | #endif // ADE_METATYPES_HPP 139 | -------------------------------------------------------------------------------- /sources/ade/include/ade/node.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file node.hpp 8 | 9 | #ifndef ADE_NODE_HPP 10 | #define ADE_NODE_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "util/range.hpp" 17 | #include "util/map_range.hpp" 18 | 19 | #include "edge.hpp" 20 | #include "handle.hpp" 21 | 22 | namespace ade 23 | { 24 | 25 | class Graph; 26 | class Edge; 27 | class Node; 28 | using NodeHandle = Handle; 29 | 30 | class Node final : public std::enable_shared_from_this 31 | { 32 | public: 33 | struct HandleMapper final 34 | { 35 | EdgeHandle operator()(Edge* obj) const; 36 | }; 37 | struct InEdgeMapper final 38 | { 39 | NodeHandle operator()(const EdgeHandle& handle) const; 40 | }; 41 | struct OutEdgeMapper final 42 | { 43 | NodeHandle operator()(const EdgeHandle& handle) const; 44 | }; 45 | 46 | using EdgeSet = std::vector; 47 | using EdgeSetRange = util::MapRange, HandleMapper>; 48 | using EdgeSetCRange = util::MapRange, HandleMapper>; 49 | using InNodeSetRange = util::MapRange; 50 | using InNodeSetCRange = util::MapRange; 51 | using OutNodeSetRange = util::MapRange; 52 | using OutNodeSetCRange = util::MapRange; 53 | 54 | EdgeSetRange inEdges(); 55 | EdgeSetCRange inEdges() const; 56 | 57 | EdgeSetRange outEdges(); 58 | EdgeSetCRange outEdges() const; 59 | 60 | InNodeSetRange inNodes(); 61 | InNodeSetCRange inNodes() const; 62 | 63 | OutNodeSetRange outNodes(); 64 | OutNodeSetCRange outNodes() const; 65 | private: 66 | friend class Graph; 67 | friend class Edge; 68 | 69 | Node(Graph* parent); 70 | ~Node(); 71 | Node(const Node&) = delete; 72 | Node& operator=(const Node&) = delete; 73 | 74 | Graph* getParent() const; 75 | 76 | void unlink(); 77 | 78 | void addInEdge(Edge* edge); 79 | void removeInEdge(Edge* edge); 80 | void addOutEdge(Edge* edge); 81 | void removeOutEdge(Edge* edge); 82 | 83 | Graph* m_parent = nullptr; 84 | EdgeSet m_inEdges; 85 | EdgeSet m_outEdges; 86 | }; 87 | 88 | } 89 | 90 | #endif // ADE_NODE_HPP 91 | -------------------------------------------------------------------------------- /sources/ade/include/ade/passes/check_cycles.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file check_cycles.hpp 8 | 9 | #ifndef ADE_CHECK_CYCLES_HPP 10 | #define ADE_CHECK_CYCLES_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/passes/pass_base.hpp" 16 | 17 | namespace ade 18 | { 19 | 20 | namespace passes 21 | { 22 | class CycleFound : public std::exception 23 | { 24 | public: 25 | virtual const char* what() const noexcept override; 26 | }; 27 | 28 | struct CheckCycles 29 | { 30 | void operator()(const PassContext& context) const; 31 | static std::string name(); 32 | }; 33 | } 34 | } 35 | 36 | #endif // ADE_CHECK_CYCLES_HPP 37 | -------------------------------------------------------------------------------- /sources/ade/include/ade/passes/communications.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file communications.hpp 8 | 9 | #ifndef ADE_COMMUNICATIONS_HPP 10 | #define ADE_COMMUNICATIONS_HPP 11 | 12 | #include "ade/passes/pass_base.hpp" 13 | 14 | #include "ade/metatypes/metatypes.hpp" 15 | 16 | namespace ade 17 | { 18 | namespace passes 19 | { 20 | 21 | struct ConnectCommChannels final 22 | { 23 | using Context = ade::passes::TypedPassContext; 30 | void operator()(Context ctx) const; 31 | static const char* name(); 32 | }; 33 | 34 | } 35 | } 36 | 37 | #endif // ADE_COMMUNICATIONS_HPP 38 | -------------------------------------------------------------------------------- /sources/ade/include/ade/passes/pass_base.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file pass_base.hpp 8 | 9 | #ifndef ADE_PASS_BASE_HPP 10 | #define ADE_PASS_BASE_HPP 11 | 12 | namespace ade 13 | { 14 | 15 | class Graph; 16 | 17 | template 18 | class TypedGraph; 19 | 20 | namespace passes 21 | { 22 | struct PassContext 23 | { 24 | Graph& graph; 25 | }; 26 | 27 | template 28 | struct TypedPassContext 29 | { 30 | TypedGraph graph; 31 | 32 | TypedPassContext(PassContext& context): 33 | graph(context.graph) {} 34 | }; 35 | 36 | } 37 | 38 | } 39 | 40 | 41 | #endif // ADE_PASS_BASE_HPP 42 | -------------------------------------------------------------------------------- /sources/ade/include/ade/passes/topological_sort.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file topological_sort.hpp 8 | 9 | #ifndef ADE_TOPOLOGICAL_SORT_HPP 10 | #define ADE_TOPOLOGICAL_SORT_HPP 11 | 12 | #include 13 | #include "utility" 14 | 15 | #include "ade/node.hpp" 16 | 17 | #include "ade/typed_graph.hpp" 18 | #include "ade/passes/pass_base.hpp" 19 | 20 | #include "ade/util/range.hpp" 21 | #include "ade/util/filter_range.hpp" 22 | 23 | namespace ade 24 | { 25 | namespace passes 26 | { 27 | 28 | struct TopologicalSortData final 29 | { 30 | struct NodesFilter final 31 | { 32 | bool operator()(const ade::NodeHandle& node) const 33 | { 34 | return nullptr != node; 35 | } 36 | }; 37 | 38 | using NodesList = std::vector; 39 | using NodesRange = util::FilterRange, NodesFilter>; 40 | 41 | TopologicalSortData(const NodesList& nodes_): 42 | m_nodes(nodes_) {} 43 | 44 | TopologicalSortData(NodesList&& nodes_): 45 | m_nodes(std::move(nodes_)) {} 46 | 47 | NodesRange nodes() const 48 | { 49 | return util::filter(util::toRange(m_nodes)); 50 | } 51 | 52 | static const char* name(); 53 | 54 | private: 55 | NodesList m_nodes; 56 | }; 57 | 58 | struct TopologicalSort final 59 | { 60 | void operator()(TypedPassContext context) const; 61 | static const char* name(); 62 | }; 63 | 64 | struct LazyTopologicalSortChecker final 65 | { 66 | bool nodeCreated(const Graph& graph, const NodeHandle& node); 67 | bool nodeAboutToBeDestroyed(const Graph& graph, const NodeHandle& node); 68 | 69 | bool edgeCreated(const Graph&, const EdgeHandle& edge); 70 | bool edgeAboutToBeDestroyed(const Graph& graph, const EdgeHandle& edge); 71 | bool edgeAboutToBeRelinked(const Graph& graph, 72 | const EdgeHandle& edge, 73 | const NodeHandle& newSrcNode, 74 | const NodeHandle& newDstNode); 75 | }; 76 | 77 | } 78 | } 79 | 80 | #endif // ADE_TOPOLOGICAL_SORT_HPP 81 | -------------------------------------------------------------------------------- /sources/ade/include/ade/passmanager.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file passmanager.hpp 8 | 9 | #ifndef ADE_PASSMANAGER_HPP 10 | #define ADE_PASSMANAGER_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "util/assert.hpp" 20 | #include "util/range.hpp" 21 | 22 | namespace ade 23 | { 24 | 25 | template 26 | class PassList; 27 | 28 | template 29 | class PassManager final 30 | { 31 | public: 32 | using StageList = std::list>>; 33 | using StagesRange = util::IterRange; 34 | using StagesCRange = util::IterRange; 35 | 36 | PassManager() = default; 37 | PassManager(PassManager&&) = default; 38 | PassManager& operator=(PassManager&&) = default; 39 | 40 | void addStage(const std::string& stageName, const std::string& prevStage) 41 | { 42 | ADE_ASSERT(!stageName.empty()); 43 | ADE_ASSERT(!prevStage.empty()); 44 | ADE_ASSERT(!hasStage(stageName)); 45 | ADE_ASSERT(hasStage(prevStage)); 46 | auto it = m_stagesMap.find(prevStage)->second; 47 | 48 | ++it; 49 | m_stages.insert(it, std::make_pair(stageName, PassList{})); 50 | --it; 51 | m_stagesMap.insert(std::make_pair(stageName, it)); //TODO: exception safety 52 | } 53 | void addStage(const std::string& stageName) 54 | { 55 | ADE_ASSERT(!stageName.empty()); 56 | ADE_ASSERT(!hasStage(stageName)); 57 | m_stages.emplace_back(std::make_pair(stageName, PassList{})); 58 | auto it = m_stages.end(); 59 | --it; 60 | m_stagesMap.insert(std::make_pair(stageName, it)); //TODO: exception safety 61 | } 62 | 63 | PassList& getStage(const std::string& stageName) 64 | { 65 | auto it = m_stagesMap.find(stageName); 66 | ADE_ASSERT(m_stagesMap.end() != it); 67 | return (*it->second).second; 68 | } 69 | 70 | 71 | template 72 | void addPass(const std::string& stageName, T&& pass) 73 | { 74 | auto& stage = getStage(stageName); 75 | stage.addPass(std::forward(pass)); 76 | } 77 | 78 | void run(Context& context) 79 | { 80 | for (auto& pass: m_stages) 81 | { 82 | pass.second.run(context); 83 | } 84 | } 85 | 86 | StagesRange stages() 87 | { 88 | return util::toRange(m_stages); 89 | } 90 | 91 | StagesCRange stages() const 92 | { 93 | return util::toRange(m_stages); 94 | } 95 | 96 | private: 97 | PassManager(const PassManager&) = delete; 98 | PassManager& operator=(const PassManager&) = delete; 99 | 100 | bool hasStage(const std::string& name) const 101 | { 102 | return m_stagesMap.end() != m_stagesMap.find(name); 103 | } 104 | 105 | StageList m_stages; 106 | using StageMap = std::unordered_map; 107 | StageMap m_stagesMap; 108 | }; 109 | 110 | namespace detail 111 | { 112 | template 113 | class PassConceptBase 114 | { 115 | public: 116 | virtual ~PassConceptBase() {} 117 | virtual void run(Context& context) = 0; 118 | }; 119 | 120 | template 121 | class PassConceptImpl : public PassConceptBase 122 | { 123 | PassT m_pass; 124 | public: 125 | template 126 | PassConceptImpl(T&& pass): m_pass(std::forward(pass)) {} 127 | 128 | virtual void run(Context& context) override 129 | { 130 | m_pass(context); 131 | } 132 | }; 133 | } 134 | 135 | template 136 | class PassList final 137 | { 138 | public: 139 | PassList() = default; 140 | PassList(PassList&&) = default; 141 | PassList& operator=(PassList&&) = default; 142 | 143 | template 144 | void addPass(PassT&& pass) 145 | { 146 | m_passes.emplace_back(new detail::PassConceptImpl(std::forward(pass))); 147 | } 148 | 149 | void run(Context& context) 150 | { 151 | for (auto& pass: m_passes) 152 | { 153 | pass->run(context); 154 | } 155 | } 156 | 157 | private: 158 | PassList(const PassList&) = delete; 159 | PassList& operator=(const PassList&) = delete; 160 | 161 | std::vector>> m_passes; 162 | }; 163 | 164 | } 165 | 166 | #endif // ADE_PASSMANAGER_HPP 167 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/assert.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file assert.hpp 8 | 9 | #ifndef ADE_UTIL_ASSERT_HPP 10 | #define ADE_UTIL_ASSERT_HPP 11 | 12 | #include 13 | #include 14 | 15 | #if defined(_MSC_VER) 16 | #define ade_unreachable() __assume(0) 17 | #elif defined(__GNUC__) 18 | #define ade_unreachable() __builtin_unreachable() 19 | #else 20 | #define ade_unreachable() do{}while(false) 21 | #endif 22 | 23 | namespace ade 24 | { 25 | namespace details 26 | { 27 | [[noreturn]] void dev_assert_abort(const char* str, int line, const char* file, 28 | const char* func); 29 | [[noreturn]] void dev_exception_abort(const char* str); 30 | } // namespace details 31 | } // namespace ade 32 | 33 | /// ADE assertion. 34 | /// Alias to standard assert in regular builds. 35 | /// Replaced with stringer version, working in release builds when 36 | /// FORCE_ADE_ASSERTS=ON 37 | /// 38 | /// @param expr Expression convertible to bool 39 | #if defined(FORCE_ADE_ASSERTS) 40 | #define ADE_ASSERT(expr) \ 41 | do { if (!(expr)) ::ade::details::dev_assert_abort( \ 42 | #expr, __LINE__, __FILE__, __func__); \ 43 | }while(false) 44 | #else 45 | #define ADE_ASSERT(expr) do { \ 46 | constexpr bool _assert_tmp = false && (expr); \ 47 | (void) _assert_tmp; \ 48 | assert(expr); \ 49 | } while(false) 50 | #endif 51 | 52 | /// Stronger version of assert which translates to compiler hint in optimized 53 | /// builds. Do not use it if you have subsequent error recovery code because 54 | /// this code can be optimized away. 55 | /// Expression is always evaluated, avoid functions calls in it. 56 | /// Static analyzers friendly and can silence "possible null pointer 57 | /// dereference" warnings. 58 | /// 59 | /// @param expr Expression convertible to bool 60 | #if defined(FORCE_ADE_ASSERTS) || !defined(NDEBUG) 61 | #define ADE_ASSERT_STRONG(expr) ADE_ASSERT(expr) 62 | #else 63 | #define ADE_ASSERT_STRONG(expr) do{ if(!(expr)) { ade_unreachable(); } }while(false) 64 | #endif 65 | 66 | /// Mark current location is not supposed to be reachable. 67 | /// Depending of FORCE_ADE_ASSERTS flag can be translated into assert or 68 | /// compiler hint. 69 | /// 70 | /// @param str String description. 71 | #define ADE_UNREACHABLE(str) ADE_ASSERT_STRONG(!str) 72 | 73 | /// Mark variable UNUSED, suitable if it is used only in ADE_ASSERT 74 | /// 75 | /// @param x Variable to mark 76 | #define ADE_UNUSED(x) (void)(x) 77 | 78 | namespace ade 79 | { 80 | /// Convenient function for exception throwing. 81 | /// Throws provided exceptions object if exceptions are enabled in compiler 82 | /// aborts othervise. 83 | /// 84 | /// @param e Exception object. 85 | template 86 | [[noreturn]] void throw_error(ExceptionType &&e) 87 | { 88 | #if defined(__EXCEPTIONS) || defined(_CPPUNWIND) 89 | throw std::forward(e); 90 | #else 91 | ::ade::details::dev_exception_abort(e.what()); 92 | #endif 93 | } 94 | } // namespace ade 95 | 96 | #endif // ADE_UTIL_ASSERT_HPP 97 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/chain_range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file chain_range.hpp 8 | 9 | #ifndef ADE_UTIL_CHAIN_RANGE_HPP 10 | #define ADE_UTIL_CHAIN_RANGE_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/util/range.hpp" 16 | #include "ade/util/type_traits.hpp" 17 | #include "ade/util/assert.hpp" 18 | #include "ade/util/range_iterator.hpp" 19 | 20 | namespace ade 21 | { 22 | namespace util 23 | { 24 | inline namespace Range 25 | { 26 | template 27 | struct ChainRange : public IterableRange> 28 | { 29 | Range1 range1; 30 | Range2 range2; 31 | 32 | ChainRange() = default; 33 | ChainRange(const ChainRange&) = default; 34 | ChainRange(ChainRange&&) = default; 35 | ChainRange& operator=(const ChainRange&) = default; 36 | ChainRange& operator=(ChainRange&&) = default; 37 | 38 | template 39 | ChainRange(R1&& r1, R2&& r2): 40 | range1(std::forward(r1)), 41 | range2(std::forward(r2)) 42 | { 43 | 44 | } 45 | 46 | // common_type will strip references from types but we want to retain them 47 | // if types exactly the same 48 | template 49 | using return_type_helper_t = typename std::conditional< 50 | std::is_same::value, 51 | First, 52 | util::common_type_t 53 | >::type; 54 | 55 | bool empty() const 56 | { 57 | return range1.empty() && range2.empty(); 58 | } 59 | 60 | void popFront() 61 | { 62 | ADE_ASSERT(!empty()); 63 | if (!range1.empty()) 64 | { 65 | range1.popFront(); 66 | } 67 | else 68 | { 69 | range2.popFront(); 70 | } 71 | } 72 | 73 | auto front() 74 | ->return_type_helper_trange1.front()),decltype(this->range2.front())> 75 | { 76 | ADE_ASSERT(!empty()); 77 | if (!range1.empty()) 78 | { 79 | return range1.front(); 80 | } 81 | return range2.front(); 82 | } 83 | 84 | auto front() const 85 | ->return_type_helper_trange1.front()),decltype(this->range2.front())> 86 | { 87 | ADE_ASSERT(!empty()); 88 | if (!range1.empty()) 89 | { 90 | return range1.front(); 91 | } 92 | return range2.front(); 93 | } 94 | 95 | template::value && 97 | details::has_size_fun::value)> = true> //SFINAE 98 | auto size() const 99 | ->util::common_type_t())), 100 | decltype(details::range_size_wrapper(std::declval()))> 101 | { 102 | return details::range_size_wrapper(range1) + details::range_size_wrapper(range2); 103 | } 104 | 105 | template()[0]) > 0 && 107 | sizeof(std::declval()[0]) > 0)> = true> //SFINAE 108 | auto operator[](std::size_t index) 109 | ->return_type_helper_t()[0]),decltype(std::declval()[0])> 110 | { 111 | ADE_ASSERT(index < size()); 112 | const auto size1 = details::range_size_wrapper(range1); 113 | if (index < size1) 114 | { 115 | return range1[index]; 116 | } 117 | return range2[index - size1]; 118 | } 119 | 120 | template()[0]) > 0 && 122 | sizeof(std::declval()[0]) > 0)> = true> //SFINAE 123 | auto operator[](std::size_t index) const 124 | ->return_type_helper_t()[0]),decltype(std::declval()[0])> 125 | { 126 | ADE_ASSERT(index < size()); 127 | const auto size1 = details::range_size_wrapper(range1); 128 | if (index < size1) 129 | { 130 | return range1[index]; 131 | } 132 | return range2[index - size1]; 133 | } 134 | }; 135 | 136 | template 137 | inline auto size(const ChainRange& range) 138 | ->decltype(range.size()) 139 | { 140 | return range.size(); 141 | } 142 | 143 | template 144 | struct chain_type; 145 | 146 | template 147 | struct chain_type { using type = remove_reference_t; }; 148 | 149 | template 150 | struct chain_type 151 | { 152 | using type = ChainRange, 153 | typename chain_type, remove_reference_t...>::type>; 154 | }; 155 | 156 | template 157 | auto chain(Range&& r) 158 | ->typename chain_type::type 159 | { 160 | return std::forward(r); 161 | } 162 | 163 | template 164 | auto chain(Range1&& r1, Range2&& r2, Ranges&&... ranges) 165 | ->typename chain_type::type 166 | { 167 | using RangeT = typename chain_type::type; 168 | return RangeT(std::forward(r1), chain(std::forward(r2), std::forward(ranges)...)); 169 | } 170 | 171 | } 172 | } 173 | } // namespace ade 174 | 175 | #endif // ADE_UTIL_CHAIN_RANGE_HPP 176 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/checked_cast.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file checked_cast.hpp 8 | 9 | #ifndef ADE_UTIL_CHECKED_CAST_HPP 10 | #define ADE_UTIL_CHECKED_CAST_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/util/assert.hpp" 16 | 17 | #undef min 18 | #undef max 19 | 20 | namespace ade 21 | { 22 | namespace util 23 | { 24 | 25 | template 26 | inline typename std::enable_if< std::is_same::value, I >::type 27 | checked_cast_impl(J value, Handler&& /*handler*/) 28 | { 29 | return value; 30 | } 31 | 32 | template 33 | inline typename std::enable_if< 34 | std::is_integral::value && std::is_integral::value && 35 | std::is_signed::value && std::is_signed::value && 36 | !std::is_same::value, 37 | I 38 | >::type checked_cast_impl(J value, Handler&& handler) 39 | { 40 | handler(value >= std::numeric_limits::lowest() && value <= std::numeric_limits::max(), value); 41 | return static_cast(value); 42 | } 43 | 44 | template 45 | inline typename std::enable_if< 46 | std::is_integral::value && std::is_integral::value && 47 | std::is_signed::value && std::is_unsigned::value, 48 | I 49 | >::type checked_cast_impl(J value, Handler&& handler) 50 | { 51 | handler(value <= static_cast::type>(std::numeric_limits::max()), value); 52 | return static_cast(value); 53 | } 54 | 55 | template 56 | inline typename std::enable_if< 57 | std::is_integral::value && std::is_integral::value && 58 | std::is_unsigned::value && std::is_signed::value, 59 | I 60 | >::type checked_cast_impl(J value, Handler&& handler) 61 | { 62 | handler(value >= 0 && static_cast::type>(value) <= std::numeric_limits::max(), value); 63 | return static_cast(value); 64 | } 65 | 66 | template 67 | inline typename std::enable_if< 68 | std::is_integral::value && std::is_integral::value && 69 | std::is_unsigned::value && std::is_unsigned::value && 70 | !std::is_same::value, 71 | I 72 | >::type checked_cast_impl(J value, Handler&& handler) 73 | { 74 | handler(value <= std::numeric_limits::max(), value); 75 | return static_cast(value); 76 | } 77 | 78 | template 79 | inline typename std::enable_if< 80 | std::is_integral::value && std::is_floating_point::value, 81 | I 82 | >::type checked_cast_impl(J value, Handler&& handler) 83 | { 84 | // This criterion may fail in the following corner cases: (1) if I=int32_t, J=float, and value=2^31 (2) if I=int64_t, J=float, and value=2^63 (3) ...etc... 85 | // For example, consider I=int and J=float and value=2^31 Due to rounding, (float)INT32_MAX equals 2^31, not 2^31-1 So checking if value <= INT32_MAX would incorrectly pass 86 | // Well, I am not sure if we should especially address this corner case If you think we should, 87 | // we may need especial floating-point constants for upper boundaries Note that this problem does not impact the lower boundaries, which are exactly -2^31, -2^63, etc 88 | handler(value <= static_cast(std::numeric_limits::max()) && value >= static_cast(std::numeric_limits::lowest()), value); 89 | return static_cast(value); 90 | } 91 | 92 | template 93 | inline typename std::enable_if< 94 | std::is_same::value && std::is_same::value, 95 | I 96 | >::type checked_cast_impl(J value, Handler&& handler) 97 | { 98 | handler(static_cast(static_cast(value)) == value, value); 99 | return static_cast(value); 100 | } 101 | 102 | struct CheckedCastDefHandler final 103 | { 104 | template 105 | void operator()(bool valid, T&& /*value*/) const 106 | { 107 | ADE_UNUSED(valid); 108 | ADE_ASSERT(valid); 109 | } 110 | }; 111 | 112 | template 113 | I checked_cast(J value) 114 | { 115 | return checked_cast_impl(value, CheckedCastDefHandler{}); 116 | } 117 | 118 | } // namespace util 119 | } // namespace ade 120 | 121 | #endif // ADE_UTIL_CHECKED_CAST_HPP 122 | 123 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/container_helper.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file container_helper.hpp 8 | 9 | #ifndef ADE_UTIL_CONTAINER_HELPER_HPP 10 | #define ADE_UTIL_CONTAINER_HELPER_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "util/memory_range.hpp" 16 | 17 | namespace ade 18 | { 19 | namespace util 20 | { 21 | 22 | template 23 | inline auto data(const std::vector& vector) -> decltype(vector.data()) 24 | { 25 | return vector.data(); 26 | } 27 | 28 | template 29 | inline std::size_t size(const std::vector& vector) 30 | { 31 | return vector.size(); 32 | } 33 | 34 | template 35 | inline auto slice(const std::vector& vector, const std::size_t start, const std::size_t newSize) 36 | ->decltype(memory_range(data(vector), size(vector)).Slice(start, newSize)) 37 | { 38 | return memory_range(data(vector), size(vector)).Slice(start, newSize); 39 | } 40 | 41 | template 42 | inline auto data(const std::array& arr) -> decltype(arr.data()) 43 | { 44 | return arr.data(); 45 | } 46 | 47 | template 48 | inline std::size_t size(const std::array& arr) 49 | { 50 | return arr.size(); 51 | } 52 | 53 | template 54 | inline auto slice(const std::array& arr, const std::size_t start, const std::size_t newSize) 55 | ->decltype(memory_range(data(arr), size(arr)).Slice(start, newSize)) 56 | { 57 | return memory_range(data(arr), size(arr)).Slice(start, newSize); 58 | } 59 | 60 | } 61 | } // namespace ade 62 | 63 | #endif // ADE_UTIL_CONTAINER_HELPER_HPP 64 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/filter_range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file filter_range.hpp 8 | 9 | #ifndef ADE_UTIL_FILTER_RANGE_HPP 10 | #define ADE_UTIL_FILTER_RANGE_HPP 11 | 12 | #include "ade/util/tuple.hpp" 13 | #include "ade/util/range.hpp" 14 | #include "ade/util/assert.hpp" 15 | #include "ade/util/iota_range.hpp" 16 | #include "ade/util/range_iterator.hpp" 17 | 18 | namespace ade 19 | { 20 | namespace util 21 | { 22 | 23 | inline namespace Range 24 | { 25 | 26 | template 27 | struct FilterRange : public IterableRange> 28 | { 29 | PrevRange prevRange; 30 | Filter filter; // TODO: implement size optimization for empty objects 31 | 32 | FilterRange() = default; 33 | FilterRange(const FilterRange&) = default; 34 | FilterRange(FilterRange&&) = default; 35 | FilterRange& operator=(const FilterRange&) = default; 36 | FilterRange& operator=(FilterRange&&) = default; 37 | template 38 | FilterRange(PR&& pr, F&& f): 39 | prevRange(std::forward(pr)), 40 | filter(std::forward(f)) 41 | { 42 | while (!prevRange.empty() && !filter(prevRange.front())) 43 | { 44 | prevRange.popFront(); 45 | } 46 | } 47 | 48 | bool empty() const 49 | { 50 | return prevRange.empty(); 51 | } 52 | 53 | void popFront() 54 | { 55 | ADE_ASSERT(!empty()); 56 | prevRange.popFront(); 57 | while (!prevRange.empty() && !filter(prevRange.front())) 58 | { 59 | prevRange.popFront(); 60 | } 61 | } 62 | 63 | auto front() -> decltype(this->prevRange.front()) 64 | { 65 | ADE_ASSERT(!empty()); 66 | return prevRange.front(); 67 | } 68 | 69 | auto front() const -> decltype(this->prevRange.front()) 70 | { 71 | ADE_ASSERT(!empty()); 72 | return prevRange.front(); 73 | } 74 | }; 75 | 76 | template 77 | FilterRange filter(PrevRange&& prevRange, Filter&& filter_) 78 | { 79 | return FilterRange(std::forward(prevRange), std::forward(filter_)); 80 | } 81 | 82 | template 83 | FilterRange filter(PrevRange&& prevRange) 84 | { 85 | return FilterRange(std::forward(prevRange), Filter()); 86 | } 87 | 88 | } 89 | } 90 | } // namespace ade 91 | 92 | #endif // ADE_UTIL_FILTER_RANGE_HPP 93 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/func_ref.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file func_ref.hpp 8 | 9 | #ifndef ADE_UTIL_FUNC_REF_HPP 10 | #define ADE_UTIL_FUNC_REF_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/util/type_traits.hpp" 16 | #include "ade/util/assert.hpp" 17 | 18 | namespace ade 19 | { 20 | namespace util 21 | { 22 | template 23 | class func_ref; // undefined 24 | 25 | /// Non-owning callable wrapper 26 | template 27 | class func_ref 28 | { 29 | using func_t = R(*)(uintptr_t, Args...); 30 | uintptr_t m_context = 0; 31 | func_t m_func = nullptr; 32 | 33 | template 34 | static R thunk(uintptr_t context, Args... args) 35 | { 36 | T* obj = reinterpret_cast(context); 37 | return (*obj)(std::forward(args)...); 38 | } 39 | 40 | public: 41 | template 42 | func_ref(Callable&& callable): 43 | m_context(reinterpret_cast(&callable)), 44 | m_func(&thunk>) 45 | { 46 | using actual_result_type = util::result_of_t; 47 | 48 | // If this condition doesn't hold, then thunk will return a reference 49 | // to the temporary returned by callable. 50 | static_assert( 51 | !std::is_reference::value || std::is_reference::value, 52 | "If R is a reference, callable must also return a reference"); 53 | } 54 | 55 | R operator()(Args... args) const 56 | { 57 | ADE_ASSERT(0 != m_context); 58 | ADE_ASSERT(nullptr != m_func); 59 | return m_func(m_context, std::forward(args)...); 60 | } 61 | }; 62 | } 63 | } // namespace ade 64 | 65 | #endif // ADE_UTIL_FUNC_REF_HPP 66 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/hash.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file hash.hpp 8 | 9 | #ifndef ADE_HASH_HPP 10 | #define ADE_HASH_HPP 11 | 12 | #include //size_t 13 | 14 | namespace ade 15 | { 16 | namespace util 17 | { 18 | 19 | /// Combines hash with seed. 20 | /// Suitable for combining multiple hashes together. 21 | /// 22 | /// @param seed 23 | /// @param hash 24 | /// @return Resulting hash 25 | inline std::size_t hash_combine(std::size_t seed, std::size_t val) 26 | { 27 | // Hash combine formula from boost 28 | return seed ^ (val + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 29 | } 30 | } // namespace util 31 | } // namespace ade 32 | 33 | #endif // ADE_HASH_HPP 34 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/iota_range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file iota_range.hpp 8 | 9 | #ifndef ADE_UTIL_IOTA_RANGE_HPP 10 | #define ADE_UTIL_IOTA_RANGE_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace ade 18 | { 19 | namespace util 20 | { 21 | 22 | inline namespace Range 23 | { 24 | 25 | template 26 | struct IotaRange 27 | { 28 | static_assert(std::is_integral::value,"T must be integral"); 29 | 30 | inline void check() const 31 | { 32 | if ( step > 0) 33 | { 34 | assert(to >= from); 35 | } 36 | else if (step < 0) 37 | { 38 | assert(from >= to); 39 | } 40 | else assert(!"Zero step"); 41 | 42 | assert(0 == ((to - from) % step)); 43 | } 44 | 45 | struct iterator 46 | { 47 | inline bool operator==(iterator const& other) const 48 | { 49 | return value == other.value; 50 | } 51 | 52 | inline bool operator!=(iterator const& other) const 53 | { 54 | return value != other.value; 55 | } 56 | 57 | inline T const& operator*() const 58 | { 59 | return value; 60 | } 61 | 62 | inline iterator& operator++() 63 | { 64 | value += step; 65 | return *this; 66 | } 67 | 68 | T value; 69 | }; 70 | 71 | bool empty() const 72 | { 73 | return to == from; 74 | } 75 | 76 | const T& front() const 77 | { 78 | assert(!empty()); 79 | return from; 80 | } 81 | 82 | void popFront() 83 | { 84 | assert(!empty()); 85 | from += step; 86 | } 87 | 88 | inline iterator begin() const 89 | { 90 | check(); 91 | return {from}; 92 | } 93 | 94 | inline iterator end() const 95 | { 96 | check(); 97 | return {to}; 98 | } 99 | 100 | bool operator==(const IotaRange& rhs) const 101 | { 102 | return from == rhs.from && to == rhs.to; 103 | } 104 | bool operator!=(const IotaRange& rhs) const 105 | { 106 | return !(*this == rhs); 107 | } 108 | 109 | /*const*/ T from; 110 | const T to; 111 | }; 112 | 113 | template 114 | struct IotaRange 115 | { 116 | static_assert(std::is_integral::value,"T must be integral"); 117 | 118 | inline void check() const 119 | { 120 | if ( step > 0) 121 | { 122 | assert(to >= from); 123 | } 124 | else if (step < 0) 125 | { 126 | assert(from >= to); 127 | } 128 | else assert(!"Zero step"); 129 | 130 | assert(0 == ((to - from) % step)); 131 | } 132 | 133 | struct iterator 134 | { 135 | inline bool operator==(iterator const& other) const 136 | { 137 | assert(step == other.step); 138 | return value == other.value; 139 | } 140 | 141 | inline bool operator!=(iterator const& other) const 142 | { 143 | assert(step == other.step); 144 | return value != other.value; 145 | } 146 | 147 | inline T const& operator*() const 148 | { 149 | return value; 150 | } 151 | 152 | inline iterator& operator++() 153 | { 154 | value += step; 155 | return *this; 156 | } 157 | 158 | T value; 159 | T step; 160 | }; 161 | 162 | bool empty() const 163 | { 164 | return to == from; 165 | } 166 | 167 | const T& front() const 168 | { 169 | assert(!empty()); 170 | return from; 171 | } 172 | 173 | void popFront() 174 | { 175 | assert(!empty()); 176 | from += step; 177 | } 178 | 179 | inline iterator begin() const 180 | { 181 | check(); 182 | return {from, step}; 183 | } 184 | 185 | inline iterator end() const 186 | { 187 | check(); 188 | return {to, step}; 189 | } 190 | 191 | bool operator==(const IotaRange& rhs) const 192 | { 193 | return from == rhs.from && to == rhs.to && step == rhs.step; 194 | } 195 | bool operator!=(const IotaRange& rhs) const 196 | { 197 | return !(*this == rhs); 198 | } 199 | 200 | /*const*/ T from; 201 | const T to; 202 | const T step; 203 | }; 204 | 205 | template 206 | inline IotaRange iota() 207 | { return { 0, std::numeric_limits::max()}; } 208 | 209 | template 210 | inline IotaRange iota(const T to) 211 | { return { 0, to}; } 212 | 213 | template 214 | inline IotaRange iota(const T from, const T to) 215 | { return {from, to}; } 216 | 217 | template 218 | inline IotaRange iota(const T from, const T to, const T step) 219 | { return {from, to, step}; } 220 | 221 | } 222 | } 223 | } // namespace ade 224 | 225 | #endif // ADE_UTIL_IOTA_RANGE_HPP 226 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/map_range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file map_range.hpp 8 | 9 | #ifndef ADE_UTIL_MAP_RANGE_HPP 10 | #define ADE_UTIL_MAP_RANGE_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "ade/util/type_traits.hpp" 17 | #include "ade/util/range.hpp" 18 | #include "ade/util/assert.hpp" 19 | #include "ade/util/range_iterator.hpp" 20 | 21 | namespace ade 22 | { 23 | namespace util 24 | { 25 | 26 | inline namespace Range 27 | { 28 | 29 | template 30 | struct MapRange : public IterableRange> 31 | { 32 | PrevRange prevRange; 33 | Mapper mapper; // TODO: implement size optimization for empty objects 34 | 35 | MapRange() = default; 36 | MapRange(const MapRange&) = default; 37 | MapRange(MapRange&&) = default; 38 | MapRange& operator=(const MapRange&) = default; 39 | MapRange& operator=(MapRange&&) = default; 40 | template 41 | MapRange(PR&& pr, M&& m): 42 | prevRange(std::forward(pr)), 43 | mapper(std::forward(m)) {} 44 | 45 | bool empty() const 46 | { 47 | return prevRange.empty(); 48 | } 49 | 50 | void popFront() 51 | { 52 | ADE_ASSERT(!empty()); 53 | prevRange.popFront(); 54 | } 55 | 56 | auto front() -> typename std::decay::type 57 | { 58 | ADE_ASSERT(!empty()); 59 | return mapper(prevRange.front()); 60 | } 61 | 62 | auto front() const -> typename std::decay::type 63 | { 64 | ADE_ASSERT(!empty()); 65 | return mapper(prevRange.front()); 66 | } 67 | 68 | template::value> = true> //SFINAE 70 | auto size() const 71 | ->decltype(details::range_size_wrapper(std::declval())) 72 | { 73 | return details::range_size_wrapper(prevRange); 74 | } 75 | }; 76 | 77 | template 78 | inline auto size(const MapRange& range) 79 | ->decltype(range.size()) 80 | { 81 | return range.size(); 82 | } 83 | 84 | template 85 | MapRange map(PrevRange&& prevRange, Mapper&& mapper) 86 | { 87 | return MapRange(std::forward(prevRange), std::forward(mapper)); 88 | } 89 | 90 | template 91 | MapRange map(PrevRange&& prevRange) 92 | { 93 | return MapRange(std::forward(prevRange), Mapper()); 94 | } 95 | 96 | } 97 | } 98 | } // namespace ade 99 | 100 | #endif // ADE_UTIL_MAP_RANGE_HPP 101 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/math.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file math.hpp 8 | 9 | #ifndef ADE_UTIL_MATH_HPP 10 | #define ADE_UTIL_MATH_HPP 11 | 12 | #include 13 | 14 | #include "ade/util/assert.hpp" 15 | 16 | namespace ade 17 | { 18 | namespace util 19 | { 20 | template 21 | inline auto is_pow2(T val) 22 | ->typename std::enable_if::value, bool>::type 23 | { 24 | return (val & (val - 1)) == 0; 25 | } 26 | 27 | template 28 | inline auto align_size(T size, T align) 29 | ->typename std::enable_if::value, T>::type 30 | { 31 | ADE_ASSERT(size > 0); 32 | ADE_ASSERT(align > 0); 33 | ADE_ASSERT(is_pow2(align)); 34 | return (size + (align - 1)) & ~(align - 1); 35 | } 36 | 37 | } 38 | } // namespace ade 39 | 40 | #endif // ADE_UTIL_MATH_HPP 41 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/md_cast.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file md_cast.hpp 8 | 9 | #ifndef ADE_UTIL_MD_CAST_HPP 10 | #define ADE_UTIL_MD_CAST_HPP 11 | 12 | namespace ade 13 | { 14 | namespace util 15 | { 16 | // TODO: find a proper place for this 17 | constexpr static const std::size_t MaxDimensions = 6; 18 | 19 | namespace detail 20 | { 21 | template 22 | struct md_cast_helper; // Undefined 23 | } 24 | 25 | template 26 | Dst md_cast(const Src& src) 27 | { 28 | return detail::md_cast_helper(src); 29 | } 30 | } 31 | } // namespace ade 32 | 33 | #endif // ADE_UTIL_MD_CAST_HPP 34 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/md_io.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file md_io.hpp 8 | 9 | #ifndef ADE_UTIL_MD_IO_HPP 10 | #define ADE_UTIL_MD_IO_HPP 11 | 12 | #include 13 | 14 | #include "ade/util/md_size.hpp" 15 | #include "ade/util/md_span.hpp" 16 | 17 | // md_* stream operators 18 | 19 | namespace ade 20 | { 21 | namespace util 22 | { 23 | 24 | inline std::ostream& operator<<(std::ostream& os, const Span& span) 25 | { 26 | os << "{" << span.begin << ", " << span.end << "}"; 27 | return os; 28 | } 29 | 30 | template 31 | inline std::ostream& operator<<(std::ostream& os, const DynMdSize& size) 32 | { 33 | os << "{"; 34 | for (auto i: util::iota(size.dims_count())) 35 | { 36 | // TODO: join range 37 | if (0 != i) 38 | { 39 | os << ", "; 40 | } 41 | os << size[i]; 42 | } 43 | os << "}"; 44 | return os; 45 | } 46 | 47 | template 48 | inline std::ostream& operator<<(std::ostream& os, const DynMdSpan& span) 49 | { 50 | os << "{"; 51 | for (auto i: util::iota(span.dims_count())) 52 | { 53 | // TODO: join range 54 | if (0 != i) 55 | { 56 | os << ", "; 57 | } 58 | os << span[i]; 59 | } 60 | os << "}"; 61 | return os; 62 | } 63 | 64 | } 65 | } // namespace ade 66 | 67 | #endif // ADE_UTIL_MD_IO_HPP 68 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/md_size.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file md_size.hpp 8 | 9 | #ifndef ADE_UTIL_MD_SIZE_HPP 10 | #define ADE_UTIL_MD_SIZE_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "ade/util/assert.hpp" 17 | #include "ade/util/iota_range.hpp" 18 | #include "ade/util/checked_cast.hpp" 19 | 20 | namespace ade 21 | { 22 | namespace util 23 | { 24 | 25 | /// Dinamically sized arbitrary dimensional size 26 | template 27 | struct DynMdSize final 28 | { 29 | using SizeT = int; 30 | std::array sizes; 31 | std::size_t dims_cnt = 0; 32 | 33 | DynMdSize() = default; 34 | 35 | DynMdSize(std::initializer_list d): 36 | dims_cnt(util::checked_castdims_cnt)>(d.size())) 37 | { 38 | ADE_ASSERT(d.size() <= MaxDimensions); 39 | std::copy(d.begin(), d.end(), sizes.begin()); 40 | } 41 | 42 | DynMdSize(const DynMdSize&) = default; 43 | DynMdSize& operator=(const DynMdSize&) = default; 44 | 45 | bool operator==(const DynMdSize& other) const 46 | { 47 | if (dims_count() != other.dims_count()) 48 | { 49 | return false; 50 | } 51 | 52 | for (auto i: util::iota(dims_count())) 53 | { 54 | if ((*this)[i] != other[i]) 55 | { 56 | return false; 57 | } 58 | } 59 | return true; 60 | } 61 | 62 | bool operator!=(const DynMdSize& other) const 63 | { 64 | return !(*this == other); 65 | } 66 | 67 | SizeT& operator[](std::size_t index) 68 | { 69 | ADE_ASSERT(index < dims_count()); 70 | return sizes[index]; 71 | } 72 | 73 | const SizeT& operator[](std::size_t index) const 74 | { 75 | ADE_ASSERT(index < dims_count()); 76 | return sizes[index]; 77 | } 78 | 79 | SizeT* data() 80 | { 81 | return sizes.data(); 82 | } 83 | 84 | const SizeT* data() const 85 | { 86 | return sizes.data(); 87 | } 88 | 89 | std::size_t dims_count() const 90 | { 91 | return dims_cnt; 92 | } 93 | 94 | void redim(std::size_t count) 95 | { 96 | ADE_ASSERT(count <= MaxDimensions); 97 | dims_cnt = count; 98 | } 99 | 100 | auto begin() 101 | ->decltype(this->sizes.begin()) 102 | { 103 | return sizes.begin(); 104 | } 105 | 106 | auto end() 107 | ->decltype(this->sizes.begin() + this->dims_count()) 108 | { 109 | return sizes.begin() + dims_count(); 110 | } 111 | 112 | auto begin() const 113 | ->decltype(this->sizes.begin()) 114 | { 115 | return sizes.begin(); 116 | } 117 | 118 | auto end() const 119 | ->decltype(this->sizes.begin() + this->dims_count()) 120 | { 121 | return sizes.begin() + dims_count(); 122 | } 123 | }; 124 | } 125 | } // namespace ade 126 | 127 | #endif // ADE_UTIL_MD_SIZE_HPP 128 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file range.hpp 8 | 9 | #ifndef ADE_UTIL_RANGE_HPP 10 | #define ADE_UTIL_RANGE_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/util/assert.hpp" 16 | #include "ade/util/type_traits.hpp" 17 | 18 | namespace ade 19 | { 20 | namespace util 21 | { 22 | 23 | namespace details 24 | { 25 | struct RangeIncrementer 26 | { 27 | template 28 | void operator()(Rng& range) const 29 | { 30 | range.popFront(); 31 | } 32 | }; 33 | struct RangeChecker 34 | { 35 | bool empty = false; 36 | 37 | template 38 | void operator()(Rng& range) 39 | { 40 | empty = empty || range.empty(); 41 | } 42 | }; 43 | struct RangeCleaner 44 | { 45 | template 46 | void operator()(Rng& range) const 47 | { 48 | range.clear(); 49 | } 50 | }; 51 | 52 | //SFINAE and decltype doesn't work wery well together 53 | // so this additional wrapper is needed 54 | template 55 | struct range_size_wrapper_helper 56 | { 57 | using type = decltype(size(std::declval())); 58 | }; 59 | 60 | template 61 | inline auto range_size_wrapper(const T& r) 62 | ->typename range_size_wrapper_helper::type 63 | { 64 | return size(r); 65 | } 66 | 67 | template 68 | class has_size_fun 69 | { 70 | using y = char; 71 | using n = long; 72 | 73 | template 74 | static y test(decltype(size(std::declval()))*); 75 | template 76 | static n test(...); 77 | public: 78 | static const constexpr bool value = (sizeof(test(0)) == sizeof(y)); 79 | }; 80 | 81 | } 82 | inline namespace Range 83 | { 84 | template 85 | struct IterRange 86 | { 87 | BeginT beginIter; 88 | EndT endIter; 89 | 90 | BeginT begin() const 91 | { 92 | return beginIter; 93 | } 94 | 95 | EndT end() const 96 | { 97 | return endIter; 98 | } 99 | 100 | bool empty() const 101 | { 102 | return beginIter == endIter; 103 | } 104 | 105 | void popFront() 106 | { 107 | ADE_ASSERT(!empty()); 108 | ++beginIter; 109 | } 110 | 111 | auto front() -> decltype(*beginIter) 112 | { 113 | ADE_ASSERT(!empty()); 114 | return *beginIter; 115 | } 116 | 117 | auto front() const -> decltype(*beginIter) 118 | { 119 | ADE_ASSERT(!empty()); 120 | return *beginIter; 121 | } 122 | 123 | bool operator==(const IterRange& rhs) const 124 | { 125 | return beginIter == rhs.beginIter && endIter == rhs.endIter; 126 | } 127 | 128 | bool operator!=(const IterRange& rhs) const 129 | { 130 | return !(*this == rhs); 131 | } 132 | 133 | template() - std::declval()) > 0)> = true> //SFINAE 135 | std::size_t size() const 136 | { 137 | auto diff = endIter - beginIter; 138 | ADE_ASSERT(diff >= 0); 139 | return static_cast(diff); 140 | } 141 | 142 | // TODO: bidirectional and random access ranges 143 | }; 144 | 145 | template 146 | inline auto size(const IterRange& range) 147 | ->decltype(range.size()) 148 | { 149 | return range.size(); 150 | } 151 | 152 | template 153 | inline auto toRange(T&& val) -> IterRange 154 | { 155 | return {std::begin(val), std::end(val)}; 156 | } 157 | 158 | template 159 | inline auto toRangeReverse(T&& val) -> IterRange 160 | { 161 | // TODO: use c++14 std::rbegin, std::rend 162 | return {val.rbegin(), val.rend()}; 163 | } 164 | 165 | template 166 | inline auto toRange(const std::pair& val) -> IterRange 167 | { 168 | return {val.first, val.second}; 169 | } 170 | 171 | template 172 | inline auto toRange(Iter&& val, std::size_t count) -> IterRange, remove_reference_t> 173 | { 174 | return {std::forward(val), std::next(val, count)}; 175 | } 176 | 177 | template 178 | inline auto index(T&& val)->decltype(std::get<0>(std::forward(val))) 179 | { 180 | return std::get<0>(std::forward(val)); 181 | } 182 | 183 | template 184 | inline auto value(T&& val)->decltype(std::get(std::forward(val))) 185 | { 186 | static_assert(I >= 0,"Invalid I"); 187 | return std::get(std::forward(val)); 188 | } 189 | 190 | template 191 | inline void advance_range(Range&& range) 192 | { 193 | range.popFront(); 194 | } 195 | 196 | } 197 | } 198 | } // namespace ade 199 | 200 | #endif // ADE_UTIL_RANGE_HPP 201 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/range_iterator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file range_iterator.hpp 8 | 9 | #ifndef ADE_UTIL_RANGE_ITERATOR_HPP 10 | #define ADE_UTIL_RANGE_ITERATOR_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "ade/util/assert.hpp" 16 | 17 | namespace ade 18 | { 19 | namespace util 20 | { 21 | 22 | inline namespace Range 23 | { 24 | 25 | template 26 | struct IterableRange 27 | { 28 | // This iterator suitable only for range for, handle with care 29 | struct iterator 30 | { 31 | R range; 32 | bool end /*= false*/; // Need C++14 33 | 34 | using value_type = typename std::remove_reference::type; 35 | using pointer = value_type*; 36 | using reference = value_type&; 37 | using iterator_category = std::input_iterator_tag; 38 | using difference_type = std::ptrdiff_t; 39 | 40 | bool operator==(iterator const& other) const 41 | { 42 | if((range.empty() && other.end) || 43 | (end && other.range.empty())) 44 | { 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | bool operator!=(iterator const& other) const 51 | { 52 | return !(*this == other); 53 | } 54 | 55 | auto operator*() -> decltype(range.front()) 56 | { 57 | ADE_ASSERT(!range.empty()); 58 | ADE_ASSERT(!end); 59 | return range.front(); 60 | } 61 | 62 | auto operator*() const -> decltype(range.front()) 63 | { 64 | ADE_ASSERT(!range.empty()); 65 | ADE_ASSERT(!end); 66 | return range.front(); 67 | } 68 | 69 | iterator& operator++() 70 | { 71 | ADE_ASSERT(!range.empty()); 72 | ADE_ASSERT(!end); 73 | range.popFront(); 74 | return *this; 75 | } 76 | }; 77 | 78 | iterator begin() 79 | { 80 | auto& src = *static_cast(this); 81 | return iterator{src, false}; 82 | } 83 | 84 | iterator end() 85 | { 86 | auto& src = *static_cast(this); 87 | return iterator{src, true}; 88 | } 89 | }; 90 | 91 | } 92 | 93 | } 94 | } // namespace ade 95 | 96 | #endif // ADE_UTIL_RANGE_ITERATOR_HPP 97 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/tuple.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file tuple.hpp 8 | 9 | #ifndef ADE_UTIL_TUPLE_HPP 10 | #define ADE_UTIL_TUPLE_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace ade 17 | { 18 | namespace util 19 | { 20 | 21 | namespace details 22 | { 23 | template 24 | struct Seq { }; 25 | 26 | template 27 | struct Gens : Gens { }; 28 | 29 | template 30 | struct Gens<0, S...> 31 | { 32 | typedef Seq type; 33 | }; 34 | 35 | template 36 | using gen_t = typename Gens::type; 37 | 38 | template 39 | inline auto tupleForeachImpl(const std::tuple& /*tup*/, F&& /*fun*/) -> typename std::enable_if<(I == sizeof...(TupleTypes))>::type 40 | { 41 | } 42 | 43 | template 44 | inline auto tupleForeachImpl(const std::tuple& tup, F&& fun) -> typename std::enable_if<(I < sizeof...(TupleTypes))>::type 45 | { 46 | fun(std::get(tup)); 47 | tupleForeachImpl(tup, std::forward(fun)); 48 | } 49 | 50 | template 51 | inline auto tupleForeachImpl(std::tuple& tup, F&& fun) -> typename std::enable_if<(I < sizeof...(TupleTypes))>::type 52 | { 53 | fun(std::get(tup)); 54 | tupleForeachImpl(tup, std::forward(fun)); 55 | } 56 | 57 | template 58 | struct fix_rval 59 | { 60 | using type = typename std::remove_reference::type; 61 | }; 62 | 63 | template 64 | struct fix_rval 65 | { 66 | using type = T&; 67 | }; 68 | 69 | 70 | template 71 | using fix_rval_t = typename fix_rval::type; 72 | 73 | } 74 | 75 | inline namespace Range 76 | { 77 | 78 | /// Converts rvalue refs to values 79 | /// but preserves lvalue refs 80 | template 81 | inline auto tuple_remove_rvalue_refs(Elements&&... args)-> 82 | std::tuple...> 83 | { 84 | return std::tuple...>(std::forward(args)...); 85 | } 86 | 87 | template 88 | inline void tupleForeach(const std::tuple& tup, F&& fun) 89 | { 90 | details::tupleForeachImpl(tup, std::forward(fun)); 91 | } 92 | 93 | template 94 | inline void tupleForeach(std::tuple& tup, F&& fun) 95 | { 96 | details::tupleForeachImpl(tup, std::forward(fun)); 97 | } 98 | 99 | } 100 | } 101 | } // namespace ade 102 | 103 | #endif // ADE_UTIL_TUPLE_HPP 104 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/type_traits.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file type_traits.hpp 8 | 9 | #ifndef ADE_UTIL_TYPE_TRAITS_HPP 10 | #define ADE_UTIL_TYPE_TRAITS_HPP 11 | 12 | #include 13 | 14 | // NB: Had to write it like this due to MSVC warning C4067 15 | #if defined(__has_include) 16 | #if __has_include() 17 | # include 18 | #endif 19 | #endif 20 | 21 | namespace ade 22 | { 23 | namespace util 24 | { 25 | 26 | template 27 | using bool_c = std::integral_constant; 28 | 29 | template 30 | using not_ = bool_c; 31 | 32 | template 33 | struct or_; 34 | 35 | template<> 36 | struct or_<> : std::true_type {}; 37 | 38 | template 39 | struct or_ : T {}; 40 | 41 | template 42 | struct or_ : bool_c< T0::value || T1::value > {}; 43 | 44 | template 45 | struct or_ : or_< T0, or_ > {}; 46 | 47 | template 48 | struct and_; 49 | 50 | template<> 51 | struct and_<> : std::true_type {}; 52 | 53 | template 54 | struct and_ : T {}; 55 | 56 | template 57 | struct and_ : bool_c< T0::value && T1::value > {}; 58 | 59 | template 60 | struct and_ : and_< T0, and_ > {}; 61 | 62 | 63 | template 64 | struct is_one_of : or_< std::is_same... > {}; 65 | 66 | template 67 | struct is_pod : std::integral_constant 68 | < 69 | bool, 70 | std::is_trivial::value && std::is_standard_layout::value 71 | > {}; 72 | 73 | template 74 | using enable_b_t = typename std::enable_if< v, bool >::type; 75 | 76 | template 77 | using require_t = enable_b_t< and_::value >; 78 | 79 | template 80 | using enable_t = typename std::enable_if< and_::value, T >::type; 81 | 82 | template 83 | using enable_if_t = typename std::enable_if::type; 84 | 85 | template 86 | using decay_t = typename std::decay::type; 87 | 88 | template< class T > 89 | using remove_reference_t = typename std::remove_reference::type; 90 | 91 | template< class T > 92 | using remove_pointer_t = typename std::remove_pointer::type; 93 | 94 | template< bool B, class T, class F > 95 | using conditional_t = typename std::conditional::type; 96 | 97 | template 98 | using common_type_t = typename std::common_type::type; 99 | 100 | #ifdef __cpp_lib_is_invocable 101 | template 102 | using result_of_t = std::invoke_result_t; 103 | #else 104 | template 105 | using result_of_t = typename std::result_of::type; 106 | #endif 107 | } // namespace util 108 | } // namespace ade 109 | 110 | #endif // ADE_UTIL_TYPE_TRAITS_HPP 111 | -------------------------------------------------------------------------------- /sources/ade/include/ade/util/zip_range.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /// @file zip_range.hpp 8 | 9 | #ifndef ADE_UTIL_ZIP_RANGE_HPP 10 | #define ADE_UTIL_ZIP_RANGE_HPP 11 | 12 | #include "ade/util/tuple.hpp" 13 | #include "ade/util/range.hpp" 14 | #include "ade/util/assert.hpp" 15 | #include "ade/util/iota_range.hpp" 16 | #include "ade/util/range_iterator.hpp" 17 | 18 | namespace ade 19 | { 20 | namespace util 21 | { 22 | 23 | inline namespace Range 24 | { 25 | 26 | template 27 | struct ZipRange : public IterableRange> 28 | { 29 | using tuple_t = decltype(std::make_tuple(toRange(std::declval())...)); 30 | tuple_t ranges; 31 | 32 | ZipRange() = default; 33 | ZipRange(const ZipRange&) = default; 34 | ZipRange(ZipRange&&) = default; 35 | ZipRange& operator=(const ZipRange&) = default; 36 | ZipRange& operator=(ZipRange&&) = default; 37 | ZipRange(Ranges&& ...r): ranges{toRange(std::forward(r))...} {} 38 | 39 | template 40 | auto unpackTuple(details::Seq) -> 41 | decltype(tuple_remove_rvalue_refs(std::get(ranges).front()...)) 42 | { 43 | return tuple_remove_rvalue_refs(std::get(ranges).front()...); 44 | } 45 | 46 | template 47 | auto unpackTuple(details::Seq) const -> 48 | decltype(tuple_remove_rvalue_refs(std::get(ranges).front()...)) 49 | { 50 | return tuple_remove_rvalue_refs(std::get(ranges).front()...); 51 | } 52 | 53 | bool empty() const 54 | { 55 | ::ade::util::details::RangeChecker checker; 56 | tupleForeach(ranges, checker); 57 | return checker.empty; 58 | } 59 | 60 | void popFront() 61 | { 62 | ADE_ASSERT(!empty()); 63 | tupleForeach(ranges, ade::util::details::RangeIncrementer()); 64 | } 65 | 66 | auto front()->decltype(this->unpackTuple(details::gen_t{})) 67 | { 68 | ADE_ASSERT(!empty()); 69 | return unpackTuple(details::gen_t{}); 70 | } 71 | 72 | auto front() const->decltype(this->unpackTuple(details::gen_t{})) 73 | { 74 | ADE_ASSERT(!empty()); 75 | return unpackTuple(details::gen_t{}); 76 | } 77 | 78 | 79 | }; 80 | 81 | template 82 | inline ZipRange zip(Ranges&&... ranges) 83 | { 84 | return {std::forward(ranges)...}; 85 | } 86 | 87 | template 88 | inline auto indexed(Containers&&... conts) -> 89 | decltype(zip(iota(), std::forward(conts)...)) 90 | { 91 | return zip(iota(), std::forward(conts)...); 92 | } 93 | 94 | } 95 | } 96 | } // namespace ade 97 | 98 | #endif // ADE_UTIL_ZIP_RANGE_HPP 99 | -------------------------------------------------------------------------------- /sources/ade/manifest.cmake: -------------------------------------------------------------------------------- 1 | set(THE_PROJECT_NAME ade) 2 | set(THE_PROJECT_VERSION 0.1.0) 3 | -------------------------------------------------------------------------------- /sources/ade/source/alloc.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/memory/alloc.hpp" 8 | 9 | #if defined(_WIN32) || defined(__ANDROID__) || defined(ANDROID) 10 | #include 11 | #else 12 | #include 13 | #include 14 | #endif 15 | 16 | #include "ade/util/math.hpp" 17 | #include "ade/util/assert.hpp" 18 | 19 | namespace ade 20 | { 21 | 22 | void* aligned_alloc(std::size_t size, std::size_t alignment) 23 | { 24 | ADE_ASSERT(util::is_pow2(alignment)); 25 | #if defined(_WIN32) 26 | return _aligned_malloc(size, alignment); 27 | #elif defined(__ANDROID__) || defined(ANDROID) 28 | return memalign(alignment, size); 29 | #else 30 | void* ret = nullptr; 31 | auto res = posix_memalign(&ret, std::max(sizeof(void*), alignment), size); 32 | (void)res; 33 | return ret; 34 | #endif 35 | } 36 | 37 | void aligned_free(void* ptr) 38 | { 39 | #if defined(_WIN32) 40 | return _aligned_free(ptr); 41 | #else 42 | return free(ptr); 43 | #endif 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /sources/ade/source/assert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/util/assert.hpp" 8 | 9 | #include 10 | #include 11 | 12 | namespace ade 13 | { 14 | namespace details 15 | { 16 | 17 | void dev_assert_abort(const char* str, int line, const char* file, 18 | const char* func) 19 | { 20 | fprintf(stderr, 21 | "%s:%d: Assertion \"%s\" in function \"%s\" failed\n", 22 | file, line, str, func); 23 | fflush(stderr); 24 | abort(); 25 | } 26 | void dev_exception_abort(const char* str) 27 | { 28 | fprintf(stderr, "An exception thrown! %s\n" , str); 29 | fflush(stderr); 30 | abort(); 31 | } 32 | 33 | } // namespace details 34 | } // namespace ade 35 | -------------------------------------------------------------------------------- /sources/ade/source/check_cycles.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/passes/check_cycles.hpp" 8 | 9 | #include 10 | 11 | #include "ade/util/assert.hpp" 12 | #include "ade/util/map_range.hpp" 13 | 14 | #include "ade/graph.hpp" 15 | #include "ade/node.hpp" 16 | 17 | namespace ade 18 | { 19 | namespace passes 20 | { 21 | enum class TraverseState 22 | { 23 | visiting, 24 | visited, 25 | }; 26 | 27 | using state_t = std::unordered_map; 28 | 29 | static void visit(state_t& state, const NodeHandle& node) 30 | { 31 | ADE_ASSERT(nullptr != node); 32 | state[node.get()] = TraverseState::visiting; 33 | for (auto adj: 34 | util::map(node->outEdges(), [](const EdgeHandle& e) { return e->dstNode(); })) 35 | { 36 | auto it = state.find(adj.get()); 37 | if (state.end() == it) // not visited 38 | { 39 | visit(state, adj); 40 | } 41 | else if (TraverseState::visiting == it->second) 42 | { 43 | throw_error(CycleFound()); 44 | } 45 | } 46 | state[node.get()] = TraverseState::visited; 47 | 48 | } 49 | 50 | void CheckCycles::operator()(const PassContext& context) const 51 | { 52 | state_t state; 53 | for (auto node: context.graph.nodes()) 54 | { 55 | if (state.end() == state.find(node.get())) 56 | { 57 | // not yet visited during recursion 58 | visit(state, node); 59 | } 60 | } 61 | } 62 | 63 | std::string CheckCycles::name() 64 | { 65 | return "CheckCycles"; 66 | } 67 | 68 | const char* CycleFound::what() const noexcept 69 | { 70 | return "Cycle was detected in graph"; 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /sources/ade/source/edge.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/edge.hpp" 8 | 9 | #include "ade/util/assert.hpp" 10 | 11 | #include "ade/node.hpp" 12 | #include "ade/graph.hpp" 13 | 14 | namespace ade 15 | { 16 | 17 | Edge::Edge(Node* prev, Node* next) 18 | { 19 | ADE_ASSERT(nullptr != prev); 20 | ADE_ASSERT(nullptr != next); 21 | resetPrevNode(prev); 22 | resetNextNode(next); 23 | } 24 | 25 | Edge::~Edge() 26 | { 27 | unlink(); 28 | } 29 | 30 | void Edge::unlink() 31 | { 32 | resetPrevNode(nullptr); 33 | resetNextNode(nullptr); 34 | } 35 | 36 | void Edge::resetPrevNode(Node* newNode) 37 | { 38 | if (newNode == m_prevNode) 39 | { 40 | return; 41 | } 42 | 43 | if (nullptr != m_prevNode) 44 | { 45 | m_prevNode->removeOutEdge(this); 46 | m_prevNode = nullptr; 47 | } 48 | if (nullptr != newNode) 49 | { 50 | newNode->addOutEdge(this); 51 | m_prevNode = newNode; 52 | } 53 | } 54 | 55 | void Edge::resetNextNode(Node* newNode) 56 | { 57 | if (newNode == m_nextNode) 58 | { 59 | return; 60 | } 61 | 62 | if (nullptr != m_nextNode) 63 | { 64 | m_nextNode->removeInEdge(this); 65 | m_nextNode = nullptr; 66 | } 67 | if (nullptr != newNode) 68 | { 69 | newNode->addInEdge(this); 70 | m_nextNode = newNode; 71 | } 72 | } 73 | 74 | Graph* Edge::getParent() const 75 | { 76 | if (nullptr != m_prevNode) 77 | { 78 | return m_prevNode->getParent(); 79 | } 80 | if (nullptr != m_nextNode) 81 | { 82 | return m_nextNode->getParent(); 83 | } 84 | return nullptr; 85 | } 86 | 87 | NodeHandle Edge::srcNode() const 88 | { 89 | ADE_ASSERT_STRONG(nullptr != m_prevNode); 90 | return Graph::HandleMapper()(m_prevNode); 91 | } 92 | 93 | NodeHandle Edge::dstNode() const 94 | { 95 | ADE_ASSERT_STRONG(nullptr != m_nextNode); 96 | return Graph::HandleMapper()(m_nextNode); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /sources/ade/source/memory_accessor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/memory/memory_accessor.hpp" 8 | 9 | #include 10 | 11 | #include "ade/util/zip_range.hpp" 12 | #include "ade/util/assert.hpp" 13 | 14 | namespace ade 15 | { 16 | 17 | MemoryAccessor::MemoryAccessor() 18 | { 19 | } 20 | 21 | MemoryAccessor::~MemoryAccessor() 22 | { 23 | if (!m_activeHandles.empty()) 24 | { 25 | onError("Data wasn't committed"); 26 | abandonAllHandles(); 27 | } 28 | 29 | ADE_ASSERT(m_activeHandles.empty() && "There are an opened handles"); 30 | 31 | for (auto listener : m_accessListeners) 32 | { 33 | listener->memoryDescriptorDestroyedImpl(); 34 | } 35 | } 36 | 37 | void MemoryAccessor::addListener(IMemoryAccessListener* listener) 38 | { 39 | ADE_ASSERT(nullptr != listener); 40 | if (!m_activeHandles.empty()) 41 | { 42 | onError("Data wasn't committed"); 43 | } 44 | ADE_ASSERT(m_accessListeners.end() == std::find(m_accessListeners.begin(), 45 | m_accessListeners.end(), 46 | listener)); 47 | m_accessListeners.push_back(listener); 48 | } 49 | 50 | void MemoryAccessor::removeListener(IMemoryAccessListener* listener) 51 | { 52 | ADE_ASSERT(nullptr != listener); 53 | if (!m_activeHandles.empty()) 54 | { 55 | onError("Data wasn't committed"); 56 | abandonListenerHandles(listener); 57 | } 58 | auto it = std::find(m_accessListeners.begin(), 59 | m_accessListeners.end(), 60 | listener); 61 | ADE_ASSERT(m_accessListeners.end() != it); 62 | *it = m_accessListeners.back(); 63 | m_accessListeners.pop_back(); 64 | } 65 | 66 | MemoryAccessor::AccessHandle MemoryAccessor::access(const MemoryDescriptor& desc, 67 | const memory::DynMdSpan& span, 68 | MemoryAccessType accessType) 69 | { 70 | ADE_ASSERT(nullptr != m_memory); 71 | return m_activeHandles.emplace(m_activeHandles.end(), this, desc, span, accessType); 72 | } 73 | 74 | void MemoryAccessor::commit(MemoryAccessor::AccessHandle handle) 75 | { 76 | ADE_ASSERT(nullptr != m_memory); 77 | ADE_ASSERT(m_activeHandles.end() != handle); 78 | m_activeHandles.erase(handle); 79 | } 80 | 81 | void MemoryAccessor::setNewView(const memory::DynMdView& mem) 82 | { 83 | if (!m_activeHandles.empty()) 84 | { 85 | onError("Data wasn't committed"); 86 | abandonAllHandles(); 87 | } 88 | for (auto& listener: m_accessListeners) 89 | { 90 | listener->memoryViewChangedImpl(m_memory, mem); 91 | } 92 | m_memory = mem; 93 | } 94 | 95 | void MemoryAccessor::abandonListenerHandles(IMemoryAccessListener* listener) 96 | { 97 | ADE_ASSERT(nullptr != listener); 98 | 99 | for (auto& h: m_activeHandles) 100 | { 101 | h.abandon(listener); 102 | } 103 | } 104 | 105 | void MemoryAccessor::abandonAllHandles() 106 | { 107 | for (auto& h: m_activeHandles) 108 | { 109 | h.abandon(); 110 | } 111 | m_activeHandles.clear(); 112 | } 113 | 114 | void MemoryAccessor::onError(const char* str) 115 | { 116 | ADE_ASSERT(nullptr != str); 117 | if (m_errorListener) 118 | { 119 | m_errorListener(str); 120 | } 121 | } 122 | 123 | MemoryAccessor::SavedHandles::SavedHandles(MemoryAccessor* parent, 124 | const MemoryDescriptor& desc, 125 | const memory::DynMdSpan& span, 126 | MemoryAccessType accessType) 127 | { 128 | ADE_ASSERT(nullptr != parent); 129 | using namespace util; 130 | 131 | // TODO: exception safety 132 | for (auto&& i: indexed(parent->m_accessListeners)) 133 | { 134 | auto listener = value(i); 135 | if (0 == index(i)) 136 | { 137 | handle = listener->access(desc, span, accessType); 138 | } 139 | else 140 | { 141 | handles.emplace_back(listener->access(desc, span, accessType)); 142 | } 143 | } 144 | } 145 | 146 | MemoryAccessor::SavedHandles::~SavedHandles() 147 | { 148 | 149 | } 150 | 151 | void MemoryAccessor::SavedHandles::abandon(IMemoryAccessListener* listener) 152 | { 153 | ADE_ASSERT(nullptr != listener); 154 | 155 | if (listener == handle.get_deleter().listener) 156 | { 157 | handle.release(); 158 | } 159 | for (auto& h: handles) 160 | { 161 | if (listener == h.get_deleter().listener) 162 | { 163 | h.release(); 164 | } 165 | } 166 | } 167 | 168 | void MemoryAccessor::SavedHandles::abandon() 169 | { 170 | handle.release(); 171 | for (auto& h: handles) 172 | { 173 | h.release(); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /sources/ade/source/memory_descriptor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/memory/memory_descriptor.hpp" 8 | 9 | #include 10 | 11 | #include "ade/util/zip_range.hpp" 12 | 13 | namespace ade 14 | { 15 | 16 | MemoryDescriptor::MemoryDescriptor(size_t element_size, 17 | const memory::DynMdSize& dims): 18 | m_elementSize(element_size), 19 | m_dims(dims) 20 | { 21 | ADE_ASSERT(dims.dims_count() > 0); 22 | ADE_ASSERT(element_size > 0); 23 | } 24 | 25 | MemoryDescriptor::~MemoryDescriptor() 26 | { 27 | } 28 | 29 | void MemoryDescriptor::addListener(IMemoryAccessListener* listener) 30 | { 31 | m_accessor.addListener(listener); 32 | } 33 | 34 | void MemoryDescriptor::removeListener(IMemoryAccessListener* listener) 35 | { 36 | m_accessor.removeListener(listener); 37 | } 38 | 39 | MemoryDescriptor::AccessHandle MemoryDescriptor::access(const memory::DynMdSpan& span, 40 | MemoryAccessType accessType) 41 | { 42 | return m_accessor.access(*this, span, accessType); 43 | } 44 | 45 | void MemoryDescriptor::commit(MemoryDescriptor::AccessHandle handle) 46 | { 47 | m_accessor.commit(handle); 48 | } 49 | 50 | const memory::DynMdSize& MemoryDescriptor::dimensions() const 51 | { 52 | return m_dims; 53 | } 54 | 55 | std::size_t MemoryDescriptor::elementSize() const 56 | { 57 | return m_elementSize; 58 | } 59 | 60 | void MemoryDescriptor::setExternalView(const memory::DynMdView& view) 61 | { 62 | ADE_ASSERT(view.elementSize() == m_elementSize); 63 | ADE_ASSERT(view.count() == m_dims.dims_count()); 64 | m_externalView = view; 65 | m_accessor.setNewView(view); 66 | } 67 | 68 | memory::DynMdView MemoryDescriptor::getExternalView() const 69 | { 70 | return m_externalView; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /sources/ade/source/memory_descriptor_ref.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include "ade/memory/memory_descriptor_ref.hpp" 10 | 11 | #include "ade/memory/memory_descriptor_view.hpp" 12 | #include "ade/memory/memory_descriptor.hpp" 13 | 14 | #include "ade/util/md_io.hpp" 15 | 16 | #include "ade/util/iota_range.hpp" 17 | 18 | namespace ade 19 | { 20 | 21 | MemoryDescriptorRef::MemoryDescriptorRef() 22 | { 23 | 24 | } 25 | 26 | MemoryDescriptorRef::MemoryDescriptorRef(MemoryDescriptorView& view): 27 | m_parent(&view) 28 | { 29 | m_span.redim(view.span().dims_count()); 30 | for (auto i: util::iota(m_span.dims_count())) 31 | { 32 | m_span[i] = util::Span(0, view.span()[i].length()); 33 | } 34 | } 35 | 36 | MemoryDescriptorRef::MemoryDescriptorRef(MemoryDescriptorView& view_, 37 | const memory::DynMdSpan& span_): 38 | m_parent(&view_), 39 | m_span(span_) 40 | { 41 | 42 | } 43 | 44 | MemoryDescriptorRef::~MemoryDescriptorRef() 45 | { 46 | 47 | } 48 | 49 | MemoryDescriptorView* MemoryDescriptorRef::getView() 50 | { 51 | return m_parent; 52 | } 53 | 54 | const MemoryDescriptorView* MemoryDescriptorRef::getView() const 55 | { 56 | return m_parent; 57 | } 58 | 59 | MemoryDescriptor*MemoryDescriptorRef::getDescriptor() 60 | { 61 | if (nullptr == m_parent) 62 | { 63 | return nullptr; 64 | } 65 | return m_parent->getDescriptor(); 66 | } 67 | 68 | const MemoryDescriptor* MemoryDescriptorRef::getDescriptor() const 69 | { 70 | if (nullptr == m_parent) 71 | { 72 | return nullptr; 73 | } 74 | return m_parent->getDescriptor(); 75 | } 76 | 77 | const memory::DynMdSpan& MemoryDescriptorRef::span() const 78 | { 79 | ADE_ASSERT(nullptr != *this); 80 | return m_span; 81 | } 82 | 83 | memory::DynMdSize MemoryDescriptorRef::size() const 84 | { 85 | return span().size(); 86 | } 87 | 88 | std::size_t MemoryDescriptorRef::elementSize() const 89 | { 90 | ADE_ASSERT(nullptr != getDescriptor()); 91 | return getDescriptor()->elementSize(); 92 | } 93 | 94 | memory::DynMdSpan MemoryDescriptorRef::originSpan() const 95 | { 96 | ADE_ASSERT(nullptr != *this); 97 | return m_span + m_parent->span().origin(); 98 | } 99 | 100 | memory::DynMdView MemoryDescriptorRef::getExternalView() const 101 | { 102 | ADE_ASSERT(nullptr != getDescriptor()); 103 | auto srcView = getDescriptor()->getExternalView(); 104 | if (nullptr == srcView) 105 | { 106 | return nullptr; 107 | } 108 | return srcView.slice(originSpan()); 109 | } 110 | 111 | bool operator==(std::nullptr_t, const MemoryDescriptorRef& ref) 112 | { 113 | return ref.m_parent == nullptr; 114 | } 115 | 116 | bool operator==(const MemoryDescriptorRef& ref, std::nullptr_t) 117 | { 118 | return ref.m_parent == nullptr; 119 | } 120 | 121 | bool operator!=(std::nullptr_t, const MemoryDescriptorRef& ref) 122 | { 123 | return ref.m_parent != nullptr; 124 | } 125 | 126 | bool operator!=(const MemoryDescriptorRef& ref, std::nullptr_t) 127 | { 128 | return ref.m_parent != nullptr; 129 | } 130 | 131 | std::ostream& operator<<(std::ostream& os, const MemoryDescriptorRef& ref) 132 | { 133 | if (nullptr == ref) 134 | { 135 | os << static_cast(nullptr); 136 | } 137 | else 138 | { 139 | os << "{"; 140 | os << "span: " << ref.span() << ", "; 141 | if (ref.originSpan() != ref.span()) 142 | { 143 | os << std::endl << "origin span: " << ref.originSpan() << ", "; 144 | } 145 | os << std::endl << "view: " << ref.getView() << " (" << ref.getView()->span() << "), "; 146 | os << std::endl << "descriptor: " << ref.getDescriptor() << " (" << ref.getDescriptor()->dimensions() << ") "; 147 | os << "}"; 148 | } 149 | return os; 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /sources/ade/source/metadata.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/typed_metadata.hpp" 8 | 9 | #include "ade/util/assert.hpp" 10 | 11 | namespace ade 12 | { 13 | namespace details 14 | { 15 | 16 | bool Metadata::contains(const MetadataId& id) const 17 | { 18 | ADE_ASSERT(nullptr != id); 19 | return m_data.end() != m_data.find(id); 20 | } 21 | 22 | void Metadata::erase(const MetadataId& id) 23 | { 24 | m_data.erase(id); 25 | } 26 | 27 | std::size_t Metadata::IdHash::operator()(const MetadataId& id) const 28 | { 29 | return std::hash()(id.m_id); 30 | } 31 | 32 | MetadataId::MetadataId(void* id): 33 | m_id(id) 34 | { 35 | ADE_ASSERT(nullptr != m_id); 36 | } 37 | 38 | bool MetadataId::operator==(const MetadataId& other) const 39 | { 40 | return m_id == other.m_id; 41 | } 42 | 43 | bool MetadataId::operator!=(const MetadataId& other) const 44 | { 45 | return m_id != other.m_id; 46 | } 47 | 48 | bool MetadataId::isNull() const 49 | { 50 | return nullptr == m_id; 51 | } 52 | 53 | bool operator==(std::nullptr_t, const MetadataId& other) 54 | { 55 | return other.isNull(); 56 | } 57 | 58 | bool operator==(const MetadataId& other, std::nullptr_t) 59 | { 60 | return other.isNull(); 61 | } 62 | 63 | bool operator!=(std::nullptr_t, const MetadataId& other) 64 | { 65 | return !other.isNull(); 66 | } 67 | 68 | bool operator!=(const MetadataId& other, std::nullptr_t) 69 | { 70 | return !other.isNull(); 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /sources/ade/source/metatypes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/metatypes/metatypes.hpp" 8 | 9 | namespace ade 10 | { 11 | namespace meta 12 | { 13 | 14 | NodeInfo::NodeInfo(const std::string& kernel, 15 | const std::string& target): 16 | kernel_name(kernel), 17 | target_name(target) 18 | { 19 | 20 | } 21 | 22 | NodeInfo::NodeId NodeInfo::getId() const 23 | { 24 | return getIdInternal().get(); 25 | } 26 | 27 | void NodeInfo::link(NodeInfo& node) 28 | { 29 | m_id = node.getIdInternal(); 30 | } 31 | 32 | const char* NodeInfo::name() 33 | { 34 | return "VxNodeInfo"; 35 | } 36 | 37 | NodeInfo::IdPtr NodeInfo::getIdInternal() const 38 | { 39 | if (nullptr == m_id) 40 | { 41 | m_id = std::make_shared(); 42 | } 43 | return m_id; 44 | } 45 | 46 | const char* DataObject::name() 47 | { 48 | return "DataObject"; 49 | } 50 | 51 | CommNode::CommNode(int producersCount_): 52 | m_producersCount(producersCount_) 53 | { 54 | ADE_ASSERT(m_producersCount > 0); 55 | } 56 | 57 | void CommNode::addDataBuffer(const std::shared_ptr& buff) 58 | { 59 | ADE_ASSERT(buff != nullptr); 60 | m_buffers.emplace_back(buff); 61 | } 62 | 63 | const char* CommNode::name() 64 | { 65 | return "CommNode"; 66 | } 67 | 68 | const char* CommChannel::name() 69 | { 70 | return "CommChannel"; 71 | } 72 | 73 | const char* CommConsumerCallback::name() 74 | { 75 | return "CommConsumerCallback"; 76 | } 77 | 78 | const char* CommProducerCallback::name() 79 | { 80 | return "CommProducerCallback"; 81 | } 82 | 83 | const char* Finalizers::name() 84 | { 85 | return "Finalizers"; 86 | } 87 | 88 | std::ostream& operator<<(std::ostream& os, const ade::meta::NodeInfo& obj) 89 | { 90 | os << obj.kernel_name << " " << obj.target_name; 91 | return os; 92 | } 93 | 94 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommNode& obj) 95 | { 96 | os << "producer_count : " << obj.producersCount(); 97 | return os; 98 | } 99 | 100 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommConsumerCallback& /*obj*/) 101 | { 102 | return os; 103 | } 104 | 105 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommProducerCallback& /*obj*/) 106 | { 107 | return os; 108 | } 109 | 110 | std::ostream& operator<<(std::ostream& os, const ade::meta::DataObject& obj) 111 | { 112 | os << "mem descriptor ref: " << obj.dataRef << ", " 113 | << "originalFormat: " << obj.originalFormat; 114 | return os; 115 | } 116 | 117 | std::ostream& operator<<(std::ostream& os, const ade::meta::CommChannel& obj) 118 | { 119 | os << obj.channel; 120 | return os; 121 | } 122 | 123 | std::ostream& operator<<(std::ostream& os, const ade::meta::Finalizers& /*obj*/) 124 | { 125 | return os; 126 | } 127 | 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /sources/ade/source/node.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/node.hpp" 8 | 9 | #include 10 | 11 | #include "ade/util/assert.hpp" 12 | #include "ade/util/algorithm.hpp" 13 | 14 | #include "ade/graph.hpp" 15 | #include "ade/edge.hpp" 16 | 17 | namespace ade 18 | { 19 | 20 | Node::Node(Graph* parent): 21 | m_parent(parent) 22 | { 23 | 24 | } 25 | 26 | Node::~Node() 27 | { 28 | unlink(); 29 | } 30 | 31 | void Node::unlink() 32 | { 33 | ADE_ASSERT(nullptr != m_parent); 34 | for (auto& edge: m_inEdges) //TODO: join ranges 35 | { 36 | ADE_ASSERT(nullptr != edge); 37 | ADE_ASSERT(this == edge->m_nextNode); 38 | edge->m_nextNode = nullptr; 39 | m_parent->removeEdge(edge); 40 | } 41 | m_inEdges.clear(); 42 | 43 | for (auto& edge: m_outEdges) //TODO: join ranges 44 | { 45 | ADE_ASSERT(nullptr != edge); 46 | ADE_ASSERT(this == edge->m_prevNode); 47 | edge->m_prevNode = nullptr; 48 | m_parent->removeEdge(edge); 49 | } 50 | m_outEdges.clear(); 51 | } 52 | 53 | void Node::addInEdge(Edge* edge) 54 | { 55 | ADE_ASSERT(nullptr != edge); 56 | ADE_ASSERT(m_inEdges.end() == util::find(m_inEdges, edge)); 57 | m_inEdges.emplace_back(edge); 58 | } 59 | 60 | void Node::removeInEdge(Edge* edge) 61 | { 62 | ADE_ASSERT(nullptr != edge); 63 | // Nodes usually have only a small amount of connections so linear search should be fine here 64 | auto it = util::find(m_inEdges, edge); 65 | ADE_ASSERT(m_inEdges.end() != it); 66 | util::unstable_erase(m_inEdges, it); 67 | } 68 | 69 | void Node::addOutEdge(Edge* edge) 70 | { 71 | ADE_ASSERT(nullptr != edge); 72 | ADE_ASSERT(m_outEdges.end() == util::find(m_outEdges, edge)); 73 | m_outEdges.emplace_back(edge); 74 | } 75 | 76 | void Node::removeOutEdge(Edge* edge) 77 | { 78 | ADE_ASSERT(nullptr != edge); 79 | // Nodes usually have only a small amount of connections so linear search should be fine here 80 | auto it = util::find(m_outEdges, edge); 81 | ADE_ASSERT(m_outEdges.end() != it); 82 | util::unstable_erase(m_outEdges, it); 83 | } 84 | 85 | Graph* Node::getParent() const 86 | { 87 | return m_parent; 88 | } 89 | 90 | Node::EdgeSetRange Node::inEdges() 91 | { 92 | return util::map(util::toRange(m_inEdges)); 93 | } 94 | 95 | Node::EdgeSetCRange Node::inEdges() const 96 | { 97 | return util::map(util::toRange(m_inEdges)); 98 | } 99 | 100 | Node::EdgeSetRange Node::outEdges() 101 | { 102 | return util::map(util::toRange(m_outEdges)); 103 | } 104 | 105 | Node::EdgeSetCRange Node::outEdges() const 106 | { 107 | return util::map(util::toRange(m_outEdges)); 108 | } 109 | 110 | Node::InNodeSetRange Node::inNodes() 111 | { 112 | return util::map(inEdges()); 113 | } 114 | 115 | Node::InNodeSetCRange Node::inNodes() const 116 | { 117 | return util::map(inEdges()); 118 | } 119 | 120 | Node::OutNodeSetRange Node::outNodes() 121 | { 122 | return util::map(outEdges()); 123 | } 124 | 125 | Node::OutNodeSetCRange Node::outNodes() const 126 | { 127 | return util::map(outEdges()); 128 | } 129 | 130 | EdgeHandle Node::HandleMapper::operator()(Edge* obj) const 131 | { 132 | ADE_ASSERT(nullptr != obj); 133 | return Graph::HandleMapper()(obj); 134 | } 135 | 136 | NodeHandle Node::InEdgeMapper::operator()(const EdgeHandle& handle) const 137 | { 138 | ADE_ASSERT(nullptr != handle); 139 | return handle->srcNode(); 140 | } 141 | 142 | NodeHandle Node::OutEdgeMapper::operator()(const EdgeHandle& handle) const 143 | { 144 | ADE_ASSERT(nullptr != handle); 145 | return handle->dstNode(); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /sources/ade/source/search.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/helpers/search.hpp" 8 | 9 | namespace ade 10 | { 11 | namespace 12 | { 13 | template 14 | void dfsHelper(const NodeHandle& node, 15 | Visitor&& visitor, 16 | Traverse&& direction) 17 | { 18 | direction(*node, [&](const NodeHandle& nextNode) 19 | { 20 | ADE_ASSERT(nullptr != nextNode); 21 | if (visitor(nextNode)) 22 | { 23 | dfsHelper(nextNode, 24 | std::forward(visitor), 25 | std::forward(direction)); 26 | } 27 | }); 28 | } 29 | } 30 | 31 | void dfs(const NodeHandle& node, 32 | util::func_ref visitor, 33 | traverse::traverse_func_type direction) 34 | { 35 | ADE_ASSERT(nullptr != node); 36 | dfsHelper(node, visitor, direction); 37 | } 38 | 39 | namespace details 40 | { 41 | 42 | namespace 43 | { 44 | template 45 | void TransitiveClosureHelperImpl( 46 | details::TransitiveClosureHelper::CacheT& cache, 47 | const NodeHandle& node, 48 | Traverse&& direction) 49 | { 50 | ADE_ASSERT(nullptr != node); 51 | ADE_ASSERT(!util::contains(cache, node)); 52 | auto& elem = cache[node]; 53 | (void)elem; // Silence klocwork warning 54 | direction(*node, [&](const NodeHandle& outNode) 55 | { 56 | ADE_ASSERT(nullptr != outNode); 57 | if (!util::contains(cache, outNode)) 58 | { 59 | TransitiveClosureHelperImpl(cache, 60 | outNode, 61 | std::forward(direction)); 62 | } 63 | ADE_ASSERT(util::contains(cache, outNode)); 64 | elem.insert(outNode); 65 | auto& nextNodes = cache[outNode]; 66 | elem.insert(nextNodes.begin(), nextNodes.end()); 67 | }); 68 | } 69 | } 70 | 71 | void details::TransitiveClosureHelper::operator()( 72 | details::TransitiveClosureHelper::CacheT& cache, 73 | const NodeHandle& node, 74 | traverse::traverse_func_type direction) const 75 | { 76 | TransitiveClosureHelperImpl(cache, node, direction); 77 | } 78 | 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /sources/ade/source/topological_sort.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "ade/passes/topological_sort.hpp" 8 | 9 | #include 10 | #include 11 | 12 | #include "ade/graph.hpp" 13 | 14 | namespace ade 15 | { 16 | namespace passes 17 | { 18 | using sorted_t = std::vector; 19 | using visited_t = std::unordered_set; 20 | 21 | static void visit(sorted_t& sorted, visited_t& visited, const NodeHandle& node) 22 | { 23 | if (visited.end() == visited.find(node.get())) 24 | { 25 | for (auto adj: 26 | util::map(node->inEdges(), [](const EdgeHandle& e) { return e->srcNode(); })) 27 | { 28 | visit(sorted, visited, adj); 29 | } 30 | sorted.push_back(node); 31 | visited.insert(node.get()); 32 | } 33 | } 34 | 35 | void TopologicalSort::operator()(TypedPassContext context) const 36 | { 37 | sorted_t sorted; 38 | visited_t visited; 39 | for (auto node: context.graph.nodes()) 40 | { 41 | visit(sorted, visited, node); 42 | } 43 | context.graph.metadata().set(TopologicalSortData(std::move(sorted))); 44 | } 45 | 46 | const char* TopologicalSort::name() 47 | { 48 | return "TopologicalSort"; 49 | } 50 | 51 | const char* TopologicalSortData::name() 52 | { 53 | return "TopologicalSortData"; 54 | } 55 | 56 | bool LazyTopologicalSortChecker::nodeCreated(const Graph& /*graph*/, const NodeHandle& /*node*/) 57 | { 58 | // We need to rebuild nodes list after nodes creation 59 | return false; 60 | } 61 | 62 | bool LazyTopologicalSortChecker::nodeAboutToBeDestroyed(const Graph& /*graph*/, const NodeHandle& /*node*/) 63 | { 64 | // Removing node cannot change topological order and sorter nodes list can correctly handle nodes removal 65 | return true; 66 | } 67 | 68 | bool LazyTopologicalSortChecker::edgeCreated(const Graph& /*graph*/, const EdgeHandle& /*edge*/) 69 | { 70 | // Adding edge CAN change topological order 71 | return false; 72 | } 73 | 74 | bool LazyTopologicalSortChecker::edgeAboutToBeDestroyed(const Graph& /*graph*/, const EdgeHandle& /*edge*/) 75 | { 76 | // Removing edge cannot change topological order 77 | return true; 78 | } 79 | 80 | bool LazyTopologicalSortChecker::edgeAboutToBeRelinked(const Graph& /*graph*/, 81 | const EdgeHandle& /*edge*/, 82 | const NodeHandle& /*newSrcNode*/, 83 | const NodeHandle& /*newDstNode*/) 84 | { 85 | // Relinking edge CAN change topological order 86 | return false; 87 | } 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /sources/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | include(ExternalProject) 8 | 9 | if(DEFINED GTEST_ROOT) 10 | find_package(GTest REQUIRED) 11 | else() 12 | set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/third_party) 13 | 14 | set(GTEST_INSTALL_DIR ${CMAKE_BINARY_DIR}/third_party/gtest-bin) 15 | 16 | ExternalProject_Add( 17 | GTest 18 | URL https://github.com/google/googletest/archive/release-1.8.1.zip 19 | CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_INSTALL_DIR} -Dgtest_force_shared_crt=ON 20 | LOG_DOWNLOAD ON 21 | LOG_CONFIGURE ON 22 | LOG_BUILD ON 23 | ) 24 | 25 | set(GTEST_LIBRARIES_PATH ${GTEST_INSTALL_DIR}/lib/) 26 | 27 | set(GTEST_LIB_PREFIX ${CMAKE_FIND_LIBRARY_PREFIXES}) 28 | if( WIN32 AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")) 29 | # Somehow in this case we get GTest compiled as gtest.lib and 30 | # prefix equals to "pub;" 31 | # Workarounds, workarounds... 32 | set(GTEST_LIB_PREFIX "") 33 | endif() 34 | 35 | set(GTEST_LIBRARY_PATH ${GTEST_LIBRARIES_PATH}/${GTEST_LIB_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX}) 36 | set(GTEST_LIBRARY gtest) 37 | add_library(${GTEST_LIBRARY} UNKNOWN IMPORTED) 38 | set_property(TARGET ${GTEST_LIBRARY} PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARY_PATH}) 39 | add_dependencies(${GTEST_LIBRARY} GTest) 40 | 41 | set(GTEST_MAIN_LIBRARY_PATH ${GTEST_LIBRARIES_PATH}/${GTEST_LIB_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX}) 42 | set(GTEST_MAIN_LIBRARY gtest-main) 43 | add_library(${GTEST_MAIN_LIBRARY} UNKNOWN IMPORTED) 44 | set_property(TARGET ${GTEST_MAIN_LIBRARY} PROPERTY IMPORTED_LOCATION ${GTEST_MAIN_LIBRARY_PATH}) 45 | add_dependencies(${GTEST_MAIN_LIBRARY} GTest) 46 | 47 | set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) 48 | set(GTEST_INCLUDE_DIRS ${GTEST_INSTALL_DIR}/include) 49 | endif() 50 | 51 | add_subdirectory(ade) 52 | add_subdirectory(common) 53 | -------------------------------------------------------------------------------- /sources/tests/ade/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | project( ade-tests ) 8 | 9 | include_directories(${GTEST_INCLUDE_DIRS}) 10 | 11 | # Required by gtest 12 | find_package(Threads REQUIRED) 13 | 14 | file( GLOB sources *.cpp ) 15 | file( GLOB include *.hpp ) 16 | 17 | add_executable(${PROJECT_NAME} ${include} ${sources}) 18 | 19 | add_security_flags( ${PROJECT_NAME} ) 20 | 21 | target_link_libraries(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES} Threads::Threads ade) 22 | 23 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin COMPONENT test) 24 | 25 | add_test(NAME ADETests COMMAND ${PROJECT_NAME} --gtest_output=xml:${CMAKE_BINARY_DIR}/${PROJECT_NAME}_test.xml) 26 | -------------------------------------------------------------------------------- /sources/tests/ade/check_cycles_pass.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using namespace ade; 13 | 14 | TEST(CheckCyclesPass, Simple) 15 | { 16 | using namespace passes; 17 | Graph gr; 18 | PassContext context{gr}; 19 | ASSERT_NO_THROW(CheckCycles()(context)); // Empty graph 20 | auto node1 = gr.createNode(); 21 | auto node2 = gr.createNode(); 22 | auto node3 = gr.createNode(); 23 | auto node4 = gr.createNode(); 24 | auto node5 = gr.createNode(); 25 | auto node6 = gr.createNode(); 26 | auto edge1 = gr.link(node2, node3); 27 | auto edge2 = gr.link(node2, node5); 28 | auto edge3 = gr.link(node3, node4); 29 | auto edge4 = gr.link(node3, node5); 30 | auto edge5 = gr.link(node4, node1); 31 | ASSERT_NO_THROW(CheckCycles()(context)); 32 | } 33 | 34 | TEST(CheckCyclesPass, Cycle1) 35 | { 36 | using namespace passes; 37 | Graph gr; 38 | PassContext context{gr}; 39 | auto node1 = gr.createNode(); 40 | auto node2 = gr.createNode(); 41 | auto edge1 = gr.link(node1, node2); 42 | auto edge2 = gr.link(node2, node1); 43 | ASSERT_THROW(CheckCycles()(context), CycleFound); 44 | } 45 | 46 | TEST(CheckCyclesPass, Cycle2) 47 | { 48 | using namespace passes; 49 | Graph gr; 50 | PassContext context{gr}; 51 | auto node1 = gr.createNode(); 52 | auto node2 = gr.createNode(); 53 | auto node3 = gr.createNode(); 54 | auto node4 = gr.createNode(); 55 | auto node5 = gr.createNode(); 56 | auto node6 = gr.createNode(); 57 | auto edge1 = gr.link(node1, node2); 58 | auto edge2 = gr.link(node2, node3); 59 | auto edge3 = gr.link(node3, node4); 60 | auto edge4 = gr.link(node4, node5); 61 | auto edge5 = gr.link(node5, node6); 62 | auto edge6 = gr.link(node6, node1); 63 | ASSERT_THROW(CheckCycles()(context), CycleFound); 64 | } 65 | 66 | TEST(CheckCyclesPass, Cycle3) 67 | { 68 | using namespace passes; 69 | Graph gr; 70 | PassContext context{gr}; 71 | auto node1 = gr.createNode(); 72 | auto node2 = gr.createNode(); 73 | auto node3 = gr.createNode(); 74 | auto node4 = gr.createNode(); 75 | auto node5 = gr.createNode(); 76 | auto node6 = gr.createNode(); 77 | auto edge1 = gr.link(node2, node3); 78 | auto edge2 = gr.link(node2, node5); 79 | auto edge3 = gr.link(node3, node4); 80 | auto edge4 = gr.link(node3, node5); 81 | auto edge5 = gr.link(node4, node1); 82 | auto edge6 = gr.link(node1, node2); 83 | auto edge7 = gr.link(node6, node3); 84 | ASSERT_THROW(CheckCycles()(context), CycleFound); 85 | } 86 | -------------------------------------------------------------------------------- /sources/tests/ade/comm_buffer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | using namespace ade; 16 | 17 | namespace 18 | { 19 | class TestBuffer : public IDataBuffer 20 | { 21 | public: 22 | int mapCalled = 0; 23 | int unmapCalled = 0; 24 | memory::DynMdView view; 25 | 26 | // IDataBuffer interface 27 | virtual MapId map(const Span& /*span*/, Access /*access*/) override 28 | { 29 | ++mapCalled; 30 | return MapId{view,0}; 31 | } 32 | virtual void unmap(const MapId& /*id*/) override 33 | { 34 | ++unmapCalled; 35 | } 36 | virtual void finalizeWrite(const Span& /*span*/) override 37 | { 38 | } 39 | virtual void finalizeRead(const Span& /*span*/) override 40 | { 41 | } 42 | virtual Size alignment(const Span& /*span*/) override 43 | { 44 | return Size{}; 45 | } 46 | }; 47 | 48 | } 49 | 50 | TEST(CommBuffer, DataBufferMapper) 51 | { 52 | memory::DynMdSpan span({util::Span(0,16),util::Span(0,16)}); 53 | std::array data; 54 | util::MemoryRange mem(data.data(), data.size() * sizeof(int)); 55 | memory::DynMdView view(mem, {util::make_dimension(16,sizeof(int)), 56 | util::make_dimension(16,16 * sizeof(int))}); 57 | 58 | TestBuffer buff; 59 | buff.view = view; 60 | DataBufferView buffview(&buff, span); 61 | { 62 | EXPECT_EQ(0, buff.mapCalled); 63 | EXPECT_EQ(0, buff.unmapCalled); 64 | DataBufferMapper mapper(buffview, span, IDataBuffer::Read); 65 | EXPECT_EQ(1, buff.mapCalled); 66 | EXPECT_EQ(0, buff.unmapCalled); 67 | auto mappedView = mapper.view(); 68 | EXPECT_EQ(mem.data, mappedView.mem.data); 69 | EXPECT_EQ(mem.size, mappedView.mem.size); 70 | ASSERT_EQ(mappedView.count(), view.count()); 71 | for (auto i: util::iota(mappedView.count())) 72 | { 73 | EXPECT_EQ(view.dimensions[i].step, view.dimensions[i].step); 74 | EXPECT_EQ(view.dimensions[i].length, view.dimensions[i].length); 75 | } 76 | } 77 | EXPECT_EQ(1, buff.mapCalled); 78 | EXPECT_EQ(1, buff.unmapCalled); 79 | } 80 | -------------------------------------------------------------------------------- /sources/tests/ade/communications.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include "ade/communication/callback_connector.hpp" 10 | 11 | #include "ade/util/algorithm.hpp" 12 | #include "ade/util/iota_range.hpp" 13 | 14 | using namespace ade; 15 | 16 | namespace 17 | { 18 | void testCommProducersConsumersCalls(int producers, int consumers) 19 | { 20 | // Producers consumers connections 21 | CallbackConnector<> comm(producers, consumers); 22 | 23 | std::vector consumersCalled(consumers); 24 | 25 | for (auto i: util::iota(consumers)) 26 | { 27 | comm.addConsumerCallback([i, &consumersCalled]() 28 | { 29 | ++consumersCalled[i]; 30 | }); 31 | } 32 | 33 | auto resetter = comm.finalize(); 34 | 35 | for (auto t: util::iota(3)) 36 | { 37 | util::fill(consumersCalled, 0); 38 | std::vector> producersCallbacks(producers); 39 | 40 | for (auto i: util::iota(producers)) 41 | { 42 | producersCallbacks[i] = comm.getProducerCallback(); 43 | } 44 | 45 | for (auto i: util::iota(producers)) 46 | { 47 | for (auto j: util::iota(consumers)) 48 | { 49 | EXPECT_EQ(0, consumersCalled[j]); 50 | } 51 | 52 | producersCallbacks[i](); 53 | 54 | // All consumers must be called exactly 1 time after all producers calls 55 | const auto callCount = (i == (producers - 1) ? 1 : 0); 56 | 57 | for (auto j: util::iota(consumers)) 58 | { 59 | EXPECT_EQ(callCount, consumersCalled[j]); 60 | } 61 | } 62 | 63 | for (auto j: util::iota(consumers)) 64 | { 65 | // Each consumer must be called exactly 1 time 66 | EXPECT_EQ(1, consumersCalled[j]); 67 | } 68 | 69 | if (nullptr != resetter) 70 | { 71 | resetter(); 72 | } 73 | } 74 | } 75 | } 76 | 77 | TEST(Communications, CallbackConnector) 78 | { 79 | for (auto i: util::iota(1,4)) 80 | { 81 | for (auto j: util::iota(1,4)) 82 | { 83 | std::stringstream ss; 84 | ss << "Test comm producer/consumer connections " << i << " " << j; 85 | SCOPED_TRACE(ss.str()); 86 | testCommProducersConsumersCalls(i, j); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /sources/tests/ade/node.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace ade; 16 | 17 | TEST(Node, Link) 18 | { 19 | Graph gr; 20 | auto node1 = gr.createNode(); 21 | ASSERT_EQ(0, node1->inEdges().size()); 22 | ASSERT_EQ(0, node1->outEdges().size()); 23 | auto node2 = gr.createNode(); 24 | auto node3 = gr.createNode(); 25 | 26 | auto edge1 = gr.link(node1, node2); 27 | ASSERT_NE(nullptr, edge1); 28 | ASSERT_EQ(node1, edge1->srcNode()); 29 | ASSERT_EQ(node2, edge1->dstNode()); 30 | ASSERT_EQ(0, node1->inEdges().size()); 31 | ASSERT_EQ(1, node1->outEdges().size()); 32 | ASSERT_EQ(1, node2->inEdges().size()); 33 | ASSERT_EQ(0, node2->outEdges().size()); 34 | 35 | ASSERT_EQ(0, node1->inNodes().size()); 36 | ASSERT_EQ(1, node1->outNodes().size()); 37 | ASSERT_EQ(1, node2->inNodes().size()); 38 | ASSERT_EQ(0, node2->outNodes().size()); 39 | 40 | auto edge2 = gr.link(node2, node3); 41 | ASSERT_NE(nullptr, edge2); 42 | ASSERT_EQ(1, node2->inEdges().size()); 43 | ASSERT_EQ(1, node2->outEdges().size()); 44 | ASSERT_EQ(1, node3->inEdges().size()); 45 | ASSERT_EQ(0, node3->outEdges().size()); 46 | 47 | ASSERT_EQ(1, node2->inNodes().size()); 48 | ASSERT_EQ(1, node2->outNodes().size()); 49 | ASSERT_EQ(1, node3->inNodes().size()); 50 | ASSERT_EQ(0, node3->outNodes().size()); 51 | 52 | gr.erase(node3); 53 | ASSERT_EQ(nullptr, edge2); 54 | ASSERT_EQ(1, node2->inEdges().size()); 55 | ASSERT_EQ(0, node2->outEdges().size()); 56 | 57 | ASSERT_EQ(1, node2->inNodes().size()); 58 | ASSERT_EQ(0, node2->outNodes().size()); 59 | 60 | gr.erase(edge1); 61 | ASSERT_EQ(nullptr, edge1); 62 | ASSERT_EQ(0, node1->inEdges().size()); 63 | ASSERT_EQ(0, node1->outEdges().size()); 64 | ASSERT_EQ(0, node2->inEdges().size()); 65 | ASSERT_EQ(0, node2->outEdges().size()); 66 | 67 | ASSERT_EQ(0, node1->inNodes().size()); 68 | ASSERT_EQ(0, node1->outNodes().size()); 69 | ASSERT_EQ(0, node2->inNodes().size()); 70 | ASSERT_EQ(0, node2->outNodes().size()); 71 | } 72 | 73 | TEST(Node, ReLink) 74 | { 75 | Graph gr; 76 | auto node1 = gr.createNode(); 77 | auto node2 = gr.createNode(); 78 | auto node3 = gr.createNode(); 79 | 80 | auto edge = gr.link(node1, node2); 81 | ASSERT_NE(nullptr, edge); 82 | ASSERT_EQ(node1, edge->srcNode()); 83 | ASSERT_EQ(node2, edge->dstNode()); 84 | ASSERT_EQ(0, node1->inEdges().size()); 85 | ASSERT_EQ(1, node1->outEdges().size()); 86 | ASSERT_EQ(1, node2->inEdges().size()); 87 | ASSERT_EQ(0, node2->outEdges().size()); 88 | ASSERT_EQ(0, node3->inEdges().size()); 89 | ASSERT_EQ(0, node3->outEdges().size()); 90 | 91 | edge = gr.link(edge, node3); 92 | ASSERT_NE(nullptr, edge); 93 | ASSERT_EQ(node1, edge->srcNode()); 94 | ASSERT_EQ(node3, edge->dstNode()); 95 | ASSERT_EQ(0, node1->inEdges().size()); 96 | ASSERT_EQ(1, node1->outEdges().size()); 97 | ASSERT_EQ(0, node2->inEdges().size()); 98 | ASSERT_EQ(0, node2->outEdges().size()); 99 | ASSERT_EQ(1, node3->inEdges().size()); 100 | ASSERT_EQ(0, node3->outEdges().size()); 101 | 102 | edge = gr.link(node2, edge); 103 | ASSERT_NE(nullptr, edge); 104 | ASSERT_EQ(node2, edge->srcNode()); 105 | ASSERT_EQ(node3, edge->dstNode()); 106 | ASSERT_EQ(0, node1->inEdges().size()); 107 | ASSERT_EQ(0, node1->outEdges().size()); 108 | ASSERT_EQ(0, node2->inEdges().size()); 109 | ASSERT_EQ(1, node2->outEdges().size()); 110 | ASSERT_EQ(1, node3->inEdges().size()); 111 | ASSERT_EQ(0, node3->outEdges().size()); 112 | 113 | gr.erase(edge); 114 | ASSERT_EQ(nullptr, edge); 115 | ASSERT_EQ(0, node1->inEdges().size()); 116 | ASSERT_EQ(0, node1->outEdges().size()); 117 | ASSERT_EQ(0, node2->inEdges().size()); 118 | ASSERT_EQ(0, node2->outEdges().size()); 119 | ASSERT_EQ(0, node3->inEdges().size()); 120 | ASSERT_EQ(0, node3->outEdges().size()); 121 | } 122 | 123 | TEST(Node, Edges) 124 | { 125 | Graph gr; 126 | auto node1 = gr.createNode(); 127 | auto node2 = gr.createNode(); 128 | auto node3 = gr.createNode(); 129 | auto node4 = gr.createNode(); 130 | 131 | EdgeHandle edges[] = { gr.link(node1, node2), 132 | gr.link(node1, node3), 133 | gr.link(node1, node4) }; 134 | ASSERT_EQ(3, node1->outEdges().size()); 135 | for (EdgeHandle e: node1->outEdges()) 136 | { 137 | ASSERT_NE(nullptr, e); 138 | auto it = std::find(std::begin(edges), std::end(edges), e); 139 | ASSERT_NE(std::end(edges), it); 140 | } 141 | 142 | ASSERT_EQ(1, node2->inEdges().size()); 143 | ASSERT_EQ(edges[0], node2->inEdges().front()); 144 | 145 | ASSERT_EQ(1, node2->inNodes().size()); 146 | ASSERT_EQ(node1, node2->inNodes().front()); 147 | 148 | ASSERT_EQ(1, node3->inEdges().size()); 149 | ASSERT_EQ(edges[1], node3->inEdges().front()); 150 | 151 | ASSERT_EQ(1, node3->inNodes().size()); 152 | ASSERT_EQ(node1, node3->inNodes().front()); 153 | 154 | ASSERT_EQ(1, node4->inEdges().size()); 155 | ASSERT_EQ(edges[2], node4->inEdges().front()); 156 | 157 | ASSERT_EQ(1, node4->inNodes().size()); 158 | ASSERT_EQ(node1, node4->inNodes().front()); 159 | } 160 | -------------------------------------------------------------------------------- /sources/tests/ade/passmanager.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | using namespace ade; 14 | 15 | struct EmptyContext{}; 16 | 17 | TEST(PassManager, PassList) 18 | { 19 | EmptyContext ctx; 20 | bool pass1called = false; 21 | bool pass2called = false; 22 | bool pass3called = false; 23 | PassList list; 24 | list.addPass([&](const EmptyContext&) 25 | { 26 | EXPECT_FALSE(pass1called); 27 | EXPECT_FALSE(pass2called); 28 | EXPECT_FALSE(pass3called); 29 | pass1called = true; 30 | }); 31 | list.addPass([&](const EmptyContext&) 32 | { 33 | EXPECT_TRUE(pass1called); 34 | EXPECT_FALSE(pass2called); 35 | EXPECT_FALSE(pass3called); 36 | pass2called = true; 37 | }); 38 | list.addPass([&](const EmptyContext&) 39 | { 40 | EXPECT_TRUE(pass1called); 41 | EXPECT_TRUE(pass2called); 42 | EXPECT_FALSE(pass3called); 43 | pass3called = true; 44 | }); 45 | list.run(ctx); 46 | EXPECT_TRUE(pass1called); 47 | EXPECT_TRUE(pass2called); 48 | EXPECT_TRUE(pass3called); 49 | } 50 | 51 | TEST(PassManager, PassStages) 52 | { 53 | EmptyContext ctx; 54 | PassManager pm; 55 | bool pass1called = false; 56 | bool pass2called = false; 57 | bool pass3called = false; 58 | pm.addStage("foo"); 59 | pm.addStage("bar"); 60 | pm.addStage("baz","foo"); 61 | pm.addPass("foo",[&](const EmptyContext&) 62 | { 63 | EXPECT_FALSE(pass1called); 64 | EXPECT_FALSE(pass2called); 65 | EXPECT_FALSE(pass3called); 66 | pass1called = true; 67 | }); 68 | pm.addPass("baz",[&](const EmptyContext&) 69 | { 70 | EXPECT_TRUE(pass1called); 71 | EXPECT_FALSE(pass2called); 72 | EXPECT_FALSE(pass3called); 73 | pass2called = true; 74 | }); 75 | pm.addPass("bar",[&](const EmptyContext&) 76 | { 77 | EXPECT_TRUE(pass1called); 78 | EXPECT_TRUE(pass2called); 79 | EXPECT_FALSE(pass3called); 80 | pass3called = true; 81 | }); 82 | pm.run(ctx); 83 | EXPECT_TRUE(pass1called); 84 | EXPECT_TRUE(pass2called); 85 | EXPECT_TRUE(pass3called); 86 | 87 | EXPECT_FALSE(pm.stages().empty()); 88 | for (auto it: indexed(pm.stages())) 89 | { 90 | auto i = util::index(it); 91 | auto& stage = util::value(it); 92 | if(0 == i) 93 | { 94 | EXPECT_EQ("foo", stage.first); 95 | } 96 | else if(1 == i) 97 | { 98 | EXPECT_EQ("baz", stage.first); 99 | } 100 | else if(2 == i) 101 | { 102 | EXPECT_EQ("bar", stage.first); 103 | } 104 | else 105 | { 106 | FAIL(); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /sources/tests/ade/topological_sort_pass.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace ade; 16 | 17 | template 18 | static std::vector toVec(T range) 19 | { 20 | return std::vector(range.begin(), range.end()); 21 | } 22 | 23 | TEST(TopologicalSortPass, Simple1) 24 | { 25 | using namespace passes; 26 | Graph gr; 27 | TypedGraph tgr(gr); 28 | PassContext context{gr}; 29 | auto node1 = gr.createNode(); 30 | auto node2 = gr.createNode(); 31 | auto edge1 = gr.link(node1, node2); 32 | TopologicalSort()(context); 33 | const auto sorted = toVec(tgr.metadata().get().nodes()); 34 | ASSERT_EQ(2, sorted.size()); 35 | ASSERT_EQ(node1, sorted[0]); 36 | ASSERT_EQ(node2, sorted[1]); 37 | } 38 | 39 | TEST(TopologicalSortPass, Simple2) 40 | { 41 | using namespace passes; 42 | Graph gr; 43 | TypedGraph tgr(gr); 44 | PassContext context{gr}; 45 | auto node1 = gr.createNode(); 46 | auto node2 = gr.createNode(); 47 | auto edge1 = gr.link(node2, node1); 48 | TopologicalSort()(context); 49 | const auto sorted = toVec(tgr.metadata().get().nodes()); 50 | ASSERT_EQ(2, sorted.size()); 51 | ASSERT_EQ(node2, sorted[0]); 52 | ASSERT_EQ(node1, sorted[1]); 53 | } 54 | 55 | static void checkOrder(const std::vector& nodes) 56 | { 57 | for (size_t i = 0; i < nodes.size(); ++i) 58 | { 59 | auto node = nodes[i]; 60 | for (auto prev: 61 | util::map(node->inEdges(), [](const EdgeHandle& e) { return e->srcNode(); })) 62 | { 63 | auto it = std::find(nodes.begin(), nodes.begin() + i, prev); 64 | EXPECT_NE(nodes.begin() + i, it); 65 | } 66 | } 67 | } 68 | 69 | TEST(TopologicalSortPass, Complex1) 70 | { 71 | using namespace passes; 72 | Graph gr; 73 | TypedGraph tgr(gr); 74 | PassContext context{gr}; 75 | auto node1 = gr.createNode(); 76 | auto node2 = gr.createNode(); 77 | auto node3 = gr.createNode(); 78 | auto node4 = gr.createNode(); 79 | auto node5 = gr.createNode(); 80 | auto node6 = gr.createNode(); 81 | auto edge1 = gr.link(node6, node5); 82 | auto edge2 = gr.link(node5, node4); 83 | auto edge3 = gr.link(node4, node2); 84 | auto edge4 = gr.link(node2, node3); 85 | auto edge5 = gr.link(node3, node1); 86 | TopologicalSort()(context); 87 | const auto sorted = toVec(tgr.metadata().get().nodes()); 88 | checkOrder(sorted); 89 | ASSERT_EQ(6, sorted.size()); 90 | ASSERT_EQ(node6, sorted[0]); 91 | ASSERT_EQ(node5, sorted[1]); 92 | ASSERT_EQ(node4, sorted[2]); 93 | ASSERT_EQ(node2, sorted[3]); 94 | ASSERT_EQ(node3, sorted[4]); 95 | ASSERT_EQ(node1, sorted[5]); 96 | } 97 | 98 | TEST(TopologicalSortPass, Complex2) 99 | { 100 | using namespace passes; 101 | Graph gr; 102 | TypedGraph tgr(gr); 103 | PassContext context{gr}; 104 | auto node1 = gr.createNode(); 105 | auto node2 = gr.createNode(); 106 | auto node3 = gr.createNode(); 107 | auto node4 = gr.createNode(); 108 | auto node5 = gr.createNode(); 109 | auto node6 = gr.createNode(); 110 | auto edge1 = gr.link(node2, node3); 111 | auto edge2 = gr.link(node2, node5); 112 | auto edge3 = gr.link(node3, node4); 113 | auto edge4 = gr.link(node3, node5); 114 | auto edge5 = gr.link(node4, node1); 115 | auto edge6 = gr.link(node4, node6); 116 | TopologicalSort()(context); 117 | const auto sorted = toVec(tgr.metadata().get().nodes()); 118 | ASSERT_EQ(6, sorted.size()); 119 | checkOrder(sorted); 120 | } 121 | 122 | TEST(TopologicalSortPass, TestNodeRemoval) 123 | { 124 | using namespace passes; 125 | Graph gr; 126 | TypedGraph tgr(gr); 127 | PassContext context{gr}; 128 | auto node1 = gr.createNode(); 129 | auto node2 = gr.createNode(); 130 | auto node3 = gr.createNode(); 131 | auto edge1 = gr.link(node1, node2); 132 | auto edge2 = gr.link(node2, node3); 133 | TopologicalSort()(context); 134 | { 135 | const auto sorted = toVec(tgr.metadata().get().nodes()); 136 | ASSERT_EQ((std::vector{node1,node2,node3}), sorted); 137 | } 138 | gr.erase(node2); 139 | { 140 | const auto sorted = toVec(tgr.metadata().get().nodes()); 141 | ASSERT_EQ((std::vector{node1,node3}), sorted); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /sources/tests/ade/typed_graph.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace ade; 18 | 19 | namespace 20 | { 21 | // Put all types in custom namespace to test ADL for metadata name 22 | namespace Tst 23 | { 24 | struct Foo 25 | { 26 | int val; 27 | static const char* name() { return "Foo"; } 28 | }; 29 | struct Bar 30 | { 31 | int val; 32 | }; 33 | struct Baz 34 | { 35 | int val; 36 | static std::string name() { return "Baz"; } 37 | }; 38 | struct Qux 39 | { 40 | int val; 41 | static std::string name() { return "Baz"; } // Qux and Baz have the same name 42 | }; 43 | 44 | const char* getMetadataName(ade::MetadataNameTag) 45 | { 46 | return "Bar"; 47 | } 48 | } 49 | } 50 | 51 | TEST(TypedGraph, NotUniqueName) 52 | { 53 | Graph srcGr; 54 | using TG = TypedGraph; 55 | EXPECT_THROW(TG gr(srcGr), std::logic_error); // Qux and Baz cannot be in one graph, because have the same name 56 | } 57 | 58 | TEST(TypedGraph, Simple) 59 | { 60 | Graph srcGr; 61 | TypedGraph gr(srcGr); 62 | 63 | auto node1 = gr.createNode(); 64 | auto node2 = gr.createNode(); 65 | auto node3 = gr.createNode(); 66 | ASSERT_NE(nullptr, node1); 67 | ASSERT_NE(nullptr, node2); 68 | ASSERT_NE(nullptr, node3); 69 | ASSERT_EQ(3, gr.nodes().size()); 70 | NodeHandle arr[] = {node1, node2, node3}; 71 | for (NodeHandle h: gr.nodes()) 72 | { 73 | ASSERT_NE(nullptr, h); 74 | auto it = std::find(std::begin(arr), std::end(arr), h); 75 | ASSERT_NE(std::end(arr), it); 76 | } 77 | gr.erase(node2); 78 | ASSERT_EQ(nullptr, node2); 79 | ASSERT_EQ(2, gr.nodes().size()); 80 | } 81 | 82 | TEST(TypedGraph, EraseMiddleNode) 83 | { 84 | Graph srcGr; 85 | TypedGraph gr(srcGr); 86 | 87 | auto node1 = gr.createNode(); 88 | auto node2 = gr.createNode(); 89 | auto node3 = gr.createNode(); 90 | 91 | gr.link(node1, node2); 92 | gr.link(node2, node3); 93 | 94 | gr.erase(node2); 95 | 96 | EXPECT_EQ(2, gr.nodes().size()); 97 | } 98 | 99 | namespace 100 | { 101 | template 102 | void checkMeta3(T& gr) 103 | { 104 | auto meta = gr.metadata(); 105 | EXPECT_EQ(42, meta.template get().val); 106 | EXPECT_EQ(77, meta.template get().val); 107 | EXPECT_EQ(123, meta.template get().val); 108 | } 109 | 110 | template 111 | void checkMeta2(T& gr) 112 | { 113 | auto meta = gr.metadata(); 114 | EXPECT_EQ(42, meta.template get().val); 115 | EXPECT_EQ(77, meta.template get().val); 116 | } 117 | } 118 | 119 | TEST(TypedGraph, Constructors) 120 | { 121 | Graph srcGr; 122 | 123 | ConstTypedGraph gr1(srcGr); 124 | TypedGraph gr2(srcGr); 125 | gr2.metadata().set(Tst::Foo{42}); 126 | gr2.metadata().set(Tst::Bar{77}); 127 | gr2.metadata().set(Tst::Baz{123}); 128 | 129 | { 130 | ConstTypedGraph gr3(gr1); 131 | checkMeta3(gr3); 132 | } 133 | 134 | { 135 | ConstTypedGraph gr3(gr2); 136 | TypedGraph gr4(gr2); 137 | checkMeta3(gr3); 138 | checkMeta3(gr4); 139 | } 140 | 141 | { 142 | ConstTypedGraph gr3(gr1); 143 | checkMeta2(gr3); 144 | } 145 | 146 | { 147 | ConstTypedGraph gr3(gr2); 148 | TypedGraph gr4(gr2); 149 | checkMeta2(gr3); 150 | checkMeta2(gr4); 151 | } 152 | } 153 | 154 | TEST(TypedGraph, TypedMetadata) 155 | { 156 | Graph srcGr; 157 | TypedGraph gr1(srcGr); 158 | ConstTypedGraph gr2(gr1); 159 | 160 | ASSERT_FALSE(gr1.metadata().contains()); 161 | ASSERT_FALSE(gr1.metadata().contains()); 162 | ASSERT_FALSE(gr1.metadata().contains()); 163 | ASSERT_FALSE(gr2.metadata().contains()); 164 | ASSERT_FALSE(gr2.metadata().contains()); 165 | ASSERT_FALSE(gr2.metadata().contains()); 166 | 167 | 168 | gr1.metadata().set(Tst::Foo{42}); 169 | ASSERT_TRUE( gr1.metadata().contains()); 170 | ASSERT_FALSE(gr1.metadata().contains()); 171 | ASSERT_FALSE(gr1.metadata().contains()); 172 | ASSERT_TRUE( gr2.metadata().contains()); 173 | ASSERT_FALSE(gr2.metadata().contains()); 174 | ASSERT_FALSE(gr2.metadata().contains()); 175 | 176 | ASSERT_EQ(42, gr1.metadata().get().val); 177 | ASSERT_EQ(42, gr2.metadata().get().val); 178 | 179 | 180 | gr1.metadata().set(Tst::Bar{77}); 181 | ASSERT_TRUE( gr1.metadata().contains()); 182 | ASSERT_TRUE( gr1.metadata().contains()); 183 | ASSERT_FALSE(gr1.metadata().contains()); 184 | ASSERT_TRUE( gr2.metadata().contains()); 185 | ASSERT_TRUE( gr2.metadata().contains()); 186 | ASSERT_FALSE(gr2.metadata().contains()); 187 | 188 | ASSERT_EQ(42, gr1.metadata().get().val); 189 | ASSERT_EQ(77, gr1.metadata().get().val); 190 | ASSERT_EQ(123, gr1.metadata().get(Tst::Baz{123}).val); 191 | ASSERT_EQ(42, gr2.metadata().get().val); 192 | ASSERT_EQ(77, gr2.metadata().get().val); 193 | ASSERT_EQ(123, gr2.metadata().get(Tst::Baz{123}).val); 194 | 195 | 196 | gr1.metadata().erase(); 197 | ASSERT_TRUE( gr1.metadata().contains()); 198 | ASSERT_FALSE(gr1.metadata().contains()); 199 | ASSERT_FALSE(gr1.metadata().contains()); 200 | ASSERT_TRUE( gr2.metadata().contains()); 201 | ASSERT_FALSE(gr2.metadata().contains()); 202 | ASSERT_FALSE(gr2.metadata().contains()); 203 | } 204 | -------------------------------------------------------------------------------- /sources/tests/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | project( common-tests ) 8 | 9 | include_directories(${GTEST_INCLUDE_DIRS}) 10 | 11 | # Required by gtest 12 | find_package(Threads REQUIRED) 13 | 14 | file( GLOB sources *.cpp ) 15 | file( GLOB include *.hpp ) 16 | 17 | add_executable(${PROJECT_NAME} ${include} ${sources}) 18 | 19 | add_security_flags( ${PROJECT_NAME} ) 20 | 21 | target_link_libraries(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES} Threads::Threads ade) 22 | 23 | add_test(NAME CommonTests COMMAND ${PROJECT_NAME} --gtest_output=xml:${CMAKE_BINARY_DIR}/${PROJECT_NAME}_test.xml) 24 | -------------------------------------------------------------------------------- /sources/tests/common/algo_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | TEST(AlgoTest, Find) 15 | { 16 | const std::vector v1 = {1,2,3}; 17 | EXPECT_EQ(v1.begin() + 1, ade::util::find(v1,2)); 18 | EXPECT_EQ(v1.end(), ade::util::find(v1,4)); 19 | 20 | const int v2[] = {1,2,3}; 21 | EXPECT_EQ(std::begin(v2) + 1, ade::util::find(v2,2)); 22 | EXPECT_EQ(std::end(v2), ade::util::find(v2,4)); 23 | } 24 | 25 | TEST(AlgoTest, Contains) 26 | { 27 | const std::map m = {{1,2},{2,3},{3,4}}; 28 | EXPECT_TRUE(ade::util::contains(m, 2)); 29 | EXPECT_FALSE(ade::util::contains(m, 6)); 30 | } 31 | 32 | static_assert(0 == ade::util::type_list_index::value, "type_list_index test failed"); 33 | static_assert(0 == ade::util::type_list_index::value, "type_list_index test failed"); 34 | static_assert(1 == ade::util::type_list_index::value, "type_list_index test failed"); 35 | static_assert(2 == ade::util::type_list_index::value, "type_list_index test failed"); 36 | static_assert(0 == ade::util::type_list_index::value, "type_list_index test failed"); 37 | 38 | // Negative test will fail compilation, keep it here for reference 39 | //static_assert(0 == ade::util::type_list_index::value, "type_list_index test failed"); 40 | -------------------------------------------------------------------------------- /sources/tests/common/chain_range_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | TEST(ChainRangeTest, Identity) 18 | { 19 | int arr[] = {1,2,3,4,5}; 20 | 21 | std::vector result; 22 | 23 | for (auto& elem: ade::util::chain(ade::util::toRange(arr))) 24 | { 25 | static_assert(std::is_same::value, "Invalid type"); 26 | result.push_back(elem); 27 | } 28 | 29 | EXPECT_EQ((std::vector{1,2,3,4,5}), result); 30 | } 31 | 32 | TEST(ChainRangeTest, SameElemTypes2) 33 | { 34 | std::array arr1 = {1,2,3}; 35 | std::vector arr2 = {4,5}; 36 | 37 | std::vector result; 38 | 39 | for (auto& elem: ade::util::chain(ade::util::toRange(arr1), 40 | ade::util::toRange(arr2))) 41 | { 42 | static_assert(std::is_same::value, "Invalid type"); 43 | result.push_back(elem); 44 | } 45 | 46 | EXPECT_EQ((std::vector{1,2,3,4,5}), result); 47 | } 48 | 49 | TEST(ChainRangeTest, DifferentElemTypes2) 50 | { 51 | std::array arr1 = {1,2,3}; 52 | short arr2[] = {4,5}; 53 | 54 | std::vector result; 55 | 56 | for (auto elem: ade::util::chain(ade::util::toRange(arr1), 57 | ade::util::toRange(arr2))) 58 | { 59 | static_assert(std::is_same::value, "Invalid type"); 60 | result.push_back(elem); 61 | } 62 | 63 | EXPECT_EQ((std::vector{1,2,3,4,5}), result); 64 | } 65 | 66 | TEST(ChainRangeTest, SameElemTypes3) 67 | { 68 | std::array arr1 = {1,2,3}; 69 | std::vector arr2 = {4,5}; 70 | int arr3[] = {6,7,8}; 71 | 72 | std::vector result; 73 | 74 | for (auto& elem: ade::util::chain(ade::util::toRange(arr1), 75 | ade::util::toRange(arr2), 76 | ade::util::toRange(arr3))) 77 | { 78 | static_assert(std::is_same::value, "Invalid type"); 79 | result.push_back(elem); 80 | } 81 | 82 | EXPECT_EQ((std::vector{1,2,3,4,5,6,7,8}), result); 83 | } 84 | 85 | TEST(ChainRangeTest, DifferentElemTypes3) 86 | { 87 | std::array arr1 = {1,2,3}; 88 | std::vector arr2 = {4,5}; 89 | long long arr3[] = {6,7,8}; 90 | 91 | std::vector result; 92 | 93 | for (auto elem: ade::util::chain(ade::util::toRange(arr1), 94 | ade::util::toRange(arr2), 95 | ade::util::toRange(arr3))) 96 | { 97 | static_assert(std::is_same::value, "Invalid type"); 98 | result.push_back(static_cast(elem)); 99 | } 100 | 101 | EXPECT_EQ((std::vector{1,2,3,4,5,6,7,8}), result); 102 | } 103 | 104 | TEST(ChainRangeTest, Test4) 105 | { 106 | std::array arr1 = {1,2,3}; 107 | std::vector arr2 = {4,5}; 108 | int arr3[] = {6,7,8}; 109 | 110 | std::vector result; 111 | 112 | for (auto elem: ade::util::chain(ade::util::toRange(arr1), 113 | ade::util::toRange(arr2), 114 | ade::util::toRange(arr3), 115 | ade::util::iota(9,12))) 116 | { 117 | static_assert(std::is_same::value, "Invalid type"); 118 | result.push_back(elem); 119 | } 120 | 121 | EXPECT_EQ((std::vector{1,2,3,4,5,6,7,8,9,10,11}), result); 122 | } 123 | 124 | TEST(ChainRangeTest, SizeAndOpIndex) 125 | { 126 | std::array arr1 = {1,2,3}; 127 | std::vector arr2 = {4,5}; 128 | int arr3[] = {6,7,8}; 129 | 130 | auto range = ade::util::chain(ade::util::memory_range(arr1.data(), arr1.size()), 131 | ade::util::memory_range(arr2.data(), arr2.size()), 132 | ade::util::memory_range(&arr3[0], 3)); 133 | const auto& crange = range; 134 | 135 | std::vector result = {1,2,3,4,5,6,7,8}; 136 | const auto count = result.size(); 137 | ASSERT_EQ(count, range.size()); 138 | ASSERT_EQ(count, crange.size()); 139 | 140 | for (auto i: ade::util::iota(count)) 141 | { 142 | EXPECT_EQ(result[i], range[i]); 143 | EXPECT_EQ(result[i], crange[i]); 144 | } 145 | range[1] = 55; 146 | result[1] = 55; 147 | range[3] = 66; 148 | result[3] = 66; 149 | range[6] = 77; 150 | result[6] = 77; 151 | for (auto i: ade::util::iota(count)) 152 | { 153 | EXPECT_EQ(result[i], range[i]); 154 | EXPECT_EQ(result[i], crange[i]); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /sources/tests/common/checkedcast_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | struct CheckedCastFailed 15 | { 16 | 17 | }; 18 | 19 | namespace 20 | { 21 | struct CheckedCastTestHandler final 22 | { 23 | template 24 | void operator()(bool valid, T&& /*value*/) const 25 | { 26 | if (!valid) 27 | { 28 | throw CheckedCastFailed(); 29 | } 30 | } 31 | }; 32 | 33 | 34 | template 35 | I checked_cast_test(J value) 36 | { 37 | return ade::util::checked_cast_impl(value, CheckedCastTestHandler{}); 38 | } 39 | } 40 | 41 | TEST(CheckedCastTest,CheckValid) 42 | { 43 | EXPECT_EQ(0, checked_cast_test((int)0)); 44 | EXPECT_EQ(0, checked_cast_test((short)0)); 45 | EXPECT_EQ(0, checked_cast_test((int)0)); 46 | EXPECT_EQ(0u, checked_cast_test((unsigned)0)); 47 | EXPECT_EQ(0, checked_cast_test((unsigned)0)); 48 | EXPECT_EQ(0u, checked_cast_test((int)0)); 49 | 50 | EXPECT_EQ((int)-1, checked_cast_test((short)-1)); 51 | EXPECT_EQ((unsigned)0xffff, checked_cast_test((unsigned short)0xffff)); 52 | 53 | EXPECT_EQ((short)0x7fff, checked_cast_test((int)0x7fff)); 54 | EXPECT_EQ((unsigned short)0xffff, checked_cast_test((unsigned)0xffff)); 55 | 56 | EXPECT_EQ(0x7fffffff, checked_cast_test((unsigned)0x7fffffff)); 57 | EXPECT_EQ(0x7fffffffu, checked_cast_test((int)0x7fffffff)); 58 | 59 | 60 | EXPECT_EQ(static_cast(0.0f), checked_cast_test(0.0f)); 61 | EXPECT_EQ(static_cast(-0.0f), checked_cast_test(-0.0f)); 62 | EXPECT_EQ(static_cast(1.0f), checked_cast_test(1.0f)); 63 | EXPECT_EQ(static_cast(-1.0f), checked_cast_test(-1.0f)); 64 | EXPECT_EQ(static_cast(1e-15), checked_cast_test(1e-15)); 65 | EXPECT_EQ(static_cast(-1e-15), checked_cast_test(-1e-15)); 66 | EXPECT_EQ(static_cast(1000000.0f), checked_cast_test(1000000.0f)); 67 | EXPECT_EQ(static_cast(-1000000.0f), checked_cast_test(-1000000.0f)); 68 | 69 | EXPECT_EQ(static_cast(0.0f), checked_cast_test(0.0f)); 70 | EXPECT_EQ(static_cast(-0.0f), checked_cast_test(-0.0f)); 71 | EXPECT_EQ(static_cast(1.0f), checked_cast_test(1.0f)); 72 | EXPECT_EQ(static_cast(1e-15), checked_cast_test(1e-15)); 73 | EXPECT_EQ(static_cast(1000000.0f), checked_cast_test(1000000.0f)); 74 | 75 | 76 | EXPECT_EQ(static_cast(0.0), checked_cast_test(0.0)); 77 | EXPECT_EQ(static_cast(-0.0), checked_cast_test(-0.0)); 78 | EXPECT_EQ(static_cast(1.0), checked_cast_test(1.0)); 79 | EXPECT_EQ(static_cast(-1.0), checked_cast_test(-1.0)); 80 | EXPECT_EQ(static_cast(static_cast(std::numeric_limits::max())), 81 | checked_cast_test(static_cast(std::numeric_limits::max()))); 82 | EXPECT_EQ(static_cast(static_cast(std::numeric_limits::min())), 83 | checked_cast_test(static_cast(std::numeric_limits::min()))); 84 | EXPECT_EQ(static_cast(1000000.0), checked_cast_test(1000000.0)); 85 | EXPECT_EQ(static_cast(-1000000.0), checked_cast_test(-1000000.0)); 86 | 87 | for(int i = std::numeric_limits::min(); i <= std::numeric_limits::max(); ++i) 88 | { 89 | EXPECT_EQ(static_cast(static_cast(i)), checked_cast_test(static_cast(i))); 90 | } 91 | } 92 | 93 | TEST(CheckedCastTest,CheckOverflows) 94 | { 95 | EXPECT_THROW(throw CheckedCastFailed(), CheckedCastFailed); 96 | EXPECT_THROW(CheckedCastTestHandler()(false, 0), CheckedCastFailed); 97 | EXPECT_THROW(checked_cast_test ((int)0xffffff), CheckedCastFailed); 98 | EXPECT_THROW(checked_cast_test((int)-1), CheckedCastFailed); 99 | EXPECT_THROW(checked_cast_test ((unsigned)0xffffffff), CheckedCastFailed); 100 | 101 | EXPECT_THROW(checked_cast_test(1e15), CheckedCastFailed); 102 | EXPECT_THROW(checked_cast_test(-1e15), CheckedCastFailed); 103 | EXPECT_THROW(checked_cast_test(1e15), CheckedCastFailed); 104 | EXPECT_THROW(checked_cast_test(-1e15), CheckedCastFailed); 105 | EXPECT_THROW(checked_cast_test(-1.0f), CheckedCastFailed); 106 | EXPECT_THROW(checked_cast_test(-1e-15), CheckedCastFailed); 107 | EXPECT_THROW(checked_cast_test(-1000000.0f), CheckedCastFailed); 108 | 109 | EXPECT_THROW(checked_cast_test(std::numeric_limits::max()), CheckedCastFailed); 110 | EXPECT_THROW(checked_cast_test(std::numeric_limits::lowest()), CheckedCastFailed); 111 | 112 | EXPECT_THROW(checked_cast_test(std::numeric_limits::infinity()), CheckedCastFailed); 113 | EXPECT_THROW(checked_cast_test(-std::numeric_limits::infinity()), CheckedCastFailed); 114 | EXPECT_THROW(checked_cast_test(std::numeric_limits::quiet_NaN()), CheckedCastFailed); 115 | 116 | EXPECT_THROW(checked_cast_test(std::numeric_limits::infinity()), CheckedCastFailed); 117 | EXPECT_THROW(checked_cast_test(-std::numeric_limits::infinity()), CheckedCastFailed); 118 | EXPECT_THROW(checked_cast_test(std::numeric_limits::quiet_NaN()), CheckedCastFailed); 119 | } 120 | -------------------------------------------------------------------------------- /sources/tests/common/filter_range_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | TEST(FilterRangeTest, Test) 15 | { 16 | using namespace ade::util; 17 | int sum1 = 0; 18 | std::vector v1 = {1,10,100,1000,10000,100000,1000000}; 19 | for (auto i: filter(toRange(v1), [&](int /*val*/) { return true; })) 20 | { 21 | sum1 += i; 22 | } 23 | EXPECT_EQ(1111111, sum1); 24 | 25 | struct Filter final 26 | { 27 | bool operator()(int /*val*/) const 28 | { 29 | return true; 30 | } 31 | }; 32 | 33 | sum1 = 0; 34 | for (auto i: filter(toRange(v1))) 35 | { 36 | sum1 += i; 37 | } 38 | EXPECT_EQ(1111111, sum1); 39 | 40 | sum1 = 0; 41 | for (auto i: filter(toRange(v1), [&](int /*val*/) { return false; })) 42 | { 43 | sum1 += i; 44 | } 45 | EXPECT_EQ(0, sum1); 46 | 47 | sum1 = 0; 48 | for (auto i: filter(toRange(v1), [&](int val) 49 | { 50 | if (1 == val) return true; 51 | return false; 52 | })) 53 | { 54 | sum1 += i; 55 | } 56 | EXPECT_EQ(1, sum1); 57 | 58 | sum1 = 0; 59 | for (auto i: filter(toRange(v1), [&](int val) 60 | { 61 | if (1000000 == val) return true; 62 | return false; 63 | })) 64 | { 65 | sum1 += i; 66 | } 67 | EXPECT_EQ(1000000, sum1); 68 | 69 | sum1 = 0; 70 | for (auto i: filter(toRange(v1), [&](int val) 71 | { 72 | if (1 == val || 1000000 == val) return true; 73 | return false; 74 | })) 75 | { 76 | sum1 += i; 77 | } 78 | EXPECT_EQ(1000001, sum1); 79 | 80 | sum1 = 0; 81 | for (auto i: filter(toRange(v1), [&](int val) 82 | { 83 | if (1000 == val || 10000 == val || 100000 == val) return true; 84 | return false; 85 | })) 86 | { 87 | sum1 += i; 88 | } 89 | EXPECT_EQ(111000, sum1); 90 | } 91 | -------------------------------------------------------------------------------- /sources/tests/common/func_ref_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | static int test_func(ade::util::func_ref func) 12 | { 13 | return func(); 14 | } 15 | 16 | static int func() 17 | { 18 | return 42; 19 | } 20 | 21 | TEST(FuncRef, Simple) 22 | { 23 | struct Functor 24 | { 25 | int operator()() 26 | { 27 | return 42; 28 | } 29 | }; 30 | 31 | Functor test; 32 | EXPECT_EQ(42, test_func(&func)); 33 | EXPECT_EQ(42, test_func(func)); 34 | EXPECT_EQ(42, test_func(test)); 35 | EXPECT_EQ(42, test_func(Functor())); 36 | EXPECT_EQ(42, test_func([](){ return 42; })); 37 | } 38 | -------------------------------------------------------------------------------- /sources/tests/common/intrusive_list_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace 14 | { 15 | struct TestStruct 16 | { 17 | ade::util::intrusive_list_node node1; 18 | ade::util::intrusive_list_node node2; 19 | }; 20 | } 21 | 22 | TEST(IntrusiveList, Basic) 23 | { 24 | ade::util::intrusive_list ilist; 25 | 26 | TestStruct s1{}; 27 | TestStruct s2{}; 28 | TestStruct s3{}; 29 | 30 | ASSERT_FALSE(s1.node1.linked()); 31 | ASSERT_FALSE(s2.node1.linked()); 32 | ASSERT_FALSE(s3.node1.linked()); 33 | 34 | ASSERT_TRUE(ilist.empty()); 35 | 36 | ilist.push_back(s1); 37 | 38 | ASSERT_TRUE(s1.node1.linked()); 39 | ASSERT_FALSE(s2.node1.linked()); 40 | ASSERT_FALSE(s3.node1.linked()); 41 | 42 | ASSERT_FALSE(ilist.empty()); 43 | 44 | std::vector vals; 45 | for (auto& s: ilist) vals.push_back(&s); 46 | 47 | ASSERT_EQ(std::vector{{&s1}}, vals); 48 | 49 | ilist.push_back(s2); 50 | 51 | ASSERT_TRUE(s1.node1.linked()); 52 | ASSERT_TRUE(s2.node1.linked()); 53 | ASSERT_FALSE(s3.node1.linked()); 54 | 55 | ASSERT_FALSE(ilist.empty()); 56 | 57 | vals.clear(); 58 | for (auto& s: ilist) vals.push_back(&s); 59 | 60 | ASSERT_EQ((std::vector{&s1,&s2}), vals); 61 | 62 | ilist.push_front(s3); 63 | 64 | ASSERT_TRUE(s1.node1.linked()); 65 | ASSERT_TRUE(s2.node1.linked()); 66 | ASSERT_TRUE(s3.node1.linked()); 67 | 68 | ASSERT_FALSE(ilist.empty()); 69 | 70 | vals.clear(); 71 | for (auto& s: ilist) vals.push_back(&s); 72 | 73 | ASSERT_EQ((std::vector{&s3,&s1,&s2}), vals); 74 | 75 | ilist.clear(); 76 | ASSERT_TRUE(ilist.empty()); 77 | 78 | ASSERT_FALSE(s1.node1.linked()); 79 | ASSERT_FALSE(s2.node1.linked()); 80 | ASSERT_FALSE(s3.node1.linked()); 81 | } 82 | 83 | TEST(IntrusiveList, AutoUnlink) 84 | { 85 | { 86 | ade::util::intrusive_list ilist; 87 | { 88 | TestStruct s1{}; 89 | TestStruct s2{}; 90 | TestStruct s3{}; 91 | 92 | ilist.push_back(s1); 93 | ilist.push_back(s2); 94 | ilist.push_back(s3); 95 | 96 | ASSERT_FALSE(ilist.empty()); 97 | } 98 | ASSERT_TRUE(ilist.empty()); 99 | } 100 | { 101 | TestStruct s1{}; 102 | TestStruct s2{}; 103 | TestStruct s3{}; 104 | 105 | ASSERT_FALSE(s1.node1.linked()); 106 | ASSERT_FALSE(s2.node1.linked()); 107 | ASSERT_FALSE(s3.node1.linked()); 108 | { 109 | ade::util::intrusive_list ilist; 110 | 111 | ilist.push_back(s1); 112 | ilist.push_back(s2); 113 | ilist.push_back(s3); 114 | 115 | ASSERT_TRUE(s1.node1.linked()); 116 | ASSERT_TRUE(s2.node1.linked()); 117 | ASSERT_TRUE(s3.node1.linked()); 118 | } 119 | ASSERT_FALSE(s1.node1.linked()); 120 | ASSERT_FALSE(s2.node1.linked()); 121 | ASSERT_FALSE(s3.node1.linked()); 122 | } 123 | } 124 | 125 | TEST(IntrusiveList, MultipleLists) 126 | { 127 | ade::util::intrusive_list ilist1; 128 | ade::util::intrusive_list ilist2; 129 | 130 | ASSERT_TRUE(ilist1.empty()); 131 | ASSERT_TRUE(ilist2.empty()); 132 | 133 | { 134 | TestStruct s1{}; 135 | 136 | ASSERT_FALSE(s1.node1.linked()); 137 | 138 | ASSERT_FALSE(s1.node2.linked()); 139 | 140 | ilist1.push_back(s1); 141 | 142 | ASSERT_TRUE(s1.node1.linked()); 143 | 144 | ASSERT_FALSE(s1.node2.linked()); 145 | 146 | ASSERT_FALSE(ilist1.empty()); 147 | ASSERT_TRUE(ilist2.empty()); 148 | 149 | ilist2.push_back(s1); 150 | 151 | ASSERT_TRUE(s1.node1.linked()); 152 | 153 | ASSERT_TRUE(s1.node2.linked()); 154 | 155 | ASSERT_FALSE(ilist1.empty()); 156 | ASSERT_FALSE(ilist2.empty()); 157 | } 158 | 159 | ASSERT_TRUE(ilist1.empty()); 160 | ASSERT_TRUE(ilist2.empty()); 161 | } 162 | 163 | TEST(IntrusiveList, InsertErase) 164 | { 165 | ade::util::intrusive_list ilist; 166 | 167 | TestStruct s1{}; 168 | TestStruct s2{}; 169 | TestStruct s3{}; 170 | 171 | auto iter1 = ilist.insert(ilist.end(), s1); 172 | ASSERT_FALSE(ilist.empty()); 173 | auto iter2 = ilist.insert(iter1, s2); 174 | ASSERT_FALSE(ilist.empty()); 175 | auto iter3 = ilist.insert(iter1, s3); 176 | ASSERT_FALSE(ilist.empty()); 177 | 178 | std::vector vals; 179 | for (auto& s: ilist) vals.push_back(&s); 180 | 181 | ASSERT_EQ((std::vector{&s2,&s3,&s1}), vals); 182 | 183 | auto iter4 = ilist.erase(iter3); 184 | ASSERT_FALSE(ilist.empty()); 185 | ASSERT_EQ(iter1, iter4); 186 | auto iter5 = ilist.erase(iter2); 187 | ASSERT_FALSE(ilist.empty()); 188 | ASSERT_EQ(iter1, iter5); 189 | auto iter6 = ilist.erase(iter1); 190 | ASSERT_TRUE(ilist.empty()); 191 | ASSERT_EQ(ilist.end(), iter6); 192 | } 193 | -------------------------------------------------------------------------------- /sources/tests/common/map_range_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | TEST(MapRangeTest, Simple) 15 | { 16 | using namespace ade::util; 17 | int sum1 = 0; 18 | std::vector v1 = {1,10,100,1000}; 19 | int coeff = 2; 20 | for (auto i: map(toRange(v1), [&](int val) { return val * coeff; })) 21 | { 22 | sum1 += i; 23 | } 24 | EXPECT_EQ(4, size(map(toRange(v1), [&](int val) { return val * coeff; }))); 25 | EXPECT_EQ(4, map(toRange(v1), [&](int val) { return val * coeff; }).size()); 26 | EXPECT_EQ(2222, sum1); 27 | 28 | struct Mapper 29 | { 30 | int operator()(int val) const 31 | { 32 | return val * 3; 33 | } 34 | }; 35 | int sum2 = 0; 36 | for (auto i: map(toRange(v1))) 37 | { 38 | sum2 += i; 39 | } 40 | EXPECT_EQ(4, size(map(toRange(v1)))); 41 | EXPECT_EQ(4, map(toRange(v1)).size()); 42 | EXPECT_EQ(3333, sum2); 43 | } 44 | -------------------------------------------------------------------------------- /sources/tests/common/range_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | TEST(RangeTest, ToRange) 15 | { 16 | using namespace ade::util; 17 | std::vector v1 = {1,10,100}; 18 | int sum = 0; 19 | for(auto i: toRange(v1)) 20 | { 21 | sum += i; 22 | } 23 | EXPECT_EQ(3, size(toRange(v1))); 24 | EXPECT_EQ(3, toRange(v1).size()); 25 | EXPECT_EQ(111,sum); 26 | 27 | int v2[] = {1,10,100}; 28 | sum = 0; 29 | for(auto i: toRange(v2)) 30 | { 31 | sum += i; 32 | } 33 | EXPECT_EQ(3, size(toRange(v2))); 34 | EXPECT_EQ(3, toRange(v2).size()); 35 | EXPECT_EQ(111,sum); 36 | 37 | sum = 0; 38 | for(auto i: toRange(std::make_pair(v1.begin(),v1.end()))) 39 | { 40 | sum += i; 41 | } 42 | EXPECT_EQ(3, size(toRange(std::make_pair(v1.begin(),v1.end())))); 43 | EXPECT_EQ(3, toRange(std::make_pair(v1.begin(),v1.end())).size()); 44 | EXPECT_EQ(111,sum); 45 | } 46 | 47 | TEST(RangeTest, IndexValue) 48 | { 49 | using namespace ade::util; 50 | int sum1 = 0; 51 | int sum2 = 0; 52 | const std::map m = {{1,3},{10,30},{100,300}}; 53 | for(auto i: m) 54 | { 55 | sum1 += index(i); 56 | sum2 += value(i); 57 | } 58 | EXPECT_EQ(111,sum1); 59 | EXPECT_EQ(333,sum2); 60 | } 61 | 62 | TEST(RangeTest, Reverse) 63 | { 64 | using namespace ade::util; 65 | std::vector v1 = {1,2,3,4}; 66 | std::vector v2; 67 | for(auto i: toRangeReverse(v1)) 68 | { 69 | v2.push_back(i); 70 | } 71 | ASSERT_EQ(4, v2.size()); 72 | ASSERT_EQ(4, v2[0]); 73 | ASSERT_EQ(3, v2[1]); 74 | ASSERT_EQ(2, v2[2]); 75 | ASSERT_EQ(1, v2[3]); 76 | } 77 | 78 | namespace 79 | { 80 | 81 | struct TestHasSize1 82 | { 83 | 84 | }; 85 | struct TestHasSize2 86 | { 87 | int size(); 88 | }; 89 | struct TestHasSize3 90 | { 91 | 92 | }; 93 | int size(const TestHasSize3&); 94 | 95 | static_assert(ade::util::details::has_size_fun::value == false, "TestHasSize1"); 96 | static_assert(ade::util::details::has_size_fun::value == false, "TestHasSize2"); 97 | static_assert(ade::util::details::has_size_fun::value == true, "TestHasSize3"); 98 | 99 | } 100 | -------------------------------------------------------------------------------- /sources/tests/common/tuple_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | TEST(TupleTest, Foreach) 14 | { 15 | auto t1 = std::make_tuple(42, std::string("123"), "456"); 16 | const auto t2 = std::make_tuple(42, std::string("123"), "456"); 17 | struct 18 | { 19 | int callCount = 0; 20 | void operator()(int i) 21 | { 22 | EXPECT_EQ(42, i); 23 | ++callCount; 24 | } 25 | 26 | void operator()(const std::string& str) 27 | { 28 | EXPECT_EQ("123", str); 29 | ++callCount; 30 | } 31 | 32 | void operator()(const char* str) 33 | { 34 | EXPECT_EQ("456", std::string(str)); 35 | ++callCount; 36 | } 37 | } fun; 38 | 39 | using namespace ade::util; 40 | tupleForeach(t1, fun); 41 | EXPECT_EQ(3, fun.callCount); 42 | tupleForeach(t2, fun); 43 | EXPECT_EQ(6, fun.callCount); 44 | } 45 | 46 | TEST(TupleTest, FixRvals) 47 | { 48 | int i = 5; 49 | const int j = 7; 50 | int& k = i; 51 | auto t = ade::util::tuple_remove_rvalue_refs(i, j, k, 11); 52 | EXPECT_EQ(5, std::get<0>(t)); 53 | EXPECT_EQ(7, std::get<1>(t)); 54 | EXPECT_EQ(5, std::get<2>(t)); 55 | EXPECT_EQ(11, std::get<3>(t)); 56 | 57 | static_assert(std::is_same::type, int&>::value, "Invalid elements type"); 58 | static_assert(std::is_same::type, const int&>::value, "Invalid elements type"); 59 | static_assert(std::is_same::type, int&>::value, "Invalid elements type"); 60 | static_assert(std::is_same::type, int>::value, "Invalid elements type"); 61 | } 62 | -------------------------------------------------------------------------------- /sources/tests/common/zip_range_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | TEST(ZipRangeTest, Indexed) 15 | { 16 | using namespace ade::util; 17 | int sum1 = 0; 18 | std::vector v1 = {1,10,100,1000}; 19 | int v2[] = {3,30,300}; 20 | int counter = 0; 21 | for(auto i: indexed(v1)) 22 | { 23 | EXPECT_EQ(counter, index(i)); 24 | sum1 += value(i); 25 | ++counter; 26 | } 27 | EXPECT_EQ(1111, sum1); 28 | 29 | sum1 = 0; 30 | int sum2 = 0; 31 | counter = 0; 32 | for(auto i: indexed(v1,v2)) 33 | { 34 | EXPECT_EQ(counter, index(i)); 35 | sum1 += value<0>(i); 36 | sum2 += value<1>(i); 37 | ++counter; 38 | } 39 | EXPECT_EQ(111, sum1); 40 | EXPECT_EQ(333, sum2); 41 | } 42 | 43 | TEST(ZipRangeTest, IndexedRvalue) 44 | { 45 | using namespace ade::util; 46 | int sum1 = 0; 47 | std::vector v1 = {1,10,100,1000}; 48 | int v2[] = {3,30,300}; 49 | int counter = 0; 50 | for(auto i: indexed(map(toRange(v1), [](int i) { return i * 2; }))) 51 | { 52 | EXPECT_EQ(counter, index(i)); 53 | sum1 += value(i); 54 | ++counter; 55 | } 56 | EXPECT_EQ(2222, sum1); 57 | 58 | sum1 = 0; 59 | int sum2 = 0; 60 | counter = 0; 61 | for(auto i: indexed(v1,map(toRange(v2), [](int i) { return i * 2; }))) 62 | { 63 | EXPECT_EQ(counter, index(i)); 64 | sum1 += value<0>(i); 65 | sum2 += value<1>(i); 66 | ++counter; 67 | } 68 | EXPECT_EQ(111, sum1); 69 | EXPECT_EQ(666, sum2); 70 | } 71 | 72 | TEST(ZipRangeTest, directRangesAsParameters) 73 | { 74 | using namespace ade::util; 75 | int sum1 = 0; 76 | std::vector v1 = {1,10,100,1000}; 77 | int v2[] = {3,30,300}; 78 | int counter = 0; 79 | 80 | sum1 = 0; 81 | int sum2 = 0; 82 | int sum3 = 0; 83 | counter = 0; 84 | enum {vector, array, index}; 85 | for(auto i: zip(v1, v2, iota())) 86 | { 87 | using std::get; 88 | sum1 += get(i); 89 | sum2 += get(i); 90 | EXPECT_EQ(counter, get(i)); 91 | ++counter; 92 | } 93 | EXPECT_EQ(111, sum1); 94 | EXPECT_EQ(333, sum2); 95 | } 96 | -------------------------------------------------------------------------------- /tutorial/01_hello.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | ade::Graph graph; 13 | std::cout << "Emtpy graph has " << graph.nodes().size() << " nodes. A great start!" << std::endl; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /tutorial/02_add_link_remove.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | // Define node and edge handles before we start. 13 | // These objects act as smart references to ADE entities. 14 | ade::NodeHandle n1, n2; 15 | ade::EdgeHandle e; 16 | 17 | auto p_edges = [](const char *name, ade::NodeHandle n) { 18 | std::cout << name << " edges: in=" << n->inEdges().size() << ", out=" << n->outEdges().size() << std::endl; 19 | }; 20 | 21 | auto p_conns = [](const char *name, ade::Node::EdgeSetRange edges) { 22 | std::cout << name << " connections: { "; 23 | for (const auto &h : edges) { std::cout << h << ":[" << h->srcNode() << "->" << h->dstNode() << "]"; } 24 | std::cout << " }" << std::endl; 25 | }; 26 | 27 | { 28 | ade::Graph graph; 29 | 30 | // Use Graph::createNode() to add a new node to graph. 31 | n1 = graph.createNode(); 32 | std::cout << "After 1st .createNode() [n1=" << n1 << "], there\'re " << graph.nodes().size() << " node(s)" << std::endl; 33 | 34 | n2 = graph.createNode(); 35 | std::cout << "After 2nd .createNode() [n2=" << n2 << "], there\'re " << graph.nodes().size() << " node(s)" << std::endl; 36 | 37 | // Linking nodes is easy - use Graph::link() 38 | std::cout << std::endl; 39 | 40 | e = graph.link(n1, n2); 41 | std::cout << "Edge handle is " << e << std::endl; 42 | p_edges("n1", n1); 43 | p_edges("n2", n2); 44 | 45 | // Walk through connections 46 | p_conns("n1 (out)", n1->outEdges()); 47 | p_conns("n2 (in) ", n2->inEdges()); 48 | 49 | // Unlinking is easy as well 50 | std::cout << std::endl; 51 | 52 | graph.erase(e); 53 | std::cout << "After edge erase: edge handle is " << e << std::endl; 54 | p_edges("n1", n1); 55 | p_edges("n2", n2); 56 | 57 | p_conns("n1 (out)", n1->outEdges()); 58 | p_conns("n2 (in) ", n2->inEdges()); 59 | 60 | // Link again, now in another order 61 | std::cout << std::endl; 62 | 63 | e = graph.link(n2, n1); 64 | 65 | p_edges("n1", n1); 66 | p_edges("n2", n2); 67 | 68 | p_conns("n1 (in) " , n1->inEdges()); 69 | p_conns("n2 (out)", n2->outEdges()); 70 | 71 | // A node can also be removed with Graph::erase() 72 | std::cout << std::endl; 73 | 74 | graph.erase(n1); 75 | std::cout << "After erase(), there\'re " << graph.nodes().size() << " node(s)" << std::endl; 76 | std::cout << "n1 is now " << n1 << std::endl; 77 | 78 | // Removing a node also removes connections 79 | p_edges("n2", n2); 80 | p_conns("n2 (out)", n2->outEdges()); 81 | } 82 | 83 | // Resource management is smart as we^well 84 | std::cout << std::endl; 85 | std::cout << "After graph destruction: n1=" << n1 << ", n2=" << n2 << ", e=" << e << std::endl; 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /tutorial/03_meta.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace tutor { 14 | // Custom metadata type 15 | struct MetaInt 16 | { 17 | int val; 18 | static const char* name() { return "MetaInt"; } 19 | }; 20 | struct MetaFloat 21 | { 22 | float val; 23 | }; 24 | struct MetaString 25 | { 26 | std::string val; 27 | static std::string name() { return "MetaString"; } 28 | }; 29 | 30 | const char* getMetadataName(ade::MetadataNameTag) 31 | { 32 | return "MetaFloat"; 33 | }; 34 | } 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | ade::Graph graph; 39 | ade::TypedGraph tg(graph); 42 | 43 | // Set data to metadata 44 | tg.metadata().set(tutor::MetaInt{42}); 45 | tg.metadata().set(tutor::MetaFloat{3.14f}); 46 | tg.metadata().set(tutor::MetaString{"ADE"}); 47 | 48 | std::cout << "tg.metadata().get = " << tg.metadata().get().val << ",\n" 49 | << "tg.metadata().get = " << tg.metadata().get().val << ",\n" 50 | << "tg.metadata().get = " << tg.metadata().get().val 51 | << std::endl; 52 | 53 | tg.metadata().set(tutor::MetaInt{32}); 54 | std::cout << "tg.metadata().get = " << tg.metadata().get().val << std::endl; 55 | 56 | std::cout << "tg.metadata().contains() = " 57 | << std::boolalpha << tg.metadata().contains() << std::endl; 58 | // You may erase data type 59 | tg.metadata().erase(); 60 | 61 | // Check contains MetaFloat in metadata 62 | std::cout << "tg.metadata().contains() = " 63 | << std::boolalpha << tg.metadata().contains() << std::endl; 64 | 65 | std::cout << std::endl; 66 | ade::NodeHandle nh = tg.createNode(); 67 | 68 | // Node metadata can be set/queried exactly in the same way, the only difference is 69 | // that NodeHandle now needs to be passes to ::metadata() 70 | std::cout << std::endl; 71 | tg.metadata(nh).set(tutor::MetaString{"ColorConvert"}); 72 | std::cout << "Node meta(" << nh << ")=" << tg.metadata(nh).get().val << std::endl; 73 | 74 | // Same applies to Edge metadata 75 | ade::NodeHandle nh2 = tg.createNode(); 76 | ade::EdgeHandle eh = tg.link(nh, nh2); 77 | 78 | tg.metadata(eh).set(tutor::MetaInt{100500}); 79 | std::cout << "Edge meta(" << eh << ")=" << tg.metadata(eh).get().val << std::endl; 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /tutorial/04_passes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | struct Node 17 | { 18 | std::string op; 19 | 20 | static const char *name() {return "Node";} 21 | }; 22 | 23 | struct State 24 | { 25 | enum { 26 | DIRTY, COMPLETE 27 | } st; 28 | 29 | static const char *name() {return "State";} 30 | }; 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | // Build the following graph: 35 | // 36 | // A ---> B ---> C ---> D L 37 | // : : ^ 38 | // V V : 39 | // F <--- E ---> G H ---> I 40 | // : : : : 41 | // : `----> J <----' : 42 | // : : V 43 | // '----> M <----' K 44 | // FM and JM shouldn't be fused! 45 | 46 | ade::Graph graph; 47 | 48 | using TGraph = ade::TypedGraph; 49 | TGraph tgraph(graph); 50 | 51 | std::unordered_map nodes; 52 | for (char c : std::string("ABCDEFGHIJKLM")) 53 | { 54 | nodes[c] = tgraph.createNode(); 55 | const char s[] = {c}; 56 | tgraph.metadata(nodes[c]).set(Node{s}); 57 | } 58 | 59 | #define L(c1,c2) graph.link(nodes[c1], nodes[c2]) 60 | L('A', 'B'); 61 | L('B', 'C'); 62 | L('C', 'D'); 63 | L('B', 'E'); 64 | L('E', 'F'); 65 | L('E', 'G'); 66 | L('E', 'J'); 67 | L('D', 'H'); 68 | L('H', 'I'); 69 | L('I', 'L'); 70 | L('I', 'K'); 71 | L('H', 'J'); 72 | L('F', 'M'); 73 | L('J', 'M'); 74 | #undef L 75 | 76 | tgraph.metadata().set(State{State::DIRTY}); 77 | 78 | // Define passes. There are two: 79 | // 1. Dump pass - dumps graph in Graphviz format 80 | auto dump_pass = [](TGraph &gr) { 81 | for (const auto src : gr.nodes()) 82 | { 83 | for (const auto out : src->outEdges()) 84 | { 85 | auto dst = out->dstNode(); 86 | std::cout << gr.metadata(src).get().op 87 | << " -> " 88 | << gr.metadata(dst).get().op 89 | << "\n"; 90 | } 91 | } 92 | }; 93 | 94 | // 2. Squash pass - Replaces a series of Nodes with a squashed 95 | // one if there's no other links in-between them 96 | // If there was nothing to squash, Graph status is set to COMPLETE 97 | auto squash_pass = [](TGraph &gr) { 98 | for (auto src : gr.nodes()) 99 | { 100 | if (src->outEdges().size() == 1) 101 | { 102 | auto dst = src->outNodes().front(); 103 | if (dst->inEdges().size() == 1) 104 | { 105 | // Node "X" node has a single consumer ("Y"), 106 | // so we can replace "X->Y" with "XY". 107 | ade::NodeHandle fused = gr.createNode(); 108 | const std::string fused_op = 109 | gr.metadata(src).get().op 110 | + gr.metadata(dst).get().op; 111 | gr.metadata(fused).set(Node{fused_op}); 112 | 113 | for (auto inNode : src->inNodes()) 114 | { 115 | gr.link(inNode, fused); 116 | } 117 | for (auto outNode : dst->outNodes()) 118 | { 119 | gr.link(fused, outNode); 120 | } 121 | 122 | gr.erase(src); 123 | gr.erase(dst); 124 | gr.metadata().set(State{State::DIRTY}); 125 | return; 126 | } 127 | } 128 | } 129 | gr.metadata().set(State{State::COMPLETE}); 130 | }; 131 | 132 | // Now define a pass list and to the squashing whenever possible! 133 | std::cout << "Initial graph" << std::endl; 134 | dump_pass(tgraph); 135 | 136 | ade::PassList list; 137 | list.addPass(squash_pass); 138 | list.addPass(dump_pass); 139 | 140 | int n = 0, origNumNodes = tgraph.nodes().size(); 141 | while ( n < origNumNodes 142 | && tgraph.metadata().get().st != State::COMPLETE) 143 | { 144 | std::cout << "====================\n"; 145 | std::cout << "Iteration #" << n << std::endl; 146 | list.run(tgraph); 147 | n++; 148 | std::cout << tgraph.nodes().size() << " nodes in graph" << std::endl; 149 | } 150 | 151 | std::cout << "====================\n" 152 | << "End!" << std::endl; 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /tutorial/06_hierarchy.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Intel Corporation 2 | // 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | struct Type 20 | { 21 | enum { OP, WRAP} t; 22 | static const char *name() { return "Type"; } 23 | }; 24 | 25 | struct Operation 26 | { 27 | std::string op; 28 | static const char *name() { return "Operation"; } 29 | }; 30 | 31 | struct Wrap 32 | { 33 | std::shared_ptr wrapped; 34 | std::string op; 35 | static const char *name() { return "Wrap"; } 36 | }; 37 | 38 | using TGraph = ade::TypedGraph; 39 | 40 | namespace m 41 | { 42 | 43 | // Returns a node handle of created operation 44 | ade::NodeHandle op(TGraph &graph, const std::string &name) 45 | { 46 | ade::NodeHandle h = graph.createNode(); 47 | graph.metadata(h).set(Type{ Type::OP }); 48 | graph.metadata(h).set(Operation{ name }); 49 | return h; 50 | } 51 | 52 | // Wraps a graph into node 53 | ade::NodeHandle wrap(TGraph &graph, 54 | std::shared_ptr g, 55 | const std::string &op) 56 | { 57 | // All checks are ok, now create a new super node and reconnect it in graph 58 | ade::NodeHandle super = graph.createNode(); 59 | graph.metadata(super).set(Type{ Type::WRAP }); 60 | graph.metadata(super).set(Wrap{ g, op }); 61 | return super; 62 | } 63 | 64 | } // namespace m 65 | 66 | void run(ade::Graph &gsrc, int depth = 0) 67 | { 68 | TGraph g(gsrc); 69 | 70 | ade::passes::PassContext context{gsrc}; 71 | ade::passes::TopologicalSort()(context); 72 | 73 | auto sorted = g.metadata().get().nodes(); 74 | for (auto n : sorted) 75 | { 76 | Type type = g.metadata(n).get(); 77 | if (type.t == Type::OP) 78 | { 79 | for (int i = 0; i < depth*4; i++) { std::cout << ' '; } 80 | std::cout << g.metadata(n).get().op << std::endl; 81 | } 82 | else if (type.t == Type::WRAP) 83 | { 84 | Wrap w = g.metadata(n).get(); 85 | for (int i = 0; i < depth*4; i++) { std::cout << ' '; } 86 | std::cout << w.op << std::endl; 87 | 88 | run(*w.wrapped, depth+1); 89 | } 90 | else ADE_ASSERT(false); 91 | } 92 | } 93 | 94 | int main(int argc, char *argv[]) 95 | { 96 | // First, define a graph we plan to nest 97 | std::shared_ptr rms(new ade::Graph); 98 | TGraph trms(*rms); 99 | 100 | ade::NodeHandle 101 | foo = m::op(trms, "foo"), 102 | bar = m::op(trms, "bar"), 103 | baz = m::op(trms, "baz"); 104 | 105 | rms->link(foo, baz); 106 | rms->link(bar, baz); 107 | 108 | // No build a supergraph using our graph 109 | ade::Graph super; 110 | TGraph tsuper(super); 111 | 112 | ade::NodeHandle 113 | pre = m::op (tsuper, "pre"), 114 | fbb = m::wrap(tsuper, rms, "fbb"), 115 | post = m::op (tsuper, "post"); 116 | 117 | run(super); 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /tutorial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Intel Corporation 2 | # 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | cmake_minimum_required(VERSION 2.8) 8 | 9 | project(ade_samples) 10 | 11 | if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 12 | if(CMAKE_VERSION VERSION_LESS "3.1" AND CMAKE_COMPILER_IS_GNUCXX) 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 14 | else() 15 | set(CMAKE_CXX_STANDARD 11) 16 | endif() 17 | find_package(ade REQUIRED) 18 | endif() 19 | 20 | function(defstep name) 21 | add_executable(${name} ${name}.cpp) 22 | add_security_flags( ${name} ) 23 | target_link_libraries(${name} ade) 24 | install(FILES ${name}.cpp DESTINATION "examples/ade" COMPONENT example) 25 | endfunction(defstep) 26 | 27 | defstep(01_hello) 28 | defstep(02_add_link_remove) 29 | defstep(03_meta) 30 | defstep(04_passes) 31 | defstep(05_backend) 32 | defstep(06_hierarchy) 33 | 34 | install(FILES README.md CMakeLists.txt DESTINATION "examples/ade" COMPONENT example) 35 | -------------------------------------------------------------------------------- /tutorial/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to ADE Tutorial 2 | 3 | This tutorial will teach you how to use ADE to: 4 | * Construct graphs; 5 | * Apply graph transformations; 6 | * Write backends which execute ADE graphs. 7 | 8 | ## Contents 9 | 10 | Current version of tutorial contains the following steps: 11 | 12 | ### `hello` 13 | 14 | The very basic "hello world"-like example, demonstrating the bare minimum which is required to build an ADE-powered application. 15 | 16 | ### `add_link_remove` 17 | 18 | This example shows general graph concepts, operations, and its semantics. 19 | 20 | ### `meta` 21 | 22 | This example illustrates graph/node/edge manipulation principles. 23 | 24 | ### `typed_meta` 25 | 26 | This example shows how to make metadata access simplified and type-safe at the same time. 27 | 28 | ### `passes` 29 | 30 | A more advanced example shows how to implement basic operation squashing ("fusion") in a 33-SLOC pass. 31 | 32 | ## `backend` 33 | 34 | The most advanced example in the suite provides you with an End-to-End demo on how a graph-based computational engine can be built with ADE. 35 | 36 | The following concepts are implemented in this sample: 37 | * A graph construction API built atop of ADE: 38 | - Named operations; 39 | - Explicit input/output data ports; 40 | - Virtual data objects; 41 | * Graph validation passes: 42 | - Cycle detection, data format & port connection validity; 43 | - Domain-specific graph metadata resolution ("virtual objects format inference"); 44 | * Graph optimization passes: 45 | - Removing unused operations from the graph; 46 | * Extending compiler with implementation/backend/plugin-specific passes; 47 | * Implementing a backend and an executable (graph interpreter). 48 | --------------------------------------------------------------------------------