diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a1cbb3fb8b8..666fefbe0cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ tvm_option(ROCM_PATH "The path to rocm" /opt/rocm) tvm_option(USE_HEXAGON "Build with Hexagon support" OFF) tvm_option(USE_HEXAGON_SDK "Path to the Hexagon SDK root (required for Hexagon support)" /path/to/sdk) tvm_option(USE_HEXAGON_RPC "Enable Hexagon RPC using minRPC implementation over Android." OFF) +tvm_option(USE_HEXAGON_GTEST "Path to Hexagon specific gtest version for runtime cpp tests." /path/to/hexagon/gtest) tvm_option(USE_RPC "Build with RPC" ON) tvm_option(USE_THREADS "Build with thread support" ON) tvm_option(USE_LLVM "Build with LLVM, can be set to specific llvm-config path" OFF) @@ -598,6 +599,15 @@ endif() target_link_libraries(tvm PRIVATE ${TVM_LINKER_LIBS} ${TVM_RUNTIME_LINKER_LIBS}) target_link_libraries(tvm_runtime PRIVATE ${TVM_RUNTIME_LINKER_LIBS}) +if(BUILD_FOR_HEXAGON AND DEFINED USE_HEXAGON_GTEST AND EXISTS ${USE_HEXAGON_GTEST}) + include(FetchContent) + FetchContent_Declare(googletest SOURCE_DIR "${USE_HEXAGON_GTEST}") + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(googletest) + target_link_libraries(tvm_runtime PUBLIC gtest) + include_directories("${USE_HEXAGON_GTEST}/include") +endif() + # Set flags for clang include(cmake/modules/ClangFlags.cmake) set(CRC16_INCLUDE_PATH "3rdparty/libcrc/include") @@ -634,7 +644,6 @@ if(GTEST_FOUND) tvm_file_glob(GLOB_RECURSE TEST_SRCS tests/cpp/*.cc) add_executable(cpptest ${TEST_SRCS}) # include runtime files for unit testing - target_include_directories(cpptest PUBLIC "src/runtime") target_link_libraries(cpptest PRIVATE ${TVM_TEST_LIBRARY_NAME} GTest::GTest GTest::Main GTest::gmock pthread dl) set_target_properties(cpptest PROPERTIES EXCLUDE_FROM_ALL 1) set_target_properties(cpptest PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1) @@ -649,6 +658,9 @@ add_custom_target(runtime DEPENDS tvm_runtime) # Installation rules install(TARGETS tvm EXPORT ${PROJECT_NAME}Targets DESTINATION lib${LIB_SUFFIX}) install(TARGETS tvm_runtime EXPORT ${PROJECT_NAME}Targets DESTINATION lib${LIB_SUFFIX}) +if(BUILD_FOR_HEXAGON AND DEFINED USE_HEXAGON_GTEST AND EXISTS ${USE_HEXAGON_GTEST}) + install(TARGETS gtest EXPORT ${PROJECT_NAME}Targets DESTINATION lib${LIB_SUFFIX}) +endif() if (INSTALL_DEV) install( diff --git a/apps/hexagon_api/CMakeLists.txt b/apps/hexagon_api/CMakeLists.txt index 40f070513e3d..1f9e982970c3 100644 --- a/apps/hexagon_api/CMakeLists.txt +++ b/apps/hexagon_api/CMakeLists.txt @@ -13,6 +13,7 @@ include(ExternalProject) # USE_HEXAGON_TOOLCHAIN (Path to Hexagon toolchain ending with "Tools") # Optional variable: # USE_OUTPUT_BINARY_DIR (Path to copy the output binaries to) +# USE_HEXAGON_GTEST (Path to Hexagon specific gtest version) set(TVM_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../..") @@ -23,6 +24,15 @@ else() endif() file(MAKE_DIRECTORY ${HEXAGON_API_BINARY_DIR}) +if(DEFINED USE_HEXAGON_GTEST) + if(EXISTS ${USE_HEXAGON_GTEST}) + message(STATUS "Found Hexagon gtest at ${USE_HEXAGON_GTEST}") + else() + message(WARNING "Could not find Hexagon gtest at ${USE_HEXAGON_GTEST}. Disabling Hexagon gtest support.") + unset(USE_HEXAGON_GTEST) + endif() +endif() + # Build X86 binaries: # - tvm_rpc_x86 @@ -109,6 +119,9 @@ ExternalProject_Add(hexagon_tvm_runtime_rpc "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "-DUSE_ALTERNATIVE_LINKER=OFF" "-DUSE_CUSTOM_LOGGING=ON" + if(DEFINED USE_HEXAGON_GTEST) + "-DUSE_HEXAGON_GTEST=${USE_HEXAGON_GTEST}" + endif() INSTALL_COMMAND "" BUILD_ALWAYS ON ) diff --git a/cmake/modules/Hexagon.cmake b/cmake/modules/Hexagon.cmake index 3b0ff7dfeae3..d45311a87fec 100644 --- a/cmake/modules/Hexagon.cmake +++ b/cmake/modules/Hexagon.cmake @@ -84,9 +84,6 @@ if(NOT USE_HEXAGON) if(BUILD_FOR_HOST) list(APPEND COMPILER_SRCS src/target/opt/build_hexagon_off.cc) endif() - list(APPEND RUNTIME_SRCS src/runtime/hexagon/hexagon_buffer.cc) - list(APPEND RUNTIME_SRCS src/runtime/hexagon/hexagon_common.cc) - list(APPEND RUNTIME_SRCS src/runtime/hexagon/hexagon_user_dma.cc) return() endif() @@ -119,14 +116,23 @@ function(add_hexagon_wrapper_paths) link_directories("${HEXAGON_TOOLCHAIN}/lib/iss") endfunction() - -# Common sources for TVM runtime with Hexagon support -file_glob_append(RUNTIME_HEXAGON_SRCS - "${TVMRT_SOURCE_DIR}/hexagon/*.cc" -) - +if(BUILD_FOR_HEXAGON OR USE_HEXAGON_RPC) + # Common sources for TVM runtime with Hexagon support + file_glob_append(RUNTIME_HEXAGON_SRCS + "${TVMRT_SOURCE_DIR}/hexagon/*.cc" + ) +else() + file_glob_append(RUNTIME_HEXAGON_SRCS + "${TVMRT_SOURCE_DIR}/hexagon/hexagon_module.cc" + ) +endif() if(BUILD_FOR_HEXAGON) + if(DEFINED USE_HEXAGON_GTEST AND EXISTS ${USE_HEXAGON_GTEST}) + file_glob_append(RUNTIME_HEXAGON_SRCS + "${CMAKE_SOURCE_DIR}/tests/cpp-runtime/hexagon/*.cc" + ) + endif() get_hexagon_sdk_property("${USE_HEXAGON_SDK}" "${USE_HEXAGON_ARCH}" SDK_INCLUDE SDK_INCLUDE_DIRS QURT_INCLUDE QURT_INCLUDE_DIRS diff --git a/cmake/modules/LibInfo.cmake b/cmake/modules/LibInfo.cmake index eefa7036a0ff..76ddbede8ac0 100644 --- a/cmake/modules/LibInfo.cmake +++ b/cmake/modules/LibInfo.cmake @@ -74,6 +74,7 @@ function(add_lib_info src_file) TVM_INFO_USE_HEXAGON="${USE_HEXAGON}" TVM_INFO_USE_HEXAGON_RPC="${USE_HEXAGON_RPC}" TVM_INFO_USE_HEXAGON_SDK="${USE_HEXAGON_SDK}" + TVM_INFO_USE_HEXAGON_GTEST="${USE_HEXAGON_GTEST}" TVM_INFO_USE_IOS_RPC="${USE_IOS_RPC}" TVM_INFO_USE_KHRONOS_SPIRV="${USE_KHRONOS_SPIRV}" TVM_INFO_USE_LIBBACKTRACE="${USE_LIBBACKTRACE}" diff --git a/src/runtime/hexagon/hexagon_buffer.cc b/src/runtime/hexagon/hexagon_buffer.cc index cfe2b528bb9f..909d37481147 100644 --- a/src/runtime/hexagon/hexagon_buffer.cc +++ b/src/runtime/hexagon/hexagon_buffer.cc @@ -52,26 +52,15 @@ struct Allocation { struct DDRAllocation : public Allocation { DDRAllocation(size_t nbytes, size_t alignment) : Allocation(nbytes, alignment) { -#ifdef _WIN32 - data_ = _aligned_malloc(nbytes, alignment); - CHECK(data_ != nullptr); -#else int ret = posix_memalign(&data_, alignment, nbytes); CHECK_EQ(ret, 0); -#endif - } - ~DDRAllocation() { -#ifdef _WIN32 - _aligned_free(data_); -#else - free(data_); -#endif } + ~DDRAllocation() { free(data_); } }; -#if defined(__hexagon__) struct VTCMAllocation : public Allocation { VTCMAllocation(size_t nbytes, size_t alignment) : Allocation(nbytes, alignment) { +#if defined(__hexagon__) compute_res_attr_t res_info; HEXAGON_SAFE_CALL(HAP_compute_res_attr_init(&res_info)); @@ -94,20 +83,16 @@ struct VTCMAllocation : public Allocation { LOG(ERROR) << "ERROR: Unable to acquire requeisted resource."; return; } - // LOG(INFO) << "VTCMAllocation() - Context ID: " << context_id_ << ", VTCM ptr: " << data_; +#endif } ~VTCMAllocation() { - // LOG(INFO) << "~VTCMAllocation() - Context ID: " << context_id_ << ", VTCM ptr: " << data_; +#if defined(__hexagon__) HEXAGON_SAFE_CALL(HAP_compute_res_release(context_id_)); data_ = nullptr; +#endif } unsigned int context_id_{0}; }; -#else -struct VTCMAllocation : public DDRAllocation { - VTCMAllocation(size_t nbytes, size_t alignment) : DDRAllocation(nbytes, alignment) {} -}; -#endif template std::unique_ptr Allocator(size_t nbytes, size_t alignment); diff --git a/src/runtime/hexagon/hexagon_user_dma.cc b/src/runtime/hexagon/hexagon_user_dma.cc index 6e286ae8b3f4..9bf7a9f6c1d4 100644 --- a/src/runtime/hexagon/hexagon_user_dma.cc +++ b/src/runtime/hexagon/hexagon_user_dma.cc @@ -68,14 +68,10 @@ int hexagon_user_dma_1d_sync_helper(void* dst, void* src, uint32_t length) { void* dma_desc = nullptr; -#ifdef _WIN32 - dma_desc = _aligned_malloc(DMA_DESC_2D_SIZE, DMA_DESC_2D_SIZE); -#else int ret = posix_memalign(&dma_desc, DMA_DESC_2D_SIZE, DMA_DESC_2D_SIZE); if (ret) { return DMA_FAILURE; } -#endif if (!dma_desc) { return DMA_FAILURE; @@ -98,20 +94,13 @@ int hexagon_user_dma_1d_sync_helper(void* dst, void* src, uint32_t length) { unsigned int status = dmwait() & DM0_STATUS_MASK; unsigned int done = dma_desc_get_done(dma_desc); -#ifdef _WIN32 - _aligned_free(dma_desc); -#else free(dma_desc); -#endif if (status == DM0_STATUS_IDLE && done == DESC_DONE_COMPLETE) { return DMA_SUCCESS; } - return DMA_FAILURE; -#else - memcpy(dst, src, length); - return DMA_SUCCESS; #endif + return DMA_FAILURE; } int hexagon_user_dma_1d_sync(void* dst, void* src, uint32_t length) { diff --git a/src/support/libinfo.cc b/src/support/libinfo.cc index c6cf916ae8a2..e6f322885e3a 100644 --- a/src/support/libinfo.cc +++ b/src/support/libinfo.cc @@ -67,6 +67,10 @@ #define TVM_INFO_USE_HEXAGON_SDK "NOT-FOUND" #endif +#ifndef TVM_INFO_USE_HEXAGON_GTEST +#define TVM_INFO_USE_HEXAGON_GTEST "NOT-FOUND" +#endif + #ifndef TVM_INFO_USE_RPC #define TVM_INFO_USE_RPC "NOT-FOUND" #endif @@ -267,6 +271,7 @@ TVM_DLL Map GetLibInfo() { {"USE_HEXAGON", TVM_INFO_USE_HEXAGON}, {"USE_HEXAGON_RPC", TVM_INFO_USE_HEXAGON_RPC}, {"USE_HEXAGON_SDK", TVM_INFO_USE_HEXAGON_SDK}, + {"USE_HEXAGON_GTEST", TVM_INFO_USE_HEXAGON_GTEST}, {"USE_IOS_RPC", TVM_INFO_USE_IOS_RPC}, {"USE_KHRONOS_SPIRV", TVM_INFO_USE_KHRONOS_SPIRV}, {"USE_LIBBACKTRACE", TVM_INFO_USE_LIBBACKTRACE}, diff --git a/tests/cpp/runtime/hexagon_buffer.cc b/tests/cpp-runtime/hexagon/hexagon_buffer_tests.cc similarity index 99% rename from tests/cpp/runtime/hexagon_buffer.cc rename to tests/cpp-runtime/hexagon/hexagon_buffer_tests.cc index 715d9b1b695d..803e67785413 100644 --- a/tests/cpp/runtime/hexagon_buffer.cc +++ b/tests/cpp-runtime/hexagon/hexagon_buffer_tests.cc @@ -18,9 +18,10 @@ */ #include -#include #include +#include "../src/runtime/hexagon/hexagon_buffer.h" + using namespace tvm::runtime; using namespace tvm::runtime::hexagon; diff --git a/tests/cpp-runtime/hexagon/run_all_tests.cc b/tests/cpp-runtime/hexagon/run_all_tests.cc new file mode 100644 index 000000000000..166d89b63566 --- /dev/null +++ b/tests/cpp-runtime/hexagon/run_all_tests.cc @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include +#include + +#include "../src/support/utils.h" + +namespace tvm { +namespace runtime { +namespace hexagon { + +TVM_REGISTER_GLOBAL("hexagon.run_all_tests").set_body([](TVMArgs args, TVMRetValue* rv) { + // gtest args are passed into this packed func as a singular string + // split gtest args using delimiter and build argument vector + std::vector parsed_args = tvm::support::Split(args[0], ' '); + std::vector argv; + + // add executable name + argv.push_back(const_cast("hexagon_run_all_tests")); + + // add parsed arguments + for (int i = 0; i < parsed_args.size(); ++i) { + argv.push_back(const_cast(parsed_args[i].data())); + } + + // end of parsed arguments + argv.push_back(nullptr); + + // set argument count + int argc = argv.size() - 1; + + // initialize gtest with arguments and run + ::testing::InitGoogleTest(&argc, argv.data()); + *rv = RUN_ALL_TESTS(); +}); + +} // namespace hexagon +} // namespace runtime +} // namespace tvm diff --git a/tests/python/contrib/test_hexagon/unit_tests.py b/tests/python/contrib/test_hexagon/unit_tests.py new file mode 100644 index 000000000000..d340cba5b150 --- /dev/null +++ b/tests/python/contrib/test_hexagon/unit_tests.py @@ -0,0 +1,42 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import pytest +import numpy as np +from tvm.contrib.hexagon.build import HexagonLauncher +from .conftest import requires_hexagon_toolchain + + +@requires_hexagon_toolchain +def test_cache_read_write_2d(hexagon_session): + # arguments to pass to gtest + # e.g. + # 1) to run all tests use: + # gtest_args = "" + # 2) to run all tests with "foo" in their name twice use: + # gtest_args = "--gtest_repeat=2 --gtest_filter=*foo*" + gtest_args = "" + try: + func = hexagon_session._rpc.get_function("hexagon.run_all_tests") + result = func(gtest_args) + except: + print( + "This test requires the USE_HEXAGON_GTEST cmake flag to be specified with a path to a Hexagon gtest version normally located at /path/to/hexagon/sdk/utils/googletest/gtest" + ) + result = 1 + + np.testing.assert_equal(result, 0) diff --git a/tests/scripts/task_build_hexagon_api.sh b/tests/scripts/task_build_hexagon_api.sh index ae4d42126810..a3b501d9c554 100755 --- a/tests/scripts/task_build_hexagon_api.sh +++ b/tests/scripts/task_build_hexagon_api.sh @@ -43,6 +43,7 @@ cmake -DANDROID_ABI=arm64-v8a \ -DUSE_HEXAGON_ARCH=v68 \ -DUSE_HEXAGON_SDK="${HEXAGON_SDK_PATH}" \ -DUSE_HEXAGON_TOOLCHAIN="${HEXAGON_TOOLCHAIN}" \ - -DUSE_OUTPUT_BINARY_DIR="${output_binary_directory}" .. + -DUSE_OUTPUT_BINARY_DIR="${output_binary_directory}" \ + -DUSE_HEXAGON_GTEST="${HEXAGON_SDK_PATH}/utils/googletest/gtest" .. make -j$(nproc)