Skip to content

Commit

Permalink
[RUNTIME] Initial implementation of Hexagon runtime support (apache#5252
Browse files Browse the repository at this point in the history
)

* [RUNTIME] Initial implementation of Hexagon runtime support

This is only the TVM runtime. The FastRPC libraries, simulator driver,
etc. will be provided in subsequent commits.

* Fix pylint complaints

* Fix some more pylint complaints

* Add link to the Hexagon SDK website

* Extract VTCM marker into a common variable

* Implement device->device memory copy

* Disable unsigned PDs by default

* Ensure that --hvx_length is present in sim_args if HVX is enabled

* Remove the line about clang from README.md

Apparently things work with libstdc++.

* Mention to set USE_RPC=OFF when building libtvm_runtime.so for Hexagon

* Remember to use codegen_hvx in validate_hvx_length

* Add a line about minimum version of LLVM
  • Loading branch information
Krzysztof Parzyszek authored and Trevor Morris committed Apr 16, 2020
1 parent e7d4a77 commit 730af76
Show file tree
Hide file tree
Showing 29 changed files with 4,341 additions and 9 deletions.
53 changes: 50 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ tvm_option(USE_OPENGL "Build with OpenGL" OFF)
tvm_option(USE_METAL "Build with Metal" OFF)
tvm_option(USE_ROCM "Build with ROCM" OFF)
tvm_option(ROCM_PATH "The path to rocm" /opt/rocm)
tvm_option(USE_HEXAGON_DEVICE "Build with Hexagon device support in TVM runtime" OFF)
tvm_option(USE_HEXAGON_SDK "Path to the Hexagon SDK root (required for Hexagon support in TVM runtime or for building TVM runtime for Hexagon)" /path/to/sdk)
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)
Expand Down Expand Up @@ -80,7 +82,7 @@ include_directories(${PICOJSON_PATH})

# initial variables
set(TVM_LINKER_LIBS "")
set(TVM_RUNTIME_LINKER_LIBS ${CMAKE_DL_LIBS})
set(TVM_RUNTIME_LINKER_LIBS "")

# Generic compilation options
if(MSVC)
Expand Down Expand Up @@ -133,8 +135,33 @@ else(MSVC)
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
set(CMAKE_CXX_FLAGS "-faligned-new ${CMAKE_CXX_FLAGS}")
endif()

