Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of uTVM #3227

Merged
merged 109 commits into from
Jul 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
7be3181
uTVM interfaces (#14)
Mutinifni Mar 26, 2019
9ebc55f
some minor interface changes
Mutinifni Mar 28, 2019
1c3e449
implemented HostLowLevelDevice
Mutinifni Mar 28, 2019
bd15740
added MicroDeviceAPI
Mutinifni Apr 1, 2019
403a5d9
implemented micro_common and added Python interfaces
Mutinifni Apr 1, 2019
d3cb9f3
current status, semi implemented micro session
Mutinifni Apr 4, 2019
e6c4448
added micro_common implementation and python interfaces (#18)
Mutinifni Apr 4, 2019
0ca1d97
current status, semi implemented
Mutinifni Apr 4, 2019
059fdc2
added micro_common implementation and python interfaces (#18)
Mutinifni Apr 4, 2019
1f6a1a6
host test working
Mutinifni Apr 8, 2019
4ede248
updated interfaces for MicroSession arguments allocation
Mutinifni Apr 17, 2019
cb1f2f1
make somewhat lint compatible
Mutinifni Apr 17, 2019
8de60be
fix based on comments
Mutinifni Apr 20, 2019
633d744
added rounding macro
Mutinifni Apr 21, 2019
985689a
fix minor bug
Mutinifni Apr 21, 2019
284905c
improvements based on comments
Mutinifni Apr 23, 2019
5218619
Clean up `binutil.py` and make Python-3-compatible
Apr 25, 2019
e94e880
Change argument allocation design
Apr 25, 2019
c7a5c48
Address feedback and lint errors
weberlo Apr 25, 2019
cb497b8
Improve binutil tests
weberlo Apr 26, 2019
db01d8d
Simplify allocator (per @tqchen's suggestions)
weberlo Apr 29, 2019
6ae42ad
Doc/style fixes
weberlo Apr 29, 2019
9aa82dd
farts
weberlo May 7, 2019
3547a70
mcgee
weberlo May 7, 2019
d65c07f
rodata section werks
weberlo May 8, 2019
05856c9
simple graph runtime werk
weberlo May 15, 2019
d1dd841
TEMP
weberlo May 16, 2019
190cd37
ResNet works, yo
weberlo May 16, 2019
ace2e9b
First round of cleanup
weberlo May 19, 2019
f81160b
More cleanup
weberlo May 20, 2019
9fd33d5
runs a dyson over the code
weberlo May 20, 2019
e8c7046
Another pass
weberlo May 21, 2019
370bee7
Fix `make lint` issues
weberlo May 21, 2019
fe54690
ready to pr... probably
weberlo May 21, 2019
b1dca33
final
weberlo May 21, 2019
ae199c2
Undo change
weberlo May 21, 2019
c21cece
Fix rebase resolution
weberlo May 22, 2019
aa89ece
Minor fixes
weberlo May 22, 2019
660c8fe
Undo changes to C codegen tests
weberlo May 22, 2019
08c2a59
Add `obj_path` in `create_micro_lib`
weberlo May 22, 2019
1d43f2d
TEMP
weberlo May 22, 2019
32ba715
Address feedback
weberlo May 23, 2019
34811bc
Add missing TODO
weberlo May 23, 2019
7da9ced
Partially address feedback
weberlo May 25, 2019
327d8d5
Fix headers
weberlo May 25, 2019
4bc1633
Switch to enum class for `SectionKind`
weberlo May 27, 2019
2bc32ff
Add missing ASF header
weberlo May 28, 2019
43d44b0
Fix lint
weberlo May 28, 2019
49bf4e3
Fix lint again
weberlo May 29, 2019
3ee73da
Fix lint
weberlo May 29, 2019
6c62a03
Kill lint warnings
weberlo May 30, 2019
fc85816
Address feedback
weberlo May 31, 2019
81c367c
Change Python interface to MicroTVM
weberlo May 31, 2019
9f6fd46
Reorder LowLevelDevice interface
weberlo Jun 18, 2019
dbfe060
Store shared ptr to session in all alloced objects
weberlo Jun 18, 2019
a6d28ed
Move helper functions out of `tvm.micro`
weberlo Jun 18, 2019
52477a8
Switch static char arr to vector
weberlo Jul 2, 2019
35dc1d5
Improve general infra and code quality
weberlo Jul 3, 2019
260ec37
Forgot a rename
weberlo Jul 3, 2019
953d217
Fix lint
weberlo Jul 3, 2019
cf95739
Add ASF header
weberlo Jul 3, 2019
efdeb23
Fix lint
weberlo Jul 3, 2019
4d929e3
Partially address MarisaKirisame's feedback
weberlo Jul 3, 2019
6f30813
Lint
weberlo Jul 3, 2019
5cf5093
Expose `MicroSession` as a node to Python
weberlo Jul 5, 2019
4f27116
Revert to using `Session` constructor
weberlo Jul 5, 2019
297cbb1
Fix compiler error
weberlo Jul 5, 2019
105e3b3
(Maybe) fix CI error
weberlo Jul 5, 2019
29782bd
Debugging
weberlo Jul 6, 2019
03c0616
Remove
weberlo Jul 6, 2019
9057d3b
Quell lint
weberlo Jul 6, 2019
d3be1fb
Switch to stack-based session contexts
weberlo Jul 9, 2019
c5ef066
Make uTVM less intrusive to host codegen
weberlo Jul 11, 2019
b3d9369
Inline UTVMArgs into UTVMTask struct
weberlo Jul 11, 2019
c8cb63b
Remove `HostLowLevelDevice` header
weberlo Jul 11, 2019
8ffbf73
Remove `BaseAddr` class
weberlo Jul 11, 2019
5e9347f
Address feedback
weberlo Jul 11, 2019
7e1bae7
Add "utvm" prefix to global vars in runtime
weberlo Jul 11, 2019
bdb21e9
Fix lint
weberlo Jul 11, 2019
f22b880
Fix CI
weberlo Jul 11, 2019
40978cd
Fix `test_binutil.py`
weberlo Jul 12, 2019
7e8bcd9
Fix submodules
weberlo Jul 12, 2019
81b178e
Remove ResNet tests
weberlo Jul 12, 2019
1aae051
Make `test_binutil.py` work with nose
weberlo Jul 12, 2019
50f5b1b
Fix CI
weberlo Jul 12, 2019
e285275
I swear this actually fixes the binutil tests
weberlo Jul 12, 2019
e280703
lint
weberlo Jul 12, 2019
ad414da
lint
weberlo Jul 12, 2019
492b472
Add fcompile-compatible cross-compile func
weberlo Jul 13, 2019
e41d718
Add docs for uTVM runtime files
weberlo Jul 13, 2019
458bd7a
Move pointer patching into `MicroSession`
weberlo Jul 13, 2019
42be5ea
Fix lint
weberlo Jul 14, 2019
b1a3d91
First attempt at unifying cross-compile APIs
weberlo Jul 14, 2019
2553c04
Fix lint
weberlo Jul 15, 2019
f62ee28
Rename `cross_compile` back to `cc`
weberlo Jul 15, 2019
b731a46
Address feedback
weberlo Jul 15, 2019
56388ab
Remove commented code
weberlo Jul 15, 2019
d358684
Lint
weberlo Jul 16, 2019
ca671d6
Figure out failing function
weberlo Jul 16, 2019
7e45f89
Remove debugging code
weberlo Jul 18, 2019
71619e3
Change "micro_dev" target to "micro"
weberlo Jul 18, 2019
0c44fdf
Add checks in tests for whether uTVM is enabled
weberlo Jul 18, 2019
d63f2ff
Add TODO for 32-bit support
weberlo Jul 18, 2019
2d516ea
Rename more "micro_dev" to "micro"
weberlo Jul 18, 2019
2b7a269
Undo rename
weberlo Jul 18, 2019
9dd60a6
Fix failing CI
weberlo Jul 23, 2019
9d05c29
Address feedback
weberlo Jul 23, 2019
3c68727
Fix lint
weberlo Jul 24, 2019
810dcb6
Merge branch 'master' into micro-tvm
weberlo Jul 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ tvm_option(USE_RELAY_DEBUG "Building Relay in debug mode..." OFF)
tvm_option(USE_SGX "Build with SGX" OFF)
tvm_option(USE_RTTI "Build with RTTI" ON)
tvm_option(USE_MSVC_MT "Build with MT" OFF)
tvm_option(USE_MICRO "Build with Micro" OFF)
tvm_option(INSTALL_DEV "Install compiler infrastructure" OFF)
tvm_option(HIDE_PRIVATE_SYMBOLS "Compile with -fvisibility=hidden." OFF)

Expand Down Expand Up @@ -207,6 +208,7 @@ include(cmake/modules/Metal.cmake)
include(cmake/modules/ROCM.cmake)
include(cmake/modules/SGX.cmake)
include(cmake/modules/LLVM.cmake)
include(cmake/modules/Micro.cmake)
include(cmake/modules/ANTLR.cmake)
include(cmake/modules/contrib/BLAS.cmake)
include(cmake/modules/contrib/Random.cmake)
Expand Down
3 changes: 3 additions & 0 deletions cmake/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ set(USE_VULKAN OFF)
# Whether enable OpenGL runtime
set(USE_OPENGL OFF)

# Whether enable MicroTVM runtime
set(USE_MICRO OFF)

# Whether to enable SGX runtime
#
# Possible values for USE_SGX:
Expand Down
22 changes: 22 additions & 0 deletions cmake/modules/Micro.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 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.

if(USE_MICRO)
message(STATUS "Build with Micro support")
file(GLOB RUNTIME_MICRO_SRCS src/runtime/micro/*.cc)
list(APPEND RUNTIME_SRCS ${RUNTIME_MICRO_SRCS})
endif(USE_MICRO)
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 @@ -81,6 +81,7 @@ typedef enum {
kDLAOCL = 5,
kDLSDAccel = 6,
kOpenGL = 11,
kDLMicroDev = 13,
// AddExtraTVMType which is not in DLPack here
} TVMDeviceExtType;

Expand Down
1 change: 1 addition & 0 deletions include/tvm/runtime/device_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ inline const char* DeviceName(int type) {
case kDLROCM: return "rocm";
case kOpenGL: return "opengl";
case kDLExtDev: return "ext_dev";
case kDLMicroDev: return "micro_dev";
default: LOG(FATAL) << "unknown type =" << type; return "Unknown";
}
}
Expand Down
2 changes: 1 addition & 1 deletion python/tvm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

from . import ndarray as nd
from .ndarray import context, cpu, gpu, opencl, cl, vulkan, metal, mtl
from .ndarray import vpi, rocm, opengl, ext_dev
from .ndarray import vpi, rocm, opengl, ext_dev, micro_dev

from ._ffi.runtime_ctypes import TypeCode, TVMType
from ._ffi.ndarray import TVMContext
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 @@ -143,6 +143,7 @@ class TVMContext(ctypes.Structure):
10: 'rocm',
11: 'opengl',
12: 'ext_dev',
13: 'micro_dev',
}
STR2MASK = {
'llvm': 1,
Expand All @@ -163,6 +164,7 @@ class TVMContext(ctypes.Structure):
'rocm': 10,
'opengl': 11,
'ext_dev': 12,
'micro_dev': 13,
}
def __init__(self, device_type, device_id):
super(TVMContext, self).__init__()
Expand Down
258 changes: 258 additions & 0 deletions python/tvm/contrib/binutil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
# 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.

"""Utilities for binary file manipulation"""
import os
import subprocess
from . import util
from .._ffi.base import py_str
from ..api import register_func

@register_func("tvm_callback_get_section_size")
def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix):
"""Finds size of the section in the binary.
Assumes `size` shell command exists (typically works only on Linux machines)
Parameters
----------
binary_path : str
path of the binary file
section_name : str
name of section
toolchain_prefix : str
prefix for binary names in target compiler toolchain
Returns
-------
size : integer
size of the section in bytes
"""
if not os.path.isfile(binary_path):
raise RuntimeError("no such file \"{}\"".format(binary_path))
# We use the "-A" flag here to get the ".rodata" section's size, which is
# not included by default.
size_proc = subprocess.Popen(
["{}size".format(toolchain_prefix), "-A", binary_path], stdout=subprocess.PIPE)
(size_output, _) = size_proc.communicate()
size_output = size_output.decode("utf-8")
if size_proc.returncode != 0:
msg = "error in finding section size:\n"
msg += py_str(out)
raise RuntimeError(msg)

# TODO(weberlo): Refactor this method and `*relocate_binary` so they are
# both aware of [".bss", ".sbss", ".sdata"] being relocated to ".bss".
section_mapping = {
".text": [".text"],
".rodata": [".rodata"],
".data": [".data", ".sdata"],
".bss": [".bss", ".sbss"],
}
sections_to_sum = section_mapping["." + section_name]
section_size = 0
# Skip the first two header lines in the `size` output.
for line in size_output.split("\n")[2:]:
tokens = list(filter(lambda s: len(s) != 0, line.split(" ")))
if len(tokens) != 3:
continue
entry_name = tokens[0]
entry_size = int(tokens[1])
if entry_name in sections_to_sum:
section_size += entry_size
return section_size


@register_func("tvm_callback_relocate_binary")
def tvm_callback_relocate_binary(
binary_path, text_addr, rodata_addr, data_addr, bss_addr, toolchain_prefix):
"""Relocates sections in the binary to new addresses
Parameters
----------
binary_path : str
path of the binary file
text_addr : str
text section absolute address
rodata_addr : str
rodata section absolute address
data_addr : str
data section absolute address
bss_addr : str
bss section absolute address
toolchain_prefix : str
prefix for binary names in target compiler toolchain
Returns
-------
rel_bin : bytearray
the relocated binary
"""
tmp_dir = util.tempdir()
rel_obj_path = tmp_dir.relpath("relocated.o")
ld_script_contents = ""
# TODO(weberlo): There should be a better way to configure this for different archs.
if "riscv" in toolchain_prefix:
ld_script_contents += "OUTPUT_ARCH( \"riscv\" )\n\n"
# TODO(weberlo): Generate the script in a more procedural manner.
ld_script_contents += """
SECTIONS
{
. = %s;
. = ALIGN(8);
.text :
{
*(.text)
. = ALIGN(8);
*(.text*)
}
. = %s;
. = ALIGN(8);
.rodata :
{
*(.rodata)
. = ALIGN(8);
*(.rodata*)
}
. = %s;
. = ALIGN(8);
.data :
{
*(.data)
. = ALIGN(8);
*(.data*)
. = ALIGN(8);
*(.sdata)
}
. = %s;
. = ALIGN(8);
.bss :
{
*(.bss)
. = ALIGN(8);
*(.bss*)
. = ALIGN(8);
*(.sbss)
}
}
""" % (text_addr, rodata_addr, data_addr, bss_addr)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This linker script generation feels a little bit ad hoc. If anyone has ideas on a better way to do this, I'd be happy to hear them. The only thing I can think of right now is to expose a linker configuration interface to the user.

I'm also perfectly happy punting this off to a future PR, when we've tested more hardware backends and figured out the pain points in the current interface.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that the linker script portion gets punted off to a different PR, after all for the work with the host emulation which is what this PR is about, this is not required is it ?

Further the linker scripts are potentially going to require slightly different values depending on hardware memory maps, and thus I wonder if we should think about having a framework for architecture wise linker scripts with configurations coming for individual boards .

rel_ld_script_path = tmp_dir.relpath("relocated.lds")
with open(rel_ld_script_path, "w") as f:
f.write(ld_script_contents)
ld_proc = subprocess.Popen(["{}ld".format(toolchain_prefix), binary_path,
"-T", rel_ld_script_path,
"-o", rel_obj_path],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(out, _) = ld_proc.communicate()
if ld_proc.returncode != 0:
msg = "linking error using ld:\n"
msg += py_str(out)
raise RuntimeError(msg)
with open(rel_obj_path, "rb") as f:
rel_bin = bytearray(f.read())
return rel_bin


@register_func("tvm_callback_read_binary_section")
def tvm_callback_read_binary_section(binary, section, toolchain_prefix):
"""Returns the contents of the specified section in the binary byte array
Parameters
----------
binary : bytearray
contents of the binary
section : str
type of section
toolchain_prefix : str
prefix for binary names in target compiler toolchain
Returns
-------
section_bin : bytearray
contents of the read section
"""
tmp_dir = util.tempdir()
tmp_bin = tmp_dir.relpath("temp.bin")
tmp_section = tmp_dir.relpath("tmp_section.bin")
with open(tmp_bin, "wb") as out_file:
out_file.write(bytes(binary))
objcopy_proc = subprocess.Popen(["{}objcopy".format(toolchain_prefix), "--dump-section",
".{}={}".format(section, tmp_section),
tmp_bin],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(out, _) = objcopy_proc.communicate()
if objcopy_proc.returncode != 0:
msg = "error in using objcopy:\n"
msg += py_str(out)
raise RuntimeError(msg)
if os.path.isfile(tmp_section):
# Get section content if it exists.
with open(tmp_section, "rb") as f:
section_bin = bytearray(f.read())
else:
# Return empty bytearray if the section does not exist.
section_bin = bytearray("", "utf-8")
return section_bin


@register_func("tvm_callback_get_symbol_map")
def tvm_callback_get_symbol_map(binary, toolchain_prefix):
"""Obtains a map of symbols to addresses in the passed binary
Parameters
----------
binary : bytearray
contents of the binary
toolchain_prefix : str
prefix for binary names in target compiler toolchain
Returns
-------
map_str : str
map of defined symbols to addresses, encoded as a series of
alternating newline-separated keys and values
"""
tmp_dir = util.tempdir()
tmp_obj = tmp_dir.relpath("tmp_obj.bin")
with open(tmp_obj, "wb") as out_file:
out_file.write(bytes(binary))
nm_proc = subprocess.Popen(["{}nm".format(toolchain_prefix), "-C", "--defined-only", tmp_obj],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(nm_output, _) = nm_proc.communicate()
if nm_proc.returncode != 0:
msg = "error in using nm:\n"
msg += py_str(nm_output)
raise RuntimeError(msg)
nm_output = nm_output.decode("utf8").splitlines()
map_str = ""
for line in nm_output:
line = line.split()
map_str += line[2] + "\n"
map_str += line[0] + "\n"
return map_str
Loading