# Detect if we're compiling for Hexagon.
set(TEST_FOR_HEXAGON_CXX
"#ifndef __hexagon__"
"#error"
"#endif"
"int main() {}"
# Define _start_main to avoid linking errors with -fPIC.
"extern \"C\" void _start_main() {}")
set(TEST_FOR_HEXAGON_DIR
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
set(TEST_FOR_HEXAGON_FILE "${TEST_FOR_HEXAGON_DIR}/test_for_hexagon.cc")
string(REPLACE ";" "\n" TEST_FOR_HEXAGON_CXX_TEXT "${TEST_FOR_HEXAGON_CXX}")
file(WRITE "${TEST_FOR_HEXAGON_FILE}" "${TEST_FOR_HEXAGON_CXX_TEXT}")
try_compile(BUILD_FOR_HEXAGON "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}"
"${TEST_FOR_HEXAGON_FILE}")
file(REMOVE "${TEST_FOR_HEXAGON_FILE}")
if(BUILD_FOR_HEXAGON)
message(STATUS "Building for Hexagon")
endif()
endif(MSVC)

# Hexagon has dlopen built into QuRT (no need for static library).
if(NOT BUILD_FOR_HEXAGON)
string(APPEND TVM_RUNTIME_LINKER_LIBS ${CMAKE_DL_LIBS})
endif()

# add source group
FILE(GLOB_RECURSE GROUP_SOURCE "src/*.cc")
FILE(GLOB_RECURSE GROUP_INCLUDE "src/*.h" "include/*.h")
Expand Down Expand Up @@ -192,6 +219,13 @@ if(USE_VM_PROFILER)
list(APPEND COMPILER_SRCS ${BACKEND_VM_PROFILER_SRCS})
endif(USE_VM_PROFILER)

if(BUILD_FOR_HEXAGON)
# Add file implementing posix_memalign.
list(APPEND RUNTIME_SRCS src/runtime/hexagon/hexagon_posix.cc)

add_definitions(-D_MACH_I32=int)
endif()

file(GLOB DATATYPE_SRCS src/target/datatype/*.cc)
list(APPEND COMPILER_SRCS ${DATATYPE_SRCS})

Expand Down Expand Up @@ -256,6 +290,7 @@ endif(USE_EXAMPLE_EXT_RUNTIME)
# Module rules
include(cmake/modules/VTA.cmake)
include(cmake/modules/CUDA.cmake)
include(cmake/modules/Hexagon.cmake)
include(cmake/modules/OpenCL.cmake)
include(cmake/modules/OpenGL.cmake)
include(cmake/modules/OpenMP.cmake)
Expand Down Expand Up @@ -299,15 +334,27 @@ else()
set_target_properties(tvm PROPERTIES COMPILE_DEFINITIONS "NDEBUG")
endif(USE_RELAY_DEBUG)

if(USE_THREADS)
if(BUILD_FOR_HEXAGON)
# Wrap pthread_create to allow setting custom stack size.
set_target_properties(tvm_runtime PROPERTIES LINK_FLAGS
"-Wl,--wrap=pthread_create")

target_include_directories(tvm_runtime
PUBLIC "${USE_HEXAGON_SDK}/libs/common/qurt/ADSPv62MP/include/posix"
PUBLIC "${USE_HEXAGON_SDK}/libs/common/qurt/ADSPv62MP/include/qurt"
PUBLIC "${USE_HEXAGON_SDK}/incs"
PUBLIC "${USE_HEXAGON_SDK}/incs/stddef")
endif()

if(USE_THREADS AND NOT BUILD_FOR_HEXAGON)
message(STATUS "Build with thread support...")
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
target_link_libraries(tvm Threads::Threads)
target_link_libraries(tvm_topi Threads::Threads)
target_link_libraries(tvm_runtime Threads::Threads)
endif(USE_THREADS)
endif()

target_link_libraries(tvm ${TVM_LINKER_LIBS} ${TVM_RUNTIME_LINKER_LIBS})
target_link_libraries(tvm_topi tvm ${TVM_LINKER_LIBS} ${TVM_RUNTIME_LINKER_LIBS})
Expand Down
3 changes: 3 additions & 0 deletions cmake/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,6 @@ set(USE_THRUST OFF)
# Whether to build the TensorFlow TVMDSOOp module
set(USE_TF_TVMDSOOP OFF)

# Whether to use hexagon device
set(USE_HEXAGON_DEVICE OFF)
set(USE_HEXAGON_SDK /path/to/sdk)
96 changes: 96 additions & 0 deletions cmake/modules/Hexagon.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# 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.

set(PICK_SIM "sim")
set(PICK_HW "target")
set(PICK_NONE "OFF")

function(find_hexagon_toolchain)
if (NOT "${USE_HEXAGON_TOOLCHAIN}" STREQUAL "")
set(TRY_PATH "${USE_HEXAGON_TOOLCHAIN}")
else()
set(TRY_PATH "${USE_HEXAGON_SDK}")
endif()
message(STATUS "Looking for Hexagon toolchain in ${TRY_PATH}")
file(GLOB_RECURSE HEXAGON_CLANG "${TRY_PATH}/*/hexagon-clang++")
if(HEXAGON_CLANG)
# The path is ${HEXAGON_TOOLCHAIN}/bin/hexagon-clang++.
get_filename_component(HEXAGON_TMP0 "${HEXAGON_CLANG}" DIRECTORY)
get_filename_component(HEXAGON_TMP1 "${HEXAGON_TMP0}" DIRECTORY)
set(HEXAGON_TOOLCHAIN "${HEXAGON_TMP1}" CACHE PATH
"Path to the Hexagon toolchain")
else(HEXAGON_CLANG)
message(SEND_ERROR "Cannot find Hexagon toolchain in ${TRY_PATH}")
endif()
endfunction()

function(find_hexagon_sdk_root)
message(STATUS "Checking Hexagon SDK root: ${USE_HEXAGON_SDK}")
file(GLOB_RECURSE HEXAGON_AEESTDDEF "${USE_HEXAGON_SDK}/*/AEEStdDef.h")
if(HEXAGON_AEESTDDEF)
# The path is ${HEXAGON_SDK_ROOT}/incs/stddef/AEEStdDef.h.
get_filename_component(HEXAGON_TMP0 "${HEXAGON_AEESTDDEF}" DIRECTORY)
get_filename_component(HEXAGON_TMP1 "${HEXAGON_TMP0}" DIRECTORY)
get_filename_component(HEXAGON_TMP2 "${HEXAGON_TMP1}" DIRECTORY)
set(HEXAGON_SDK_ROOT "${HEXAGON_TMP2}" CACHE PATH
"Root directory of Hexagon SDK")
else(HEXAGON_AEESTDDEF)
message(SEND_ERROR "Cannot validate Hexagon SDK in ${USE_HEXAGON_SDK}")
endif()
endfunction()

if(USE_HEXAGON_DEVICE STREQUAL "OFF")
list(APPEND COMPILER_SRCS src/target/opt/build_hexagon_off.cc)
return()
elseif(NOT USE_HEXAGON_DEVICE STREQUAL "${PICK_SIM}" AND
NOT USE_HEXAGON_DEVICE STREQUAL "${PICK_HW}")
set(ERROR_MSG
"USE_HEXAGON_DEVICE must be one of [${PICK_NONE}|${PICK_SIM}|${PICK_HW}]")
message(SEND_ERROR "${ERROR_MSG}")
return()
endif()
# If USE_HEXAGON_DEVICE is set to a valid value, make sure that USE_HEXAGON_SDK
# is defined.
if (NOT USE_HEXAGON_SDK)
message(SEND_ERROR "Please set USE_HEXAGON_SDK to the Hexagon SDK root")
return()
endif()

if(USE_HEXAGON_DEVICE STREQUAL "${PICK_SIM}")
find_hexagon_toolchain()
message(STATUS "Hexagon toolchain: ${HEXAGON_TOOLCHAIN}")
file(GLOB RUNTIME_HEXAGON_SIM_SRCS src/runtime/hexagon/sim/*.cc)
include_directories("${HEXAGON_TOOLCHAIN}/include/iss")
link_directories("${HEXAGON_TOOLCHAIN}/lib/iss")
list(APPEND TVM_RUNTIME_LINKER_LIBS "-lwrapper")
elseif(USE_HEXAGON_DEVICE STREQUAL "${PICK_HW}")
find_hexagon_sdk_root()
find_hexagon_toolchain()
message(STATUS "Hexagon SDK: ${HEXAGON_SDK_ROOT}")
file(GLOB RUNTIME_HEXAGON_DEVICE_SRCS src/runtime/hexagon/target/*.cc)
include_directories("${HEXAGON_SDK_ROOT}/incs/stddef")
include_directories("${HEXAGON_SDK_ROOT}/libs/common/rpcmem/inc")
include_directories(
"${HEXAGON_SDK_ROOT}/libs/common/remote/ship/android_Release_aarch64")
include_directories("${HEXAGON_TOOLCHAIN}/include/iss")
list(APPEND TVM_RUNTIME_LINKER_LIBS "-ldl")
endif()

file(GLOB RUNTIME_HEXAGON_SRCS src/runtime/hexagon/*.cc)
list(APPEND RUNTIME_SRCS ${RUNTIME_HEXAGON_SRCS} ${RUNTIME_HEXAGON_SIM_SRCS}
${RUNTIME_HEXAGON_DEVICE_SRCS})

1 change: 1 addition & 0 deletions include/tvm/runtime/c_runtime_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ typedef enum {
kDLSDAccel = 6,
kOpenGL = 11,
kDLMicroDev = 13,
kDLHexagon = 14,
// AddExtraTVMType which is not in DLPack here
} TVMDeviceExtType;

Expand Down
5 changes: 3 additions & 2 deletions include/tvm/runtime/device_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ enum DeviceAttrKind : int {
};

/*! \brief Number of bytes each allocation must align to */
constexpr int kAllocAlignment = 64;
constexpr int kAllocAlignment = 128;

/*! \brief Number of bytes each allocation must align to in temporary allocation */
constexpr int kTempAllocaAlignment = 64;
constexpr int kTempAllocaAlignment = 128;

/*! \brief Maximum size that can be allocated on stack */
constexpr int kMaxStackAlloca = 1024;
Expand Down Expand Up @@ -218,6 +218,7 @@ inline const char* DeviceName(int type) {
case kOpenGL: return "opengl";
case kDLExtDev: return "ext_dev";
case kDLMicroDev: return "micro_dev";
case kDLHexagon: return "hexagon";
default: LOG(FATAL) << "unknown type =" << type; return "Unknown";
}
}
Expand Down
4 changes: 4 additions & 0 deletions include/tvm/target/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ TVM_DLL Target stackvm(const std::vector<std::string>& options =
/*! \return A target for external device */
TVM_DLL Target ext_dev(const std::vector<std::string>& options =
std::vector<std::string>());

/*! \return A target for hexagon */
TVM_DLL Target hexagon(const std::vector<std::string>& options =
std::vector<std::string>());
} // namespace target

/*!
Expand Down
15 changes: 15 additions & 0 deletions jvm/core/src/main/java/org/apache/tvm/TVMContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class TVMContext {
MASK2STR.put(7, "vulkan");
MASK2STR.put(8, "metal");
MASK2STR.put(9, "vpi");
MASK2STR.put(14, "hexagon");

STR2MASK.put("cpu", 1);
STR2MASK.put("gpu", 2);
Expand All @@ -42,6 +43,7 @@ public class TVMContext {
STR2MASK.put("vulkan", 7);
STR2MASK.put("metal", 8);
STR2MASK.put("vpi", 9);
STR2MASK.put("hexagon", 14);
}

/**
Expand Down Expand Up @@ -122,6 +124,19 @@ public static TVMContext vpi() {
return vpi(0);
}

/**
* Construct a Hexagon device.
* @param devId The device id
* @return The created context
*/
public static TVMContext hexagon(int devId) {
return new TVMContext(14, devId);
}

public static TVMContext hexagon() {
return hexagon(0);
}

public final int deviceType;
public final int deviceId;

Expand Down
2 changes: 1 addition & 1 deletion python/tvm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
# tvm.runtime
from .runtime.object import Object
from .runtime.ndarray import context, cpu, gpu, opencl, cl, vulkan, metal, mtl
from .runtime.ndarray import vpi, rocm, opengl, ext_dev, micro_dev
from .runtime.ndarray import vpi, rocm, opengl, ext_dev, micro_dev, hexagon
from .runtime import ndarray as nd

# tvm.error
Expand Down
2 changes: 2 additions & 0 deletions python/tvm/_ffi/runtime_ctypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class TVMContext(ctypes.Structure):
11: 'opengl',
12: 'ext_dev',
13: 'micro_dev',
14: 'hexagon',
}
STR2MASK = {
'llvm': 1,
Expand All @@ -166,6 +167,7 @@ class TVMContext(ctypes.Structure):
'opengl': 11,
'ext_dev': 12,
'micro_dev': 13,
'hexagon': 14,
}
def __init__(self, device_type, device_id):
super(TVMContext, self).__init__()
Expand Down
16 changes: 16 additions & 0 deletions python/tvm/runtime/ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,22 @@ def micro_dev(dev_id=0):
return TVMContext(13, dev_id)


def hexagon(dev_id=0):
"""Construct a Hexagon device
Parameters
----------
dev_id : int, optional
The integer device id
Returns
-------
ctx : TVMContext
The created context
"""
return TVMContext(14, dev_id)


cl = opencl
mtl = metal

Expand Down
2 changes: 1 addition & 1 deletion python/tvm/target/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
We can also use other specific function in this module to create specific targets.
"""
from .target import Target, create
from .target import cuda, rocm, mali, intel_graphics, opengl, arm_cpu, rasp, vta, bifrost
from .target import cuda, rocm, mali, intel_graphics, opengl, arm_cpu, rasp, vta, bifrost, hexagon
from .generic_func import GenericFunc
from .generic_func import generic_func, get_native_generic_func, override_native_generic_func
from . import datatype
Expand Down
Loading

0 comments on commit 730af76

Please sign in to comment.