From dbbffbd9c8ffb81dc5fd301f78a9b03e41ba6f07 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 1 Oct 2019 16:25:10 -0700 Subject: [PATCH 01/70] TEMP --- python/tvm/micro/__init__.py | 2 +- python/tvm/micro/base.py | 121 ++++++++++-- src/runtime/micro/device/utvm_runtime.h | 2 + src/runtime/micro/micro_common.h | 8 + src/runtime/micro/micro_module.cc | 28 ++- src/runtime/micro/micro_session.cc | 181 +++++++++++++----- src/runtime/micro/micro_session.h | 12 +- src/runtime/micro/openocd_low_level_device.cc | 14 +- tests/python/unittest/test_runtime_micro.py | 76 +++++++- 9 files changed, 356 insertions(+), 88 deletions(-) diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 2f3981903cab..91fe76ea2abc 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,4 +23,4 @@ """ from ..contrib import binutil -from .base import Session, cross_compiler, create_micro_lib +from .base import Session, cross_compiler, create_micro_lib, _get_micro_device_dir # TODO: REMOVE LAST diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index cab6f78363b5..0fe351b444c1 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -64,35 +64,129 @@ class Session: def __init__(self, device_type, toolchain_prefix, **kwargs): if device_type not in SUPPORTED_DEVICE_TYPES: raise RuntimeError("unknown micro device type \"{}\"".format(device_type)) - self._check_system() - self._check_args(device_type, kwargs) + #self._check_system() + #self._check_args(device_type, kwargs) # First, find and compile runtime library. - runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") - tmp_dir = _util.tempdir() - runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") - create_micro_lib( - runtime_obj_path, runtime_src_path, toolchain_prefix, include_dev_lib_header=False) + #tmp_dir = _util.tempdir() + #runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") + #create_micro_lib( + # runtime_obj_path, runtime_src_path, toolchain_prefix, include_dev_lib_header=False) + + self.op_modules = [] + + self.device_type = device_type + self.toolchain_prefix = toolchain_prefix + self.base_addr = kwargs.get("base_addr", 0) + self.server_addr = kwargs.get("server_addr", "") + self.port = kwargs.get("port", 0) - base_addr = kwargs.get("base_addr", 0) - server_addr = kwargs.get("server_addr", "") - port = kwargs.get("port", 0) self.module = _CreateSession( - device_type, runtime_obj_path, toolchain_prefix, base_addr, server_addr, port) + self.device_type, "", self.toolchain_prefix, self.base_addr, self.server_addr, self.port) self._enter = self.module["enter"] self._exit = self.module["exit"] + def add_module(self, c_mod): + self.op_modules.append(c_mod) + + def bake(self): + import subprocess + import os + import copy + from shutil import copyfile + + from tvm._ffi.libinfo import find_include_path + from tvm.micro import _get_micro_device_dir + from tvm.contrib import binutil + + op_srcs = [] + for op_module in self.op_modules: + op_src = op_module.get_source() + op_src = op_src[op_src.index("TVM_DLL"):] + op_srcs.append(op_src) + op_srcs = "\n".join(op_srcs) + + runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") + with open(runtime_src_path) as f: + runtime_src = f.read() + + include_str = "#include \"utvm_runtime.h\"" + split_idx = runtime_src.index(include_str) + len(include_str) + 2 + merged_src = (runtime_src[:split_idx] \ + + "#include \"stm32f7xx_nucleo_144.h\"\n" \ + + op_srcs \ + + runtime_src[split_idx:] \ + # TODO: figure out how to prevent DCE from kicking in without creating dummy calls. + + "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n") + + print(merged_src) + + # TODO: We need to somehow prevent the utvm funcs from being optimized + # away. we can either call all of them in `main`, or we can instruct + # the compiler to leave them in. + # + # can't use __attribute__((used)) because arm's compiler ignores it. + + nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" + with open(f"{nucleo_path}/src/main.c", "w") as f: + f.write(merged_src) + print(merged_src) + + paths = [path for path in find_include_path()] + paths += ["/home/pratyush/Code/tvm/src/runtime/micro/device"] + print(paths) + child_env = copy.deepcopy(os.environ) + child_env["LD_LIBRARY_PATH"] += ":" + ":".join(paths) + + print("[FLASHING]") + proc = subprocess.Popen( + ["make", "flash"], + cwd=nucleo_path, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + (out, _) = proc.communicate() + if proc.returncode != 0: + msg = "Compilation error:\n" + msg += out.decode("utf-8") + raise RuntimeError(msg) + + result_binary_path = f"{nucleo_path}/blinky.elf" + + print(binutil.tvm_callback_get_section_size(result_binary_path, "text", self.toolchain_prefix)) + print(binutil.tvm_callback_get_section_size(result_binary_path, "rodata", self.toolchain_prefix)) + print(binutil.tvm_callback_get_section_size(result_binary_path, "data", self.toolchain_prefix)) + print(binutil.tvm_callback_get_section_size(result_binary_path, "bss", self.toolchain_prefix)) + + with open(result_binary_path, "rb") as f: + result_binary_contents = bytearray(f.read()) + + sym_map_str = binutil.tvm_callback_get_symbol_map(result_binary_contents, self.toolchain_prefix) + sym_map_lines = list(filter(lambda s: len(s) != 0, sym_map_str.split('\n'))) + + sym_map_iter = iter(sym_map_lines) + sym_map = {} + for sym_name in sym_map_iter: + sym_loc = next(sym_map_iter) + sym_map[sym_name] = sym_loc + + print('UTVMMain: ' + sym_map['UTVMMain']) + print('UTVMDone: ' + sym_map['UTVMDone']) + print('fadd: ' + sym_map['fadd']) + print('TVMBackendAllocWorkspace: ' + sym_map['TVMBackendAllocWorkspace']) + print('TVMBackendFreeWorkspace: ' + sym_map['TVMBackendFreeWorkspace']) + print('TVMAPISetLastError: ' + sym_map['TVMAPISetLastError']) + def _check_system(self): """Check if the user's system is supported by MicroTVM. Raises error if not supported. """ if not sys.platform.startswith("linux"): - raise RuntimeError("microTVM is currently only supported on Linux") + raise RuntimeError("MicroTVM is currently only supported on Linux") # TODO(weberlo): Add 32-bit support. # It's primarily the compilation pipeline that isn't compatible. if sys.maxsize <= 2**32: - raise RuntimeError("microTVM is currently only supported on 64-bit platforms") + raise RuntimeError("MicroTVM is currently only supported on 64-bit platforms") def _check_args(self, device_type, args): """Check if the given configuration is valid.""" @@ -105,6 +199,7 @@ def _check_args(self, device_type, args): def __enter__(self): self._enter() + return self def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() diff --git a/src/runtime/micro/device/utvm_runtime.h b/src/runtime/micro/device/utvm_runtime.h index 3aa171223e01..0a9adf7af2de 100644 --- a/src/runtime/micro/device/utvm_runtime.h +++ b/src/runtime/micro/device/utvm_runtime.h @@ -30,6 +30,8 @@ extern "C" { #include #include +// TODO(weberlo): do we need this? +#include /*! * \brief Task structure for uTVM diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 10ae9d50b8bc..5fc8fbcbf23c 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -239,6 +239,14 @@ struct BinaryInfo { SymbolMap symbol_map; }; +struct BinaryContents { + BinaryInfo binary_info; + std::string text_contents; + std::string rodata_contents; + std::string data_contents; + std::string bss_contents; +}; + // TODO(weberlo): should this be here? /*! \brief number of bytes in each page */ constexpr int kPageSize = 4096; diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index e66c45b3f063..5c6413fdf2eb 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -38,6 +38,17 @@ namespace runtime { */ class MicroModuleNode final : public ModuleNode { public: + // TODO(weberlo): enqueue each loaded module into a vector of bin contents. + // then concatenate the contents, build it, and flush it once a function call + // is attempted. + // + // We might not be able to flush *all* sections. Depends how st-flash works. + // it only asks to specify the start of the flash section, so does it also + // flash the RAM sections? It's also weird that it asks for the start of the + // flash section, because that should already be encoded in the binary. check + // the .bin files to see if symbol addrs are assigned. also, check the + // st-flash docs, because the arg could just be for the address of `main`. + MicroModuleNode() {} ~MicroModuleNode() {} @@ -55,8 +66,10 @@ class MicroModuleNode final : public ModuleNode { */ void InitMicroModule(const std::string& binary_path) { session_ = MicroSession::Current(); - binary_path_ = binary_path; - binary_info_ = session_->LoadBinary(binary_path_); + //binary_path_ = binary_path; + std::cout << "AYY" << std::endl; + //binary_info_ = session_->EnqueueBinary(binary_path_); + std::cout << "LMAO" << std::endl; } /*! @@ -70,10 +83,11 @@ class MicroModuleNode final : public ModuleNode { } private: - /*! \brief module binary info */ - BinaryInfo binary_info_; - /*! \brief path to module binary */ - std::string binary_path_; + BinaryContents binary_contents_; + ///*! \brief module binary info */ + //BinaryInfo binary_info_; + ///*! \brief path to module binary */ + //std::string binary_path_; /*! \brief global session pointer */ ObjectPtr session_; }; @@ -109,7 +123,7 @@ PackedFunc MicroModuleNode::GetFunction( const std::string& name, const ObjectPtr& sptr_to_self) { DevBaseOffset func_offset = - session_->low_level_device()->ToDevOffset(binary_info_.symbol_map[name]); + session_->low_level_device()->ToDevOffset(binary_contents_.binary_info.symbol_map[name]); MicroWrappedFunc f(this, session_, name, func_offset); return PackedFunc(f); } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index febf726184d9..42273d5e2c75 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,16 +57,80 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { - DevBaseOffset curr_start_offset = kDeviceStart; - for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - size_t section_size = GetDefaultSectionSize(static_cast(i)); - section_allocators_[i] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = section_size, - }); - curr_start_offset += section_size; - } - memory_size_ = curr_start_offset.cast_to(); + //DevBaseOffset curr_start_offset = kDeviceStart; + //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + // size_t section_size = GetDefaultSectionSize(static_cast(i)); + // section_allocators_[i] = std::make_shared(DevMemRegion { + // .start = curr_start_offset, + // .size = section_size, + // }); + // curr_start_offset += section_size; + //} + //memory_size_ = curr_start_offset.cast_to(); + + /* Linker script sample + * #if !defined(MBED_APP_START) + * #define MBED_APP_START 0x08000000 + * #endif + * + * #if !defined(MBED_APP_SIZE) + * #define MBED_APP_SIZE 1024K + * #endif + * + * MEMORY + * { + * FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE + * RAM (rwx) : ORIGIN = 0x200001C8, LENGTH = 320K - 0x1C8 + * } + */ + + size_t half_flash_size = 512000; // 0.5 MB + DevBaseOffset curr_start_offset = DevBaseOffset(0x08000000); + section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = half_flash_size, + }); + curr_start_offset += half_flash_size; + section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = half_flash_size, + }); + curr_start_offset += half_flash_size; + + curr_start_offset = DevBaseOffset(0x200001C8); + size_t one_sixth_ram_size = 53256; + section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + + memory_size_ = 0; } MicroSession::~MicroSession() { @@ -88,32 +152,36 @@ void MicroSession::CreateSession(const std::string& device_type, low_level_device_ = HostLowLevelDeviceCreate(memory_size_); } else if (device_type == "openocd") { // TODO(weberlo): We need a better way of configuring devices. + std::cout << "BEFORE OPENOCD CREATE" << std::endl; low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); + std::cout << "AFTER OPENOCD CREATE" << std::endl; } else { LOG(FATAL) << "unsupported micro low-level device"; } - SetRuntimeBinaryPath(binary_path); - CHECK(!runtime_binary_path_.empty()) << "uTVM runtime not initialized"; - runtime_bin_info_ = LoadBinary(runtime_binary_path_, /* patch_dylib_pointers */ false); - utvm_main_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMMain"]); - utvm_done_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMDone"]); + //CHECK(!binary_path.empty()) << "uTVM runtime not initialized"; + //runtime_bin_info_ = LoadBinary(binary_path, /* patch_dylib_pointers */ false); + //utvm_main_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMMain"]); + //utvm_done_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMDone"]); - if (device_type == "openocd") { - // Set OpenOCD device's stack pointer. - auto stack_section = GetAllocator(SectionKind::kStack); - low_level_device_->SetStackTop(stack_section->max_end_offset()); - } + //if (device_type == "openocd") { + // // Set OpenOCD device's stack pointer. + // auto stack_section = GetAllocator(SectionKind::kStack); + // low_level_device_->SetStackTop(stack_section->max_end_offset()); + //} // Patch workspace pointers to the start of the workspace section. - DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); - DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); - void* workspace_start_addr = - low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); - void* workspace_end_addr = - low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); - DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_begin", workspace_start_addr); - DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_end", workspace_end_addr); + //DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); + //DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); + //void* workspace_start_addr = + // low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); + //void* workspace_end_addr = + // low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); + // TODO(weberlo): A lot of these symbol writes can be converted into symbols + // in the C source, where the symbols are created by the linker script we + // generate in python. + //DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_begin", workspace_start_addr); + //DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_end", workspace_end_addr); } void MicroSession::PushToExecQueue(DevBaseOffset func, const TVMArgs& args) { @@ -246,7 +314,7 @@ void MicroSession::CheckDeviceError() { } } -BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { +void MicroSession::EnqueueBinary(const std::string& binary_path) { DevMemRegion text_section; DevMemRegion rodata_section; DevMemRegion data_section; @@ -276,26 +344,47 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); - low_level_device_->Write(text_section.start, &text_contents[0], text_section.size); - low_level_device_->Write(rodata_section.start, &rodata_contents[0], rodata_section.size); - low_level_device_->Write(data_section.start, &data_contents[0], data_section.size); - low_level_device_->Write(bss_section.start, &bss_contents[0], bss_section.size); SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; - if (patch_dylib_pointers) { - // Patch device lib pointers. - PatchImplHole(symbol_map, "TVMBackendAllocWorkspace"); - PatchImplHole(symbol_map, "TVMBackendFreeWorkspace"); - PatchImplHole(symbol_map, "TVMAPISetLastError"); - } - - return BinaryInfo { + bin_queue_.push_back(BinaryContents { + .binary_info = BinaryInfo { .text_section = text_section, .rodata_section = rodata_section, .data_section = data_section, .bss_section = bss_section, .symbol_map = symbol_map, - }; + }, + .text_contents = text_contents, + .rodata_contents = rodata_contents, + .data_contents = data_contents, + .bss_contents = bss_contents, + }); +} + +// TODO: Do experiment where you check if any data is flushed into RAM from st-flash. + +/* +void MicroSession::FlushAllBinaries() { + int i = 0; + // TODO: If we have all of the binaries available at once, we can patch the + // pointers before we even load them on the board. + for (const auto& bin_contents : bin_queue_) { + if (i == 0) { + // Load runtime + } else { + // Load function + } + i++ + } + // FlushBinary(merged_bin_contents); +} +*/ + +void MicroSession::FlushBinary(const BinaryContents& bin_contents) { + //// Patch device lib pointers. + //PatchImplHole(bin_contents.symbol_map, "TVMBackendAllocWorkspace"); + //PatchImplHole(bin_contents.symbol_map, "TVMBackendFreeWorkspace"); + //PatchImplHole(bin_contents.symbol_map, "TVMAPISetLastError"); } void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { @@ -305,10 +394,6 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); } -void MicroSession::SetRuntimeBinaryPath(std::string path) { - runtime_binary_path_ = path; -} - std::string MicroSession::ReadString(DevBaseOffset str_offset) { std::ostringstream result; const size_t buf_size = 256; @@ -377,8 +462,10 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") const std::string& server_addr = args[4]; int port = args[5]; ObjectPtr session = make_object(); + //session->CreateSession( + // device_type, binary_path, toolchain_prefix, base_addr, server_addr, port); session->CreateSession( - device_type, binary_path, toolchain_prefix, base_addr, server_addr, port); + "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); *rv = Module(session); }); diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 65b64218313b..c61d919be0e8 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -131,13 +131,9 @@ class MicroSession : public ModuleNode { */ void PushToExecQueue(DevBaseOffset func, const TVMArgs& args); - /*! - * \brief loads binary onto device - * \param binary_path path to binary object file - * \param patch_dylib_pointers whether runtime API function pointer patching is needed - * \return info about loaded binary - */ - BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers = true); + void EnqueueBinary(const std::string& binary_path); + + void FlushBinary(const BinaryContents& bin_contents); /*! * \brief read value of symbol from device memory @@ -185,6 +181,8 @@ class MicroSession : public ModuleNode { /*! \brief offset of the runtime exit breakpoint */ DevBaseOffset utvm_done_symbol_; + std::vector bin_queue_; + /*! * \brief patches a function pointer in this module to an implementation * \param func_name name of the function pointer being patched diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 97730efef4ff..233adcb622f9 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -44,13 +44,18 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { explicit OpenOCDLowLevelDevice(std::uintptr_t base_addr, const std::string& server_addr, int port) : socket_() { - socket_.Connect(tvm::common::SockAddr(server_addr.c_str(), port)); - socket_.cmd_builder() << "reset halt"; - socket_.SendCommand(); + server_addr_ = server_addr; + port_ = port; base_addr_ = base_addr; CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; } + void Connect() { + socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); + socket_.cmd_builder() << "reset halt"; + socket_.SendCommand(); + } + void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { if (num_bytes == 0) { return; @@ -229,6 +234,9 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { /*! \brief socket used to communicate with the device through Tcl */ TclSocket socket_; + std::string server_addr_; + int port_; + /*! \brief number of bytes in a word on the target device (64-bit) */ static const constexpr ssize_t kWordSize = 8; // NOTE: OpenOCD will call any request larger than this constant an "absurd diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 82c279712e20..f8d87189c251 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,8 +25,10 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -DEVICE_TYPE = "host" -TOOLCHAIN_PREFIX = "" +DEVICE_TYPE = "openocd" +TOOLCHAIN_PREFIX = "arm-none-eabi-" +#DEVICE_TYPE = "host" +#TOOLCHAIN_PREFIX = "" def create_micro_mod(c_mod, toolchain_prefix): """Produces a micro module from a given module. @@ -49,7 +51,9 @@ def create_micro_mod(c_mod, toolchain_prefix): c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix=toolchain_prefix)) + print("BEFORE") micro_mod = tvm.module.load(lib_obj_path, "micro_dev") + print("AFTER") return micro_mod @@ -113,13 +117,18 @@ def test_add(): c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): + print("A") micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + print("B") micro_func = micro_mod[func_name] + print("C") ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + print("D") micro_func(a, b, c) + print("E") tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + b.asnumpy()) @@ -299,12 +308,59 @@ def test_inactive_session_use(): add_result, np_tensor_a + 1.0) +#-------------------------------------------------------------------------------- +#-------------------------------------------------------------------------------- +#-------------------------------------------------------------------------------- + + +def test_arm_add(): + """Test a module which performs addition.""" + import tvm + if not tvm.module.enabled("micro_dev"): + return + shape = (1024,) + dtype = "float32" + + import subprocess + import os + import copy + from shutil import copyfile + + from tvm._ffi.libinfo import find_include_path + from tvm.micro import _get_micro_device_dir + from tvm.contrib import binutil + + # Construct TVM expression. + tvm_shape = tvm.convert(shape) + A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) + B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) + C = tvm.compute(A.shape, lambda *i: A(*i) + B(*i), name="C") + s = tvm.create_schedule(C.op) + + func_name = "fadd" + c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) + + with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) as sess: + sess.add_module(c_mod) + sess.bake() + + #ctx = tvm.micro_dev(0) + #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + #micro_func(a, b, c) + + #tvm.testing.assert_allclose( + # c.asnumpy(), a.asnumpy() + b.asnumpy()) + + if __name__ == "__main__": - test_alloc() - test_add() - test_workspace_add() - test_graph_runtime() - test_multiple_modules() - test_interleave_sessions() - test_nested_sessions() - test_inactive_session_use() + #test_alloc() + #test_add() + #test_workspace_add() + #test_graph_runtime() + #test_multiple_modules() + #test_interleave_sessions() + #test_nested_sessions() + #test_inactive_session_use() + test_arm_add() From 5b356a7a6feb73ad6bcd64f1e39de95182022530 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 3 Oct 2019 21:06:15 -0700 Subject: [PATCH 02/70] TEMP 2 --- python/tvm/micro/__init__.py | 2 +- python/tvm/micro/base.py | 84 ++++++----- src/runtime/micro/device/utvm_runtime.c | 6 +- src/runtime/micro/host_low_level_device.cc | 2 + src/runtime/micro/low_level_device.h | 2 + src/runtime/micro/micro_session.cc | 139 +++++++----------- src/runtime/micro/micro_session.h | 26 ++-- src/runtime/micro/openocd_low_level_device.cc | 10 +- tests/python/unittest/test_runtime_micro.py | 47 ++++-- 9 files changed, 162 insertions(+), 156 deletions(-) diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 91fe76ea2abc..2f3981903cab 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,4 +23,4 @@ """ from ..contrib import binutil -from .base import Session, cross_compiler, create_micro_lib, _get_micro_device_dir # TODO: REMOVE LAST +from .base import Session, cross_compiler, create_micro_lib diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 0fe351b444c1..3cfb318b0156 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -81,10 +81,12 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): self.server_addr = kwargs.get("server_addr", "") self.port = kwargs.get("port", 0) + print('creating session') self.module = _CreateSession( self.device_type, "", self.toolchain_prefix, self.base_addr, self.server_addr, self.port) self._enter = self.module["enter"] self._exit = self.module["exit"] + print('finished session init') def add_module(self, c_mod): self.op_modules.append(c_mod) @@ -96,7 +98,6 @@ def bake(self): from shutil import copyfile from tvm._ffi.libinfo import find_include_path - from tvm.micro import _get_micro_device_dir from tvm.contrib import binutil op_srcs = [] @@ -104,7 +105,7 @@ def bake(self): op_src = op_module.get_source() op_src = op_src[op_src.index("TVM_DLL"):] op_srcs.append(op_src) - op_srcs = "\n".join(op_srcs) + op_srcs = "\n\n".join(op_srcs) runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") with open(runtime_src_path) as f: @@ -119,26 +120,17 @@ def bake(self): # TODO: figure out how to prevent DCE from kicking in without creating dummy calls. + "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n") - print(merged_src) - - # TODO: We need to somehow prevent the utvm funcs from being optimized - # away. we can either call all of them in `main`, or we can instruct - # the compiler to leave them in. - # - # can't use __attribute__((used)) because arm's compiler ignores it. - + print('writing src to main.c') nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" with open(f"{nucleo_path}/src/main.c", "w") as f: f.write(merged_src) - print(merged_src) paths = [path for path in find_include_path()] paths += ["/home/pratyush/Code/tvm/src/runtime/micro/device"] - print(paths) child_env = copy.deepcopy(os.environ) child_env["LD_LIBRARY_PATH"] += ":" + ":".join(paths) - print("[FLASHING]") + print('flashing to device') proc = subprocess.Popen( ["make", "flash"], cwd=nucleo_path, @@ -149,32 +141,55 @@ def bake(self): msg = "Compilation error:\n" msg += out.decode("utf-8") raise RuntimeError(msg) + print('finished') result_binary_path = f"{nucleo_path}/blinky.elf" - - print(binutil.tvm_callback_get_section_size(result_binary_path, "text", self.toolchain_prefix)) - print(binutil.tvm_callback_get_section_size(result_binary_path, "rodata", self.toolchain_prefix)) - print(binutil.tvm_callback_get_section_size(result_binary_path, "data", self.toolchain_prefix)) - print(binutil.tvm_callback_get_section_size(result_binary_path, "bss", self.toolchain_prefix)) - with open(result_binary_path, "rb") as f: result_binary_contents = bytearray(f.read()) - sym_map_str = binutil.tvm_callback_get_symbol_map(result_binary_contents, self.toolchain_prefix) - sym_map_lines = list(filter(lambda s: len(s) != 0, sym_map_str.split('\n'))) - - sym_map_iter = iter(sym_map_lines) - sym_map = {} - for sym_name in sym_map_iter: - sym_loc = next(sym_map_iter) - sym_map[sym_name] = sym_loc - - print('UTVMMain: ' + sym_map['UTVMMain']) - print('UTVMDone: ' + sym_map['UTVMDone']) - print('fadd: ' + sym_map['fadd']) - print('TVMBackendAllocWorkspace: ' + sym_map['TVMBackendAllocWorkspace']) - print('TVMBackendFreeWorkspace: ' + sym_map['TVMBackendFreeWorkspace']) - print('TVMAPISetLastError: ' + sym_map['TVMAPISetLastError']) + #sym_map_str = binutil.tvm_callback_get_symbol_map(result_binary_contents, self.toolchain_prefix) + #sym_map_lines = list(filter(lambda s: len(s) != 0, sym_map_str.split('\n'))) + + #sym_map_iter = iter(sym_map_lines) + #sym_map = {} + #for sym_name in sym_map_iter: + # sym_loc = next(sym_map_iter) + # sym_map[sym_name] = sym_loc + + #print('UTVMMain: ' + sym_map['UTVMMain']) + #print('UTVMDone: ' + sym_map['UTVMDone']) + #print('fadd: ' + sym_map['fadd']) + #print('TVMBackendAllocWorkspace: ' + sym_map['TVMBackendAllocWorkspace']) + #print('TVMBackendFreeWorkspace: ' + sym_map['TVMBackendFreeWorkspace']) + #print('TVMAPISetLastError: ' + sym_map['TVMAPISetLastError']) + + # TODO: we might need to start OpenOCD in a separate process + input('start openocd! ') + # wait until the server has started up until attempting to connect in C++ + #openocd_script_dir = '/usr/share/openocd/scripts' + #cmd = [ + # 'openocd', + # '-f', f'{openocd_script_dir}/interface/stlink-v2-1.cfg', + # '-f', f'{openocd_script_dir}/target/stm32f7x.cfg' + #] + #self.openocd_process = subprocess.Popen( + # cmd, + # stdout=subprocess.PIPE, + # stderr=subprocess.STDOUT) + #print('waiting for OpenOCD to start up') + #while True: + # output = self.openocd_process.stdout.readline() + # if 'stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints' in output.decode('utf-8'): + # break + # if output: + # print(output.strip()) + # rc = self.openocd_process.poll() + #print('finished starting up') + + _BakeSession(result_binary_contents); + + def get_func(self, func_name): + return _GetFunction(func_name); def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -203,6 +218,7 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() + #self.openocd_process.kill() def _get_micro_device_dir(): diff --git a/src/runtime/micro/device/utvm_runtime.c b/src/runtime/micro/device/utvm_runtime.c index beb749a01f1e..bc8dbff738c0 100644 --- a/src/runtime/micro/device/utvm_runtime.c +++ b/src/runtime/micro/device/utvm_runtime.c @@ -35,7 +35,7 @@ extern "C" { #include "utvm_runtime.h" // Task pointers must be patched before calling a function. -UTVMTask task; +UTVMTask utvm_task; // These pointers are patched at load time to point to the workspace section. char* utvm_workspace_begin = NULL; // NOLINT(*) @@ -56,8 +56,8 @@ void UTVMMain() { utvm_num_active_allocs = 0; utvm_last_error = NULL; // NOLINT(*) utvm_return_code = 0; - utvm_return_code = task.func((void*) task.arg_values, (void*) task.arg_type_codes, // NOLINT(*) - task.num_args); + utvm_return_code = utvm_task.func((void*) utvm_task.arg_values, (void*) utvm_task.arg_type_codes, // NOLINT(*) + utvm_task.num_args); UTVMDone(); } diff --git a/src/runtime/micro/host_low_level_device.cc b/src/runtime/micro/host_low_level_device.cc index 4eea88aaaffd..48d55ba239c1 100644 --- a/src/runtime/micro/host_low_level_device.cc +++ b/src/runtime/micro/host_low_level_device.cc @@ -72,6 +72,8 @@ class HostLowLevelDevice final : public LowLevelDevice { reinterpret_cast(func_addr.value())(); } + void Connect() {} + std::uintptr_t base_addr() const final { return base_addr_; } diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index 3cdfa77d30bc..95fe545021f0 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -66,6 +66,8 @@ class LowLevelDevice { */ virtual void Execute(DevBaseOffset func_offset, DevBaseOffset breakpoint) = 0; + virtual void Connect() = 0; + // TODO(weberlo): Should we just give the device the *entire* memory layout // decided by the session? diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 42273d5e2c75..36df83b68d7c 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -152,17 +152,15 @@ void MicroSession::CreateSession(const std::string& device_type, low_level_device_ = HostLowLevelDeviceCreate(memory_size_); } else if (device_type == "openocd") { // TODO(weberlo): We need a better way of configuring devices. - std::cout << "BEFORE OPENOCD CREATE" << std::endl; low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); - std::cout << "AFTER OPENOCD CREATE" << std::endl; } else { LOG(FATAL) << "unsupported micro low-level device"; } //CHECK(!binary_path.empty()) << "uTVM runtime not initialized"; //runtime_bin_info_ = LoadBinary(binary_path, /* patch_dylib_pointers */ false); - //utvm_main_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMMain"]); - //utvm_done_symbol_ = low_level_device()->ToDevOffset(runtime_symbol_map()["UTVMDone"]); + //utvm_main_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMMain"]); + //utvm_done_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMDone"]); //if (device_type == "openocd") { // // Set OpenOCD device's stack pointer. @@ -180,14 +178,20 @@ void MicroSession::CreateSession(const std::string& device_type, // TODO(weberlo): A lot of these symbol writes can be converted into symbols // in the C source, where the symbols are created by the linker script we // generate in python. - //DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_begin", workspace_start_addr); - //DevSymbolWrite(runtime_symbol_map(), "utvm_workspace_end", workspace_end_addr); + //DevSymbolWrite(symbol_map_, "utvm_workspace_begin", workspace_start_addr); + //DevSymbolWrite(symbol_map_, "utvm_workspace_end", workspace_end_addr); } -void MicroSession::PushToExecQueue(DevBaseOffset func, const TVMArgs& args) { +void MicroSession::BakeSession(const std::string& binary) { + symbol_map_ = SymbolMap(binary, toolchain_prefix_); + std::cout << symbol_map_["UTVMMain"].value() << std::endl; + std::cout << symbol_map_["utvm_task"].value() << std::endl; + low_level_device()->Connect(); +} + +void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { int32_t (*func_dev_addr)(void*, void*, int32_t) = - reinterpret_cast( - low_level_device()->ToDevPtr(func).value()); + reinterpret_cast(func_ptr.value()); // Create an allocator stream for the memory region after the most recent // allocation in the args section. @@ -210,7 +214,7 @@ void MicroSession::PushToExecQueue(DevBaseOffset func, const TVMArgs& args) { .num_args = args.num_args, }; // Write the task. - DevSymbolWrite(runtime_symbol_map(), "task", task); + DevSymbolWrite(symbol_map_, "utvm_task", task); low_level_device()->Execute(utvm_main_symbol_, utvm_done_symbol_); // Check if there was an error during execution. If so, log it. @@ -297,11 +301,11 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr } void MicroSession::CheckDeviceError() { - int32_t return_code = DevSymbolRead(runtime_symbol_map(), "utvm_return_code"); + int32_t return_code = DevSymbolRead(symbol_map_, "utvm_return_code"); if (return_code) { std::uintptr_t last_error = - DevSymbolRead(runtime_symbol_map(), "utvm_last_error"); + DevSymbolRead(symbol_map_, "utvm_last_error"); std::string last_error_str; if (last_error) { DevBaseOffset last_err_offset = low_level_device()->ToDevOffset(DevPtr(last_error)); @@ -314,81 +318,8 @@ void MicroSession::CheckDeviceError() { } } -void MicroSession::EnqueueBinary(const std::string& binary_path) { - DevMemRegion text_section; - DevMemRegion rodata_section; - DevMemRegion data_section; - DevMemRegion bss_section; - - text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_); - rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_); - data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_); - bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_); - - text_section.start = AllocateInSection(SectionKind::kText, text_section.size); - rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); - data_section.start = AllocateInSection(SectionKind::kData, data_section.size); - bss_section.start = AllocateInSection(SectionKind::kBss, bss_section.size); - CHECK(text_section.start != nullptr && rodata_section.start != nullptr && - data_section.start != nullptr && bss_section.start != nullptr) - << "not enough space to load module on device"; - - std::string relocated_bin = RelocateBinarySections( - binary_path, - low_level_device_->ToDevPtr(text_section.start), - low_level_device_->ToDevPtr(rodata_section.start), - low_level_device_->ToDevPtr(data_section.start), - low_level_device_->ToDevPtr(bss_section.start), - toolchain_prefix_); - std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); - std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); - std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); - std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); - SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; - - bin_queue_.push_back(BinaryContents { - .binary_info = BinaryInfo { - .text_section = text_section, - .rodata_section = rodata_section, - .data_section = data_section, - .bss_section = bss_section, - .symbol_map = symbol_map, - }, - .text_contents = text_contents, - .rodata_contents = rodata_contents, - .data_contents = data_contents, - .bss_contents = bss_contents, - }); -} - -// TODO: Do experiment where you check if any data is flushed into RAM from st-flash. - -/* -void MicroSession::FlushAllBinaries() { - int i = 0; - // TODO: If we have all of the binaries available at once, we can patch the - // pointers before we even load them on the board. - for (const auto& bin_contents : bin_queue_) { - if (i == 0) { - // Load runtime - } else { - // Load function - } - i++ - } - // FlushBinary(merged_bin_contents); -} -*/ - -void MicroSession::FlushBinary(const BinaryContents& bin_contents) { - //// Patch device lib pointers. - //PatchImplHole(bin_contents.symbol_map, "TVMBackendAllocWorkspace"); - //PatchImplHole(bin_contents.symbol_map, "TVMBackendFreeWorkspace"); - //PatchImplHole(bin_contents.symbol_map, "TVMAPISetLastError"); -} - void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { - void* runtime_impl_addr = runtime_symbol_map()[func_name].cast_to(); + void* runtime_impl_addr = symbol_map_[func_name].cast_to(); std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); @@ -452,6 +383,25 @@ PackedFunc MicroSession::GetFunction( } } +class MicroWrappedFunc { + public: + MicroWrappedFunc(std::shared_ptr session, + DevPtr func_ptr) { + session_ = session; + func_ptr_ = func_ptr; + } + + void operator()(TVMArgs args, TVMRetValue* rv) const { + session_->PushToExecQueue(func_ptr_, args); + } + + private: + /*! \brief reference to the session for this function (to keep the session alive) */ + std::shared_ptr session_; + /*! \brief offset of the function to be called */ + DevPtr func_ptr_; +}; + // create micro session and low-level device from Python frontend TVM_REGISTER_GLOBAL("micro._CreateSession") .set_body([](TVMArgs args, TVMRetValue* rv) { @@ -469,5 +419,22 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") *rv = Module(session); }); +TVM_REGISTER_GLOBAL("micro._BakeSession") +.set_body([](TVMArgs args, TVMRetValue* rv) { + const std::string& binary = args[0]; + + std::shared_ptr& session = MicroSession::Current(); + session->BakeSession(binary); + }); + +TVM_REGISTER_GLOBAL("micro._GetFunction") +.set_body([](TVMArgs args, TVMRetValue* rv) { + const std::string& name = args[0]; + std::shared_ptr& session = MicroSession::Current(); + + DevPtr func_ptr = session->GetSymbolLoc(name); + *rv = PackedFunc(MicroWrappedFunc(session, func_ptr)); + }); + } // namespace runtime } // namespace tvm diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index c61d919be0e8..bd5a6af5c495 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -97,6 +97,8 @@ class MicroSession : public ModuleNode { const std::string& server_addr, int port); + void BakeSession(const std::string& binary); + /*! * \brief ends the session by destructing the low-level device and its allocators */ @@ -129,11 +131,15 @@ class MicroSession : public ModuleNode { * \param func address of the function to be executed * \param args args to the packed function */ - void PushToExecQueue(DevBaseOffset func, const TVMArgs& args); + void PushToExecQueue(DevPtr func, const TVMArgs& args); + + DevPtr GetSymbolLoc(const std::string& sym_name) { + return symbol_map_[sym_name]; + } - void EnqueueBinary(const std::string& binary_path); + //void EnqueueBinary(const std::string& binary_path); - void FlushBinary(const BinaryContents& bin_contents); + //void FlushBinary(const BinaryContents& bin_contents); /*! * \brief read value of symbol from device memory @@ -172,8 +178,8 @@ class MicroSession : public ModuleNode { section_allocators_[static_cast(SectionKind::kNumKinds)]; /*! \brief total number of bytes of usable device memory for this session */ size_t memory_size_; - /*! \brief uTVM runtime binary info */ - BinaryInfo runtime_bin_info_; + ///*! \brief uTVM runtime binary info */ + //BinaryInfo runtime_bin_info_; /*! \brief path to uTVM runtime source code */ std::string runtime_binary_path_; /*! \brief offset of the runtime entry function */ @@ -181,7 +187,7 @@ class MicroSession : public ModuleNode { /*! \brief offset of the runtime exit breakpoint */ DevBaseOffset utvm_done_symbol_; - std::vector bin_queue_; + SymbolMap symbol_map_; /*! * \brief patches a function pointer in this module to an implementation @@ -225,14 +231,6 @@ class MicroSession : public ModuleNode { return section_allocators_[static_cast(kind)]; } - /*! - * \brief returns the symbol map for the uTVM runtime - * \return reference to symbol map - */ - const SymbolMap& runtime_symbol_map() { - return runtime_bin_info_.symbol_map; - } - /*! * \brief Push a new session context onto the thread-local stack. * The session on top of the stack is used as the current global session. diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 233adcb622f9..08af32bcbe94 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -52,7 +52,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { void Connect() { socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); - socket_.cmd_builder() << "reset halt"; + socket_.cmd_builder() << "reset ahalt"; socket_.SendCommand(); } @@ -185,10 +185,10 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); - // Set up the stack pointer. - DevPtr stack_end = stack_top() - 8; - socket_.cmd_builder() << "reg sp " << stack_end.cast_to(); - socket_.SendCommand(); + //// Set up the stack pointer. + //DevPtr stack_end = stack_top() - 8; + //socket_.cmd_builder() << "reg sp " << stack_end.cast_to(); + //socket_.SendCommand(); // Set a breakpoint at the beginning of `UTVMDone`. socket_.cmd_builder() << "bp " << ToDevPtr(breakpoint).cast_to() << " 2"; diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index f8d87189c251..cc4001f4c7b8 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -315,21 +315,22 @@ def test_inactive_session_use(): def test_arm_add(): """Test a module which performs addition.""" - import tvm + #import tvm if not tvm.module.enabled("micro_dev"): return shape = (1024,) dtype = "float32" - import subprocess - import os - import copy - from shutil import copyfile + #import subprocess + #import os + #import copy + #from shutil import copyfile - from tvm._ffi.libinfo import find_include_path - from tvm.micro import _get_micro_device_dir - from tvm.contrib import binutil + #from tvm._ffi.libinfo import find_include_path + #from tvm.micro import _get_micro_device_dir + #from tvm.contrib import binutil + print('constructing tvm expr') # Construct TVM expression. tvm_shape = tvm.convert(shape) A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) @@ -340,15 +341,35 @@ def test_arm_add(): func_name = "fadd" c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) + print('starting session') with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) as sess: + # TODO: since we're adding modules with `sess.add_module`, we're not + # creating micro modules (like below). how do we get packed funcs from + # the session though? we might need to do the enqueueing in C++ and + # call into a Python function that does all of the baking. If that's + # the case, then we'll need to create all of the micro mods we want, + # *then* call sess.bake, which should just execute the same Python code + # as in micro/base.py, but with a trip to C++ in between. + #micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + #micro_func = micro_mod[func_name] + sess.add_module(c_mod) + print('baking session') sess.bake() + print(f'grabbing {func_name} from session') + micro_func = sess.get_func(func_name) + print(f'grabbed it') - #ctx = tvm.micro_dev(0) - #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - #micro_func(a, b, c) + ctx = tvm.micro_dev(0) + a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + print(a) + print(b) + print(c) + micro_func(a, b, c) + print('--------------------------------------------------------------------------------') + print(c) #tvm.testing.assert_allclose( # c.asnumpy(), a.asnumpy() + b.asnumpy()) From 93e706856856d40b4ae1e9923b96185875352065 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 5 Oct 2019 20:11:58 -0700 Subject: [PATCH 03/70] GDB-driven execution works next stop: Tcl-driven --- python/tvm/micro/base.py | 4 + src/runtime/micro/micro_common.h | 3 +- src/runtime/micro/micro_session.cc | 93 ++++++++++++++++--- src/runtime/micro/openocd_low_level_device.cc | 2 +- .../micro/target_data_layout_encoder.h | 7 +- tests/python/unittest/test_runtime_micro.py | 6 ++ 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 3cfb318b0156..f513e38510e0 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -118,12 +118,16 @@ def bake(self): + op_srcs \ + runtime_src[split_idx:] \ # TODO: figure out how to prevent DCE from kicking in without creating dummy calls. + # TODO: splice `main` in *before* the end of the `extern C` block + "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n") print('writing src to main.c') nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" with open(f"{nucleo_path}/src/main.c", "w") as f: f.write(merged_src) + print('[BEGIN SRC]') + print(merged_src) + print('[END SRC]') paths = [path for path in find_include_path()] paths += ["/home/pratyush/Code/tvm/src/runtime/micro/device"] diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 5fc8fbcbf23c..669971e51f1d 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -53,7 +53,6 @@ enum class SectionKind : size_t { }; /*! \brief default size alignment */ -constexpr int kDefaultSizeAlignment = 8; /*! \brief Base class for interfacing with device locations (pointers/offsets) */ class DeviceLocation { @@ -314,7 +313,7 @@ std::string ReadSection(const std::string& binary, size_t GetSectionSize(const std::string& binary_name, SectionKind section, const std::string& toolchain_prefix, - size_t align = kDefaultSizeAlignment); + size_t align); } // namespace runtime } // namespace tvm diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 36df83b68d7c..b40b2ac7b41b 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,6 +57,9 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { + std::cout << "sizeof(TVMArray): " << sizeof(TVMArray) << std::endl; + std::cout << "sizeof(TVMValue): " << sizeof(TVMValue) << std::endl; + //DevBaseOffset curr_start_offset = kDeviceStart; //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { // size_t section_size = GetDefaultSectionSize(static_cast(i)); @@ -189,9 +192,16 @@ void MicroSession::BakeSession(const std::string& binary) { low_level_device()->Connect(); } +// ARM and other manufacturers use the LSB of a function address to determine +// whether it's a "thumb mode" function (TODO: figure out what that means). +const bool kRequiresThumbModeBit = true; void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { int32_t (*func_dev_addr)(void*, void*, int32_t) = reinterpret_cast(func_ptr.value()); + // TODO: make this a parameter. + if (kRequiresThumbModeBit) { + func_dev_addr += 1; + } // Create an allocator stream for the memory region after the most recent // allocation in the args section. @@ -207,16 +217,38 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { reinterpret_cast(encoder.data()), encoder.buf_size()); - UTVMTask task = { - .func = func_dev_addr, - .arg_values = std::get<0>(arg_field_addrs).cast_to(), - .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), - .num_args = args.num_args, + //UTVMTask task = { + // .func = func_dev_addr, + // .arg_values = std::get<0>(arg_field_addrs).cast_to(), + // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), + // .num_args = args.num_args, + //}; + typedef struct StructARMUTVMTask { + /*! \brief Pointer to function to call for this task */ + uint32_t func; + /*! \brief Array of argument values */ + uint32_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint32_t arg_type_codes; + /*! \brief Number of arguments */ + uint32_t num_args; + } ARMUTVMTask; + TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + ARMUTVMTask task = { + .func = *((uint32_t*) &func_dev_addr), + .arg_values = *((uint32_t*) &arg_values_dev_addr), + .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), + .num_args = (uint32_t) args.num_args, }; // Write the task. + std::cout << "utvm_task loc: " << GetSymbolLoc("utvm_task").value() << std::endl; DevSymbolWrite(symbol_map_, "utvm_task", task); - low_level_device()->Execute(utvm_main_symbol_, utvm_done_symbol_); + //low_level_device()->Execute(utvm_main_symbol_, utvm_done_symbol_); + std::cout << "do execution things: "; + char tmp; + std::cin >> tmp; // Check if there was an error during execution. If so, log it. CheckDeviceError(); @@ -267,7 +299,20 @@ std::tuple MicroSession::EncoderAppend( } DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { - auto tvm_arr_slot = encoder->Alloc(); + typedef struct StructARMTVMArray { + uint32_t data; + DLContext ctx; + int ndim; + DLDataType dtype; + uint32_t shape; + uint32_t strides; + uint32_t pad1; + uint32_t byte_offset; + uint32_t pad2; + } ARMTVMArray; + + //auto tvm_arr_slot = encoder->Alloc(); + auto tvm_arr_slot = encoder->Alloc(); auto shape_slot = encoder->Alloc(arr.ndim); // `shape` and `strides` are stored on the host, so we need to write them to @@ -282,9 +327,33 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr strides_addr = stride_slot.start_addr(); } + int64_t* dev_shape = shape_addr.cast_to(); + int64_t* dev_strides = strides_addr.cast_to(); + std::cout << "writing byte_offset " << arr.byte_offset << std::endl; + ARMTVMArray dev_arr = { + .data = *((uint32_t*) &arr.data), + .ctx = arr.ctx, + .ndim = arr.ndim, + .dtype = arr.dtype, + .shape = *((uint32_t*) &dev_shape), + .strides = *((uint32_t*) &dev_strides), + .pad1 = 0, + .byte_offset = *((uint32_t*) &arr.byte_offset), + .pad2 = 0, + }; + + std::cout << "sizeof(ARMTVMArray): " << sizeof(ARMTVMArray) << std::endl; + std::cout << "data offs: " << (((uintptr_t) &(dev_arr.data)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "ctx offs: " << (((uintptr_t) &(dev_arr.ctx)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "ndim offs: " << (((uintptr_t) &(dev_arr.ndim)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "dtype offs: " << (((uintptr_t) &(dev_arr.dtype)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "strides offs: " << (((uintptr_t) &(dev_arr.strides)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "byte_offset offs: " << (((uintptr_t) &(dev_arr.byte_offset)) - ((uintptr_t) &dev_arr)) << std::endl; + + // Copy `arr`, update the copy's pointers to be device pointers, then // write the copy to `tvm_arr_slot`. - TVMArray dev_arr = arr; + //TVMArray dev_arr = arr; // Update the device type to look like a host, because codegen generates // checks that it is a host array. CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) @@ -292,10 +361,10 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr dev_arr.ctx.device_type = DLDeviceType::kDLCPU; // Add the base address of the device to the array's data's device offset to // get a device address. - DevBaseOffset arr_offset(reinterpret_cast(arr.data)); - dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); - dev_arr.shape = shape_addr.cast_to(); - dev_arr.strides = strides_addr.cast_to(); + //DevBaseOffset arr_offset(reinterpret_cast(arr.data)); + //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); + //dev_arr.shape = shape_addr.cast_to(); + //dev_arr.strides = strides_addr.cast_to(); tvm_arr_slot.WriteValue(dev_arr); return tvm_arr_slot.start_addr(); } diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 08af32bcbe94..6488df47f9da 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -52,7 +52,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { void Connect() { socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); - socket_.cmd_builder() << "reset ahalt"; + socket_.cmd_builder() << "reset halt"; socket_.SendCommand(); } diff --git a/src/runtime/micro/target_data_layout_encoder.h b/src/runtime/micro/target_data_layout_encoder.h index a5b649bd131f..d78ec7cc8187 100644 --- a/src/runtime/micro/target_data_layout_encoder.h +++ b/src/runtime/micro/target_data_layout_encoder.h @@ -32,6 +32,9 @@ namespace runtime { // TODO(weberlo): Handle endianness. +// TODO: make this parameterizable +static const int kWordSize = 4; + /*! * \brief data encoder for uTVM that builds a host-side buffer */ @@ -98,7 +101,7 @@ class TargetDataLayoutEncoder { */ explicit TargetDataLayoutEncoder(DevPtr start_addr) : buf_(std::vector()), curr_offset_(0) { - start_addr_ = DevPtr(UpperAlignValue(start_addr.value(), 8)); + start_addr_ = DevPtr(UpperAlignValue(start_addr.value(), kWordSize)); } /*! @@ -108,7 +111,7 @@ class TargetDataLayoutEncoder { */ template Slot Alloc(size_t num_elems = 1) { - curr_offset_ = UpperAlignValue(curr_offset_, 8); + curr_offset_ = UpperAlignValue(curr_offset_, kWordSize); size_t size = sizeof(T) * num_elems; if (curr_offset_ + size > buf_.size()) { buf_.resize(curr_offset_ + size); diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index cc4001f4c7b8..7e2e5b590845 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -367,10 +367,16 @@ def test_arm_add(): print(a) print(b) print(c) + # TODO: the fadd example is leaving the C vector with all zeros. the + # device must not be executing the fadd. do a GDB stepthrough. could + # also try loading in the original blinky program (or some slight + # variant of it) to see if we're loading shit onto the device + # correctly. micro_func(a, b, c) print('--------------------------------------------------------------------------------') print(c) + #tvm.testing.assert_allclose( # c.asnumpy(), a.asnumpy() + b.asnumpy()) From cbce8e0e104d3ed2244efdeb72d9cf3d3f6db43d Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 5 Oct 2019 20:27:19 -0700 Subject: [PATCH 04/70] fadd works! --- src/runtime/micro/micro_session.cc | 14 +++++++++---- src/runtime/micro/openocd_low_level_device.cc | 20 ++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index b40b2ac7b41b..2d2ae2e3eae6 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -245,10 +245,16 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "utvm_task loc: " << GetSymbolLoc("utvm_task").value() << std::endl; DevSymbolWrite(symbol_map_, "utvm_task", task); - //low_level_device()->Execute(utvm_main_symbol_, utvm_done_symbol_); - std::cout << "do execution things: "; - char tmp; - std::cin >> tmp; + DevBaseOffset utvm_main_loc = DevBaseOffset(GetSymbolLoc("UTVMMain").value()); + DevBaseOffset utvm_done_loc = DevBaseOffset(GetSymbolLoc("UTVMDone").value()); + if (kRequiresThumbModeBit) { + utvm_main_loc += 1; + } + low_level_device()->Execute(utvm_main_loc, utvm_done_loc); + + //std::cout << "do execution things: "; + //char tmp; + //std::cin >> tmp; // Check if there was an error during execution. If so, log it. CheckDeviceError(); diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 6488df47f9da..0eb47e63a24a 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -44,16 +44,22 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { explicit OpenOCDLowLevelDevice(std::uintptr_t base_addr, const std::string& server_addr, int port) : socket_() { - server_addr_ = server_addr; - port_ = port; - base_addr_ = base_addr; - CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; + server_addr_ = server_addr; + port_ = port; + base_addr_ = base_addr; + CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; } void Connect() { - socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); - socket_.cmd_builder() << "reset halt"; - socket_.SendCommand(); + socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); + + // run through system init once + socket_.cmd_builder() << "reset run"; + socket_.SendCommand(); + socket_.cmd_builder() << "wait_halt " << kWaitTime; + socket_.SendCommand(); + socket_.cmd_builder() << "halt 0"; + socket_.SendCommand(); } void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { From c6f6f2b5275c217239bba3353217eca84c00fee9 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sun, 6 Oct 2019 20:40:02 -0700 Subject: [PATCH 05/70] RAM-only fadd works --- python/tvm/micro/base.py | 3 +-- src/runtime/micro/openocd_low_level_device.cc | 10 ++++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index f513e38510e0..640bfdae8094 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -136,7 +136,7 @@ def bake(self): print('flashing to device') proc = subprocess.Popen( - ["make", "flash"], + ["make", "blinky.elf"], cwd=nucleo_path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -168,7 +168,6 @@ def bake(self): #print('TVMAPISetLastError: ' + sym_map['TVMAPISetLastError']) # TODO: we might need to start OpenOCD in a separate process - input('start openocd! ') # wait until the server has started up until attempting to connect in C++ #openocd_script_dir = '/usr/share/openocd/scripts' #cmd = [ diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 0eb47e63a24a..d0d179161173 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -52,14 +52,12 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { void Connect() { socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); - - // run through system init once - socket_.cmd_builder() << "reset run"; - socket_.SendCommand(); - socket_.cmd_builder() << "wait_halt " << kWaitTime; + socket_.cmd_builder() << "halt"; socket_.SendCommand(); - socket_.cmd_builder() << "halt 0"; + std::cout << "LOADING BINARY" << std::endl; + socket_.cmd_builder() << "load_image /home/pratyush/Code/nucleo-interaction-from-scratch/blinky.elf"; socket_.SendCommand(); + std::cout << "FINISHED LOADING BINARY" << std::endl; } void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { From a9f173677f49ddc354570e5a2e74eeb807c45dd1 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 8 Oct 2019 12:47:41 -0700 Subject: [PATCH 06/70] Remove unnecessary include --- python/tvm/micro/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 640bfdae8094..ac49a4207146 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -114,7 +114,6 @@ def bake(self): include_str = "#include \"utvm_runtime.h\"" split_idx = runtime_src.index(include_str) + len(include_str) + 2 merged_src = (runtime_src[:split_idx] \ - + "#include \"stm32f7xx_nucleo_144.h\"\n" \ + op_srcs \ + runtime_src[split_idx:] \ # TODO: figure out how to prevent DCE from kicking in without creating dummy calls. From bc87f1875eac564976139a49b4b108270a14e428 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 11 Oct 2019 17:21:18 -0700 Subject: [PATCH 07/70] TEMP --- python/tvm/micro/base.py | 109 +++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index ac49a4207146..cbe60e134af3 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -88,9 +88,6 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): self._exit = self.module["exit"] print('finished session init') - def add_module(self, c_mod): - self.op_modules.append(c_mod) - def bake(self): import subprocess import os @@ -111,14 +108,7 @@ def bake(self): with open(runtime_src_path) as f: runtime_src = f.read() - include_str = "#include \"utvm_runtime.h\"" - split_idx = runtime_src.index(include_str) + len(include_str) + 2 - merged_src = (runtime_src[:split_idx] \ - + op_srcs \ - + runtime_src[split_idx:] \ - # TODO: figure out how to prevent DCE from kicking in without creating dummy calls. - # TODO: splice `main` in *before* the end of the `extern C` block - + "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n") + merged_src = self.gen_merged_src(runtime_src, op_srcs) print('writing src to main.c') nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" @@ -133,7 +123,7 @@ def bake(self): child_env = copy.deepcopy(os.environ) child_env["LD_LIBRARY_PATH"] += ":" + ":".join(paths) - print('flashing to device') + print('compiling bin') proc = subprocess.Popen( ["make", "blinky.elf"], cwd=nucleo_path, @@ -150,46 +140,65 @@ def bake(self): with open(result_binary_path, "rb") as f: result_binary_contents = bytearray(f.read()) - #sym_map_str = binutil.tvm_callback_get_symbol_map(result_binary_contents, self.toolchain_prefix) - #sym_map_lines = list(filter(lambda s: len(s) != 0, sym_map_str.split('\n'))) - - #sym_map_iter = iter(sym_map_lines) - #sym_map = {} - #for sym_name in sym_map_iter: - # sym_loc = next(sym_map_iter) - # sym_map[sym_name] = sym_loc - - #print('UTVMMain: ' + sym_map['UTVMMain']) - #print('UTVMDone: ' + sym_map['UTVMDone']) - #print('fadd: ' + sym_map['fadd']) - #print('TVMBackendAllocWorkspace: ' + sym_map['TVMBackendAllocWorkspace']) - #print('TVMBackendFreeWorkspace: ' + sym_map['TVMBackendFreeWorkspace']) - #print('TVMAPISetLastError: ' + sym_map['TVMAPISetLastError']) - - # TODO: we might need to start OpenOCD in a separate process - # wait until the server has started up until attempting to connect in C++ - #openocd_script_dir = '/usr/share/openocd/scripts' - #cmd = [ - # 'openocd', - # '-f', f'{openocd_script_dir}/interface/stlink-v2-1.cfg', - # '-f', f'{openocd_script_dir}/target/stm32f7x.cfg' - #] - #self.openocd_process = subprocess.Popen( - # cmd, - # stdout=subprocess.PIPE, - # stderr=subprocess.STDOUT) - #print('waiting for OpenOCD to start up') - #while True: - # output = self.openocd_process.stdout.readline() - # if 'stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints' in output.decode('utf-8'): - # break - # if output: - # print(output.strip()) - # rc = self.openocd_process.poll() - #print('finished starting up') - _BakeSession(result_binary_contents); + def add_module(self, c_mod): + self.op_modules.append(c_mod) + + def gen_merged_src(self, runtime_src, op_srcs): + include_str = "#include \"utvm_runtime.h\"" + split_idx = runtime_src.index(include_str) + len(include_str) + 2 + merged_src = runtime_src[:split_idx] + op_srcs + runtime_src[split_idx:] + merged_src += "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n" + + return merged_src + + #print(merged_src) + #print('--------------------------------------------------------------------------------') + + ## TODO: figure out how to prevent DCE from kicking in without creating dummy calls. + ## TODO: splice `main` in *before* the end of the `extern C` block + #import re + #func_regex = re.compile(r' *(TVM_DLL)? *(int|int32_t|void|void\*|const char\*) *([a-zA-Z0-9_]+) *\((.*)\) *{? *') + #matches = [] + #for line in merged_src.split('\n'): + # match = func_regex.match(line) + # if match is not None: + # func_name = match.group(3) + # args = match.group(4) + # matches.append((func_name, args)) + + #method_calls = [] + #for func_name, args in matches: + # call_args = [] + # args = args.strip() + # if len(args) != 0: + # args = list(map(lambda s: s.strip(), args.split(','))) + # for arg in args: + # if arg.startswith('const char*'): + # call_args.append('NULL') + # elif arg.startswith('void*'): + # call_args.append('NULL') + # elif arg.startswith('int32_t'): + # call_args.append('0') + # elif arg.startswith('int'): + # call_args.append('0') + # else: + # raise RuntimeError('ayy lmao') + # call_args = ','.join(call_args) + # method_calls.append(f'{func_name}({call_args});') + #print(method_calls) + #print('--------------------------------------------------------------------------------') + #input('look at dat source') + #return merged_src + + def extract_method_sigs(self, merged_src): + #for line in merged_src.split('\n'): + # if line.startswith('TVM_DLL'): + # line = line[len('TVM_DLL'):] + # print(line) + pass + def get_func(self, func_name): return _GetFunction(func_name); From bbffe9586944e703953d639e6c0f78913284d65c Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 14 Oct 2019 19:34:47 -0700 Subject: [PATCH 08/70] compiling as obj instead of shared actually relocating the binary now --- python/tvm/contrib/binutil.py | 111 +++- python/tvm/micro/base.py | 87 ++- src/runtime/micro/2 | 622 ++++++++++++++++++ .../micro/device/UTVM_STM32F746ZGTx_FLASH.ld | 89 +++ .../micro/device/utvm_startup_stm32f767xx.s | 75 +++ .../utvm_device_dylib_redirect.c | 0 .../{device => host_driven}/utvm_runtime.c | 7 +- .../{device => host_driven}/utvm_runtime.h | 0 src/runtime/micro/host_low_level_device.cc | 2 - src/runtime/micro/low_level_device.h | 2 - src/runtime/micro/micro_session.cc | 140 +++- src/runtime/micro/micro_session.h | 6 +- src/runtime/micro/openocd_low_level_device.cc | 7 +- .../micro/target_data_layout_encoder.h | 2 +- 14 files changed, 1087 insertions(+), 63 deletions(-) create mode 100644 src/runtime/micro/2 create mode 100644 src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld create mode 100644 src/runtime/micro/device/utvm_startup_stm32f767xx.s rename src/runtime/micro/{device => host_driven}/utvm_device_dylib_redirect.c (100%) rename src/runtime/micro/{device => host_driven}/utvm_runtime.c (96%) rename src/runtime/micro/{device => host_driven}/utvm_runtime.h (100%) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index a323272c6a73..6fde7447f913 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -74,8 +74,10 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): continue entry_name = tokens[0] entry_size = int(tokens[1]) - if entry_name in sections_to_sum: - section_size += entry_size + for section_name in sections_to_sum: + if entry_name.startswith(section_name): + section_size += entry_size + break # NOTE: For some reason, the size of the BSS section on the RISC-V # GCC is sometimes reported to be smaller than it is, so we need to adjust @@ -126,56 +128,125 @@ def tvm_callback_relocate_binary( 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" + #rel_obj_path = tmp_dir.relpath("relocated.o") + rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_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" + print(f'binary path: {binary_path}') + # TODO(weberlo): Generate the script in a more procedural manner. - ld_script_contents += """ + ld_script_contents = """ +/* Highest address of the user mode stack */ +_estack = 0x20050000; /* end of RAM */ + +/* Specify the memory areas */ +/* +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} +*/ + +/* Define output sections */ SECTIONS { . = %s; - . = ALIGN(8); + . = ALIGN(4); .text : { + . = ALIGN(4); *(.text) - . = ALIGN(8); *(.text*) + . = ALIGN(4); } + . = %s; - . = ALIGN(8); + . = ALIGN(4); .rodata : { + . = ALIGN(4); *(.rodata) - . = ALIGN(8); *(.rodata*) + . = ALIGN(4); } + . = %s; - . = ALIGN(8); + . = ALIGN(4); .data : { + . = ALIGN(4); *(.data) - . = ALIGN(8); *(.data*) - . = ALIGN(8); - *(.sdata) + . = ALIGN(4); } + . = %s; - . = ALIGN(8); + . = ALIGN(4); .bss : { + . = ALIGN(4); *(.bss) - . = ALIGN(8); *(.bss*) - . = ALIGN(8); - *(.sbss) + . = ALIGN(4); } } """ % (text_addr, rodata_addr, data_addr, bss_addr) + + print(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) rel_ld_script_path = tmp_dir.relpath("relocated.lds") with open(rel_ld_script_path, "w") as f: f.write(ld_script_contents) + ld_cmd = ' '.join(["{}ld".format(toolchain_prefix), binary_path, + "-T", rel_ld_script_path, + "-o", rel_obj_path]) + print(f'runnin ld cmd: {ld_cmd}') ld_proc = subprocess.Popen(["{}ld".format(toolchain_prefix), binary_path, "-T", rel_ld_script_path, "-o", rel_obj_path], diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index cbe60e134af3..532febef188e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -119,28 +119,93 @@ def bake(self): print('[END SRC]') paths = [path for path in find_include_path()] - paths += ["/home/pratyush/Code/tvm/src/runtime/micro/device"] - child_env = copy.deepcopy(os.environ) - child_env["LD_LIBRARY_PATH"] += ":" + ":".join(paths) + #print(paths) + #input() + #paths += ["/home/pratyush/Code/tvm/src/runtime/micro/host_driven"] + paths += [_get_micro_device_dir()] print('compiling bin') + compile_cmd = [ + 'arm-none-eabi-gcc', + 'src/main.o', + '-static', + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-Wl,--gc-sections', + '-Wl,--print-gc-sections', + '-Wl,--cref,-Map=blinky.map', + '-c', + '-L', + '.', + '-T', + 'UTVM_STM32F746ZGTx_FLASH.ld', + '-o', + 'blinky.elf' + ] proc = subprocess.Popen( - ["make", "blinky.elf"], + ['make', 'clean'], cwd=nucleo_path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (out, _) = proc.communicate() + if proc.returncode != 0: + msg = "Compilation error:\n" + msg += out.decode("utf-8") + raise RuntimeError(msg) + proc = subprocess.Popen( + ['make', 'blinky.elf'], + cwd=nucleo_path, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + + + #['arm-none-eabi-gcc', + # '-std=c11', + # '-Wall', + # '-Wextra', + # '--pedantic', + # '-Wa,-aghlms=src/main.lst', + # '-fstack-usage', + # '-mcpu=cortex-m7', + # '-mlittle-endian', + # '-mfloat-abi=hard', + # '-mfpu=fpv5-sp-d16', + # '-O0', + # '-g', + # '-gdwarf-5', + # '-nostartfiles', + # '-nodefaultlibs', + # '-nostdlib', + # '-fdata-sections', + # '-ffunction-sections', + # '-I', 'src', + # '-I', '/home/pratyush/Code/tvm/include', + # '-I', '/home/pratyush/Code/tvm/3rdparty/dlpack/include', + # '-I', '/home/pratyush/Code/tvm/src/runtime/micro/device', + # '-c', + # '-o', 'src/main.o', + # 'src/main.c'] + #proc = subprocess.Popen( + # ['arm-none-eabi-gcc',], + # cwd=nucleo_path, + # stdout=subprocess.PIPE, + # stderr=subprocess.STDOUT) + (out, _) = proc.communicate() if proc.returncode != 0: msg = "Compilation error:\n" msg += out.decode("utf-8") raise RuntimeError(msg) print('finished') - result_binary_path = f"{nucleo_path}/blinky.elf" - with open(result_binary_path, "rb") as f: - result_binary_contents = bytearray(f.read()) + #result_binary_path = f"{nucleo_path}/blinky.elf" + #with open(result_binary_path, "rb") as f: + # result_binary_contents = bytearray(f.read()) + #_BakeSession(result_binary_contents); - _BakeSession(result_binary_contents); + result_binary_path = f"{nucleo_path}/src/main.o" + _BakeSession(result_binary_path); def add_module(self, c_mod): self.op_modules.append(c_mod) @@ -149,7 +214,7 @@ def gen_merged_src(self, runtime_src, op_srcs): include_str = "#include \"utvm_runtime.h\"" split_idx = runtime_src.index(include_str) + len(include_str) + 2 merged_src = runtime_src[:split_idx] + op_srcs + runtime_src[split_idx:] - merged_src += "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n" + #merged_src += "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n" return merged_src @@ -233,7 +298,7 @@ def __exit__(self, exc_type, exc_value, exc_traceback): def _get_micro_device_dir(): - """Get directory path for uTVM runtime source files. + """Get directory path for uTVM host-driven runtime source files. Return ------ @@ -242,7 +307,7 @@ def _get_micro_device_dir(): """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) micro_device_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "device") + "src", "runtime", "micro", "host_driven") return micro_device_dir diff --git a/src/runtime/micro/2 b/src/runtime/micro/2 new file mode 100644 index 000000000000..9fed326ebdae --- /dev/null +++ b/src/runtime/micro/2 @@ -0,0 +1,622 @@ +/* + * 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. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file micro_session.cc + */ + +#include +#include +#include +#include +#include +#include +#include "micro_session.h" +#include "low_level_device.h" +#include "target_data_layout_encoder.h" + +namespace tvm { +namespace runtime { + +struct TVMMicroSessionThreadLocalEntry { + std::stack> session_stack; +}; + +typedef dmlc::ThreadLocalStore TVMMicroSessionThreadLocalStore; + +std::shared_ptr& MicroSession::Current() { + TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); + CHECK_GT(entry->session_stack.size(), 0) << "No current session"; + return entry->session_stack.top(); +} + +void MicroSession::EnterWithScope(std::shared_ptr session) { + TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); + entry->session_stack.push(session); +} + +void MicroSession::ExitWithScope() { + TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); + CHECK(!entry->session_stack.empty()); + entry->session_stack.pop(); +} + +MicroSession::MicroSession() { + //DevBaseOffset curr_start_offset = kDeviceStart; + //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + // size_t section_size = GetDefaultSectionSize(static_cast(i)); + // section_allocators_[i] = std::make_shared(DevMemRegion { + // .start = curr_start_offset, + // .size = section_size, + // }); + // curr_start_offset += section_size; + //} + //memory_size_ = curr_start_offset.cast_to(); + + /* Linker script sample + * #if !defined(MBED_APP_START) + * #define MBED_APP_START 0x08000000 + * #endif + * + * #if !defined(MBED_APP_SIZE) + * #define MBED_APP_SIZE 1024K + * #endif + * + * MEMORY + * { + * FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE + * RAM (rwx) : ORIGIN = 0x200001C8, LENGTH = 320K - 0x1C8 + * } + */ + + /* + size_t half_flash_size = 512000; // 0.5 MB + DevBaseOffset curr_start_offset = DevBaseOffset(0x08000000); + section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = half_flash_size, + }); + curr_start_offset += half_flash_size; + section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = half_flash_size, + }); + curr_start_offset += half_flash_size; + + curr_start_offset = DevBaseOffset(0x200001C8); + size_t one_sixth_ram_size = 53256; + section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_sixth_ram_size, + }); + curr_start_offset += one_sixth_ram_size; + + memory_size_ = 0; + */ + + // TODO: why do we need to start 0x1c8 bytes after the start of ram? + //curr_start_offset = DevBaseOffset(0x200001C8); + DevBaseOffset curr_start_offset = DevBaseOffset(0x20000000); + size_t one_eighth_ram_size = 40000; + section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + + // NOTE: we don't use this for openocd + memory_size_ = 0; +} + +MicroSession::~MicroSession() { + for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + section_allocators_[i] = nullptr; + } + low_level_device_ = nullptr; +} + +void MicroSession::CreateSession(const std::string& device_type, + const std::string& binary_path, + const std::string& toolchain_prefix, + std::uintptr_t base_addr, + const std::string& server_addr, + int port) { + // TODO(weberlo): make device type enum + toolchain_prefix_ = toolchain_prefix; + if (device_type == "host") { + low_level_device_ = HostLowLevelDeviceCreate(memory_size_); + } else if (device_type == "openocd") { + // TODO(weberlo): We need a better way of configuring devices. + low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); + } else { + LOG(FATAL) << "unsupported micro low-level device"; + } + + //CHECK(!binary_path.empty()) << "uTVM runtime not initialized"; + //runtime_bin_info_ = LoadBinary(binary_path, /* patch_dylib_pointers */ false); + //utvm_main_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMMain"]); + //utvm_done_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMDone"]); + + //if (device_type == "openocd") { + // // Set OpenOCD device's stack pointer. + // auto stack_section = GetAllocator(SectionKind::kStack); + // low_level_device_->SetStackTop(stack_section->max_end_offset()); + //} + + // Patch workspace pointers to the start of the workspace section. + //DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); + //DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); + //void* workspace_start_addr = + // low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); + //void* workspace_end_addr = + // low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); + // TODO(weberlo): A lot of these symbol writes can be converted into symbols + // in the C source, where the symbols are created by the linker script we + // generate in python. + //DevSymbolWrite(symbol_map_, "utvm_workspace_begin", workspace_start_addr); + //DevSymbolWrite(symbol_map_, "utvm_workspace_end", workspace_end_addr); +} + +void MicroSession::BakeSession(const std::string& binary_path) { + //symbol_map_ = SymbolMap(binary, toolchain_prefix_); + symbol_map_ = LoadBinary(binary_path, false).symbol_map; + std::cout << symbol_map_["UTVMMain"].value() << std::endl; + std::cout << symbol_map_["utvm_task"].value() << std::endl; +} + +// ARM and other manufacturers use the LSB of a function address to determine +// whether it's a "thumb mode" function (TODO: figure out what that means). +const bool kRequiresThumbModeBit = true; +void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { + int32_t (*func_dev_addr)(void*, void*, int32_t) = + reinterpret_cast(func_ptr.value()); + // TODO: make this a parameter. + if (kRequiresThumbModeBit) { + func_dev_addr += 1; + } + + // Create an allocator stream for the memory region after the most recent + // allocation in the args section. + DevPtr args_addr = + low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); + TargetDataLayoutEncoder encoder(args_addr); + + std::tuple arg_field_addrs = EncoderAppend(&encoder, args); + // Flush `stream` to device memory. + DevBaseOffset stream_dev_offset = + GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); + low_level_device()->Write(stream_dev_offset, + reinterpret_cast(encoder.data()), + encoder.buf_size()); + + //UTVMTask task = { + // .func = func_dev_addr, + // .arg_values = std::get<0>(arg_field_addrs).cast_to(), + // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), + // .num_args = args.num_args, + //}; + typedef struct StructARMUTVMTask { + /*! \brief Pointer to function to call for this task */ + uint32_t func; + /*! \brief Array of argument values */ + uint32_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint32_t arg_type_codes; + /*! \brief Number of arguments */ + uint32_t num_args; + } ARMUTVMTask; + TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + ARMUTVMTask task = { + .func = *((uint32_t*) &func_dev_addr), + .arg_values = *((uint32_t*) &arg_values_dev_addr), + .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), + .num_args = (uint32_t) args.num_args, + }; + // Write the task. + DevSymbolWrite(symbol_map_, "utvm_task", task); + + DevBaseOffset utvm_main_loc = DevBaseOffset(GetSymbolLoc("UTVMMain").value()); + DevBaseOffset utvm_done_loc = DevBaseOffset(GetSymbolLoc("UTVMDone").value()); + if (kRequiresThumbModeBit) { + utvm_main_loc += 1; + } + + // TODO: figure out why it's not running anymore when we compile it with "-c" + // instead of "-shared". we should be relocating the binary. + std::cout << "do execution things: "; + char tmp; + std::cin >> tmp; + //low_level_device()->Execute(utvm_main_loc, utvm_done_loc); + + // Check if there was an error during execution. If so, log it. + CheckDeviceError(); + + GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); +} + +BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { + DevMemRegion text_section; + DevMemRegion rodata_section; + DevMemRegion data_section; + DevMemRegion bss_section; + + text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, kWordSize); + rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, kWordSize); + data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, kWordSize); + bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, kWordSize); + + text_section.start = AllocateInSection(SectionKind::kText, text_section.size); + rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); + data_section.start = AllocateInSection(SectionKind::kData, data_section.size); + bss_section.start = AllocateInSection(SectionKind::kBss, bss_section.size); + CHECK(text_section.start != nullptr && rodata_section.start != nullptr && + data_section.start != nullptr && bss_section.start != nullptr) + << "not enough space to load module on device"; + + std::cout << "text start: " << text_section.start << std::endl; + std::cout << "rodata start: " << rodata_section.start << std::endl; + std::cout << "data start: " << data_section.start << std::endl; + std::cout << "bss start: " << bss_section.start << std::endl; + std::string relocated_bin = RelocateBinarySections( + binary_path, + low_level_device_->ToDevPtr(text_section.start), + low_level_device_->ToDevPtr(rodata_section.start), + low_level_device_->ToDevPtr(data_section.start), + low_level_device_->ToDevPtr(bss_section.start), + toolchain_prefix_); + std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); + std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); + std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); + std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); + low_level_device_->Write(text_section.start, &text_contents[0], text_section.size); + low_level_device_->Write(rodata_section.start, &rodata_contents[0], rodata_section.size); + low_level_device_->Write(data_section.start, &data_contents[0], data_section.size); + low_level_device_->Write(bss_section.start, &bss_contents[0], bss_section.size); + SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; + + if (patch_dylib_pointers) { + // Patch device lib pointers. + PatchImplHole(symbol_map, "TVMBackendAllocWorkspace"); + PatchImplHole(symbol_map, "TVMBackendFreeWorkspace"); + PatchImplHole(symbol_map, "TVMAPISetLastError"); + } + + return BinaryInfo { + .text_section = text_section, + .rodata_section = rodata_section, + .data_section = data_section, + .bss_section = bss_section, + .symbol_map = symbol_map, + }; +} + +std::tuple MicroSession::EncoderAppend( + TargetDataLayoutEncoder* encoder, const TVMArgs& args) { + const int* type_codes = args.type_codes; + int num_args = args.num_args; + + auto tvm_vals_slot = encoder->Alloc(num_args); + auto type_codes_slot = encoder->Alloc(num_args); + + for (int i = 0; i < num_args; i++) { + switch (type_codes[i]) { + case kNDArrayContainer: + case kArrayHandle: { + TVMArray* base_arr_handle = args[i]; + // All uTVM arrays store a `MicroDevSpace` struct in their `data` field, + // which wraps the actual data and stores a reference to the session, in + // order to prevent premature session destruction. + void* old_data = base_arr_handle->data; + // Mutate the array to unwrap the `data` field. + base_arr_handle->data = reinterpret_cast(old_data)->data; + // Now, encode the unwrapped version. + void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + // And restore the original wrapped version. + base_arr_handle->data = old_data; + + TVMValue val; + val.v_handle = arr_ptr; + tvm_vals_slot.WriteValue(val); + break; + } + // TODO(weberlo): Implement `double` and `int64` case. + case kDLFloat: + case kDLInt: + case kDLUInt: + default: + LOG(FATAL) << "unsupported type code for writing args: " << type_codes[i]; + break; + } + } + type_codes_slot.WriteArray(type_codes, num_args); + + return std::make_tuple(tvm_vals_slot.start_addr(), type_codes_slot.start_addr()); +} + +DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { + typedef struct StructARMTVMArray { + uint32_t data; + DLContext ctx; + int ndim; + DLDataType dtype; + uint32_t shape; + uint32_t strides; + uint32_t pad1; + uint32_t byte_offset; + uint32_t pad2; + } ARMTVMArray; + + //auto tvm_arr_slot = encoder->Alloc(); + auto tvm_arr_slot = encoder->Alloc(); + auto shape_slot = encoder->Alloc(arr.ndim); + + // `shape` and `strides` are stored on the host, so we need to write them to + // the device first. The `data` field is already allocated on the device and + // is a device pointer, so we don't need to write it. + shape_slot.WriteArray(arr.shape, arr.ndim); + DevPtr shape_addr = shape_slot.start_addr(); + DevPtr strides_addr = DevPtr(nullptr); + if (arr.strides != nullptr) { + auto stride_slot = encoder->Alloc(arr.ndim); + stride_slot.WriteArray(arr.strides, arr.ndim); + strides_addr = stride_slot.start_addr(); + } + + int64_t* dev_shape = shape_addr.cast_to(); + int64_t* dev_strides = strides_addr.cast_to(); + std::cout << "writing byte_offset " << arr.byte_offset << std::endl; + ARMTVMArray dev_arr = { + .data = *((uint32_t*) &arr.data), + .ctx = arr.ctx, + .ndim = arr.ndim, + .dtype = arr.dtype, + .shape = *((uint32_t*) &dev_shape), + .strides = *((uint32_t*) &dev_strides), + .pad1 = 0, + .byte_offset = *((uint32_t*) &arr.byte_offset), + .pad2 = 0, + }; + + std::cout << "sizeof(ARMTVMArray): " << sizeof(ARMTVMArray) << std::endl; + std::cout << "data offs: " << (((uintptr_t) &(dev_arr.data)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "ctx offs: " << (((uintptr_t) &(dev_arr.ctx)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "ndim offs: " << (((uintptr_t) &(dev_arr.ndim)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "dtype offs: " << (((uintptr_t) &(dev_arr.dtype)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "strides offs: " << (((uintptr_t) &(dev_arr.strides)) - ((uintptr_t) &dev_arr)) << std::endl; + std::cout << "byte_offset offs: " << (((uintptr_t) &(dev_arr.byte_offset)) - ((uintptr_t) &dev_arr)) << std::endl; + + + // Copy `arr`, update the copy's pointers to be device pointers, then + // write the copy to `tvm_arr_slot`. + //TVMArray dev_arr = arr; + // Update the device type to look like a host, because codegen generates + // checks that it is a host array. + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) + << "attempt to write TVMArray with non-micro device type"; + dev_arr.ctx.device_type = DLDeviceType::kDLCPU; + // Add the base address of the device to the array's data's device offset to + // get a device address. + //DevBaseOffset arr_offset(reinterpret_cast(arr.data)); + //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); + //dev_arr.shape = shape_addr.cast_to(); + //dev_arr.strides = strides_addr.cast_to(); + tvm_arr_slot.WriteValue(dev_arr); + return tvm_arr_slot.start_addr(); +} + +void MicroSession::CheckDeviceError() { + int32_t return_code = DevSymbolRead(symbol_map_, "utvm_return_code"); + + if (return_code) { + std::uintptr_t last_error = + DevSymbolRead(symbol_map_, "utvm_last_error"); + std::string last_error_str; + if (last_error) { + DevBaseOffset last_err_offset = low_level_device()->ToDevOffset(DevPtr(last_error)); + last_error_str = ReadString(last_err_offset); + } + LOG(FATAL) << "error during micro function execution:\n" + << " return code: " << std::dec << return_code << "\n" + << " dev str addr: 0x" << std::hex << last_error << "\n" + << " dev str data: " << last_error_str << std::endl; + } +} + +void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { + void* runtime_impl_addr = symbol_map_[func_name].cast_to(); + std::ostringstream func_name_underscore; + func_name_underscore << func_name << "_"; + DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); +} + +std::string MicroSession::ReadString(DevBaseOffset str_offset) { + std::ostringstream result; + const size_t buf_size = 256; + std::vector buf(buf_size, 0); + size_t i = buf_size; + while (i == buf_size) { + low_level_device()->Read(str_offset, buf.data(), buf_size); + i = 0; + while (i < buf_size) { + if (buf[i] == 0) break; + result << buf[i]; + i++; + } + str_offset = str_offset + i; + } + return result.str(); +} + +DevBaseOffset MicroSession::AllocateInSection(SectionKind type, size_t size) { + return GetAllocator(type)->Allocate(size); +} + +void MicroSession::FreeInSection(SectionKind type, DevBaseOffset ptr) { + return GetAllocator(type)->Free(ptr); +} + +template +T MicroSession::DevSymbolRead(const SymbolMap& symbol_map, const std::string& symbol) { + DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); + T result; + low_level_device()->Read(sym_offset, &result, sizeof(T)); + return result; +} + +template +void MicroSession::DevSymbolWrite(const SymbolMap& symbol_map, + const std::string& symbol, + const T& value) { + DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); + low_level_device()->Write(sym_offset, &value, sizeof(T)); +} + +PackedFunc MicroSession::GetFunction( + const std::string& name, + const std::shared_ptr& sptr_to_self) { + if (name == "enter") { + return PackedFunc([sptr_to_self](TVMArgs args, TVMRetValue* rv) { + MicroSession::EnterWithScope(std::dynamic_pointer_cast(sptr_to_self)); + }); + } else if (name == "exit") { + return PackedFunc([sptr_to_self](TVMArgs args, TVMRetValue* rv) { + MicroSession::ExitWithScope(); + }); + } else { + return PackedFunc(); + } +} + +class MicroWrappedFunc { + public: + MicroWrappedFunc(std::shared_ptr session, + DevPtr func_ptr) { + session_ = session; + func_ptr_ = func_ptr; + } + + void operator()(TVMArgs args, TVMRetValue* rv) const { + session_->PushToExecQueue(func_ptr_, args); + } + + private: + /*! \brief reference to the session for this function (to keep the session alive) */ + std::shared_ptr session_; + /*! \brief offset of the function to be called */ + DevPtr func_ptr_; +}; + +// create micro session and low-level device from Python frontend +TVM_REGISTER_GLOBAL("micro._CreateSession") +.set_body([](TVMArgs args, TVMRetValue* rv) { + const std::string& device_type = args[0]; + const std::string& binary_path = args[1]; + const std::string& toolchain_prefix = args[2]; + uint64_t base_addr = args[3]; + const std::string& server_addr = args[4]; + int port = args[5]; + std::shared_ptr session = std::make_shared(); + //session->CreateSession( + // device_type, binary_path, toolchain_prefix, base_addr, server_addr, port); + session->CreateSession( + "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); + *rv = Module(session); + }); + +TVM_REGISTER_GLOBAL("micro._BakeSession") +.set_body([](TVMArgs args, TVMRetValue* rv) { + const std::string& binary = args[0]; + + std::shared_ptr& session = MicroSession::Current(); + session->BakeSession(binary); + }); + +TVM_REGISTER_GLOBAL("micro._GetFunction") +.set_body([](TVMArgs args, TVMRetValue* rv) { + const std::string& name = args[0]; + std::shared_ptr& session = MicroSession::Current(); + + DevPtr func_ptr = session->GetSymbolLoc(name); + *rv = PackedFunc(MicroWrappedFunc(session, func_ptr)); + }); + +} // namespace runtime +} // namespace tvm diff --git a/src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld b/src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld new file mode 100644 index 000000000000..d62165e60b20 --- /dev/null +++ b/src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld @@ -0,0 +1,89 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F746ZGTx Device with +** 1024KByte FLASH, 320KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20050000; /* end of RAM */ + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} + +/* Define output sections */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + . = ALIGN(4); + } >RAM + + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >RAM + + .data : + { + . = ALIGN(4); + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + . = ALIGN(4); + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + *(.bss) + *(.bss*) + . = ALIGN(4); + } >RAM + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } +} + diff --git a/src/runtime/micro/device/utvm_startup_stm32f767xx.s b/src/runtime/micro/device/utvm_startup_stm32f767xx.s new file mode 100644 index 000000000000..2921a8e2c46d --- /dev/null +++ b/src/runtime/micro/device/utvm_startup_stm32f767xx.s @@ -0,0 +1,75 @@ +/** + ****************************************************************************** + * @file startup_stm32f767xx.s + * @author MCD Application Team + * @brief STM32F767xx Devices vector table for GCC based toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M7 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +.syntax unified +.cpu cortex-m7 +.fpu softvfp +.thumb + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ +.section .text.Reset_Handler +.weak Reset_Handler +.type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + bl main + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ +.section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler diff --git a/src/runtime/micro/device/utvm_device_dylib_redirect.c b/src/runtime/micro/host_driven/utvm_device_dylib_redirect.c similarity index 100% rename from src/runtime/micro/device/utvm_device_dylib_redirect.c rename to src/runtime/micro/host_driven/utvm_device_dylib_redirect.c diff --git a/src/runtime/micro/device/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c similarity index 96% rename from src/runtime/micro/device/utvm_runtime.c rename to src/runtime/micro/host_driven/utvm_runtime.c index bc8dbff738c0..9702ef9862e4 100644 --- a/src/runtime/micro/device/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -35,7 +35,12 @@ extern "C" { #include "utvm_runtime.h" // Task pointers must be patched before calling a function. -UTVMTask utvm_task; +UTVMTask utvm_task = { + .func = NULL, + .arg_values = NULL, + .arg_type_codes = NULL, + .num_args = 0, +}; // These pointers are patched at load time to point to the workspace section. char* utvm_workspace_begin = NULL; // NOLINT(*) diff --git a/src/runtime/micro/device/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h similarity index 100% rename from src/runtime/micro/device/utvm_runtime.h rename to src/runtime/micro/host_driven/utvm_runtime.h diff --git a/src/runtime/micro/host_low_level_device.cc b/src/runtime/micro/host_low_level_device.cc index 48d55ba239c1..4eea88aaaffd 100644 --- a/src/runtime/micro/host_low_level_device.cc +++ b/src/runtime/micro/host_low_level_device.cc @@ -72,8 +72,6 @@ class HostLowLevelDevice final : public LowLevelDevice { reinterpret_cast(func_addr.value())(); } - void Connect() {} - std::uintptr_t base_addr() const final { return base_addr_; } diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index 95fe545021f0..3cdfa77d30bc 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -66,8 +66,6 @@ class LowLevelDevice { */ virtual void Execute(DevBaseOffset func_offset, DevBaseOffset breakpoint) = 0; - virtual void Connect() = 0; - // TODO(weberlo): Should we just give the device the *entire* memory layout // decided by the session? diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 2d2ae2e3eae6..2329c15c6735 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,9 +57,6 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { - std::cout << "sizeof(TVMArray): " << sizeof(TVMArray) << std::endl; - std::cout << "sizeof(TVMValue): " << sizeof(TVMValue) << std::endl; - //DevBaseOffset curr_start_offset = kDeviceStart; //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { // size_t section_size = GetDefaultSectionSize(static_cast(i)); @@ -87,6 +84,7 @@ MicroSession::MicroSession() { * } */ + /* size_t half_flash_size = 512000; // 0.5 MB DevBaseOffset curr_start_offset = DevBaseOffset(0x08000000); section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { @@ -134,6 +132,55 @@ MicroSession::MicroSession() { curr_start_offset += one_sixth_ram_size; memory_size_ = 0; + */ + + // TODO: why do we need to start 0x1c8 bytes after the start of ram? + //curr_start_offset = DevBaseOffset(0x200001C8); + DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); + size_t one_eighth_ram_size = 40000; + section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + + // NOTE: we don't use this for openocd + memory_size_ = 0; } MicroSession::~MicroSession() { @@ -185,11 +232,11 @@ void MicroSession::CreateSession(const std::string& device_type, //DevSymbolWrite(symbol_map_, "utvm_workspace_end", workspace_end_addr); } -void MicroSession::BakeSession(const std::string& binary) { - symbol_map_ = SymbolMap(binary, toolchain_prefix_); +void MicroSession::BakeSession(const std::string& binary_path) { + //symbol_map_ = SymbolMap(binary, toolchain_prefix_); + symbol_map_ = LoadBinary(binary_path, false).symbol_map; std::cout << symbol_map_["UTVMMain"].value() << std::endl; std::cout << symbol_map_["utvm_task"].value() << std::endl; - low_level_device()->Connect(); } // ARM and other manufacturers use the LSB of a function address to determine @@ -242,7 +289,6 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { .num_args = (uint32_t) args.num_args, }; // Write the task. - std::cout << "utvm_task loc: " << GetSymbolLoc("utvm_task").value() << std::endl; DevSymbolWrite(symbol_map_, "utvm_task", task); DevBaseOffset utvm_main_loc = DevBaseOffset(GetSymbolLoc("UTVMMain").value()); @@ -250,17 +296,85 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { if (kRequiresThumbModeBit) { utvm_main_loc += 1; } - low_level_device()->Execute(utvm_main_loc, utvm_done_loc); + // TODO: figure out why it's not running anymore when we compile it with "-c" + // instead of "-shared". we should be relocating the binary. //std::cout << "do execution things: "; //char tmp; //std::cin >> tmp; + low_level_device()->Execute(utvm_main_loc, utvm_done_loc); + // Check if there was an error during execution. If so, log it. CheckDeviceError(); GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); } +BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { + DevMemRegion text_section; + DevMemRegion rodata_section; + DevMemRegion data_section; + DevMemRegion bss_section; + + text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, kWordSize); + rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, kWordSize); + data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, kWordSize); + bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, kWordSize); + std::cout << "text size: " << std::hex << text_section.size << std::endl; + std::cout << "rodata size: " << std::hex << rodata_section.size << std::endl; + std::cout << "data size: " << std::hex << data_section.size << std::endl; + std::cout << "bss size: " << std::hex << bss_section.size << std::endl; + + text_section.start = AllocateInSection(SectionKind::kText, text_section.size); + rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); + data_section.start = AllocateInSection(SectionKind::kData, data_section.size); + bss_section.start = AllocateInSection(SectionKind::kBss, bss_section.size); + CHECK(text_section.start != nullptr && rodata_section.start != nullptr && + data_section.start != nullptr && bss_section.start != nullptr) + << "not enough space to load module on device"; + + std::cout << "text start: " << std::hex << text_section.start.value() << std::endl; + std::cout << "rodata start: " << std::hex << rodata_section.start.value() << std::endl; + std::cout << "data start: " << std::hex << data_section.start.value() << std::endl; + std::cout << "bss start: " << std::hex << bss_section.start.value() << std::endl; + std::string relocated_bin = RelocateBinarySections( + binary_path, + low_level_device_->ToDevPtr(text_section.start), + low_level_device_->ToDevPtr(rodata_section.start), + low_level_device_->ToDevPtr(data_section.start), + low_level_device_->ToDevPtr(bss_section.start), + toolchain_prefix_); + std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); + std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); + std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); + std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); + + std::cout << "writing text (size = " << std::dec << text_contents.size() << ")" << std::endl; + low_level_device_->Write(text_section.start, &text_contents[0], text_section.size); + std::cout << "writing rodata (size = " << std::dec << rodata_contents.size() << ")" << std::endl; + low_level_device_->Write(rodata_section.start, &rodata_contents[0], rodata_section.size); + std::cout << "writing data (size = " << std::dec << data_contents.size() << ")" << std::endl; + low_level_device_->Write(data_section.start, &data_contents[0], data_section.size); + std::cout << "writing bss (size = " << std::dec << bss_contents.size() << ")" << std::endl; + low_level_device_->Write(bss_section.start, &bss_contents[0], bss_section.size); + SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; + + if (patch_dylib_pointers) { + // Patch device lib pointers. + PatchImplHole(symbol_map, "TVMBackendAllocWorkspace"); + PatchImplHole(symbol_map, "TVMBackendFreeWorkspace"); + PatchImplHole(symbol_map, "TVMAPISetLastError"); + } + + return BinaryInfo { + .text_section = text_section, + .rodata_section = rodata_section, + .data_section = data_section, + .bss_section = bss_section, + .symbol_map = symbol_map, + }; +} + std::tuple MicroSession::EncoderAppend( TargetDataLayoutEncoder* encoder, const TVMArgs& args) { const int* type_codes = args.type_codes; @@ -335,7 +449,6 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); - std::cout << "writing byte_offset " << arr.byte_offset << std::endl; ARMTVMArray dev_arr = { .data = *((uint32_t*) &arr.data), .ctx = arr.ctx, @@ -348,15 +461,6 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr .pad2 = 0, }; - std::cout << "sizeof(ARMTVMArray): " << sizeof(ARMTVMArray) << std::endl; - std::cout << "data offs: " << (((uintptr_t) &(dev_arr.data)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "ctx offs: " << (((uintptr_t) &(dev_arr.ctx)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "ndim offs: " << (((uintptr_t) &(dev_arr.ndim)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "dtype offs: " << (((uintptr_t) &(dev_arr.dtype)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "strides offs: " << (((uintptr_t) &(dev_arr.strides)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "byte_offset offs: " << (((uintptr_t) &(dev_arr.byte_offset)) - ((uintptr_t) &dev_arr)) << std::endl; - - // Copy `arr`, update the copy's pointers to be device pointers, then // write the copy to `tvm_arr_slot`. //TVMArray dev_arr = arr; diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index bd5a6af5c495..924a748f3d65 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -47,7 +47,7 @@ #include #include "low_level_device.h" -#include "device/utvm_runtime.h" +#include "host_driven/utvm_runtime.h" #include "target_data_layout_encoder.h" namespace tvm { @@ -97,7 +97,9 @@ class MicroSession : public ModuleNode { const std::string& server_addr, int port); - void BakeSession(const std::string& binary); + void BakeSession(const std::string& binary_path); + + BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers); /*! * \brief ends the session by destructing the low-level device and its allocators diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index d0d179161173..1ec3e5b1a008 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -48,16 +48,10 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { port_ = port; base_addr_ = base_addr; CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; - } - void Connect() { socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); socket_.cmd_builder() << "halt"; socket_.SendCommand(); - std::cout << "LOADING BINARY" << std::endl; - socket_.cmd_builder() << "load_image /home/pratyush/Code/nucleo-interaction-from-scratch/blinky.elf"; - socket_.SendCommand(); - std::cout << "FINISHED LOADING BINARY" << std::endl; } void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { @@ -132,6 +126,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } void Write(DevBaseOffset offset, const void* buf, size_t num_bytes) { + std::cout << "here and writing " << std::dec << num_bytes << " bytes" << std::endl; if (num_bytes == 0) { return; } diff --git a/src/runtime/micro/target_data_layout_encoder.h b/src/runtime/micro/target_data_layout_encoder.h index d78ec7cc8187..b3b992809e3f 100644 --- a/src/runtime/micro/target_data_layout_encoder.h +++ b/src/runtime/micro/target_data_layout_encoder.h @@ -25,7 +25,7 @@ #define TVM_RUNTIME_MICRO_TARGET_DATA_LAYOUT_ENCODER_H_ #include -#include "device/utvm_runtime.h" +#include "host_driven/utvm_runtime.h" namespace tvm { namespace runtime { From 043297d282190008355187d36b3a9aaf33865a4b Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 14 Oct 2019 20:04:59 -0700 Subject: [PATCH 09/70] no longer relying on external makefile --- python/tvm/micro/base.py | 90 ++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 532febef188e..d61b26c6b8fb 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -110,43 +110,67 @@ def bake(self): merged_src = self.gen_merged_src(runtime_src, op_srcs) - print('writing src to main.c') - nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" - with open(f"{nucleo_path}/src/main.c", "w") as f: + tmp_dir = _util.tempdir() + + temp_src_path = tmp_dir.relpath("temp.c") + #nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" + with open(temp_src_path, "w") as f: f.write(merged_src) - print('[BEGIN SRC]') - print(merged_src) - print('[END SRC]') - paths = [path for path in find_include_path()] + paths = [('-I', path) for path in find_include_path()] #print(paths) #input() #paths += ["/home/pratyush/Code/tvm/src/runtime/micro/host_driven"] - paths += [_get_micro_device_dir()] + paths += [('-I', _get_micro_device_dir())] + print('compiling bin') + #ld_cmd = [ + # 'arm-none-eabi-gcc', + # 'src/main.o', + # '-static', + # '-mcpu=cortex-m7', + # '-mlittle-endian', + # '-mfloat-abi=hard', + # '-mfpu=fpv5-sp-d16', + # '-Wl,--gc-sections', + # '-Wl,--print-gc-sections', + # '-Wl,--cref,-Map=blinky.map', + # '-c', + # '-L', + # '.', + # '-T', + # 'UTVM_STM32F746ZGTx_FLASH.ld', + # '-o', + # 'blinky.elf' + # ] compile_cmd = [ 'arm-none-eabi-gcc', - 'src/main.o', - '-static', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-fstack-usage', '-mcpu=cortex-m7', '-mlittle-endian', '-mfloat-abi=hard', '-mfpu=fpv5-sp-d16', - '-Wl,--gc-sections', - '-Wl,--print-gc-sections', - '-Wl,--cref,-Map=blinky.map', - '-c', - '-L', - '.', - '-T', - 'UTVM_STM32F746ZGTx_FLASH.ld', - '-o', - 'blinky.elf' - ] + '-O0', + '-g', + '-gdwarf-5', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + '-c'] + for s, path in paths: + compile_cmd += [s, path] + temp_obj_path = tmp_dir.relpath('temp.o') + compile_cmd += ['-o', temp_obj_path, temp_src_path] + proc = subprocess.Popen( - ['make', 'clean'], - cwd=nucleo_path, + compile_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (out, _) = proc.communicate() @@ -154,12 +178,6 @@ def bake(self): msg = "Compilation error:\n" msg += out.decode("utf-8") raise RuntimeError(msg) - proc = subprocess.Popen( - ['make', 'blinky.elf'], - cwd=nucleo_path, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - #['arm-none-eabi-gcc', # '-std=c11', @@ -192,11 +210,11 @@ def bake(self): # cwd=nucleo_path, # stdout=subprocess.PIPE, # stderr=subprocess.STDOUT) - (out, _) = proc.communicate() - if proc.returncode != 0: - msg = "Compilation error:\n" - msg += out.decode("utf-8") - raise RuntimeError(msg) + #(out, _) = proc.communicate() + #if proc.returncode != 0: + # msg = "Compilation error:\n" + # msg += out.decode("utf-8") + # raise RuntimeError(msg) print('finished') #result_binary_path = f"{nucleo_path}/blinky.elf" @@ -204,8 +222,8 @@ def bake(self): # result_binary_contents = bytearray(f.read()) #_BakeSession(result_binary_contents); - result_binary_path = f"{nucleo_path}/src/main.o" - _BakeSession(result_binary_path); + #result_binary_path = f"{nucleo_path}/src/main.o" + _BakeSession(temp_obj_path); def add_module(self, c_mod): self.op_modules.append(c_mod) From 5e48b68d88a2a9879b8a0087f4a572db369f08de Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 14 Oct 2019 20:53:46 -0700 Subject: [PATCH 10/70] working with dynamically loaded kernels --- python/tvm/micro/base.py | 206 ++++++++------------ src/runtime/micro/micro_module.cc | 41 ++-- src/runtime/micro/micro_session.cc | 83 +++----- src/runtime/micro/micro_session.h | 8 +- tests/python/unittest/test_runtime_micro.py | 11 +- 5 files changed, 125 insertions(+), 224 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index d61b26c6b8fb..6c8fd4a22563 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -68,10 +68,11 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): #self._check_args(device_type, kwargs) # First, find and compile runtime library. - #tmp_dir = _util.tempdir() - #runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") - #create_micro_lib( - # runtime_obj_path, runtime_src_path, toolchain_prefix, include_dev_lib_header=False) + runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") + tmp_dir = _util.tempdir() + runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") + create_micro_lib( + runtime_obj_path, runtime_src_path, toolchain_prefix, include_dev_lib_header=False) self.op_modules = [] @@ -83,7 +84,7 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): print('creating session') self.module = _CreateSession( - self.device_type, "", self.toolchain_prefix, self.base_addr, self.server_addr, self.port) + self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) self._enter = self.module["enter"] self._exit = self.module["exit"] print('finished session init') @@ -113,37 +114,13 @@ def bake(self): tmp_dir = _util.tempdir() temp_src_path = tmp_dir.relpath("temp.c") - #nucleo_path = "/home/pratyush/Code/nucleo-interaction-from-scratch" with open(temp_src_path, "w") as f: f.write(merged_src) paths = [('-I', path) for path in find_include_path()] - #print(paths) - #input() - #paths += ["/home/pratyush/Code/tvm/src/runtime/micro/host_driven"] paths += [('-I', _get_micro_device_dir())] - print('compiling bin') - #ld_cmd = [ - # 'arm-none-eabi-gcc', - # 'src/main.o', - # '-static', - # '-mcpu=cortex-m7', - # '-mlittle-endian', - # '-mfloat-abi=hard', - # '-mfpu=fpv5-sp-d16', - # '-Wl,--gc-sections', - # '-Wl,--print-gc-sections', - # '-Wl,--cref,-Map=blinky.map', - # '-c', - # '-L', - # '.', - # '-T', - # 'UTVM_STM32F746ZGTx_FLASH.ld', - # '-o', - # 'blinky.elf' - # ] compile_cmd = [ 'arm-none-eabi-gcc', '-std=c11', @@ -179,111 +156,21 @@ def bake(self): msg += out.decode("utf-8") raise RuntimeError(msg) - #['arm-none-eabi-gcc', - # '-std=c11', - # '-Wall', - # '-Wextra', - # '--pedantic', - # '-Wa,-aghlms=src/main.lst', - # '-fstack-usage', - # '-mcpu=cortex-m7', - # '-mlittle-endian', - # '-mfloat-abi=hard', - # '-mfpu=fpv5-sp-d16', - # '-O0', - # '-g', - # '-gdwarf-5', - # '-nostartfiles', - # '-nodefaultlibs', - # '-nostdlib', - # '-fdata-sections', - # '-ffunction-sections', - # '-I', 'src', - # '-I', '/home/pratyush/Code/tvm/include', - # '-I', '/home/pratyush/Code/tvm/3rdparty/dlpack/include', - # '-I', '/home/pratyush/Code/tvm/src/runtime/micro/device', - # '-c', - # '-o', 'src/main.o', - # 'src/main.c'] - #proc = subprocess.Popen( - # ['arm-none-eabi-gcc',], - # cwd=nucleo_path, - # stdout=subprocess.PIPE, - # stderr=subprocess.STDOUT) - #(out, _) = proc.communicate() - #if proc.returncode != 0: - # msg = "Compilation error:\n" - # msg += out.decode("utf-8") - # raise RuntimeError(msg) print('finished') - #result_binary_path = f"{nucleo_path}/blinky.elf" - #with open(result_binary_path, "rb") as f: - # result_binary_contents = bytearray(f.read()) - #_BakeSession(result_binary_contents); + _BakeSession(temp_obj_path) - #result_binary_path = f"{nucleo_path}/src/main.o" - _BakeSession(temp_obj_path); - - def add_module(self, c_mod): - self.op_modules.append(c_mod) + #def add_module(self, c_mod): + # self.op_modules.append(c_mod) def gen_merged_src(self, runtime_src, op_srcs): include_str = "#include \"utvm_runtime.h\"" split_idx = runtime_src.index(include_str) + len(include_str) + 2 merged_src = runtime_src[:split_idx] + op_srcs + runtime_src[split_idx:] - #merged_src += "\nint main() {UTVMMain(); UTVMDone(); fadd(NULL, NULL, 0); TVMBackendAllocWorkspace(0, 0, 0, 0, 0); TVMBackendFreeWorkspace(0, 0, NULL); TVMAPISetLastError(NULL);}\n" - return merged_src - #print(merged_src) - #print('--------------------------------------------------------------------------------') - - ## TODO: figure out how to prevent DCE from kicking in without creating dummy calls. - ## TODO: splice `main` in *before* the end of the `extern C` block - #import re - #func_regex = re.compile(r' *(TVM_DLL)? *(int|int32_t|void|void\*|const char\*) *([a-zA-Z0-9_]+) *\((.*)\) *{? *') - #matches = [] - #for line in merged_src.split('\n'): - # match = func_regex.match(line) - # if match is not None: - # func_name = match.group(3) - # args = match.group(4) - # matches.append((func_name, args)) - - #method_calls = [] - #for func_name, args in matches: - # call_args = [] - # args = args.strip() - # if len(args) != 0: - # args = list(map(lambda s: s.strip(), args.split(','))) - # for arg in args: - # if arg.startswith('const char*'): - # call_args.append('NULL') - # elif arg.startswith('void*'): - # call_args.append('NULL') - # elif arg.startswith('int32_t'): - # call_args.append('0') - # elif arg.startswith('int'): - # call_args.append('0') - # else: - # raise RuntimeError('ayy lmao') - # call_args = ','.join(call_args) - # method_calls.append(f'{func_name}({call_args});') - #print(method_calls) - #print('--------------------------------------------------------------------------------') - #input('look at dat source') - #return merged_src - - def extract_method_sigs(self, merged_src): - #for line in merged_src.split('\n'): - # if line.startswith('TVM_DLL'): - # line = line[len('TVM_DLL'):] - # print(line) - pass - - def get_func(self, func_name): - return _GetFunction(func_name); + #def get_func(self, func_name): + # return _GetFunction(func_name); def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -312,7 +199,6 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() - #self.openocd_process.kill() def _get_micro_device_dir(): @@ -386,6 +272,13 @@ def create_micro_lib( whether to include the device library header containing definitions of library functions. """ + if toolchain_prefix == '': + create_host_micro_lib(obj_path, src_path, toolchain_prefix, options, include_dev_lib_header) + elif toolchain_prefix == 'arm-none-eabi-': + create_arm_micro_lib(obj_path, src_path, toolchain_prefix, options, include_dev_lib_header) + +def create_host_micro_lib( + obj_path, src_path, toolchain_prefix, options, include_dev_lib_header): def replace_suffix(s, new_suffix): if "." in os.path.basename(s): # There already exists an extension. @@ -427,5 +320,68 @@ def replace_suffix(s, new_suffix): _cc.create_shared(obj_path, src_path, options, compile_cmd) +def create_arm_micro_lib( + obj_path, src_path, toolchain_prefix, options, include_dev_lib_header): + import subprocess + import os + import copy + from shutil import copyfile + + from tvm._ffi.libinfo import find_include_path + from tvm.contrib import binutil + + tmp_dir = _util.tempdir() + if include_dev_lib_header: + # Create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath("temp.c") + with open(src_path, "r") as f: + src_lines = f.read().splitlines() + src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") + with open(temp_src_path, "w") as f: + f.write("\n".join(src_lines)) + src_path = temp_src_path + + paths = [('-I', path) for path in find_include_path()] + paths += [('-I', _get_micro_device_dir())] + + print('compiling bin') + compile_cmd = [ + 'arm-none-eabi-gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-fstack-usage', + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-O0', + '-g', + '-gdwarf-5', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + '-c'] + for s, path in paths: + compile_cmd += [s, path] + temp_obj_path = tmp_dir.relpath('temp.o') + compile_cmd += ['-o', obj_path, src_path] + + proc = subprocess.Popen( + compile_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + (out, _) = proc.communicate() + if proc.returncode != 0: + msg = "Compilation error:\n" + msg += out.decode("utf-8") + raise RuntimeError(msg) + + print('finished') + _init_api("tvm.micro", "tvm.micro.base") diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 5c6413fdf2eb..8c2b6787210f 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -66,65 +66,50 @@ class MicroModuleNode final : public ModuleNode { */ void InitMicroModule(const std::string& binary_path) { session_ = MicroSession::Current(); - //binary_path_ = binary_path; - std::cout << "AYY" << std::endl; - //binary_info_ = session_->EnqueueBinary(binary_path_); - std::cout << "LMAO" << std::endl; + symbol_map_ = session_->LoadBinary(binary_path, true).symbol_map; } /*! * \brief runs selected function on the micro device * \param func_name name of the function to be run - * \param func_offset offset of the function to be run + * \param func_ptr offset of the function to be run * \param args type-erased arguments passed to the function */ - void RunFunction(const std::string& func_name, DevBaseOffset func_offset, const TVMArgs& args) { - session_->PushToExecQueue(func_offset, args); + void RunFunction(DevPtr func_ptr, const TVMArgs& args) { + session_->PushToExecQueue(func_ptr, args); } private: - BinaryContents binary_contents_; - ///*! \brief module binary info */ - //BinaryInfo binary_info_; - ///*! \brief path to module binary */ //std::string binary_path_; + SymbolMap symbol_map_; /*! \brief global session pointer */ ObjectPtr session_; }; class MicroWrappedFunc { public: - MicroWrappedFunc(MicroModuleNode* m, - ObjectPtr session, - const std::string& func_name, - DevBaseOffset func_offset) { - m_ = m; + MicroWrappedFunc(ObjectPtr session, + DevPtr func_ptr) { session_ = session; - func_name_ = func_name; - func_offset_ = func_offset; + func_ptr_ = func_ptr; } void operator()(TVMArgs args, TVMRetValue* rv) const { - m_->RunFunction(func_name_, func_offset_, args); + session_->PushToExecQueue(func_ptr_, args); } private: - /*! \brief internal module */ - MicroModuleNode* m_; /*! \brief reference to the session for this function (to keep the session alive) */ - ObjectPtr session_; - /*! \brief name of the function */ - std::string func_name_; + std::shared_ptr session_; /*! \brief offset of the function to be called */ - DevBaseOffset func_offset_; + DevPtr func_ptr_; }; PackedFunc MicroModuleNode::GetFunction( const std::string& name, const ObjectPtr& sptr_to_self) { - DevBaseOffset func_offset = - session_->low_level_device()->ToDevOffset(binary_contents_.binary_info.symbol_map[name]); - MicroWrappedFunc f(this, session_, name, func_offset); + DevPtr func_ptr = symbol_map_[name]; + MicroWrappedFunc f(session_, func_ptr); return PackedFunc(f); } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 2329c15c6735..c5de77743363 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -207,10 +207,9 @@ void MicroSession::CreateSession(const std::string& device_type, LOG(FATAL) << "unsupported micro low-level device"; } - //CHECK(!binary_path.empty()) << "uTVM runtime not initialized"; - //runtime_bin_info_ = LoadBinary(binary_path, /* patch_dylib_pointers */ false); - //utvm_main_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMMain"]); - //utvm_done_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMDone"]); + runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; + std::cout << runtime_symbol_map_["UTVMMain"].value() << std::endl; + std::cout << runtime_symbol_map_["utvm_task"].value() << std::endl; //if (device_type == "openocd") { // // Set OpenOCD device's stack pointer. @@ -219,25 +218,25 @@ void MicroSession::CreateSession(const std::string& device_type, //} // Patch workspace pointers to the start of the workspace section. - //DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); - //DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); - //void* workspace_start_addr = - // low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); - //void* workspace_end_addr = - // low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); + DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); + DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); + void* workspace_start_addr = + low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); + void* workspace_end_addr = + low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); // TODO(weberlo): A lot of these symbol writes can be converted into symbols // in the C source, where the symbols are created by the linker script we // generate in python. - //DevSymbolWrite(symbol_map_, "utvm_workspace_begin", workspace_start_addr); - //DevSymbolWrite(symbol_map_, "utvm_workspace_end", workspace_end_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_begin", workspace_start_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); } -void MicroSession::BakeSession(const std::string& binary_path) { - //symbol_map_ = SymbolMap(binary, toolchain_prefix_); - symbol_map_ = LoadBinary(binary_path, false).symbol_map; - std::cout << symbol_map_["UTVMMain"].value() << std::endl; - std::cout << symbol_map_["utvm_task"].value() << std::endl; -} +//void MicroSession::BakeSession(const std::string& binary_path) { +// //runtime_symbol_map_ = SymbolMap(binary, toolchain_prefix_); +// runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; +// std::cout << runtime_symbol_map_["UTVMMain"].value() << std::endl; +// std::cout << runtime_symbol_map_["utvm_task"].value() << std::endl; +//} // ARM and other manufacturers use the LSB of a function address to determine // whether it's a "thumb mode" function (TODO: figure out what that means). @@ -289,10 +288,10 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { .num_args = (uint32_t) args.num_args, }; // Write the task. - DevSymbolWrite(symbol_map_, "utvm_task", task); + DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); - DevBaseOffset utvm_main_loc = DevBaseOffset(GetSymbolLoc("UTVMMain").value()); - DevBaseOffset utvm_done_loc = DevBaseOffset(GetSymbolLoc("UTVMDone").value()); + DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); + DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); if (kRequiresThumbModeBit) { utvm_main_loc += 1; } @@ -480,11 +479,11 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr } void MicroSession::CheckDeviceError() { - int32_t return_code = DevSymbolRead(symbol_map_, "utvm_return_code"); + int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); if (return_code) { std::uintptr_t last_error = - DevSymbolRead(symbol_map_, "utvm_last_error"); + DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); std::string last_error_str; if (last_error) { DevBaseOffset last_err_offset = low_level_device()->ToDevOffset(DevPtr(last_error)); @@ -498,7 +497,7 @@ void MicroSession::CheckDeviceError() { } void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { - void* runtime_impl_addr = symbol_map_[func_name].cast_to(); + void* runtime_impl_addr = runtime_symbol_map_[func_name].cast_to(); std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); @@ -562,25 +561,6 @@ PackedFunc MicroSession::GetFunction( } } -class MicroWrappedFunc { - public: - MicroWrappedFunc(std::shared_ptr session, - DevPtr func_ptr) { - session_ = session; - func_ptr_ = func_ptr; - } - - void operator()(TVMArgs args, TVMRetValue* rv) const { - session_->PushToExecQueue(func_ptr_, args); - } - - private: - /*! \brief reference to the session for this function (to keep the session alive) */ - std::shared_ptr session_; - /*! \brief offset of the function to be called */ - DevPtr func_ptr_; -}; - // create micro session and low-level device from Python frontend TVM_REGISTER_GLOBAL("micro._CreateSession") .set_body([](TVMArgs args, TVMRetValue* rv) { @@ -598,22 +578,5 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") *rv = Module(session); }); -TVM_REGISTER_GLOBAL("micro._BakeSession") -.set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& binary = args[0]; - - std::shared_ptr& session = MicroSession::Current(); - session->BakeSession(binary); - }); - -TVM_REGISTER_GLOBAL("micro._GetFunction") -.set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& name = args[0]; - std::shared_ptr& session = MicroSession::Current(); - - DevPtr func_ptr = session->GetSymbolLoc(name); - *rv = PackedFunc(MicroWrappedFunc(session, func_ptr)); - }); - } // namespace runtime } // namespace tvm diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 924a748f3d65..8950e3850324 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -97,7 +97,7 @@ class MicroSession : public ModuleNode { const std::string& server_addr, int port); - void BakeSession(const std::string& binary_path); + //void BakeSession(const std::string& binary_path); BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers); @@ -135,10 +135,6 @@ class MicroSession : public ModuleNode { */ void PushToExecQueue(DevPtr func, const TVMArgs& args); - DevPtr GetSymbolLoc(const std::string& sym_name) { - return symbol_map_[sym_name]; - } - //void EnqueueBinary(const std::string& binary_path); //void FlushBinary(const BinaryContents& bin_contents); @@ -189,7 +185,7 @@ class MicroSession : public ModuleNode { /*! \brief offset of the runtime exit breakpoint */ DevBaseOffset utvm_done_symbol_; - SymbolMap symbol_map_; + SymbolMap runtime_symbol_map_; /*! * \brief patches a function pointer in this module to an implementation diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 7e2e5b590845..bc9857013f24 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -350,14 +350,14 @@ def test_arm_add(): # the case, then we'll need to create all of the micro mods we want, # *then* call sess.bake, which should just execute the same Python code # as in micro/base.py, but with a trip to C++ in between. - #micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) - #micro_func = micro_mod[func_name] + micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + micro_func = micro_mod[func_name] - sess.add_module(c_mod) + #sess.add_module(c_mod) print('baking session') - sess.bake() + #sess.bake() print(f'grabbing {func_name} from session') - micro_func = sess.get_func(func_name) + #micro_func = sess.get_func(func_name) print(f'grabbed it') ctx = tvm.micro_dev(0) @@ -372,6 +372,7 @@ def test_arm_add(): # also try loading in the original blinky program (or some slight # variant of it) to see if we're loading shit onto the device # correctly. + input('not gon work') micro_func(a, b, c) print('--------------------------------------------------------------------------------') print(c) From c476648f8904fa2c7b3ad573907b6e019370a8bf Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 17 Oct 2019 17:33:54 -0700 Subject: [PATCH 11/70] Make conv2d werk --- python/tvm/contrib/binutil.py | 24 +- python/tvm/micro/base.py | 84 --- python/tvm/relay/build_module.py | 13 + src/codegen/build_module.cc | 3 + src/relay/backend/graph_runtime_codegen.cc | 3 + src/runtime/micro/2 | 622 ------------------ .../micro/device/utvm_api_stm32f767xx.c | 0 .../micro/device/utvm_startup_stm32f767xx.s | 20 +- src/runtime/micro/host_driven/utvm_runtime.c | 8 +- src/runtime/micro/host_driven/utvm_runtime.h | 12 + src/runtime/micro/micro_common.cc | 20 +- src/runtime/micro/micro_common.h | 2 +- src/runtime/micro/micro_module.cc | 2 +- src/runtime/micro/micro_section_allocator.h | 2 +- src/runtime/micro/micro_session.cc | 177 +++-- src/runtime/micro/openocd_low_level_device.cc | 1 - tests/python/unittest/test_runtime_micro.py | 155 ++--- 17 files changed, 256 insertions(+), 892 deletions(-) delete mode 100644 src/runtime/micro/2 create mode 100644 src/runtime/micro/device/utvm_api_stm32f767xx.c diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 6fde7447f913..a61664ac5b30 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -127,15 +127,25 @@ def tvm_callback_relocate_binary( rel_bin : bytearray the relocated binary """ + global TEMPDIR_REFS tmp_dir = util.tempdir() - #rel_obj_path = tmp_dir.relpath("relocated.o") - rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_relocated.o' + TEMPDIR_REFS.append(tmp_dir) + rel_obj_path = tmp_dir.relpath("relocated.o") + #rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_relocated.o' + with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'r') as f: + gdbinit_contents = f.read().split('\n') + new_contents = [] + for line in gdbinit_contents: + new_contents.append(line) + if line.startswith('target'): + new_contents.append(f'add-symbol-file {rel_obj_path}') + with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: + f.write('\n'.join(new_contents)) #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" - print(f'binary path: {binary_path}') # TODO(weberlo): Generate the script in a more procedural manner. ld_script_contents = """ @@ -196,9 +206,6 @@ def tvm_callback_relocate_binary( } """ % (text_addr, rodata_addr, data_addr, bss_addr) - print(ld_script_contents) - - #""" #SECTIONS #{ @@ -243,10 +250,6 @@ def tvm_callback_relocate_binary( rel_ld_script_path = tmp_dir.relpath("relocated.lds") with open(rel_ld_script_path, "w") as f: f.write(ld_script_contents) - ld_cmd = ' '.join(["{}ld".format(toolchain_prefix), binary_path, - "-T", rel_ld_script_path, - "-o", rel_obj_path]) - print(f'runnin ld cmd: {ld_cmd}') ld_proc = subprocess.Popen(["{}ld".format(toolchain_prefix), binary_path, "-T", rel_ld_script_path, "-o", rel_obj_path], @@ -258,6 +261,7 @@ def tvm_callback_relocate_binary( msg += py_str(out) raise RuntimeError(msg) + print(f'relocated obj path is {rel_obj_path}') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 6c8fd4a22563..f7e0cbdee7e6 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -89,89 +89,6 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): self._exit = self.module["exit"] print('finished session init') - def bake(self): - import subprocess - import os - import copy - from shutil import copyfile - - from tvm._ffi.libinfo import find_include_path - from tvm.contrib import binutil - - op_srcs = [] - for op_module in self.op_modules: - op_src = op_module.get_source() - op_src = op_src[op_src.index("TVM_DLL"):] - op_srcs.append(op_src) - op_srcs = "\n\n".join(op_srcs) - - runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") - with open(runtime_src_path) as f: - runtime_src = f.read() - - merged_src = self.gen_merged_src(runtime_src, op_srcs) - - tmp_dir = _util.tempdir() - - temp_src_path = tmp_dir.relpath("temp.c") - with open(temp_src_path, "w") as f: - f.write(merged_src) - - paths = [('-I', path) for path in find_include_path()] - paths += [('-I', _get_micro_device_dir())] - - print('compiling bin') - compile_cmd = [ - 'arm-none-eabi-gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-fstack-usage', - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-O0', - '-g', - '-gdwarf-5', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - '-c'] - for s, path in paths: - compile_cmd += [s, path] - temp_obj_path = tmp_dir.relpath('temp.o') - compile_cmd += ['-o', temp_obj_path, temp_src_path] - - proc = subprocess.Popen( - compile_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - (out, _) = proc.communicate() - if proc.returncode != 0: - msg = "Compilation error:\n" - msg += out.decode("utf-8") - raise RuntimeError(msg) - - print('finished') - - _BakeSession(temp_obj_path) - - #def add_module(self, c_mod): - # self.op_modules.append(c_mod) - - def gen_merged_src(self, runtime_src, op_srcs): - include_str = "#include \"utvm_runtime.h\"" - split_idx = runtime_src.index(include_str) + len(include_str) + 2 - merged_src = runtime_src[:split_idx] + op_srcs + runtime_src[split_idx:] - return merged_src - - #def get_func(self, func_name): - # return _GetFunction(func_name); - def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -345,7 +262,6 @@ def create_arm_micro_lib( paths = [('-I', path) for path in find_include_path()] paths += [('-I', _get_micro_device_dir())] - print('compiling bin') compile_cmd = [ 'arm-none-eabi-gcc', '-std=c11', diff --git a/python/tvm/relay/build_module.py b/python/tvm/relay/build_module.py index 28ce16b9b452..b8503df78a5b 100644 --- a/python/tvm/relay/build_module.py +++ b/python/tvm/relay/build_module.py @@ -100,7 +100,20 @@ def build(self, func, target=None, target_host=None, params=None): params : dict The parameters of the final graph. """ + print(type(target)) + print(target) + print(type(list(target.keys())[0])) + print(list(target.keys())[0]) + print(type(list(target.values())[0])) + print(list(target.values())[0]) target = _update_target(target) + print('WEEEEEEEEE') + print(type(target)) + print(target) + print(type(list(target.keys())[0])) + print(list(target.keys())[0]) + print(type(list(target.values())[0])) + print(list(target.values())[0]) # Setup the params. if params: diff --git a/src/codegen/build_module.cc b/src/codegen/build_module.cc index ac991d4bfea3..064840d286ee 100644 --- a/src/codegen/build_module.cc +++ b/src/codegen/build_module.cc @@ -230,6 +230,9 @@ Target Target::Create(const std::string& target_str) { options.push_back(item); } + std::cout << "target str: " << target_str << std::endl; + std::cout << "target name: " << target_name << std::endl; + return CreateTarget(target_name, options); } diff --git a/src/relay/backend/graph_runtime_codegen.cc b/src/relay/backend/graph_runtime_codegen.cc index e2881785766c..b8a3c75d0264 100644 --- a/src/relay/backend/graph_runtime_codegen.cc +++ b/src/relay/backend/graph_runtime_codegen.cc @@ -201,6 +201,7 @@ class GraphRuntimeCodegen auto pf = GetPackedFunc("relay.backend.GraphPlanMemory"); storage_device_map_ = (*pf)(func); // First we convert all the parameters into input nodes. + std::cout << "we have " << func->params.size() << " params" << std::endl; for (auto param : func->params) { auto node_ptr = GraphInputNode::make_node_ptr(param->name_hint(), GraphAttrs()); var_map_[param.get()] = AddNode(node_ptr, param); @@ -212,6 +213,7 @@ class GraphRuntimeCodegen LoweredOutput ret; ret.graph_json = os.str(); ret.params = params_; + std::cout << "we have " << lowered_funcs_.size() << " lowered funcs" << std::endl; for (auto& kv : lowered_funcs_) { if (ret.lowered_funcs.count(kv.first) == 0) { ret.lowered_funcs.Set(kv.first, Array()); @@ -226,6 +228,7 @@ class GraphRuntimeCodegen } ret.lowered_funcs.Set(kv.first, tmp); } + std::cout << "finished codegen" << std::endl; return ret; } diff --git a/src/runtime/micro/2 b/src/runtime/micro/2 deleted file mode 100644 index 9fed326ebdae..000000000000 --- a/src/runtime/micro/2 +++ /dev/null @@ -1,622 +0,0 @@ -/* - * 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. - */ - -/*! - * Copyright (c) 2019 by Contributors - * \file micro_session.cc - */ - -#include -#include -#include -#include -#include -#include -#include "micro_session.h" -#include "low_level_device.h" -#include "target_data_layout_encoder.h" - -namespace tvm { -namespace runtime { - -struct TVMMicroSessionThreadLocalEntry { - std::stack> session_stack; -}; - -typedef dmlc::ThreadLocalStore TVMMicroSessionThreadLocalStore; - -std::shared_ptr& MicroSession::Current() { - TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); - CHECK_GT(entry->session_stack.size(), 0) << "No current session"; - return entry->session_stack.top(); -} - -void MicroSession::EnterWithScope(std::shared_ptr session) { - TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); - entry->session_stack.push(session); -} - -void MicroSession::ExitWithScope() { - TVMMicroSessionThreadLocalEntry *entry = TVMMicroSessionThreadLocalStore::Get(); - CHECK(!entry->session_stack.empty()); - entry->session_stack.pop(); -} - -MicroSession::MicroSession() { - //DevBaseOffset curr_start_offset = kDeviceStart; - //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - // size_t section_size = GetDefaultSectionSize(static_cast(i)); - // section_allocators_[i] = std::make_shared(DevMemRegion { - // .start = curr_start_offset, - // .size = section_size, - // }); - // curr_start_offset += section_size; - //} - //memory_size_ = curr_start_offset.cast_to(); - - /* Linker script sample - * #if !defined(MBED_APP_START) - * #define MBED_APP_START 0x08000000 - * #endif - * - * #if !defined(MBED_APP_SIZE) - * #define MBED_APP_SIZE 1024K - * #endif - * - * MEMORY - * { - * FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE - * RAM (rwx) : ORIGIN = 0x200001C8, LENGTH = 320K - 0x1C8 - * } - */ - - /* - size_t half_flash_size = 512000; // 0.5 MB - DevBaseOffset curr_start_offset = DevBaseOffset(0x08000000); - section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = half_flash_size, - }); - curr_start_offset += half_flash_size; - section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = half_flash_size, - }); - curr_start_offset += half_flash_size; - - curr_start_offset = DevBaseOffset(0x200001C8); - size_t one_sixth_ram_size = 53256; - section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - - memory_size_ = 0; - */ - - // TODO: why do we need to start 0x1c8 bytes after the start of ram? - //curr_start_offset = DevBaseOffset(0x200001C8); - DevBaseOffset curr_start_offset = DevBaseOffset(0x20000000); - size_t one_eighth_ram_size = 40000; - section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - - // NOTE: we don't use this for openocd - memory_size_ = 0; -} - -MicroSession::~MicroSession() { - for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - section_allocators_[i] = nullptr; - } - low_level_device_ = nullptr; -} - -void MicroSession::CreateSession(const std::string& device_type, - const std::string& binary_path, - const std::string& toolchain_prefix, - std::uintptr_t base_addr, - const std::string& server_addr, - int port) { - // TODO(weberlo): make device type enum - toolchain_prefix_ = toolchain_prefix; - if (device_type == "host") { - low_level_device_ = HostLowLevelDeviceCreate(memory_size_); - } else if (device_type == "openocd") { - // TODO(weberlo): We need a better way of configuring devices. - low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); - } else { - LOG(FATAL) << "unsupported micro low-level device"; - } - - //CHECK(!binary_path.empty()) << "uTVM runtime not initialized"; - //runtime_bin_info_ = LoadBinary(binary_path, /* patch_dylib_pointers */ false); - //utvm_main_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMMain"]); - //utvm_done_symbol_ = low_level_device()->ToDevOffset(symbol_map_["UTVMDone"]); - - //if (device_type == "openocd") { - // // Set OpenOCD device's stack pointer. - // auto stack_section = GetAllocator(SectionKind::kStack); - // low_level_device_->SetStackTop(stack_section->max_end_offset()); - //} - - // Patch workspace pointers to the start of the workspace section. - //DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); - //DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); - //void* workspace_start_addr = - // low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); - //void* workspace_end_addr = - // low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); - // TODO(weberlo): A lot of these symbol writes can be converted into symbols - // in the C source, where the symbols are created by the linker script we - // generate in python. - //DevSymbolWrite(symbol_map_, "utvm_workspace_begin", workspace_start_addr); - //DevSymbolWrite(symbol_map_, "utvm_workspace_end", workspace_end_addr); -} - -void MicroSession::BakeSession(const std::string& binary_path) { - //symbol_map_ = SymbolMap(binary, toolchain_prefix_); - symbol_map_ = LoadBinary(binary_path, false).symbol_map; - std::cout << symbol_map_["UTVMMain"].value() << std::endl; - std::cout << symbol_map_["utvm_task"].value() << std::endl; -} - -// ARM and other manufacturers use the LSB of a function address to determine -// whether it's a "thumb mode" function (TODO: figure out what that means). -const bool kRequiresThumbModeBit = true; -void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { - int32_t (*func_dev_addr)(void*, void*, int32_t) = - reinterpret_cast(func_ptr.value()); - // TODO: make this a parameter. - if (kRequiresThumbModeBit) { - func_dev_addr += 1; - } - - // Create an allocator stream for the memory region after the most recent - // allocation in the args section. - DevPtr args_addr = - low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); - TargetDataLayoutEncoder encoder(args_addr); - - std::tuple arg_field_addrs = EncoderAppend(&encoder, args); - // Flush `stream` to device memory. - DevBaseOffset stream_dev_offset = - GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); - low_level_device()->Write(stream_dev_offset, - reinterpret_cast(encoder.data()), - encoder.buf_size()); - - //UTVMTask task = { - // .func = func_dev_addr, - // .arg_values = std::get<0>(arg_field_addrs).cast_to(), - // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), - // .num_args = args.num_args, - //}; - typedef struct StructARMUTVMTask { - /*! \brief Pointer to function to call for this task */ - uint32_t func; - /*! \brief Array of argument values */ - uint32_t arg_values; - /*! \brief Array of type codes for each argument value */ - uint32_t arg_type_codes; - /*! \brief Number of arguments */ - uint32_t num_args; - } ARMUTVMTask; - TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); - ARMUTVMTask task = { - .func = *((uint32_t*) &func_dev_addr), - .arg_values = *((uint32_t*) &arg_values_dev_addr), - .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), - .num_args = (uint32_t) args.num_args, - }; - // Write the task. - DevSymbolWrite(symbol_map_, "utvm_task", task); - - DevBaseOffset utvm_main_loc = DevBaseOffset(GetSymbolLoc("UTVMMain").value()); - DevBaseOffset utvm_done_loc = DevBaseOffset(GetSymbolLoc("UTVMDone").value()); - if (kRequiresThumbModeBit) { - utvm_main_loc += 1; - } - - // TODO: figure out why it's not running anymore when we compile it with "-c" - // instead of "-shared". we should be relocating the binary. - std::cout << "do execution things: "; - char tmp; - std::cin >> tmp; - //low_level_device()->Execute(utvm_main_loc, utvm_done_loc); - - // Check if there was an error during execution. If so, log it. - CheckDeviceError(); - - GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); -} - -BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { - DevMemRegion text_section; - DevMemRegion rodata_section; - DevMemRegion data_section; - DevMemRegion bss_section; - - text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, kWordSize); - rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, kWordSize); - data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, kWordSize); - bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, kWordSize); - - text_section.start = AllocateInSection(SectionKind::kText, text_section.size); - rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); - data_section.start = AllocateInSection(SectionKind::kData, data_section.size); - bss_section.start = AllocateInSection(SectionKind::kBss, bss_section.size); - CHECK(text_section.start != nullptr && rodata_section.start != nullptr && - data_section.start != nullptr && bss_section.start != nullptr) - << "not enough space to load module on device"; - - std::cout << "text start: " << text_section.start << std::endl; - std::cout << "rodata start: " << rodata_section.start << std::endl; - std::cout << "data start: " << data_section.start << std::endl; - std::cout << "bss start: " << bss_section.start << std::endl; - std::string relocated_bin = RelocateBinarySections( - binary_path, - low_level_device_->ToDevPtr(text_section.start), - low_level_device_->ToDevPtr(rodata_section.start), - low_level_device_->ToDevPtr(data_section.start), - low_level_device_->ToDevPtr(bss_section.start), - toolchain_prefix_); - std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); - std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); - std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); - std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); - low_level_device_->Write(text_section.start, &text_contents[0], text_section.size); - low_level_device_->Write(rodata_section.start, &rodata_contents[0], rodata_section.size); - low_level_device_->Write(data_section.start, &data_contents[0], data_section.size); - low_level_device_->Write(bss_section.start, &bss_contents[0], bss_section.size); - SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; - - if (patch_dylib_pointers) { - // Patch device lib pointers. - PatchImplHole(symbol_map, "TVMBackendAllocWorkspace"); - PatchImplHole(symbol_map, "TVMBackendFreeWorkspace"); - PatchImplHole(symbol_map, "TVMAPISetLastError"); - } - - return BinaryInfo { - .text_section = text_section, - .rodata_section = rodata_section, - .data_section = data_section, - .bss_section = bss_section, - .symbol_map = symbol_map, - }; -} - -std::tuple MicroSession::EncoderAppend( - TargetDataLayoutEncoder* encoder, const TVMArgs& args) { - const int* type_codes = args.type_codes; - int num_args = args.num_args; - - auto tvm_vals_slot = encoder->Alloc(num_args); - auto type_codes_slot = encoder->Alloc(num_args); - - for (int i = 0; i < num_args; i++) { - switch (type_codes[i]) { - case kNDArrayContainer: - case kArrayHandle: { - TVMArray* base_arr_handle = args[i]; - // All uTVM arrays store a `MicroDevSpace` struct in their `data` field, - // which wraps the actual data and stores a reference to the session, in - // order to prevent premature session destruction. - void* old_data = base_arr_handle->data; - // Mutate the array to unwrap the `data` field. - base_arr_handle->data = reinterpret_cast(old_data)->data; - // Now, encode the unwrapped version. - void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); - // And restore the original wrapped version. - base_arr_handle->data = old_data; - - TVMValue val; - val.v_handle = arr_ptr; - tvm_vals_slot.WriteValue(val); - break; - } - // TODO(weberlo): Implement `double` and `int64` case. - case kDLFloat: - case kDLInt: - case kDLUInt: - default: - LOG(FATAL) << "unsupported type code for writing args: " << type_codes[i]; - break; - } - } - type_codes_slot.WriteArray(type_codes, num_args); - - return std::make_tuple(tvm_vals_slot.start_addr(), type_codes_slot.start_addr()); -} - -DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { - typedef struct StructARMTVMArray { - uint32_t data; - DLContext ctx; - int ndim; - DLDataType dtype; - uint32_t shape; - uint32_t strides; - uint32_t pad1; - uint32_t byte_offset; - uint32_t pad2; - } ARMTVMArray; - - //auto tvm_arr_slot = encoder->Alloc(); - auto tvm_arr_slot = encoder->Alloc(); - auto shape_slot = encoder->Alloc(arr.ndim); - - // `shape` and `strides` are stored on the host, so we need to write them to - // the device first. The `data` field is already allocated on the device and - // is a device pointer, so we don't need to write it. - shape_slot.WriteArray(arr.shape, arr.ndim); - DevPtr shape_addr = shape_slot.start_addr(); - DevPtr strides_addr = DevPtr(nullptr); - if (arr.strides != nullptr) { - auto stride_slot = encoder->Alloc(arr.ndim); - stride_slot.WriteArray(arr.strides, arr.ndim); - strides_addr = stride_slot.start_addr(); - } - - int64_t* dev_shape = shape_addr.cast_to(); - int64_t* dev_strides = strides_addr.cast_to(); - std::cout << "writing byte_offset " << arr.byte_offset << std::endl; - ARMTVMArray dev_arr = { - .data = *((uint32_t*) &arr.data), - .ctx = arr.ctx, - .ndim = arr.ndim, - .dtype = arr.dtype, - .shape = *((uint32_t*) &dev_shape), - .strides = *((uint32_t*) &dev_strides), - .pad1 = 0, - .byte_offset = *((uint32_t*) &arr.byte_offset), - .pad2 = 0, - }; - - std::cout << "sizeof(ARMTVMArray): " << sizeof(ARMTVMArray) << std::endl; - std::cout << "data offs: " << (((uintptr_t) &(dev_arr.data)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "ctx offs: " << (((uintptr_t) &(dev_arr.ctx)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "ndim offs: " << (((uintptr_t) &(dev_arr.ndim)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "dtype offs: " << (((uintptr_t) &(dev_arr.dtype)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "strides offs: " << (((uintptr_t) &(dev_arr.strides)) - ((uintptr_t) &dev_arr)) << std::endl; - std::cout << "byte_offset offs: " << (((uintptr_t) &(dev_arr.byte_offset)) - ((uintptr_t) &dev_arr)) << std::endl; - - - // Copy `arr`, update the copy's pointers to be device pointers, then - // write the copy to `tvm_arr_slot`. - //TVMArray dev_arr = arr; - // Update the device type to look like a host, because codegen generates - // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) - << "attempt to write TVMArray with non-micro device type"; - dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - // Add the base address of the device to the array's data's device offset to - // get a device address. - //DevBaseOffset arr_offset(reinterpret_cast(arr.data)); - //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); - //dev_arr.shape = shape_addr.cast_to(); - //dev_arr.strides = strides_addr.cast_to(); - tvm_arr_slot.WriteValue(dev_arr); - return tvm_arr_slot.start_addr(); -} - -void MicroSession::CheckDeviceError() { - int32_t return_code = DevSymbolRead(symbol_map_, "utvm_return_code"); - - if (return_code) { - std::uintptr_t last_error = - DevSymbolRead(symbol_map_, "utvm_last_error"); - std::string last_error_str; - if (last_error) { - DevBaseOffset last_err_offset = low_level_device()->ToDevOffset(DevPtr(last_error)); - last_error_str = ReadString(last_err_offset); - } - LOG(FATAL) << "error during micro function execution:\n" - << " return code: " << std::dec << return_code << "\n" - << " dev str addr: 0x" << std::hex << last_error << "\n" - << " dev str data: " << last_error_str << std::endl; - } -} - -void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { - void* runtime_impl_addr = symbol_map_[func_name].cast_to(); - std::ostringstream func_name_underscore; - func_name_underscore << func_name << "_"; - DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); -} - -std::string MicroSession::ReadString(DevBaseOffset str_offset) { - std::ostringstream result; - const size_t buf_size = 256; - std::vector buf(buf_size, 0); - size_t i = buf_size; - while (i == buf_size) { - low_level_device()->Read(str_offset, buf.data(), buf_size); - i = 0; - while (i < buf_size) { - if (buf[i] == 0) break; - result << buf[i]; - i++; - } - str_offset = str_offset + i; - } - return result.str(); -} - -DevBaseOffset MicroSession::AllocateInSection(SectionKind type, size_t size) { - return GetAllocator(type)->Allocate(size); -} - -void MicroSession::FreeInSection(SectionKind type, DevBaseOffset ptr) { - return GetAllocator(type)->Free(ptr); -} - -template -T MicroSession::DevSymbolRead(const SymbolMap& symbol_map, const std::string& symbol) { - DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); - T result; - low_level_device()->Read(sym_offset, &result, sizeof(T)); - return result; -} - -template -void MicroSession::DevSymbolWrite(const SymbolMap& symbol_map, - const std::string& symbol, - const T& value) { - DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); - low_level_device()->Write(sym_offset, &value, sizeof(T)); -} - -PackedFunc MicroSession::GetFunction( - const std::string& name, - const std::shared_ptr& sptr_to_self) { - if (name == "enter") { - return PackedFunc([sptr_to_self](TVMArgs args, TVMRetValue* rv) { - MicroSession::EnterWithScope(std::dynamic_pointer_cast(sptr_to_self)); - }); - } else if (name == "exit") { - return PackedFunc([sptr_to_self](TVMArgs args, TVMRetValue* rv) { - MicroSession::ExitWithScope(); - }); - } else { - return PackedFunc(); - } -} - -class MicroWrappedFunc { - public: - MicroWrappedFunc(std::shared_ptr session, - DevPtr func_ptr) { - session_ = session; - func_ptr_ = func_ptr; - } - - void operator()(TVMArgs args, TVMRetValue* rv) const { - session_->PushToExecQueue(func_ptr_, args); - } - - private: - /*! \brief reference to the session for this function (to keep the session alive) */ - std::shared_ptr session_; - /*! \brief offset of the function to be called */ - DevPtr func_ptr_; -}; - -// create micro session and low-level device from Python frontend -TVM_REGISTER_GLOBAL("micro._CreateSession") -.set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& device_type = args[0]; - const std::string& binary_path = args[1]; - const std::string& toolchain_prefix = args[2]; - uint64_t base_addr = args[3]; - const std::string& server_addr = args[4]; - int port = args[5]; - std::shared_ptr session = std::make_shared(); - //session->CreateSession( - // device_type, binary_path, toolchain_prefix, base_addr, server_addr, port); - session->CreateSession( - "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); - *rv = Module(session); - }); - -TVM_REGISTER_GLOBAL("micro._BakeSession") -.set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& binary = args[0]; - - std::shared_ptr& session = MicroSession::Current(); - session->BakeSession(binary); - }); - -TVM_REGISTER_GLOBAL("micro._GetFunction") -.set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& name = args[0]; - std::shared_ptr& session = MicroSession::Current(); - - DevPtr func_ptr = session->GetSymbolLoc(name); - *rv = PackedFunc(MicroWrappedFunc(session, func_ptr)); - }); - -} // namespace runtime -} // namespace tvm diff --git a/src/runtime/micro/device/utvm_api_stm32f767xx.c b/src/runtime/micro/device/utvm_api_stm32f767xx.c new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/runtime/micro/device/utvm_startup_stm32f767xx.s b/src/runtime/micro/device/utvm_startup_stm32f767xx.s index 2921a8e2c46d..0b5446e3035f 100644 --- a/src/runtime/micro/device/utvm_startup_stm32f767xx.s +++ b/src/runtime/micro/device/utvm_startup_stm32f767xx.s @@ -5,7 +5,7 @@ * @brief STM32F767xx Devices vector table for GCC based toolchain. * This module performs: * - Set the initial SP - * - Set the initial PC == Reset_Handler, + * - Set the initial PC == UTVMInit, * - Set the vector table entries with the exceptions ISR address * - Branches to main in the C library (which eventually * calls main()). @@ -46,20 +46,12 @@ .fpu softvfp .thumb -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ -.section .text.Reset_Handler -.weak Reset_Handler -.type Reset_Handler, %function -Reset_Handler: +.section .text.UTVMInit +.weak UTVMInit +.type UTVMInit, %function +UTVMInit: ldr sp, =_estack /* set stack pointer */ - bl main + bl UTVMMain /** * @brief This is the code that gets called when the processor receives an diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 9702ef9862e4..d48fc513bb73 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -52,10 +52,6 @@ size_t utvm_num_active_allocs = 0; const char* utvm_last_error = NULL; // NOLINT(*) int32_t utvm_return_code = 0; // NOLINT(*) -// We use a dummy function to signal execution is finished for device -// backends which require breakpoints. -void UTVMDone() { } - void UTVMMain() { utvm_workspace_curr = utvm_workspace_begin; utvm_num_active_allocs = 0; @@ -66,6 +62,10 @@ void UTVMMain() { UTVMDone(); } +// We use a dummy function to signal execution is finished for device +// backends which require breakpoints. +void UTVMDone() { } + void* TVMBackendAllocWorkspace(int device_type, int device_id, uint64_t size, int dtype_code_hint, int dtype_bits_hint) { // Align up to 8 bytes. diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index 0a9adf7af2de..bb956c89e8ec 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -47,6 +47,18 @@ typedef struct { int32_t num_args; } UTVMTask; +extern void UTVMInit(); + +extern void UTVMTimerStart(); + +extern void UTVMTimerStop(); + +extern int32_t UTVMTimerRead(); + +void UTVMMain(); + +void UTVMDone(); + #ifdef __cplusplus } // TVM_EXTERN_C #endif diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 72eb40961fbc..3779b957fc9a 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -38,21 +38,21 @@ namespace runtime { size_t GetDefaultSectionSize(SectionKind kind) { switch (kind) { case SectionKind::kText: - return 0xF000; + return 0x5000; case SectionKind::kRodata: - return 0xF000; + return 0x5000; case SectionKind::kData: - return 0xF00; + return 0x300; case SectionKind::kBss: - return 0xF00; + return 0x300; case SectionKind::kArgs: - return 0xF0000; - case SectionKind::kStack: - return 0xF000; + return 0x500; case SectionKind::kHeap: - return 0xF00000; + return 0x40000; case SectionKind::kWorkspace: - return 0xF0000; + return 0x5000; + case SectionKind::kStack: + return 0x50; default: LOG(FATAL) << "invalid section " << static_cast(kind); return 0; @@ -66,9 +66,9 @@ const char* SectionToString(SectionKind section) { case SectionKind::kData: return "data"; case SectionKind::kBss: return "bss"; case SectionKind::kArgs: return "args"; - case SectionKind::kStack: return "stack"; case SectionKind::kHeap: return "heap"; case SectionKind::kWorkspace: return "workspace"; + case SectionKind::kStack: return "stack"; default: return ""; } } diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 669971e51f1d..77f16a31813d 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -46,9 +46,9 @@ enum class SectionKind : size_t { kData, kBss, kArgs, - kStack, kHeap, kWorkspace, + kStack, kNumKinds, }; diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 8c2b6787210f..304cff18ab3d 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -80,7 +80,6 @@ class MicroModuleNode final : public ModuleNode { } private: - //std::string binary_path_; SymbolMap symbol_map_; /*! \brief global session pointer */ ObjectPtr session_; @@ -95,6 +94,7 @@ class MicroWrappedFunc { } void operator()(TVMArgs args, TVMRetValue* rv) const { + std::cout << "pushing func_ptr " << func_ptr_.cast_to() << std::endl; session_->PushToExecQueue(func_ptr_, args); } diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index c950075c179d..5443d042dfed 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -59,7 +59,7 @@ class MicroSectionAllocator { size_ = UpperAlignValue(size_, 8); CHECK(size_ + size < capacity_) << "cannot alloc " << size << " bytes in section with start_addr " << - start_offset_.value(); + start_offset_.cast_to(); DevBaseOffset alloc_ptr = start_offset_ + size_; size_ += size; alloc_map_[alloc_ptr.value()] = size; diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index c5de77743363..762454d7108a 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,15 +57,31 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { - //DevBaseOffset curr_start_offset = kDeviceStart; - //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - // size_t section_size = GetDefaultSectionSize(static_cast(i)); - // section_allocators_[i] = std::make_shared(DevMemRegion { - // .start = curr_start_offset, - // .size = section_size, - // }); - // curr_start_offset += section_size; - //} + DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); + for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + size_t section_size = GetDefaultSectionSize(static_cast(i)); + section_allocators_[i] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = section_size, + }); + curr_start_offset += section_size; + } + + + CHECK(curr_start_offset.value() < 0x20050000) << "exceeded available RAM on device (" << std::endl; + + std::cout << "[Memory Layout]" << std::endl; + std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_offset().cast_to() << std::endl; + std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_offset().cast_to() << std::endl; + std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_offset().cast_to() << std::endl; + std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_offset().cast_to() << std::endl; + std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_offset().cast_to() << std::endl; + std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_offset().cast_to() << std::endl; + std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_offset().cast_to() << std::endl; + std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_offset().cast_to() << std::endl; + + // NOTE: we don't use this for openocd + memory_size_ = 0; //memory_size_ = curr_start_offset.cast_to(); /* Linker script sample @@ -134,53 +150,64 @@ MicroSession::MicroSession() { memory_size_ = 0; */ + /* // TODO: why do we need to start 0x1c8 bytes after the start of ram? //curr_start_offset = DevBaseOffset(0x200001C8); - DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); size_t one_eighth_ram_size = 40000; - section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - - // NOTE: we don't use this for openocd - memory_size_ = 0; + DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); + + std::cout << "[Memory Layout]" << std::endl; + std::cout << "text start: " << curr_start_offset.cast_to() << std::endl; + size_t text_size + section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "rodata start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "data start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "bss start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "args start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "stack start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "heap start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "workspace start: " << curr_start_offset.cast_to() << std::endl; + section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { + .start = curr_start_offset, + .size = one_eighth_ram_size, + }); + curr_start_offset += one_eighth_ram_size; + std::cout << "WHAT THE FUCK" << std::endl; + */ } MicroSession::~MicroSession() { @@ -208,8 +235,8 @@ void MicroSession::CreateSession(const std::string& device_type, } runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; - std::cout << runtime_symbol_map_["UTVMMain"].value() << std::endl; - std::cout << runtime_symbol_map_["utvm_task"].value() << std::endl; + std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; + std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; //if (device_type == "openocd") { // // Set OpenOCD device's stack pointer. @@ -242,26 +269,31 @@ void MicroSession::CreateSession(const std::string& device_type, // whether it's a "thumb mode" function (TODO: figure out what that means). const bool kRequiresThumbModeBit = true; void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { - int32_t (*func_dev_addr)(void*, void*, int32_t) = - reinterpret_cast(func_ptr.value()); // TODO: make this a parameter. if (kRequiresThumbModeBit) { - func_dev_addr += 1; + func_ptr += 1; } + int32_t (*func_dev_addr)(void*, void*, int32_t) = + reinterpret_cast(func_ptr.value()); + std::cout << "AA" << std::endl; // Create an allocator stream for the memory region after the most recent // allocation in the args section. DevPtr args_addr = low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); TargetDataLayoutEncoder encoder(args_addr); + std::cout << "BB" << std::endl; std::tuple arg_field_addrs = EncoderAppend(&encoder, args); + std::cout << "BBB" << std::endl; // Flush `stream` to device memory. DevBaseOffset stream_dev_offset = GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); + std::cout << "BBBB" << std::endl; low_level_device()->Write(stream_dev_offset, reinterpret_cast(encoder.data()), encoder.buf_size()); + std::cout << "CC" << std::endl; //UTVMTask task = { // .func = func_dev_addr, @@ -289,12 +321,14 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { }; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); + std::cout << "DD" << std::endl; DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); if (kRequiresThumbModeBit) { utvm_main_loc += 1; } + std::cout << "EE" << std::endl; // TODO: figure out why it's not running anymore when we compile it with "-c" // instead of "-shared". we should be relocating the binary. @@ -379,10 +413,13 @@ std::tuple MicroSession::EncoderAppend( const int* type_codes = args.type_codes; int num_args = args.num_args; + std::cout << "AYY" << std::endl; auto tvm_vals_slot = encoder->Alloc(num_args); auto type_codes_slot = encoder->Alloc(num_args); + std::cout << "LMAO" << std::endl; for (int i = 0; i < num_args; i++) { + std::cout << "WAZ " << i << std::endl; switch (type_codes[i]) { case kNDArrayContainer: case kArrayHandle: { @@ -393,8 +430,10 @@ std::tuple MicroSession::EncoderAppend( void* old_data = base_arr_handle->data; // Mutate the array to unwrap the `data` field. base_arr_handle->data = reinterpret_cast(old_data)->data; + std::cout << " GLOMO" << std::endl; // Now, encode the unwrapped version. void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + std::cout << " FOMO" << std::endl; // And restore the original wrapped version. base_arr_handle->data = old_data; @@ -434,6 +473,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr auto tvm_arr_slot = encoder->Alloc(); auto shape_slot = encoder->Alloc(arr.ndim); + std::cout << "WRITE" << std::endl; // `shape` and `strides` are stored on the host, so we need to write them to // the device first. The `data` field is already allocated on the device and // is a device pointer, so we don't need to write it. @@ -445,6 +485,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr stride_slot.WriteArray(arr.strides, arr.ndim); strides_addr = stride_slot.start_addr(); } + std::cout << "ON" << std::endl; int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); @@ -460,13 +501,17 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr .pad2 = 0, }; + std::cout << "DIDDLY" << std::endl; + // Copy `arr`, update the copy's pointers to be device pointers, then // write the copy to `tvm_arr_slot`. //TVMArray dev_arr = arr; // Update the device type to look like a host, because codegen generates // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) - << "attempt to write TVMArray with non-micro device type"; + std::cout << "DEV TYPE: " << dev_arr.ctx.device_type << std::endl; + std::cout << "DEV TYPE == MICRO: " << (dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << std::endl; + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; + std::cout << "FRICKIN" << std::endl; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; // Add the base address of the device to the array's data's device offset to // get a device address. @@ -474,7 +519,9 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); //dev_arr.shape = shape_addr.cast_to(); //dev_arr.strides = strides_addr.cast_to(); + std::cout << "DANG" << std::endl; tvm_arr_slot.WriteValue(dev_arr); + std::cout << "TIME" << std::endl; return tvm_arr_slot.start_addr(); } @@ -497,10 +544,16 @@ void MicroSession::CheckDeviceError() { } void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { - void* runtime_impl_addr = runtime_symbol_map_[func_name].cast_to(); + //void* runtime_impl_addr = runtime_symbol_map_[func_name].cast_to(); + DevPtr runtime_impl_addr = runtime_symbol_map_[func_name]; + if (kRequiresThumbModeBit) { + runtime_impl_addr += 1; + } + std::cout << "patching " << func_name << " with addr " << runtime_impl_addr.cast_to() << std::endl; std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; - DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr); + DevSymbolWrite(symbol_map, func_name_underscore.str(), (int32_t) runtime_impl_addr.value()); + std::cout << "finished patching" << std::endl; } std::string MicroSession::ReadString(DevBaseOffset str_offset) { diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 1ec3e5b1a008..13f856fed828 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -126,7 +126,6 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } void Write(DevBaseOffset offset, const void* buf, size_t num_bytes) { - std::cout << "here and writing " << std::dec << num_bytes << " bytes" << std::endl; if (num_bytes == 0) { return; } diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index bc9857013f24..ad4f8ee637cc 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -51,9 +51,7 @@ def create_micro_mod(c_mod, toolchain_prefix): c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix=toolchain_prefix)) - print("BEFORE") micro_mod = tvm.module.load(lib_obj_path, "micro_dev") - print("AFTER") return micro_mod @@ -82,6 +80,26 @@ def relay_micro_build(func, toolchain_prefix, params=None): return mod +def reset_gdbinit(): + with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: + gdbinit_contents = """ +layout asm +target remote localhost:3333 +print "(*((TVMValue*) utvm_task.arg_values)).v_handle" +print (*((TVMValue*) utvm_task.arg_values)).v_handle +print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" +print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) +print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" +print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] +print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" +print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] +break UTVMMain +break UTVMDone +jump UTVMMain + """ + f.write(gdbinit_contents) + + # TODO(weberlo): Add example program to test scalar double/int TVMValue serialization. # TODO(weberlo): How can we test the OpenOCD device? The CI would need to have OpenOCD # and Spike installed. @@ -117,18 +135,13 @@ def test_add(): c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - print("A") micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) - print("B") micro_func = micro_mod[func_name] - print("C") ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print("D") micro_func(a, b, c) - print("E") tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + b.asnumpy()) @@ -141,6 +154,8 @@ def test_workspace_add(): shape = (1024,) dtype = "float32" + reset_gdbinit() + # Construct TVM expression. tvm_shape = tvm.convert(shape) A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) @@ -188,6 +203,53 @@ def test_graph_runtime(): result, x_in * x_in + 1.0) +def test_conv2d(): + if not tvm.module.enabled("micro_dev"): + return + + from tvm.relay import create_executor + from tvm.relay import transform + + reset_gdbinit() + + dshape = (1, 4, 16, 16) + for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: + # Construct Relay program. + x = relay.var("x", shape=dshape, dtype=dtype) + conv_expr = relay.nn.conv2d( + x, relay.var("w"), + kernel_size=(3, 3), + padding=(1, 1), + channels=4) + func = relay.Function(relay.analysis.free_vars(conv_expr), conv_expr) + mod = relay.Module.from_expr(func) + mod = transform.InferType()(mod) + + x_shape = list(map(lambda x: x.value, mod['main'].params[0].checked_type.shape)) + w_shape = list(map(lambda x: x.value, mod['main'].params[1].checked_type.shape)) + out_shape = list(map(lambda x: x.value, mod['main'].ret_type.shape)) + + with tvm.build_config(disable_vectorize=True): + graph, c_mod, params = relay.build(mod, target="c") + + with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): + micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + micro_func = micro_mod[func_name] + ctx = tvm.micro_dev(0) + + x_data = tvm.nd.array(np.random.uniform(size=x_shape).astype(dtype), ctx) + w_data = tvm.nd.array(np.random.uniform(size=w_shape).astype(dtype), ctx) + result = tvm.nd.array(np.zeros(shape=out_shape, dtype=dtype), ctx) + micro_func(x_data, w_data, result) + + out_data = np.zeros(out_shape, dtype=dtype) + params = { 'x': x_data.asnumpy(), 'w': w_data.asnumpy() } + intrp = create_executor('debug') + expected_result = intrp.evaluate(mod['main'])(x_data, w_data).data + + tvm.testing.assert_allclose(result.asnumpy(), expected_result.asnumpy()) + + def test_multiple_modules(): """Test loading multiple modules on the device simultaneously.""" if not tvm.module.enabled("micro_dev"): @@ -308,87 +370,16 @@ def test_inactive_session_use(): add_result, np_tensor_a + 1.0) -#-------------------------------------------------------------------------------- -#-------------------------------------------------------------------------------- -#-------------------------------------------------------------------------------- - - -def test_arm_add(): - """Test a module which performs addition.""" - #import tvm - if not tvm.module.enabled("micro_dev"): - return - shape = (1024,) - dtype = "float32" - - #import subprocess - #import os - #import copy - #from shutil import copyfile - - #from tvm._ffi.libinfo import find_include_path - #from tvm.micro import _get_micro_device_dir - #from tvm.contrib import binutil - - print('constructing tvm expr') - # Construct TVM expression. - tvm_shape = tvm.convert(shape) - A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) - B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) - C = tvm.compute(A.shape, lambda *i: A(*i) + B(*i), name="C") - s = tvm.create_schedule(C.op) - - func_name = "fadd" - c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) - - print('starting session') - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) as sess: - # TODO: since we're adding modules with `sess.add_module`, we're not - # creating micro modules (like below). how do we get packed funcs from - # the session though? we might need to do the enqueueing in C++ and - # call into a Python function that does all of the baking. If that's - # the case, then we'll need to create all of the micro mods we want, - # *then* call sess.bake, which should just execute the same Python code - # as in micro/base.py, but with a trip to C++ in between. - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) - micro_func = micro_mod[func_name] - - #sess.add_module(c_mod) - print('baking session') - #sess.bake() - print(f'grabbing {func_name} from session') - #micro_func = sess.get_func(func_name) - print(f'grabbed it') - - ctx = tvm.micro_dev(0) - a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print(a) - print(b) - print(c) - # TODO: the fadd example is leaving the C vector with all zeros. the - # device must not be executing the fadd. do a GDB stepthrough. could - # also try loading in the original blinky program (or some slight - # variant of it) to see if we're loading shit onto the device - # correctly. - input('not gon work') - micro_func(a, b, c) - print('--------------------------------------------------------------------------------') - print(c) - - - #tvm.testing.assert_allclose( - # c.asnumpy(), a.asnumpy() + b.asnumpy()) - - if __name__ == "__main__": #test_alloc() #test_add() #test_workspace_add() #test_graph_runtime() + + test_conv2d() + #test_multiple_modules() #test_interleave_sessions() #test_nested_sessions() #test_inactive_session_use() - test_arm_add() + #test_arm_add() From 70e9b7558fb23735804a8213a267b1aa8a390225 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 21 Oct 2019 16:18:21 -0700 Subject: [PATCH 12/70] added timing funcs but now floating point instructions don't work --- python/tvm/contrib/binutil.py | 1 + python/tvm/micro/__init__.py | 2 +- python/tvm/micro/base.py | 152 ++++++++++++------ src/runtime/micro/device/stm32f746/utvm_api.c | 55 +++++++ .../utvm_init.s} | 4 +- .../utvm_link.ld} | 32 ++-- .../micro/device/utvm_api_stm32f767xx.c | 0 src/runtime/micro/host_driven/utvm_runtime.h | 3 +- src/runtime/micro/micro_session.cc | 3 +- tests/python/unittest/test_runtime_micro.py | 41 ++--- 10 files changed, 207 insertions(+), 86 deletions(-) create mode 100644 src/runtime/micro/device/stm32f746/utvm_api.c rename src/runtime/micro/device/{utvm_startup_stm32f767xx.s => stm32f746/utvm_init.s} (92%) rename src/runtime/micro/device/{UTVM_STM32F746ZGTx_FLASH.ld => stm32f746/utvm_link.ld} (73%) delete mode 100644 src/runtime/micro/device/utvm_api_stm32f767xx.c diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index a61664ac5b30..77aae18c19f1 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -262,6 +262,7 @@ def tvm_callback_relocate_binary( raise RuntimeError(msg) print(f'relocated obj path is {rel_obj_path}') + input('check it out') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 2f3981903cab..1162dc804c0f 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,4 +23,4 @@ """ from ..contrib import binutil -from .base import Session, cross_compiler, create_micro_lib +from .base import LibType, Session, cross_compiler, create_micro_lib diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index f7e0cbdee7e6..317a596bdf94 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -22,6 +22,7 @@ import logging import os import sys +from enum import Enum from tvm.contrib import util as _util from tvm.contrib import cc as _cc @@ -31,6 +32,11 @@ SUPPORTED_DEVICE_TYPES = ["host", "openocd"] +class LibType(Enum): + RUNTIME = 0 + OPERATOR = 1 + + class Session: """MicroTVM Device Session @@ -68,11 +74,11 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): #self._check_args(device_type, kwargs) # First, find and compile runtime library. - runtime_src_path = os.path.join(_get_micro_device_dir(), "utvm_runtime.c") + runtime_src_path = os.path.join(_get_micro_host_driven_dir(), "utvm_runtime.c") tmp_dir = _util.tempdir() runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") create_micro_lib( - runtime_obj_path, runtime_src_path, toolchain_prefix, include_dev_lib_header=False) + runtime_obj_path, runtime_src_path, toolchain_prefix, LibType.RUNTIME) self.op_modules = [] @@ -118,7 +124,7 @@ def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() -def _get_micro_device_dir(): +def _get_micro_host_driven_dir(): """Get directory path for uTVM host-driven runtime source files. Return @@ -127,12 +133,26 @@ def _get_micro_device_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, "..", "..", "..", + micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", "src", "runtime", "micro", "host_driven") + return micro_host_driven_dir + + +def _get_micro_device_dir(): + """Get directory path for TODO + + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_device_dir = os.path.join(micro_dir, "..", "..", "..", + "src", "runtime", "micro", "device") return micro_device_dir -def cross_compiler(toolchain_prefix, include_dev_lib_header=True): +def cross_compiler(toolchain_prefix, lib_type): """Creates a cross compile function that wraps `create_micro_lib`. For use in `tvm.module.Module.export_library`. @@ -166,12 +186,12 @@ def compile_func(obj_path, src_path, **kwargs): if isinstance(src_path, list): src_path = src_path[0] create_micro_lib(obj_path, src_path, toolchain_prefix, - kwargs.get("options", None), include_dev_lib_header) + lib_type, kwargs.get("options", None)) return _cc.cross_compiler(compile_func) def create_micro_lib( - obj_path, src_path, toolchain_prefix, options=None, include_dev_lib_header=True): + obj_path, src_path, toolchain_prefix, lib_type, options=None): """Compiles code into a binary for the target micro device. Parameters @@ -190,12 +210,12 @@ def create_micro_lib( library functions. """ if toolchain_prefix == '': - create_host_micro_lib(obj_path, src_path, toolchain_prefix, options, include_dev_lib_header) + create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) elif toolchain_prefix == 'arm-none-eabi-': - create_arm_micro_lib(obj_path, src_path, toolchain_prefix, options, include_dev_lib_header) + create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) def create_host_micro_lib( - obj_path, src_path, toolchain_prefix, options, include_dev_lib_header): + obj_path, src_path, toolchain_prefix, lib_type, options): def replace_suffix(s, new_suffix): if "." in os.path.basename(s): # There already exists an extension. @@ -214,7 +234,7 @@ def replace_suffix(s, new_suffix): obj_path = replace_suffix(obj_path, "obj") options = ["-I" + path for path in find_include_path()] - options += ["-I{}".format(_get_micro_device_dir())] + options += ["-I{}".format(_get_micro_host_driven_dir())] options += ["-fno-stack-protector"] # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host # device. @@ -237,8 +257,9 @@ def replace_suffix(s, new_suffix): _cc.create_shared(obj_path, src_path, options, compile_cmd) + def create_arm_micro_lib( - obj_path, src_path, toolchain_prefix, options, include_dev_lib_header): + obj_path, src_path, toolchain_prefix, lib_type, options): import subprocess import os import copy @@ -247,32 +268,38 @@ def create_arm_micro_lib( from tvm._ffi.libinfo import find_include_path from tvm.contrib import binutil - tmp_dir = _util.tempdir() - if include_dev_lib_header: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - temp_src_path = tmp_dir.relpath("temp.c") - with open(src_path, "r") as f: - src_lines = f.read().splitlines() - src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") - with open(temp_src_path, "w") as f: - f.write("\n".join(src_lines)) - src_path = temp_src_path - - paths = [('-I', path) for path in find_include_path()] - paths += [('-I', _get_micro_device_dir())] + def replace_suffix(s, new_suffix): + if "." in os.path.basename(s): + # There already exists an extension. + return os.path.join( + os.path.dirname(s), + ".".join(os.path.basename(s).split(".")[:-1] + [new_suffix])) + # No existing extension; we can just append. + return s + "." + new_suffix - compile_cmd = [ + def run_cmd(cmd): + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + (out, _) = proc.communicate() + if proc.returncode != 0: + msg = "Compilation error:\n" + msg += out.decode("utf-8") + raise RuntimeError(msg) + + base_compile_cmd = [ 'arm-none-eabi-gcc', '-std=c11', '-Wall', '-Wextra', '--pedantic', - '-fstack-usage', '-mcpu=cortex-m7', '-mlittle-endian', '-mfloat-abi=hard', '-mfpu=fpv5-sp-d16', + '-mthumb', + '-c', '-O0', '-g', '-gdwarf-5', @@ -280,24 +307,57 @@ def create_arm_micro_lib( '-nodefaultlibs', '-nostdlib', '-fdata-sections', - '-ffunction-sections', - '-c'] - for s, path in paths: - compile_cmd += [s, path] - temp_obj_path = tmp_dir.relpath('temp.o') - compile_cmd += ['-o', obj_path, src_path] - - proc = subprocess.Popen( - compile_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - (out, _) = proc.communicate() - if proc.returncode != 0: - msg = "Compilation error:\n" - msg += out.decode("utf-8") - raise RuntimeError(msg) - - print('finished') + '-ffunction-sections'] + + src_paths = [] + ld_script_path = None + tmp_dir = _util.tempdir() + if lib_type == LibType.RUNTIME: + import glob + DEVICE_ID = 'stm32f746' + dev_dir = _get_micro_device_dir() + '/' + DEVICE_ID + + dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + assert dev_src_paths + src_paths += dev_src_paths + elif lib_type == LibType.OPERATOR: + # Create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath("temp.c") + with open(src_path, "r") as f: + src_lines = f.read().splitlines() + src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") + with open(temp_src_path, "w") as f: + f.write("\n".join(src_lines)) + src_path = temp_src_path + + base_compile_cmd += ['-c'] + else: + raise RuntimeError('unknown lib type') + + src_paths += [src_path] + + include_paths = find_include_path() + [_get_micro_host_driven_dir()] + for path in include_paths: + base_compile_cmd += ['-I', path] + + prereq_obj_paths = [] + for src_path in src_paths: + print(f'compiling {src_path}') + curr_obj_path = replace_suffix(src_path, 'o') + prereq_obj_paths.append(curr_obj_path) + curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + + #compile_cmd_str = ' '.join(curr_compile_cmd) + #print(f'running "{compile_cmd_str}"') + run_cmd(curr_compile_cmd) + print(f'finished compiling {src_path}') + + ld_cmd = ['arm-none-eabi-ld', '-relocatable'] + ld_cmd += prereq_obj_paths + ld_cmd += ['-o', obj_path] + run_cmd(ld_cmd) + input(f'check obj {obj_path}') _init_api("tvm.micro", "tvm.micro.base") diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c new file mode 100644 index 000000000000..7174ffb21d2c --- /dev/null +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -0,0 +1,55 @@ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "utvm_runtime.h" + +#define SYST_CSR (*((volatile unsigned long *) 0xE000E010)) +#define SYST_RVR (*((volatile unsigned long *) 0xE000E014)) +#define SYST_CVR (*((volatile unsigned long *) 0xE000E018)) +#define SYST_CALIB (*((volatile unsigned long *) 0xE000E01C)) + +#define SYST_CSR_ENABLE 0 +#define SYST_CSR_TICKINT 1 +#define SYST_CSR_CLKSOURCE 2 +#define SYST_COUNTFLAG 16 + +#define SYST_CALIB_NOREF 31 +#define SYST_CALIB_SKEW 30 + +unsigned long start_time = 0; +unsigned long stop_time = 0; +unsigned long duration = 0; + +void UTVMTimerStart() { + SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); + // wait until timer starts + while (SYST_CVR == 0); + start_time = SYST_CVR; +} + +void UTVMTimerStop() { + SYST_CSR = 0; + stop_time = SYST_CVR; +} + +void UTVMTimerReset() { + SYST_CSR = 0; + // maximum reload value (24-bit) + SYST_RVR = (~((unsigned long) 0)) >> 8; + SYST_CVR = 0; +} + +int32_t UTVMTimerRead() { + if (!(SYST_CSR & SYST_COUNTFLAG)) { + return start_time - stop_time; + } else { + TVMAPISetLastError("timer overflowed"); + return -1; + } +} + +#ifdef __cplusplus +} // TVM_EXTERN_C +#endif diff --git a/src/runtime/micro/device/utvm_startup_stm32f767xx.s b/src/runtime/micro/device/stm32f746/utvm_init.s similarity index 92% rename from src/runtime/micro/device/utvm_startup_stm32f767xx.s rename to src/runtime/micro/device/stm32f746/utvm_init.s index 0b5446e3035f..02be2efc2c71 100644 --- a/src/runtime/micro/device/utvm_startup_stm32f767xx.s +++ b/src/runtime/micro/device/stm32f746/utvm_init.s @@ -50,7 +50,9 @@ .weak UTVMInit .type UTVMInit, %function UTVMInit: - ldr sp, =_estack /* set stack pointer */ + /* ldr sp, =_estack */ /* set stack pointer */ + /* ldr sp, =0x20050000 */ /* set stack pointer */ + ldr sp, =0x2004fffc /* set stack pointer */ bl UTVMMain /** diff --git a/src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld b/src/runtime/micro/device/stm32f746/utvm_link.ld similarity index 73% rename from src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld rename to src/runtime/micro/device/stm32f746/utvm_link.ld index d62165e60b20..c90c140dd19d 100644 --- a/src/runtime/micro/device/UTVM_STM32F746ZGTx_FLASH.ld +++ b/src/runtime/micro/device/stm32f746/utvm_link.ld @@ -30,7 +30,7 @@ */ /* Entry Point */ -ENTRY(Reset_Handler) +ENTRY(UTVMInit) /* Highest address of the user mode stack */ _estack = 0x20050000; /* end of RAM */ @@ -45,45 +45,43 @@ FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K /* Define output sections */ SECTIONS { + /* . = %s; */ + . = ALIGN(4); .text : { . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ + *(.text) + *(.text*) . = ALIGN(4); } >RAM + /* . = %s; */ + . = ALIGN(4); .rodata : { . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.rodata) + *(.rodata*) . = ALIGN(4); } >RAM + /* . = %s; */ + . = ALIGN(4); .data : { . = ALIGN(4); - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ + *(.data) + *(.data*) . = ALIGN(4); } >RAM - /* Uninitialized data section */ + /* . = %s; */ . = ALIGN(4); .bss : { + . = ALIGN(4); *(.bss) *(.bss*) . = ALIGN(4); } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } } - diff --git a/src/runtime/micro/device/utvm_api_stm32f767xx.c b/src/runtime/micro/device/utvm_api_stm32f767xx.c deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index bb956c89e8ec..7030fdf0bc5f 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -30,7 +30,6 @@ extern "C" { #include #include -// TODO(weberlo): do we need this? #include /*! @@ -53,6 +52,8 @@ extern void UTVMTimerStart(); extern void UTVMTimerStop(); +extern void UTVMTimerReset(); + extern int32_t UTVMTimerRead(); void UTVMMain(); diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 762454d7108a..885e7827c463 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -323,7 +323,8 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); std::cout << "DD" << std::endl; - DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); + //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); + DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); if (kRequiresThumbModeBit) { utvm_main_loc += 1; diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index ad4f8ee637cc..6b5d78e0755e 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -50,7 +50,7 @@ def create_micro_mod(c_mod, toolchain_prefix): lib_obj_path = temp_dir.relpath("dev_lib.obj") c_mod.export_library( lib_obj_path, - fcompile=tvm.micro.cross_compiler(toolchain_prefix=toolchain_prefix)) + fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path, "micro_dev") return micro_mod @@ -82,21 +82,21 @@ def relay_micro_build(func, toolchain_prefix, params=None): def reset_gdbinit(): with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: - gdbinit_contents = """ -layout asm + gdbinit_contents = ( +"""layout asm target remote localhost:3333 -print "(*((TVMValue*) utvm_task.arg_values)).v_handle" -print (*((TVMValue*) utvm_task.arg_values)).v_handle -print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" -print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) -print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" -print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] -print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" -print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] -break UTVMMain -break UTVMDone -jump UTVMMain - """ + +#print "(*((TVMValue*) utvm_task.arg_values)).v_handle" +#print (*((TVMValue*) utvm_task.arg_values)).v_handle +#print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" +#print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) +#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" +#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] +#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" +#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] +#break UTVMMain +#break UTVMDone +#jump UTVMMain""") f.write(gdbinit_contents) @@ -124,6 +124,8 @@ def test_add(): shape = (1024,) dtype = "float32" + reset_gdbinit() + # Construct TVM expression. tvm_shape = tvm.convert(shape) A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) @@ -210,10 +212,11 @@ def test_conv2d(): from tvm.relay import create_executor from tvm.relay import transform - reset_gdbinit() - dshape = (1, 4, 16, 16) - for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: + #for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: + for dtype, func_name in [('int8', 'fused_nn_conv2d')]: + reset_gdbinit() + # Construct Relay program. x = relay.var("x", shape=dshape, dtype=dtype) conv_expr = relay.nn.conv2d( @@ -222,7 +225,7 @@ def test_conv2d(): padding=(1, 1), channels=4) func = relay.Function(relay.analysis.free_vars(conv_expr), conv_expr) - mod = relay.Module.from_expr(func) + mod = relay.Module.from_expr(func) mod = transform.InferType()(mod) x_shape = list(map(lambda x: x.value, mod['main'].params[0].checked_type.shape)) From 61974233170d4c32eb866ee6357971907f53789f Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 23 Oct 2019 14:25:00 -0700 Subject: [PATCH 13/70] bring FPU back online and print execution times --- python/tvm/micro/base.py | 22 +++++++++++++++++++ src/runtime/micro/device/stm32f746/utvm_api.c | 3 ++- .../micro/device/stm32f746/utvm_init.s | 10 ++++++++- src/runtime/micro/host_driven/utvm_runtime.c | 7 ++++++ src/runtime/micro/micro_module.cc | 1 - src/runtime/micro/micro_session.cc | 3 +++ tests/python/unittest/test_runtime_micro.py | 3 +-- 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 317a596bdf94..d93a32d469e8 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -353,6 +353,28 @@ def run_cmd(cmd): run_cmd(curr_compile_cmd) print(f'finished compiling {src_path}') + #base_compile_cmd = [ + # 'arm-none-eabi-gcc', + # '-std=c11', + # '-Wall', + # '-Wextra', + # '--pedantic', + # '-mcpu=cortex-m7', + # '-mlittle-endian', + # '-mfloat-abi=hard', + # '-mfpu=fpv5-sp-d16', + # '-mthumb', + # '-O0', + # '-g', + # '-gdwarf-5', + # '-nostartfiles', + # '-nodefaultlibs', + # '-nostdlib', + # '-fdata-sections', + # '-ffunction-sections'] + #curr_compile_cmd = base_compile_cmd + prereq_obj_paths + ['-o', obj_path] + #run_cmd(curr_compile_cmd) + ld_cmd = ['arm-none-eabi-ld', '-relocatable'] ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c index 7174ffb21d2c..16bb541f48c0 100644 --- a/src/runtime/micro/device/stm32f746/utvm_api.c +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -23,7 +23,8 @@ unsigned long stop_time = 0; unsigned long duration = 0; void UTVMTimerStart() { - SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); + //SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); + SYST_CSR = (1 << SYST_CSR_ENABLE); // wait until timer starts while (SYST_CVR == 0); start_time = SYST_CVR; diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s b/src/runtime/micro/device/stm32f746/utvm_init.s index 02be2efc2c71..c78ae02c32f0 100644 --- a/src/runtime/micro/device/stm32f746/utvm_init.s +++ b/src/runtime/micro/device/stm32f746/utvm_init.s @@ -52,7 +52,15 @@ UTVMInit: /* ldr sp, =_estack */ /* set stack pointer */ /* ldr sp, =0x20050000 */ /* set stack pointer */ - ldr sp, =0x2004fffc /* set stack pointer */ + ldr r0, =0xE000ED88 + ldr r1, [r0] + ldr r2, =0xF00000 + orr r1, r2 + str r1, [r0] + dsb + isb + /* set stack pointer */ + ldr sp, =0x2004fffc bl UTVMMain /** diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index d48fc513bb73..0ed996d0f246 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -52,13 +52,20 @@ size_t utvm_num_active_allocs = 0; const char* utvm_last_error = NULL; // NOLINT(*) int32_t utvm_return_code = 0; // NOLINT(*) +int32_t utvm_task_time = 0; + +// Gets called by UTVMInit, after device-specific initialization is finished. void UTVMMain() { utvm_workspace_curr = utvm_workspace_begin; utvm_num_active_allocs = 0; utvm_last_error = NULL; // NOLINT(*) utvm_return_code = 0; + UTVMTimerReset(); + UTVMTimerStart(); utvm_return_code = utvm_task.func((void*) utvm_task.arg_values, (void*) utvm_task.arg_type_codes, // NOLINT(*) utvm_task.num_args); + UTVMTimerStop(); + utvm_task_time = UTVMTimerRead(); UTVMDone(); } diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 304cff18ab3d..abfc6b36f2f9 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -94,7 +94,6 @@ class MicroWrappedFunc { } void operator()(TVMArgs args, TVMRetValue* rv) const { - std::cout << "pushing func_ptr " << func_ptr_.cast_to() << std::endl; session_->PushToExecQueue(func_ptr_, args); } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 885e7827c463..0e176a23beae 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -341,6 +341,9 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Check if there was an error during execution. If so, log it. CheckDeviceError(); + int32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); + std::cout << "TASK TIME WAS " << task_time << std::endl; + GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); } diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 6b5d78e0755e..2bef7fd0be12 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -213,8 +213,7 @@ def test_conv2d(): from tvm.relay import transform dshape = (1, 4, 16, 16) - #for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: - for dtype, func_name in [('int8', 'fused_nn_conv2d')]: + for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: reset_gdbinit() # Construct Relay program. From 88e34dd7d436d0afc7282aa87af00fdbbb3a0800 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 23 Oct 2019 20:34:44 -0700 Subject: [PATCH 14/70] Add alternative timing impl --- python/tvm/contrib/binutil.py | 2 +- python/tvm/micro/base.py | 31 +------ python/tvm/relay/build_module.py | 13 --- src/codegen/build_module.cc | 3 - src/codegen/codegen_c_host.cc | 24 +++--- src/runtime/micro/device/stm32f746/utvm_api.c | 43 +++++++++- src/runtime/micro/host_driven/utvm_runtime.h | 4 +- src/runtime/micro/micro_session.cc | 24 ------ tests/python/unittest/test_runtime_micro.py | 82 +++++++++++++++++-- 9 files changed, 130 insertions(+), 96 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 77aae18c19f1..26dfa99789fe 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -262,7 +262,7 @@ def tvm_callback_relocate_binary( raise RuntimeError(msg) print(f'relocated obj path is {rel_obj_path}') - input('check it out') + #input('check it out') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index d93a32d469e8..ab5c801b37ba 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -343,43 +343,16 @@ def run_cmd(cmd): prereq_obj_paths = [] for src_path in src_paths: - print(f'compiling {src_path}') - curr_obj_path = replace_suffix(src_path, 'o') + curr_obj_path = tmp_dir.relpath(replace_suffix(os.path.basename(src_path), 'o')) prereq_obj_paths.append(curr_obj_path) curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] - - #compile_cmd_str = ' '.join(curr_compile_cmd) - #print(f'running "{compile_cmd_str}"') run_cmd(curr_compile_cmd) - print(f'finished compiling {src_path}') - - #base_compile_cmd = [ - # 'arm-none-eabi-gcc', - # '-std=c11', - # '-Wall', - # '-Wextra', - # '--pedantic', - # '-mcpu=cortex-m7', - # '-mlittle-endian', - # '-mfloat-abi=hard', - # '-mfpu=fpv5-sp-d16', - # '-mthumb', - # '-O0', - # '-g', - # '-gdwarf-5', - # '-nostartfiles', - # '-nodefaultlibs', - # '-nostdlib', - # '-fdata-sections', - # '-ffunction-sections'] - #curr_compile_cmd = base_compile_cmd + prereq_obj_paths + ['-o', obj_path] - #run_cmd(curr_compile_cmd) ld_cmd = ['arm-none-eabi-ld', '-relocatable'] ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] run_cmd(ld_cmd) - input(f'check obj {obj_path}') + print(f'compiled obj {obj_path}') _init_api("tvm.micro", "tvm.micro.base") diff --git a/python/tvm/relay/build_module.py b/python/tvm/relay/build_module.py index b8503df78a5b..28ce16b9b452 100644 --- a/python/tvm/relay/build_module.py +++ b/python/tvm/relay/build_module.py @@ -100,20 +100,7 @@ def build(self, func, target=None, target_host=None, params=None): params : dict The parameters of the final graph. """ - print(type(target)) - print(target) - print(type(list(target.keys())[0])) - print(list(target.keys())[0]) - print(type(list(target.values())[0])) - print(list(target.values())[0]) target = _update_target(target) - print('WEEEEEEEEE') - print(type(target)) - print(target) - print(type(list(target.keys())[0])) - print(list(target.keys())[0]) - print(type(list(target.values())[0])) - print(list(target.values())[0]) # Setup the params. if params: diff --git a/src/codegen/build_module.cc b/src/codegen/build_module.cc index 064840d286ee..ac991d4bfea3 100644 --- a/src/codegen/build_module.cc +++ b/src/codegen/build_module.cc @@ -230,9 +230,6 @@ Target Target::Create(const std::string& target_str) { options.push_back(item); } - std::cout << "target str: " << target_str << std::endl; - std::cout << "target name: " << target_name << std::endl; - return CreateTarget(target_name, options); } diff --git a/src/codegen/codegen_c_host.cc b/src/codegen/codegen_c_host.cc index 8e8c6633c22c..986c4f94ec94 100644 --- a/src/codegen/codegen_c_host.cc +++ b/src/codegen/codegen_c_host.cc @@ -109,7 +109,7 @@ void CodeGenCHost::PrintType(Type t, std::ostream& os) { // NOLINT(*) if (t.is_float()) { switch (t.bits()) { case 16: - os << "half"; + os << "_Float16"; break; case 32: os << "float"; break; case 64: @@ -237,17 +237,17 @@ void CodeGenCHost::VisitExpr_(const Call *op, std::ostream& os) { // NOLINT(*) } void CodeGenCHost::VisitStmt_(const AssertStmt *op) { // NOLINT(*) - std::string cond = PrintExpr(op->condition); - PrintIndent(); - stream << "if (!(" << cond << ")) {\n"; - int assert_if_scope = this->BeginScope(); - PrintIndent(); - stream << "TVMAPISetLastError(\"" << op->message.as()->value << "\");\n"; - PrintIndent(); - stream << "return -1;\n"; - this->EndScope(assert_if_scope); - PrintIndent(); - stream << "}\n"; + //std::string cond = PrintExpr(op->condition); + //PrintIndent(); + //stream << "if (!(" << cond << ")) {\n"; + //int assert_if_scope = this->BeginScope(); + //PrintIndent(); + //stream << "TVMAPISetLastError(\"" << op->message.as()->value << "\");\n"; + //PrintIndent(); + //stream << "return -1;\n"; + //this->EndScope(assert_if_scope); + //PrintIndent(); + //stream << "}\n"; this->PrintStmt(op->body); } diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c index 16bb541f48c0..459afe6a2bb0 100644 --- a/src/runtime/micro/device/stm32f746/utvm_api.c +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -20,11 +20,9 @@ extern "C" { unsigned long start_time = 0; unsigned long stop_time = 0; -unsigned long duration = 0; void UTVMTimerStart() { - //SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); - SYST_CSR = (1 << SYST_CSR_ENABLE); + SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); // wait until timer starts while (SYST_CVR == 0); start_time = SYST_CVR; @@ -51,6 +49,45 @@ int32_t UTVMTimerRead() { } } +/* +#define DWT_CTRL (*((volatile unsigned long *) 0xE0001000)) +#define DWT_CYCCNT (*((volatile unsigned long *) 0xE0001004)) + +#define DWT_CTRL_NOCYCCNT 25 +#define DWT_CTRL_CYCCNTENA 0 + +unsigned long start_time = 0; +unsigned long stop_time = 0; + +void UTVMTimerReset() { + DWT_CYCCNT = 0; +} + +void UTVMTimerStart() { + // TODO: change API so we can return errors from here + //if (DWT_CTRL & DWT_CTRL_NOCYCCNT) { + // TVMAPISetLastError("cycle counter not implemented on device"); + // return -1; + //} + start_time = DWT_CYCCNT; + DWT_CTRL |= (1 << DWT_CTRL_CYCCNTENA); +} + +void UTVMTimerStop() { + stop_time = DWT_CYCCNT; + DWT_CTRL &= ~(1 << DWT_CTRL_CYCCNTENA); +} + +int32_t UTVMTimerRead() { + if (stop_time > stop_time) { + return stop_time - start_time; + } else { + unsigned long largest = ~0; + return (largest - start_time) + stop_time; + } +} +*/ + #ifdef __cplusplus } // TVM_EXTERN_C #endif diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index 7030fdf0bc5f..8c789298d072 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -48,12 +48,12 @@ typedef struct { extern void UTVMInit(); +extern void UTVMTimerReset(); + extern void UTVMTimerStart(); extern void UTVMTimerStop(); -extern void UTVMTimerReset(); - extern int32_t UTVMTimerRead(); void UTVMMain(); diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 0e176a23beae..720e8a7d354b 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -276,24 +276,19 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { int32_t (*func_dev_addr)(void*, void*, int32_t) = reinterpret_cast(func_ptr.value()); - std::cout << "AA" << std::endl; // Create an allocator stream for the memory region after the most recent // allocation in the args section. DevPtr args_addr = low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); TargetDataLayoutEncoder encoder(args_addr); - std::cout << "BB" << std::endl; std::tuple arg_field_addrs = EncoderAppend(&encoder, args); - std::cout << "BBB" << std::endl; // Flush `stream` to device memory. DevBaseOffset stream_dev_offset = GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); - std::cout << "BBBB" << std::endl; low_level_device()->Write(stream_dev_offset, reinterpret_cast(encoder.data()), encoder.buf_size()); - std::cout << "CC" << std::endl; //UTVMTask task = { // .func = func_dev_addr, @@ -321,7 +316,6 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { }; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); - std::cout << "DD" << std::endl; //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); @@ -329,10 +323,7 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { if (kRequiresThumbModeBit) { utvm_main_loc += 1; } - std::cout << "EE" << std::endl; - // TODO: figure out why it's not running anymore when we compile it with "-c" - // instead of "-shared". we should be relocating the binary. //std::cout << "do execution things: "; //char tmp; //std::cin >> tmp; @@ -417,13 +408,10 @@ std::tuple MicroSession::EncoderAppend( const int* type_codes = args.type_codes; int num_args = args.num_args; - std::cout << "AYY" << std::endl; auto tvm_vals_slot = encoder->Alloc(num_args); auto type_codes_slot = encoder->Alloc(num_args); - std::cout << "LMAO" << std::endl; for (int i = 0; i < num_args; i++) { - std::cout << "WAZ " << i << std::endl; switch (type_codes[i]) { case kNDArrayContainer: case kArrayHandle: { @@ -434,10 +422,8 @@ std::tuple MicroSession::EncoderAppend( void* old_data = base_arr_handle->data; // Mutate the array to unwrap the `data` field. base_arr_handle->data = reinterpret_cast(old_data)->data; - std::cout << " GLOMO" << std::endl; // Now, encode the unwrapped version. void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); - std::cout << " FOMO" << std::endl; // And restore the original wrapped version. base_arr_handle->data = old_data; @@ -477,7 +463,6 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr auto tvm_arr_slot = encoder->Alloc(); auto shape_slot = encoder->Alloc(arr.ndim); - std::cout << "WRITE" << std::endl; // `shape` and `strides` are stored on the host, so we need to write them to // the device first. The `data` field is already allocated on the device and // is a device pointer, so we don't need to write it. @@ -489,7 +474,6 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr stride_slot.WriteArray(arr.strides, arr.ndim); strides_addr = stride_slot.start_addr(); } - std::cout << "ON" << std::endl; int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); @@ -505,17 +489,12 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr .pad2 = 0, }; - std::cout << "DIDDLY" << std::endl; - // Copy `arr`, update the copy's pointers to be device pointers, then // write the copy to `tvm_arr_slot`. //TVMArray dev_arr = arr; // Update the device type to look like a host, because codegen generates // checks that it is a host array. - std::cout << "DEV TYPE: " << dev_arr.ctx.device_type << std::endl; - std::cout << "DEV TYPE == MICRO: " << (dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << std::endl; CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; - std::cout << "FRICKIN" << std::endl; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; // Add the base address of the device to the array's data's device offset to // get a device address. @@ -523,9 +502,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); //dev_arr.shape = shape_addr.cast_to(); //dev_arr.strides = strides_addr.cast_to(); - std::cout << "DANG" << std::endl; tvm_arr_slot.WriteValue(dev_arr); - std::cout << "TIME" << std::endl; return tvm_arr_slot.start_addr(); } @@ -557,7 +534,6 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; DevSymbolWrite(symbol_map, func_name_underscore.str(), (int32_t) runtime_impl_addr.value()); - std::cout << "finished patching" << std::endl; } std::string MicroSession::ReadString(DevBaseOffset str_offset) { diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 2bef7fd0be12..b3b3a2f9a649 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -48,6 +48,7 @@ def create_micro_mod(c_mod, toolchain_prefix): """ temp_dir = util.tempdir() lib_obj_path = temp_dir.relpath("dev_lib.obj") + print(c_mod.get_source()) c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) @@ -122,7 +123,19 @@ def test_add(): if not tvm.module.enabled("micro_dev"): return shape = (1024,) - dtype = "float32" + #dtype = "float32" + dtype = "int32" + + # int32: 47049 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 + # int32: 46780 reset_gdbinit() @@ -140,16 +153,62 @@ def test_add(): micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) - a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + def run_func(): + a = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) + b = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) + #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + micro_func(a, b, c) + + for _ in range(10): + run_func() + + #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + #micro_func(a, b, c) + #tvm.testing.assert_allclose( + # c.asnumpy(), a.asnumpy() + b.asnumpy()) + + +def test_int_workspace_add(): + """Test a module which uses a workspace to compute an intermediate value.""" + if not tvm.module.enabled("micro_dev"): + return + shape = (1024,) + dtype = "int32" + + reset_gdbinit() + + # Construct TVM expression. + tvm_shape = tvm.convert(shape) + A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) + B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) + B = tvm.compute(A.shape, lambda *i: A(*i) + 1, name="B") + # TODO: need to force the dtype of `C` to be int8 instead of int32 somehow, + # if we want to benchmark int8. + C = tvm.compute(A.shape, lambda *i: B(*i) + 1, name="C") + s = tvm.create_schedule(C.op) + + func_name = "fadd_two_workspace" + c_mod = tvm.build(s, [A, C], target="c", name=func_name) + + with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): + micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + micro_func = micro_mod[func_name] + ctx = tvm.micro_dev(0) + a = tvm.nd.array(np.random.randint(1, 50, size=shape).astype(dtype), ctx) + print(a) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - micro_func(a, b, c) + print(c) + micro_func(a, c) tvm.testing.assert_allclose( - c.asnumpy(), a.asnumpy() + b.asnumpy()) + c.asnumpy(), a.asnumpy() + 2) -def test_workspace_add(): +def test_float_workspace_add(): """Test a module which uses a workspace to compute an intermediate value.""" if not tvm.module.enabled("micro_dev"): return @@ -174,7 +233,9 @@ def test_workspace_add(): micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + print(a) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + print(c) micro_func(a, c) tvm.testing.assert_allclose( @@ -374,11 +435,14 @@ def test_inactive_session_use(): if __name__ == "__main__": #test_alloc() - #test_add() - #test_workspace_add() + test_add() + + #test_int_workspace_add() + #test_float_workspace_add() + #test_graph_runtime() - test_conv2d() + #test_conv2d() #test_multiple_modules() #test_interleave_sessions() From 6f630053125c7e41ed6808305d71d3f40e886e30 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 24 Oct 2019 14:15:39 -0700 Subject: [PATCH 15/70] prepping to try host micro rpc --- python/tvm/micro/base.py | 13 ++- python/tvm/micro/rpc_server.py | 121 ++++++++++++++++++++ python/tvm/module.py | 3 + tests/python/unittest/test_runtime_micro.py | 16 +-- 4 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 python/tvm/micro/rpc_server.py diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index ab5c801b37ba..9441f5e6119e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -67,6 +67,7 @@ class Session: micro_mod = tvm.module.load(lib_obj_path, "micro_dev") """ + # TODO(weberlo): remove required trailing dash in toolchain_prefix def __init__(self, device_type, toolchain_prefix, **kwargs): if device_type not in SUPPORTED_DEVICE_TYPES: raise RuntimeError("unknown micro device type \"{}\"".format(device_type)) @@ -89,8 +90,12 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): self.port = kwargs.get("port", 0) print('creating session') - self.module = _CreateSession( - self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) + if 'remote_create_func' in kwargs: + self.module = kwargs['remote_create_func']( + self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) + else: + self.module = _CreateSession( + self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) self._enter = self.module["enter"] self._exit = self.module["exit"] print('finished session init') @@ -243,7 +248,7 @@ def replace_suffix(s, new_suffix): options += ["-mcmodel=large"] compile_cmd = "{}gcc".format(toolchain_prefix) - if include_dev_lib_header: + if lib_type == LibType.OPERATOR: # Create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. tmp_dir = _util.tempdir() @@ -348,6 +353,8 @@ def run_cmd(cmd): curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] run_cmd(curr_compile_cmd) + # TODO(weberlo): adding '-fPIC' here causes the pc-relative data pools to + # not be updated when the obj is reloced. why? ld_cmd = ['arm-none-eabi-ld', '-relocatable'] ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py new file mode 100644 index 000000000000..716b844d70a5 --- /dev/null +++ b/python/tvm/micro/rpc_server.py @@ -0,0 +1,121 @@ +import logging +import argparse +import os +import ctypes +import json +import tvm +from tvm import rpc +from tvm import micro + +@tvm.register_func("tvm.rpc.server.start", override=True) +def server_start(): + # pylint: disable=unused-variable + curr_path = os.path.dirname( + os.path.abspath(os.path.expanduser(__file__))) + proj_root = os.path.abspath(os.path.join(curr_path, "../../../../")) + dll_path = find_libvta("libvta")[0] + cfg_path = os.path.abspath(os.path.join(proj_root, "build/vta_config.json")) + runtime_dll = [] + _load_module = tvm.get_global_func("tvm.rpc.server.load_module") + + def load_vta_dll(): + """Try to load vta dll""" + if not runtime_dll: + runtime_dll.append(ctypes.CDLL(dll_path, ctypes.RTLD_GLOBAL)) + logging.info("Loading VTA library: %s", dll_path) + return runtime_dll[0] + + @tvm.register_func("tvm.rpc.server.load_module", override=True) + def load_module(file_name): + load_vta_dll() + return _load_module(file_name) + + @tvm.register_func("device_api.ext_dev") + def ext_dev_callback(): + load_vta_dll() + return tvm.get_global_func("device_api.ext_dev")() + + @tvm.register_func("tvm.contrib.vta.init", override=True) + def program_fpga(file_name): + from pynq import xlnk + # Reset xilinx driver + xlnk.Xlnk().xlnk_reset() + path = tvm.get_global_func("tvm.rpc.server.workpath")(file_name) + env = get_env() + program_bitstream.bitstream_program(env.TARGET, path) + logging.info("Program FPGA with %s ", file_name) + + @tvm.register_func("tvm.rpc.server.shutdown", override=True) + def server_shutdown(): + if runtime_dll: + runtime_dll[0].VTARuntimeShutdown() + runtime_dll.pop() + + @tvm.register_func("tvm.contrib.vta.reconfig_runtime", override=True) + def reconfig_runtime(cfg_json): + """Rebuild and reload runtime with new configuration. + Parameters + ---------- + cfg_json : str + JSON string used for configurations. + """ + if runtime_dll: + raise RuntimeError("Can only reconfig in the beginning of session...") + env = get_env() + cfg = json.loads(cfg_json) + cfg["TARGET"] = env.TARGET + pkg = PkgConfig(cfg, proj_root) + # check if the configuration is already the same + if os.path.isfile(cfg_path): + old_cfg = json.loads(open(cfg_path, "r").read()) + if pkg.same_config(old_cfg): + logging.info("Skip reconfig_runtime due to same config.") + return + cflags = ["-O2", "-std=c++11"] + cflags += pkg.cflags + ldflags = pkg.ldflags + lib_name = dll_path + source = pkg.lib_source + logging.info("Rebuild runtime:\n output=%s,\n cflags=%s,\n source=%s,\n ldflags=%s", + dll_path, '\n\t'.join(cflags), '\n\t'.join(source), '\n\t'.join(ldflags)) + cc.create_shared(lib_name, source, cflags + ldflags) + with open(cfg_path, "w") as outputfile: + outputfile.write(pkg.cfg_json) + + +def main(): + """Main function""" + parser = argparse.ArgumentParser() + parser.add_argument('--host', type=str, default="0.0.0.0", + help='the hostname of the server') + parser.add_argument('--port', type=int, default=9091, + help='The port of the RPC') + parser.add_argument('--port-end', type=int, default=9199, + help='The end search port of the RPC') + parser.add_argument('--key', type=str, default="", + help="RPC key used to identify the connection type.") + parser.add_argument('--tracker', type=str, default="", + help="Report to RPC tracker") + args = parser.parse_args() + logging.basicConfig(level=logging.INFO) + + if args.tracker: + url, port = args.tracker.split(":") + port = int(port) + tracker_addr = (url, port) + if not args.key: + raise RuntimeError( + "Need key to present type of resource when tracker is available") + else: + tracker_addr = None + + server = rpc.Server(args.host, + args.port, + args.port_end, + key=args.key, + tracker_addr=tracker_addr) + server.proc.join() + + +if __name__ == "__main__": + main() diff --git a/python/tvm/module.py b/python/tvm/module.py index 2790227f32c7..765b664d1041 100644 --- a/python/tvm/module.py +++ b/python/tvm/module.py @@ -265,6 +265,9 @@ def load(path, fmt=""): files = [tar_temp.relpath(x) for x in tar_temp.listdir()] _cc.create_shared(path + ".so", files) path += ".so" + # TODO(weberlo): unhackify + elif path.endswith(".obj"): + fmt = "micro_dev" # Redirect to the load API return _LoadFromFile(path, fmt) diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index b3b3a2f9a649..3da7453d875c 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -52,7 +52,7 @@ def create_micro_mod(c_mod, toolchain_prefix): c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) - micro_mod = tvm.module.load(lib_obj_path, "micro_dev") + micro_mod = tvm.module.load(lib_obj_path) return micro_mod @@ -126,16 +126,8 @@ def test_add(): #dtype = "float32" dtype = "int32" - # int32: 47049 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 - # int32: 46780 + # int32: 47049, 46780, 46780, 46780, 46780, 46780, 46780, 46780, 46780, 46780 + # float32: 46803 46780 46780 46780 46780 46780 46780 46780 46780 46780 reset_gdbinit() @@ -203,6 +195,7 @@ def test_int_workspace_add(): c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) print(c) micro_func(a, c) + print(c) tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + 2) @@ -237,6 +230,7 @@ def test_float_workspace_add(): c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) print(c) micro_func(a, c) + print(c) tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + 2.0) From 7d0c079836aa90ab0b4e7ad3f2dbc782c5fe0689 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 24 Oct 2019 17:48:11 -0700 Subject: [PATCH 16/70] Add microRPC support --- arm-auto-utvm-demo/demo.py | 78 ++++++ arm-auto-utvm-demo/test_micro_rpc.py | 136 ++++++++++ python/tvm/micro/base.py | 250 ++++++++++++------ python/tvm/rpc/client.py | 4 + src/runtime/micro/device/host/utvm_api.c | 24 ++ src/runtime/micro/micro_session.cc | 8 +- src/runtime/micro/openocd_low_level_device.cc | 7 +- 7 files changed, 414 insertions(+), 93 deletions(-) create mode 100644 arm-auto-utvm-demo/demo.py create mode 100644 arm-auto-utvm-demo/test_micro_rpc.py create mode 100644 src/runtime/micro/device/host/utvm_api.c diff --git a/arm-auto-utvm-demo/demo.py b/arm-auto-utvm-demo/demo.py new file mode 100644 index 000000000000..5d6993c83268 --- /dev/null +++ b/arm-auto-utvm-demo/demo.py @@ -0,0 +1,78 @@ +import logging +import sys + +import numpy as np +import tvm + +from tvm import autotvm + +@autotvm.template +def matmul(N, L, M, dtype): + A = tvm.placeholder((N, L), name='A', dtype=dtype) + B = tvm.placeholder((L, M), name='B', dtype=dtype) + + k = tvm.reduce_axis((0, L), name='k') + C = tvm.compute((N, M), lambda i, j: tvm.sum(A[i, k] * B[k, j], axis=k), name='C') + s = tvm.create_schedule(C.op) + + # schedule + y, x = s[C].op.axis + k = s[C].op.reduce_axis[0] + + ##### define space begin ##### + cfg = autotvm.get_config() + cfg.define_split("tile_y", y, num_outputs=2) + cfg.define_split("tile_x", x, num_outputs=2) + ##### define space end ##### + + # schedule according to config + yo, yi = cfg["tile_y"].apply(s, C, y) + xo, xi = cfg["tile_x"].apply(s, C, x) + + s[C].reorder(yo, xo, k, yi, xi) + + return s, [A, B, C] + + +N, L, M = 512, 512, 512 +task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target='c') +print(task.config_space) + +# logging config (for printing tuning log to the screen) +logging.getLogger('autotvm').setLevel(logging.DEBUG) +logging.getLogger('autotvm').addHandler(logging.StreamHandler(sys.stdout)) + +TOOLCHAIN_PREFIX = 'arm-none-eabi-' +import tvm.micro as micro + +# There are two steps for measuring a config: build and run. +# By default, we use all CPU cores to compile program. Then measure them sequentially. +# We measure 5 times and take average to reduce variance. +measure_option = autotvm.measure_option( + builder=autotvm.LocalBuilder( + build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR)), + runner=autotvm.LocalRunner(number=5)) +print(measure_option) +input() + +# begin tuning, log records to file `matmul.log` +tuner = autotvm.tuner.RandomTuner(task) +tuner.tune(n_trial=10, + measure_option=measure_option, + callbacks=[autotvm.callback.log_to_file('matmul.log')]) + +# apply history best from log file +with autotvm.apply_history_best('matmul.log'): + with tvm.target.create("llvm"): + s, arg_bufs = matmul(N, L, M, 'float32') + func = tvm.build(s, arg_bufs) + +# check correctness +a_np = np.random.uniform(size=(N, L)).astype(np.float32) +b_np = np.random.uniform(size=(L, M)).astype(np.float32) +c_np = a_np.dot(b_np) + +c_tvm = tvm.nd.empty(c_np.shape) +func(tvm.nd.array(a_np), tvm.nd.array(b_np), c_tvm) + +tvm.testing.assert_allclose(c_np, c_tvm.asnumpy(), rtol=1e-2) diff --git a/arm-auto-utvm-demo/test_micro_rpc.py b/arm-auto-utvm-demo/test_micro_rpc.py new file mode 100644 index 000000000000..fd980dc7b140 --- /dev/null +++ b/arm-auto-utvm-demo/test_micro_rpc.py @@ -0,0 +1,136 @@ +import logging +import os + +import numpy as np + +import tvm +from tvm import rpc +from tvm import micro +from tvm.contrib import graph_runtime, util + +assert tvm.module.enabled("rpc") +assert tvm.module.enabled("micro_dev") + +def create_and_load_micro_mod(remote, c_mod, name, toolchain_prefix): + """Produces a micro module from a given module. + + Parameters + ---------- + c_mod : tvm.module.Module + module with "c" as its target backend + + toolchain_prefix : str + toolchain prefix to be used (see `tvm.micro.Session` docs) + + Return + ------ + micro_mod : tvm.module.Module + micro module for the target device + """ + temp_dir = util.tempdir() + lib_obj_path = temp_dir.relpath(f'{name}.obj') + c_mod.export_library( + lib_obj_path, + fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) + remote.upload(lib_obj_path) + micro_mod = remote.load_module(os.path.basename(lib_obj_path)) + #micro_mod = tvm.module.load(lib_obj_path) + return micro_mod + + +def reset_gdbinit(): + with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: + gdbinit_contents = ( +"""layout asm +target remote localhost:3333 + +#print "(*((TVMValue*) utvm_task.arg_values)).v_handle" +#print (*((TVMValue*) utvm_task.arg_values)).v_handle +#print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" +#print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) +#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" +#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] +#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" +#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] +#break UTVMMain +#break UTVMDone +#jump UTVMMain""") + f.write(gdbinit_contents) + + +#DEVICE_TYPE = 'host' +#TOOLCHAIN_PREFIX = '' +DEVICE_TYPE = 'openocd' +TOOLCHAIN_PREFIX = 'arm-none-eabi-' + +def test_utvm_session(): + server = rpc.Server("localhost", key="micro") + remote = rpc.connect(server.host, server.port, key="micro") + utvm_sess_create = remote.get_function("micro.create_session") + sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) + sess['enter']() + sess['exit']() + + +def test_rpc_alloc(): + shape = (1024,) + dtype = "float32" + + server = rpc.Server("localhost", key="micro") + remote = rpc.connect(server.host, server.port, key="micro") + utvm_sess_create = remote.get_function("micro.create_session") + sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) + sess['enter']() + + ctx = remote.micro_dev(0) + np_tensor = np.random.uniform(size=shape).astype(dtype) + micro_tensor = tvm.nd.array(np_tensor, ctx) + tvm.testing.assert_allclose(np_tensor, micro_tensor.asnumpy()) + + sess['exit']() + + +def test_rpc_add(): + shape = (1024,) + dtype = "float32" + + reset_gdbinit() + + server = rpc.Server("localhost", key="micro") + remote = rpc.connect(server.host, server.port, key="micro") + utvm_sess_create = remote.get_function("micro.create_session") + sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) + + # Construct TVM expression. + tvm_shape = tvm.convert(shape) + A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) + B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) + C = tvm.compute(A.shape, lambda *i: A(*i) + B(*i), name="C") + s = tvm.create_schedule(C.op) + + func_name = 'fadd' + c_mod = tvm.build(s, [A, B, C], target='c', name=func_name) + + sess['enter']() + + micro_mod = create_and_load_micro_mod(remote, c_mod, 'fadd', TOOLCHAIN_PREFIX) + micro_func = micro_mod[func_name] + + ctx = remote.micro_dev(0) + a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + print(a) + b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + print(b) + c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + print(c) + micro_func(a, b, c) + print(c) + + sess['exit']() + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + #test_utvm_session() + #test_rpc_alloc() + test_rpc_add() diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 9441f5e6119e..b2b5c0ccedc5 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -23,7 +23,9 @@ import os import sys from enum import Enum +from pathlib import Path +import tvm from tvm.contrib import util as _util from tvm.contrib import cc as _cc @@ -37,6 +39,12 @@ class LibType(Enum): OPERATOR = 1 +@tvm.register_func('micro.create_session') +def create_session(device_type, toolchain_prefix, **kwargs): + res = Session(device_type, toolchain_prefix, **kwargs) + return res.module + + class Session: """MicroTVM Device Session @@ -89,16 +97,10 @@ def __init__(self, device_type, toolchain_prefix, **kwargs): self.server_addr = kwargs.get("server_addr", "") self.port = kwargs.get("port", 0) - print('creating session') - if 'remote_create_func' in kwargs: - self.module = kwargs['remote_create_func']( - self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) - else: - self.module = _CreateSession( - self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) + self.module = _CreateSession( + self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) self._enter = self.module["enter"] self._exit = self.module["exit"] - print('finished session init') def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -139,7 +141,7 @@ def _get_micro_host_driven_dir(): """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "host_driven") + "src", "runtime", "micro", "host_driven") return micro_host_driven_dir @@ -214,57 +216,6 @@ def create_micro_lib( whether to include the device library header containing definitions of library functions. """ - if toolchain_prefix == '': - create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) - elif toolchain_prefix == 'arm-none-eabi-': - create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) - -def create_host_micro_lib( - obj_path, src_path, toolchain_prefix, lib_type, options): - def replace_suffix(s, new_suffix): - if "." in os.path.basename(s): - # There already exists an extension. - return os.path.join( - os.path.dirname(s), - ".".join(os.path.basename(s).split(".")[:-1] + [new_suffix])) - # No existing extension; we can just append. - return s + "." + new_suffix - - # uTVM object files cannot have an ".o" suffix, because it triggers the - # code path for creating shared objects in `tvm.module.load`. So we replace - # ".o" suffixes with ".obj". - if obj_path.endswith(".o"): - logging.warning( - "\".o\" suffix in \"%s\" has been replaced with \".obj\"", obj_path) - obj_path = replace_suffix(obj_path, "obj") - - options = ["-I" + path for path in find_include_path()] - options += ["-I{}".format(_get_micro_host_driven_dir())] - options += ["-fno-stack-protector"] - # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host - # device. - if toolchain_prefix == "" and sys.maxsize > 2**32 and sys.platform.startswith("linux"): - # Only add this option if the host is a 64-bit Linux. - options += ["-mcmodel=large"] - compile_cmd = "{}gcc".format(toolchain_prefix) - - if lib_type == LibType.OPERATOR: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - tmp_dir = _util.tempdir() - temp_src_path = tmp_dir.relpath("temp.c") - with open(src_path, "r") as f: - src_lines = f.read().splitlines() - src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") - with open(temp_src_path, "w") as f: - f.write("\n".join(src_lines)) - src_path = temp_src_path - - _cc.create_shared(obj_path, src_path, options, compile_cmd) - - -def create_arm_micro_lib( - obj_path, src_path, toolchain_prefix, lib_type, options): import subprocess import os import copy @@ -273,15 +224,6 @@ def create_arm_micro_lib( from tvm._ffi.libinfo import find_include_path from tvm.contrib import binutil - def replace_suffix(s, new_suffix): - if "." in os.path.basename(s): - # There already exists an extension. - return os.path.join( - os.path.dirname(s), - ".".join(os.path.basename(s).split(".")[:-1] + [new_suffix])) - # No existing extension; we can just append. - return s + "." + new_suffix - def run_cmd(cmd): proc = subprocess.Popen( cmd, @@ -294,33 +236,43 @@ def run_cmd(cmd): raise RuntimeError(msg) base_compile_cmd = [ - 'arm-none-eabi-gcc', + f'{toolchain_prefix}gcc', '-std=c11', '-Wall', '-Wextra', '--pedantic', - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-mthumb', '-c', '-O0', '-g', - '-gdwarf-5', '-nostartfiles', '-nodefaultlibs', '-nostdlib', '-fdata-sections', '-ffunction-sections'] + if toolchain_prefix == 'arm-none-eabi-': + device_id = 'stm32f746' + base_compile_cmd += [ + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-mthumb', + '-gdwarf-5' + ] + elif toolchain_prefix == '': + device_id = 'host' + if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + base_compile_cmd += ['-mcmodel=large'] + else: + assert False + src_paths = [] ld_script_path = None tmp_dir = _util.tempdir() if lib_type == LibType.RUNTIME: import glob - DEVICE_ID = 'stm32f746' - dev_dir = _get_micro_device_dir() + '/' + DEVICE_ID + dev_dir = _get_micro_device_dir() + '/' + device_id dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') assert dev_src_paths @@ -328,11 +280,11 @@ def run_cmd(cmd): elif lib_type == LibType.OPERATOR: # Create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. - temp_src_path = tmp_dir.relpath("temp.c") - with open(src_path, "r") as f: + temp_src_path = tmp_dir.relpath('temp.c') + with open(src_path, 'r') as f: src_lines = f.read().splitlines() - src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") - with open(temp_src_path, "w") as f: + src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') + with open(temp_src_path, 'w') as f: f.write("\n".join(src_lines)) src_path = temp_src_path @@ -348,18 +300,148 @@ def run_cmd(cmd): prereq_obj_paths = [] for src_path in src_paths: - curr_obj_path = tmp_dir.relpath(replace_suffix(os.path.basename(src_path), 'o')) + curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) prereq_obj_paths.append(curr_obj_path) curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] run_cmd(curr_compile_cmd) # TODO(weberlo): adding '-fPIC' here causes the pc-relative data pools to # not be updated when the obj is reloced. why? - ld_cmd = ['arm-none-eabi-ld', '-relocatable'] + ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] run_cmd(ld_cmd) print(f'compiled obj {obj_path}') + #if toolchain_prefix == '': + # create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) + #elif toolchain_prefix == 'arm-none-eabi-': + # create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) + + +def create_host_micro_lib( + obj_path, src_path, toolchain_prefix, lib_type, options): + # uTVM object files cannot have an ".o" suffix, because it triggers the + # code path for creating shared objects in `tvm.module.load`. So we replace + # ".o" suffixes with ".obj". + if obj_path.endswith(".o"): + logging.warning( + "\".o\" suffix in \"%s\" has been replaced with \".obj\"", obj_path) + obj_path = str(Path(obj_path).with_suffix("obj")) + + options = ["-I" + path for path in find_include_path()] + options += ["-I{}".format(_get_micro_host_driven_dir())] + options += ["-fno-stack-protector"] + # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host + # device. + if toolchain_prefix == "" and sys.maxsize > 2**32 and sys.platform.startswith("linux"): + # Only add this option if the host is a 64-bit Linux. + options += ["-mcmodel=large"] + compile_cmd = "{}gcc".format(toolchain_prefix) + + if lib_type == LibType.OPERATOR: + # Create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + tmp_dir = _util.tempdir() + temp_src_path = tmp_dir.relpath("temp.c") + with open(src_path, "r") as f: + src_lines = f.read().splitlines() + src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") + with open(temp_src_path, "w") as f: + f.write("\n".join(src_lines)) + src_path = temp_src_path + + _cc.create_shared(obj_path, src_path, options, compile_cmd) + + +#def create_arm_micro_lib( +# obj_path, src_path, toolchain_prefix, lib_type, options): +# import subprocess +# import os +# import copy +# from shutil import copyfile +# +# from tvm._ffi.libinfo import find_include_path +# from tvm.contrib import binutil +# +# def run_cmd(cmd): +# proc = subprocess.Popen( +# cmd, +# stdout=subprocess.PIPE, +# stderr=subprocess.STDOUT) +# (out, _) = proc.communicate() +# if proc.returncode != 0: +# msg = "Compilation error:\n" +# msg += out.decode("utf-8") +# raise RuntimeError(msg) +# +# base_compile_cmd = [ +# 'arm-none-eabi-gcc', +# '-std=c11', +# '-Wall', +# '-Wextra', +# '--pedantic', +# '-mcpu=cortex-m7', +# '-mlittle-endian', +# '-mfloat-abi=hard', +# '-mfpu=fpv5-sp-d16', +# '-mthumb', +# '-c', +# '-O0', +# '-g', +# '-gdwarf-5', +# '-nostartfiles', +# '-nodefaultlibs', +# '-nostdlib', +# '-fdata-sections', +# '-ffunction-sections'] +# +# src_paths = [] +# ld_script_path = None +# tmp_dir = _util.tempdir() +# if lib_type == LibType.RUNTIME: +# import glob +# DEVICE_ID = 'stm32f746' +# dev_dir = _get_micro_device_dir() + '/' + DEVICE_ID +# +# dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') +# assert dev_src_paths +# src_paths += dev_src_paths +# elif lib_type == LibType.OPERATOR: +# # Create a temporary copy of the source, so we can inject the dev lib +# # header without modifying the original. +# temp_src_path = tmp_dir.relpath("temp.c") +# with open(src_path, "r") as f: +# src_lines = f.read().splitlines() +# src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") +# with open(temp_src_path, "w") as f: +# f.write("\n".join(src_lines)) +# src_path = temp_src_path +# +# base_compile_cmd += ['-c'] +# else: +# raise RuntimeError('unknown lib type') +# +# src_paths += [src_path] +# +# include_paths = find_include_path() + [_get_micro_host_driven_dir()] +# for path in include_paths: +# base_compile_cmd += ['-I', path] +# +# prereq_obj_paths = [] +# for src_path in src_paths: +# curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('o').name) +# prereq_obj_paths.append(curr_obj_path) +# curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] +# run_cmd(curr_compile_cmd) +# +# # TODO(weberlo): adding '-fPIC' here causes the pc-relative data pools to +# # not be updated when the obj is reloced. why? +# ld_cmd = ['arm-none-eabi-ld', '-relocatable'] +# ld_cmd += prereq_obj_paths +# ld_cmd += ['-o', obj_path] +# run_cmd(ld_cmd) +# print(f'compiled obj {obj_path}') + _init_api("tvm.micro", "tvm.micro.base") diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index 9c0dea5b0863..d13b5ac00355 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -175,6 +175,10 @@ def ext_dev(self, dev_id=0): """Construct extension device.""" return self.context(12, dev_id) + def micro_dev(self, dev_id=0): + """Construct OpenGL device.""" + return self.context(13, dev_id) + class LocalSession(RPCSession): """RPCSession interface backed by local environment. diff --git a/src/runtime/micro/device/host/utvm_api.c b/src/runtime/micro/device/host/utvm_api.c new file mode 100644 index 000000000000..53a9c83bc72a --- /dev/null +++ b/src/runtime/micro/device/host/utvm_api.c @@ -0,0 +1,24 @@ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "utvm_runtime.h" + +// TODO(weberlo): use this? https://stackoverflow.com/questions/5141960/get-the-current-time-in-c + +void UTVMInit() { } + +void UTVMTimerStart() { } + +void UTVMTimerStop() { } + +void UTVMTimerReset() { } + +int32_t UTVMTimerRead() { + return 420; +} + +#ifdef __cplusplus +} // TVM_EXTERN_C +#endif diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 720e8a7d354b..633fcf44509e 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -318,16 +318,18 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); - DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); + DevBaseOffset utvm_init_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); if (kRequiresThumbModeBit) { - utvm_main_loc += 1; + utvm_init_loc += 1; } + std::cout << "UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; + std::cout << "UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; //std::cout << "do execution things: "; //char tmp; //std::cin >> tmp; - low_level_device()->Execute(utvm_main_loc, utvm_done_loc); + low_level_device()->Execute(utvm_init_loc, utvm_done_loc); // Check if there was an error during execution. If so, log it. CheckDeviceError(); diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 13f856fed828..f5bc41774f8d 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -50,7 +50,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); - socket_.cmd_builder() << "halt"; + socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); } @@ -183,11 +183,6 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); - //// Set up the stack pointer. - //DevPtr stack_end = stack_top() - 8; - //socket_.cmd_builder() << "reg sp " << stack_end.cast_to(); - //socket_.SendCommand(); - // Set a breakpoint at the beginning of `UTVMDone`. socket_.cmd_builder() << "bp " << ToDevPtr(breakpoint).cast_to() << " 2"; socket_.SendCommand(); From 61c6fe8239dd3f9703ded19e35880bfeb10626a4 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 28 Oct 2019 13:46:02 -0700 Subject: [PATCH 17/70] I think AutoTVM just fucking worked --- arm-auto-utvm-demo/demo.py | 21 +- arm-auto-utvm-demo/tune_relay_utvm.py | 334 ++++++++++++++++++ include/tvm/runtime/c_runtime_api.h | 2 +- python/tvm/autotvm/measure/measure.py | 6 + python/tvm/autotvm/measure/measure_methods.py | 7 +- python/tvm/autotvm/task/task.py | 3 + python/tvm/micro/base.py | 2 +- python/tvm/micro/rpc_server.py | 85 ++--- python/tvm/rpc/client.py | 16 + python/tvm/rpc/server.py | 2 + python/tvm/rpc/tracker.py | 3 + src/runtime/micro/micro_module.cc | 5 + src/runtime/micro/micro_session.cc | 22 +- src/runtime/micro/openocd_low_level_device.cc | 2 + src/runtime/rpc/rpc_session.cc | 52 +++ src/runtime/rpc/rpc_session.h | 48 +-- tests/python/unittest/test_runtime_micro.py | 2 + 17 files changed, 515 insertions(+), 97 deletions(-) create mode 100644 arm-auto-utvm-demo/tune_relay_utvm.py diff --git a/arm-auto-utvm-demo/demo.py b/arm-auto-utvm-demo/demo.py index 5d6993c83268..f8386daa0adc 100644 --- a/arm-auto-utvm-demo/demo.py +++ b/arm-auto-utvm-demo/demo.py @@ -45,15 +45,30 @@ def matmul(N, L, M, dtype): TOOLCHAIN_PREFIX = 'arm-none-eabi-' import tvm.micro as micro +def test_build_func(obj_path, src_paths, **kwargs): + assert len(src_paths) == 1 + cross_compiler = tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR) + cross_compiler(obj_path, src_paths) + input('check obj') +test_build_func.output_format = 'obj' + +# TODO(weberlo): look at `tune_relay_vta.py` and `vta.exec.rpc_server` to +# figure out how to override the default rpc server with utvm infra. merge in +# what you've done in `test_micro_rpc.py`. + # There are two steps for measuring a config: build and run. # By default, we use all CPU cores to compile program. Then measure them sequentially. # We measure 5 times and take average to reduce variance. + +#measure_option = autotvm.measure_option( +# builder=autotvm.LocalBuilder( +# build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR), n_parallel=1, do_fork=False), +# runner=autotvm.LocalRunner(number=5)) measure_option = autotvm.measure_option( builder=autotvm.LocalBuilder( - build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR)), + build_func=test_build_func, n_parallel=1, do_fork=False), + # TODO(webelrl)o: we need to make the local runner use utvm infra runner=autotvm.LocalRunner(number=5)) -print(measure_option) -input() # begin tuning, log records to file `matmul.log` tuner = autotvm.tuner.RandomTuner(task) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py new file mode 100644 index 000000000000..605570719641 --- /dev/null +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -0,0 +1,334 @@ +# 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. +""" +Auto-tuning a convolutional network on VTA +========================================== +**Author**: `Lianmin Zheng `_, `Thierry Moreau `_ + +Auto-tuning for a specific accelerator design is critical for getting the best +performance for any given operator. This is a tutorial showcases how to tune a +whole convolutional network on VTA. + +The operator implementation for VTA in TVM is written in template form. +The template has many tunable knobs (tile factor, virtual threads, etc). +We will tune all convolution operators in the neural network. After tuning, +we produce a log file which stores the best schedule parameters for all tuned +operators. When the TVM compiler compiles these operators, it will query this +log file to get the best knob parameters. + +""" + +###################################################################### +# Install dependencies +# -------------------- +# To use the autotvm package in tvm, we need to install some extra dependencies. +# (change "3" to "2" if you use python2): +# +# .. code-block:: bash +# +# pip3 install --user psutil xgboost tornado mxnet requests pillow +# +# To make TVM run faster during tuning, it is recommended to use cython +# as FFI of TVM. In the root directory of TVM, execute +# (change "3" to "2" if you use python2): +# +# .. code-block:: bash +# +# pip3 install --user cython +# sudo make cython3 +# +# Now return to python code. Import packages. + +import os +from mxnet.gluon.model_zoo import vision +import numpy as np +from PIL import Image + +import topi +import tvm +from tvm import rpc, autotvm, relay +from tvm.contrib import graph_runtime, util, download +from tvm.autotvm.measure.measure_methods import request_remote +from tvm.autotvm.tuner import XGBTuner, GATuner, RandomTuner, GridSearchTuner + +import vta +from vta.testing import simulator +from vta.top import graph_pack + +################################################################# +# Compile network +# --------------- +# Perform vta-specific compilation with Relay from a Gluon model + +#def compile_network(env, target, model, start_pack, stop_pack): +# +# # Populate the shape and data type dictionary +# dtype_dict = {"data": 'float32'} +# shape_dict = {"data": (env.BATCH, 3, 224, 224)} +# +# # Get off the shelf gluon model, and convert to relay +# gluon_model = vision.get_model(model, pretrained=True) +# mod, params = relay.frontend.from_mxnet(gluon_model, shape_dict) +# +# # Update shape and type dictionary +# shape_dict.update({k: v.shape for k, v in params.items()}) +# dtype_dict.update({k: str(v.dtype) for k, v in params.items()}) +# +# # Perform quantization in Relay +# with relay.quantize.qconfig(global_scale=8.0, +# skip_conv_layers=[0]): +# relay_prog = relay.quantize.quantize(mod["main"], params=params) +# +# # Perform graph packing and constant folding for VTA target +# if target.device_name == "vta": +# assert env.BLOCK_IN == env.BLOCK_OUT +# relay_prog = graph_pack( +# relay_prog, +# env.BATCH, +# env.BLOCK_OUT, +# env.WGT_WIDTH, +# start_name=start_pack, +# stop_name=stop_pack) +# +# return relay_prog, params + + +################################################################# +# Start RPC Tracker +# ----------------- +# TVM uses an RPC session to communicate with Pynq boards. +# During tuning, the tuner will send the generated code to the board and +# measure the speed of code on the board. +# +# To scale up tuning, TVM uses an RPC Tracker to manage multiple devices. +# The RPC Tracker is a centralized master node. We can register all devices to +# the tracker. For example, if we have 10 Pynq boards, we can register all of them +# to the tracker, and run 10 measurements in parallel, accelerating the tuning process. +# +# To start an RPC tracker, run this command on the host machine. The tracker is +# required during the whole tuning process, so we need to open a new terminal for +# this command: +# +# .. code-block:: bash +# +# python -m tvm.exec.rpc_tracker --host=0.0.0.0 --port=9190 +# +# The expected output is: +# +# .. code-block:: bash +# +# INFO:RPCTracker:bind to 0.0.0.0:9190 + +################################################################# +# Register devices to RPC Tracker +# ----------------------------------- +# Now we can register our devices to the tracker. The first step is to +# build the TVM runtime for the Pynq devices. +# +# Follow `this section `_ +# to build the TVM runtime on the device. Then register the device to the tracker with: +# +# .. code-block:: bash +# +# python -m tvm.exec.rpc_server --tracker=[HOST_IP]:9190 --key=pynq +# +# (replace :code:`[HOST_IP]` with the IP address of your host machine) +# +# After registering devices, we can confirm it by querying the rpc_tracker: +# +# .. code-block:: bash +# +# python -m tvm.exec.query_rpc_tracker --host=0.0.0.0 --port=9190 +# +# For example, if we have 6 Pynq boards and 11 Raspberry Pi 3B, +# the output can be +# +# .. code-block:: bash +# +# Queue Status +# ---------------------------------- +# key total free pending +# ---------------------------------- +# pynq 6 6 0 +# rpi3b 11 11 0 +# ---------------------------------- +# +# You can register multiple devices to the tracker to accelerate tuning. + +########################################### +# Set Tuning Options +# ------------------ +# Before tuning, we should apply some configurations. +# Here we use an Pynq-Z1 board as an example. + +# Tracker host and port can be set by your environment +#tracker_host = os.environ.get("TVM_TRACKER_HOST", '0.0.0.0') +#tracker_port = int(os.environ.get("TVM_TRACKER_PORT", 9190)) + +# Load VTA parameters from the vta/config/vta_config.json file +#env = vta.get_env() + +# This target is used for cross compilation. You can query it by :code:`gcc -v` on your device. +# Set ``device=arm_cpu`` to run inference on the CPU +# or ``device=vta`` to run inference on the FPGA. +#device = "vta" +#target = env.target if device == "vta" else env.target_vta_cpu + +# Name of Gluon model to compile +# The ``start_pack`` and ``stop_pack`` labels indicate where +# to start and end the graph packing relay pass: in other words +# where to start and finish offloading to VTA. +#network = "resnet18_v1" +#start_pack="nn.max_pool2d" +#stop_pack="nn.global_avg_pool2d" + +@autotvm.template +def matmul(N, L, M, dtype): + A = tvm.placeholder((N, L), name='A', dtype=dtype) + B = tvm.placeholder((L, M), name='B', dtype=dtype) + + k = tvm.reduce_axis((0, L), name='k') + C = tvm.compute((N, M), lambda i, j: tvm.sum(A[i, k] * B[k, j], axis=k), name='C') + s = tvm.create_schedule(C.op) + + # schedule + y, x = s[C].op.axis + k = s[C].op.reduce_axis[0] + + ##### define space begin ##### + cfg = autotvm.get_config() + cfg.define_split("tile_y", y, num_outputs=2) + cfg.define_split("tile_x", x, num_outputs=2) + ##### define space end ##### + + # schedule according to config + yo, yi = cfg["tile_y"].apply(s, C, y) + xo, xi = cfg["tile_x"].apply(s, C, x) + + s[C].reorder(yo, xo, k, yi, xi) + + return s, [A, B, C] + + +def tune(): + N, L, M = 32, 32, 32 + #task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target='c') + micro_target = tvm.target.create('c -device=micro_dev') + task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target=micro_target) + print(task.config_space) + + DEVICE_TYPE = 'openocd' + TOOLCHAIN_PREFIX = 'arm-none-eabi-' + DEVICE = 'arm-cortex-m' + SERVER_ADDR = '0.0.0.0' + SERVER_PORT = 9190 + import tvm.micro as micro + + log_filename = '%s.%s.log' % (DEVICE, 'test') + n_trial = 10 + early_stopping = None + measure_option = autotvm.measure_option( + builder=autotvm.LocalBuilder( + build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR)), + runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=1, number=5) + ) + + # create tmp log file + tmp_log_file = log_filename + ".tmp" + if os.path.exists(tmp_log_file): + os.remove(tmp_log_file) + + tuner = RandomTuner(task) + + # do tuning + tuner.tune(n_trial=min(n_trial, len(task.config_space)), + early_stopping=early_stopping, + measure_option=measure_option, + callbacks=[ + autotvm.callback.progress_bar(n_trial, prefix='[Matmul Task]'), + autotvm.callback.log_to_file(tmp_log_file)]) + + # pick best records to a cache file + autotvm.record.pick_best(tmp_log_file, log_filename) + os.remove(tmp_log_file) + + +def evaluate(): + # compile kernels with history best records + with autotvm.tophub.context(target, extra_files=[log_file]): + # Compile network + print("Compile...") + with relay.build_config(opt_level=3, disabled_pass={"AlterOpLayout"}): + if target.device_name != "vta": + graph, lib, params = relay.build( + relay_prog, target=target, + params=params, target_host=env.target_host) + else: + with vta.build_config(): + graph, lib, params = relay.build( + relay_prog, target=target, + params=params, target_host=env.target_host) + + # Export library + print("Upload...") + temp = util.tempdir() + lib.save(temp.relpath("graphlib.o")) + remote.upload(temp.relpath("graphlib.o")) + lib = remote.load_module("graphlib.o") + + # Generate the graph runtime + ctx = remote.ext_dev(0) if device == "vta" else remote.cpu(0) + m = graph_runtime.create(graph, lib, ctx) + + # upload parameters to device + image = tvm.nd.array( + (np.random.uniform(size=(1, 3, 224, 224))).astype('float32')) + m.set_input(**params) + m.set_input('data', image) + + # evaluate + print("Evaluate inference time cost...") + timer = m.module.time_evaluator("run", ctx, number=1, repeat=10) + tcost = timer() + prof_res = np.array(tcost.results) * 1000 # convert to millisecond + print("Mean inference time (std dev): %.2f ms (%.2f ms)" % + (np.mean(prof_res), np.std(prof_res))) + +#sess['exit']() + +## We should have extracted 10 convolution tasks +#assert len(tasks) == 10 +#print("Extracted {} conv2d tasks:".format(len(tasks))) +#for tsk in tasks: +# inp = tsk.args[0][1] +# wgt = tsk.args[1][1] +# batch = inp[0]*inp[4] +# in_filter = inp[1]*inp[5] +# out_filter = wgt[0]*wgt[4] +# height, width = inp[2], inp[3] +# hkernel, wkernel = wgt[2], wgt[3] +# hstride, wstride = tsk.args[2][0], tsk.args[2][1] +# hpad, wpad = tsk.args[3][0], tsk.args[3][1] +# print("({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})".format( +# batch, height, width, in_filter, out_filter, +# hkernel, wkernel, hpad, wpad, hstride, wstride +# )) + +# We do not run the tuning in our webpage server since it takes too long. +# Comment the following line to run it by yourself. +#return + diff --git a/include/tvm/runtime/c_runtime_api.h b/include/tvm/runtime/c_runtime_api.h index 5053326058bc..d6f9f19af4c0 100644 --- a/include/tvm/runtime/c_runtime_api.h +++ b/include/tvm/runtime/c_runtime_api.h @@ -81,7 +81,7 @@ typedef enum { kDLAOCL = 5, kDLSDAccel = 6, kOpenGL = 11, - kDLMicroDev = 13, + //kDLMicroDev = 13, // AddExtraTVMType which is not in DLPack here } TVMDeviceExtType; diff --git a/python/tvm/autotvm/measure/measure.py b/python/tvm/autotvm/measure/measure.py index 0836fb741bd2..29bd4148fa4e 100644 --- a/python/tvm/autotvm/measure/measure.py +++ b/python/tvm/autotvm/measure/measure.py @@ -258,7 +258,13 @@ def create_measure_batch(task, option): def measure_batch(measure_inputs): build_results = builder.build(measure_inputs) + print(type(build_results)) + print(build_results) + #input('check em') results = runner.run(measure_inputs, build_results) + print(type(results)) + print(results) + #input('check em') return results measure_batch.n_parallel = builder.n_parallel diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index 861719fffe53..294ac0b6b8bb 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -76,7 +76,7 @@ class LocalBuilder(Builder): If is 'ndk', use function for android ndk If is callable, use it as custom build function, expect lib_format field. """ - def __init__(self, timeout=10, n_parallel=None, build_func='default'): + def __init__(self, timeout=10, n_parallel=None, build_func='default', do_fork=True): super(LocalBuilder, self).__init__(timeout, n_parallel) if isinstance(build_func, str): @@ -87,7 +87,7 @@ def __init__(self, timeout=10, n_parallel=None, build_func='default'): else: raise ValueError("Invalid build_func" + build_func) self.build_func = _wrap_build_func(build_func) - self.executor = LocalExecutor(timeout=timeout) + self.executor = LocalExecutor(timeout=timeout, do_fork=do_fork) self.tmp_dir = tempfile.mkdtemp() def build(self, measure_inputs): @@ -206,6 +206,7 @@ def set_task(self, task): self.task = task if check_remote(task.target, self.key, self.host, self.port): + print('Get devices for measurement successfully!') logger.info("Get devices for measurement successfully!") else: raise RuntimeError("Cannot get remote devices from the tracker. " @@ -463,8 +464,10 @@ def run_through_rpc(measure_input, build_result, from vta import program_fpga, reconfig_runtime program_fpga(remote, None) reconfig_runtime(remote) + print('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') remote.upload(build_result.filename) func = remote.load_module(os.path.split(build_result.filename)[1]) + func.entry_name = 'default_function' ctx = remote.context(str(measure_input.target), 0) time_f = func.time_evaluator( func.entry_name, ctx, number=number, repeat=repeat, min_repeat_ms=min_repeat_ms) diff --git a/python/tvm/autotvm/task/task.py b/python/tvm/autotvm/task/task.py index 7f36914eb0a6..97828101260f 100644 --- a/python/tvm/autotvm/task/task.py +++ b/python/tvm/autotvm/task/task.py @@ -180,6 +180,8 @@ def create(func_name, args, target, target_host=None, template_key=None): if isinstance(target, str): target = _target.create(target) + print('[autotvm.task.create]') + print(f' target: {target}') # init config space ret.config_space = ConfigSpace() @@ -190,6 +192,7 @@ def create(func_name, args, target, target_host=None, template_key=None): with target: sch, _ = func(*args) ret.config_space.code_hash = getattr(sch, 'code_hash', None) + print(f' ctx: {ctx}') ret.workload = ctx.workload ret.flop = ret.config_space.flop or compute_flop(sch) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index b2b5c0ccedc5..54c5fadf4127 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -194,7 +194,7 @@ def compile_func(obj_path, src_path, **kwargs): src_path = src_path[0] create_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, kwargs.get("options", None)) - return _cc.cross_compiler(compile_func) + return _cc.cross_compiler(compile_func, output_format='obj') def create_micro_lib( diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 716b844d70a5..dc45c64f0370 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -7,80 +7,39 @@ from tvm import rpc from tvm import micro +DEVICE_TYPE = 'openocd' +TOOLCHAIN_PREFIX = 'arm-none-eabi-' + @tvm.register_func("tvm.rpc.server.start", override=True) def server_start(): - # pylint: disable=unused-variable - curr_path = os.path.dirname( - os.path.abspath(os.path.expanduser(__file__))) - proj_root = os.path.abspath(os.path.join(curr_path, "../../../../")) - dll_path = find_libvta("libvta")[0] - cfg_path = os.path.abspath(os.path.join(proj_root, "build/vta_config.json")) - runtime_dll = [] + ## pylint: disable=unused-variable + #curr_path = os.path.dirname( + # os.path.abspath(os.path.expanduser(__file__))) + #proj_root = os.path.abspath(os.path.join(curr_path, "../../../../")) + #dll_path = find_libvta("libvta")[0] + #cfg_path = os.path.abspath(os.path.join(proj_root, "build/vta_config.json")) + #runtime_dll = [] + session = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) + session._enter() _load_module = tvm.get_global_func("tvm.rpc.server.load_module") - def load_vta_dll(): - """Try to load vta dll""" - if not runtime_dll: - runtime_dll.append(ctypes.CDLL(dll_path, ctypes.RTLD_GLOBAL)) - logging.info("Loading VTA library: %s", dll_path) - return runtime_dll[0] - @tvm.register_func("tvm.rpc.server.load_module", override=True) def load_module(file_name): - load_vta_dll() - return _load_module(file_name) + #load_vta_dll() + print(f'BEFORE MOD LOAD for {file_name}') + res = _load_module(file_name) + print(f'AFTER MOD LOAD: {res}') + return res - @tvm.register_func("device_api.ext_dev") - def ext_dev_callback(): - load_vta_dll() - return tvm.get_global_func("device_api.ext_dev")() - @tvm.register_func("tvm.contrib.vta.init", override=True) - def program_fpga(file_name): - from pynq import xlnk - # Reset xilinx driver - xlnk.Xlnk().xlnk_reset() - path = tvm.get_global_func("tvm.rpc.server.workpath")(file_name) - env = get_env() - program_bitstream.bitstream_program(env.TARGET, path) - logging.info("Program FPGA with %s ", file_name) + #@tvm.register_func("device_api.ext_dev") + #def ext_dev_callback(): + # load_vta_dll() + # return tvm.get_global_func("device_api.ext_dev")() @tvm.register_func("tvm.rpc.server.shutdown", override=True) def server_shutdown(): - if runtime_dll: - runtime_dll[0].VTARuntimeShutdown() - runtime_dll.pop() - - @tvm.register_func("tvm.contrib.vta.reconfig_runtime", override=True) - def reconfig_runtime(cfg_json): - """Rebuild and reload runtime with new configuration. - Parameters - ---------- - cfg_json : str - JSON string used for configurations. - """ - if runtime_dll: - raise RuntimeError("Can only reconfig in the beginning of session...") - env = get_env() - cfg = json.loads(cfg_json) - cfg["TARGET"] = env.TARGET - pkg = PkgConfig(cfg, proj_root) - # check if the configuration is already the same - if os.path.isfile(cfg_path): - old_cfg = json.loads(open(cfg_path, "r").read()) - if pkg.same_config(old_cfg): - logging.info("Skip reconfig_runtime due to same config.") - return - cflags = ["-O2", "-std=c++11"] - cflags += pkg.cflags - ldflags = pkg.ldflags - lib_name = dll_path - source = pkg.lib_source - logging.info("Rebuild runtime:\n output=%s,\n cflags=%s,\n source=%s,\n ldflags=%s", - dll_path, '\n\t'.join(cflags), '\n\t'.join(source), '\n\t'.join(ldflags)) - cc.create_shared(lib_name, source, cflags + ldflags) - with open(cfg_path, "w") as outputfile: - outputfile.write(pkg.cfg_json) + session._exit() def main(): diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index d13b5ac00355..9c992e6bb000 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -70,9 +70,16 @@ def context(self, dev_type, dev_id=0): ctx: TVMContext The corresponding encoded remote context. """ + print('[RPCSession.context]') + print(f' dev_type: {dev_type}') + print(f' dev_id: {dev_id}') + if 'micro_dev' in dev_type: + print(' IS MICRO_DEV') + dev_type = 'micro_dev' ctx = nd.context(dev_type, dev_id) encode = (self._tbl_index + 1) * base.RPC_SESS_MASK ctx.device_type += encode + print(f' encoded dev_type: {ctx.device_type}') ctx._rpc_sess = self return ctx @@ -228,9 +235,13 @@ def __del__(self): self.close() def _connect(self): + print('AYY ' + str(self._addr)) self._sock = base.connect_with_retry(self._addr) + print('LMAO') self._sock.sendall(struct.pack("LoadBinary(binary_path, true).symbol_map; + std::cout << " end" << std::endl; } /*! @@ -94,6 +97,7 @@ class MicroWrappedFunc { } void operator()(TVMArgs args, TVMRetValue* rv) const { + std::cout << "[MicroWrappedFunc::operator()]" << std::endl; session_->PushToExecQueue(func_ptr_, args); } @@ -107,6 +111,7 @@ class MicroWrappedFunc { PackedFunc MicroModuleNode::GetFunction( const std::string& name, const ObjectPtr& sptr_to_self) { + std::cout << "[MicroModuleNode::GetFunction(name=" << name << ")]" << std::endl; DevPtr func_ptr = symbol_map_[name]; MicroWrappedFunc f(session_, func_ptr); return PackedFunc(f); diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 633fcf44509e..174cfe9664ee 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -269,6 +269,7 @@ void MicroSession::CreateSession(const std::string& device_type, // whether it's a "thumb mode" function (TODO: figure out what that means). const bool kRequiresThumbModeBit = true; void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { + std::cout << "[MicroSession::PushToExecQueue]" << std::endl; // TODO: make this a parameter. if (kRequiresThumbModeBit) { func_ptr += 1; @@ -282,13 +283,19 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); TargetDataLayoutEncoder encoder(args_addr); + std::cout << " after encoder alloc" << std::endl; + std::tuple arg_field_addrs = EncoderAppend(&encoder, args); + + std::cout << " after encoder append" << std::endl; // Flush `stream` to device memory. DevBaseOffset stream_dev_offset = GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); + std::cout << " low-level device: " << low_level_device() << std::endl; low_level_device()->Write(stream_dev_offset, reinterpret_cast(encoder.data()), encoder.buf_size()); + std::cout << " after encoder write" << std::endl; //UTVMTask task = { // .func = func_dev_addr, @@ -317,6 +324,8 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); + std::cout << " after task write" << std::endl; + //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); DevBaseOffset utvm_init_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); @@ -324,8 +333,8 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { utvm_init_loc += 1; } - std::cout << "UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; - std::cout << "UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; + std::cout << " UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; + std::cout << " UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; //std::cout << "do execution things: "; //char tmp; //std::cin >> tmp; @@ -335,7 +344,7 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { CheckDeviceError(); int32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); - std::cout << "TASK TIME WAS " << task_time << std::endl; + std::cout << " TASK TIME WAS " << task_time << std::endl; GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); } @@ -407,12 +416,14 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::tuple MicroSession::EncoderAppend( TargetDataLayoutEncoder* encoder, const TVMArgs& args) { + std::cout << "[MicroSession::EncoderAppend]" << std::endl; const int* type_codes = args.type_codes; int num_args = args.num_args; auto tvm_vals_slot = encoder->Alloc(num_args); auto type_codes_slot = encoder->Alloc(num_args); + std::cout << " num_args: " << num_args << std::endl; for (int i = 0; i < num_args; i++) { switch (type_codes[i]) { case kNDArrayContainer: @@ -425,7 +436,9 @@ std::tuple MicroSession::EncoderAppend( // Mutate the array to unwrap the `data` field. base_arr_handle->data = reinterpret_cast(old_data)->data; // Now, encode the unwrapped version. + std::cout << " before array encode" << std::endl; void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + std::cout << " after array encode" << num_args << std::endl; // And restore the original wrapped version. base_arr_handle->data = old_data; @@ -443,7 +456,10 @@ std::tuple MicroSession::EncoderAppend( break; } } + std::cout << " past args loop" << std::endl; type_codes_slot.WriteArray(type_codes, num_args); + std::cout << " tvm_vals_slot.start_addr(): " << tvm_vals_slot.start_addr().cast_to() << std::endl; + std::cout << " type_codes_slot.start_addr(): " << type_codes_slot.start_addr().cast_to() << std::endl; return std::make_tuple(tvm_vals_slot.start_addr(), type_codes_slot.start_addr()); } diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index f5bc41774f8d..ffdfc958ef4a 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -44,6 +44,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { explicit OpenOCDLowLevelDevice(std::uintptr_t base_addr, const std::string& server_addr, int port) : socket_() { + std::cout << "[OpenOCDLowLevelDevice]" << std::endl; server_addr_ = server_addr; port_ = port; base_addr_ = base_addr; @@ -52,6 +53,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); + std::cout << " finished init" << std::endl; } void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index 3500533157f5..4658752bcf4c 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -21,6 +21,7 @@ * \file rpc_session.cc * \brief RPC session for remote function call. */ +#include #include #include #include @@ -40,6 +41,37 @@ namespace tvm { namespace runtime { + +std::string RPCCodeToString(RPCCode code) { + switch (code) { + case RPCCode::kNone: return "None"; + case RPCCode::kCallFunc: return "CallFunc"; + case RPCCode::kReturn: return "Return"; + case RPCCode::kException: return "Exception"; + case RPCCode::kShutdown: return "Shutdown"; + case RPCCode::kCopyFromRemote: return "CopyFromRemote"; + case RPCCode::kCopyToRemote: return "CopyToRemote"; + case RPCCode::kCopyAck: return "CopyAck"; + case RPCCode::kSystemFuncStart: return "SystemFuncStart"; + case RPCCode::kGetGlobalFunc: return "GetGlobalFunc"; + case RPCCode::kGetTimeEvaluator: return "GetTimeEvaluator"; + case RPCCode::kFreeFunc: return "FreeFunc"; + case RPCCode::kDevSetDevice: return "DevSetDevice"; + case RPCCode::kDevGetAttr: return "DevGetAttr"; + case RPCCode::kDevAllocData: return "DevAllocData"; + case RPCCode::kDevFreeData: return "DevFreeData"; + case RPCCode::kDevStreamSync: return "DevStreamSync"; + case RPCCode::kCopyAmongRemote: return "CopyAmongRemote"; + case RPCCode::kModuleLoad: return "ModuleLoad"; + case RPCCode::kModuleImport: return "ModuleImport"; + case RPCCode::kModuleFree: return "ModuleFree"; + case RPCCode::kModuleGetFunc: return "ModuleGetFunc"; + case RPCCode::kModuleGetSource: return "ModuleGetSource"; + case RPCCode::kNDArrayFree: return "NDArrayFree"; + default: CHECK(false) << "invalid RPC code"; + } +} + // Temp buffer for data array struct RPCByteArrayBuffer { TVMByteArray arr; @@ -871,6 +903,12 @@ void RPCSession::Init() { &reader_, &writer_, table_index_, name_, &remote_key_); // Quick function to call remote. call_remote_ = PackedFunc([this](TVMArgs args, TVMRetValue* rv) { + std::cout << "[RPCSession::call_remote_]" << std::endl; + if (args.type_codes[0] == kTVMContext) { + const TVMContext ctx = args[0]; + std::cout << " ctx.device_type: " << ctx.device_type << std::endl; + std::cout << " ctx.device_id: " << ctx.device_id << std::endl; + } handler_->SendPackedSeq(args.values, args.type_codes, args.num_args); RPCCode code = HandleUntilReturnEvent(rv, true, nullptr); CHECK(code == RPCCode::kReturn) << "code=" << static_cast(code); @@ -1050,7 +1088,10 @@ void RPCDevSetDevice(TVMArgs args, TVMRetValue *rv) { } void RPCDevGetAttr(TVMArgs args, TVMRetValue *rv) { + std::cout << "[RPCDevGetAttr]" << std::endl; TVMContext ctx = args[0]; + std::cout << " ctx.device_type: " << ctx.device_type << std::endl; + std::cout << " ctx.device_id: " << ctx.device_id << std::endl; DeviceAttrKind kind = static_cast(args[1].operator int()); if (kind == kExist) { DeviceAPI* api = DeviceAPI::Get(ctx, true); @@ -1066,7 +1107,10 @@ void RPCDevGetAttr(TVMArgs args, TVMRetValue *rv) { } void RPCDevAllocData(TVMArgs args, TVMRetValue *rv) { + std::cout << "[RPCDevAllocData]" << std::endl; TVMContext ctx = args[0]; + std::cout << " ctx.device_type: " << ctx.device_type << std::endl; + std::cout << " ctx.device_id: " << ctx.device_id << std::endl; uint64_t nbytes = args[1]; uint64_t alignment = args[2]; TVMType type_hint = args[3]; @@ -1088,13 +1132,18 @@ void RPCDevStreamSync(TVMArgs args, TVMRetValue *rv) { } void RPCCopyAmongRemote(TVMArgs args, TVMRetValue *rv) { + std::cout << "[RPCCopyAmongRemote]" << std::endl; void* from = args[0]; uint64_t from_offset = args[1]; void* to = args[2]; uint64_t to_offset = args[3]; uint64_t size = args[4]; TVMContext ctx_from = args[5]; + std::cout << " ctx_from.device_type: " << ctx_from.device_type << std::endl; + std::cout << " ctx_from.device_id: " << ctx_from.device_type << std::endl; TVMContext ctx_to = args[6]; + std::cout << " ctx_to.device_type: " << ctx_to.device_type << std::endl; + std::cout << " ctx_to.device_id: " << ctx_to.device_type << std::endl; TVMType type_hint = args[7]; TVMStreamHandle stream = args[8]; TVMContext ctx = ctx_from; @@ -1169,6 +1218,7 @@ void RPCGetTimeEvaluator(TVMArgs args, TVMRetValue *rv) { } void RPCSession::EventHandler::HandlePackedCall() { + std::cout << "[RPCSession::EventHandler::HandlePackedCall]" << std::endl; CHECK_EQ(pending_request_bytes_, 0U); if (code_ == RPCCode::kReturn) { state_ = kReturnReceived; return; @@ -1177,6 +1227,7 @@ void RPCSession::EventHandler::HandlePackedCall() { state_ = kRecvCode; this->RequestBytes(sizeof(RPCCode)); // Event handler sit at clean state at this point. + std::cout << " RPC code is " << RPCCodeToString(code_) << std::endl; switch (code_) { case RPCCode::kCallFunc: { PackedFunc* pf = reinterpret_cast(call_handle_); @@ -1191,6 +1242,7 @@ void RPCSession::EventHandler::HandlePackedCall() { std::ostringstream os; os << "Except caught from RPC call: " << arg_buf_->value[0].v_str; arg_buf_.reset(); + std::cout << os.str() << std::endl; throw dmlc::Error(os.str()); break; } diff --git a/src/runtime/rpc/rpc_session.h b/src/runtime/rpc/rpc_session.h index ab5f16dadc46..743dc8d1e6e0 100644 --- a/src/runtime/rpc/rpc_session.h +++ b/src/runtime/rpc/rpc_session.h @@ -63,31 +63,31 @@ struct RPCArgBuffer; /*! \brief The RPC code */ enum class RPCCode : int { - kNone, - kCallFunc, - kReturn, - kException, - kShutdown, - kCopyFromRemote, - kCopyToRemote, - kCopyAck, + kNone = 0, + kCallFunc = 1, + kReturn = 2, + kException = 3, + kShutdown = 4, + kCopyFromRemote = 5, + kCopyToRemote = 6, + kCopyAck = 7, // The following are code that can send over CallRemote - kSystemFuncStart, - kGetGlobalFunc, - kGetTimeEvaluator, - kFreeFunc, - kDevSetDevice, - kDevGetAttr, - kDevAllocData, - kDevFreeData, - kDevStreamSync, - kCopyAmongRemote, - kModuleLoad, - kModuleImport, - kModuleFree, - kModuleGetFunc, - kModuleGetSource, - kNDArrayFree + kSystemFuncStart = 8, + kGetGlobalFunc = 9, + kGetTimeEvaluator = 10, + kFreeFunc = 11, + kDevSetDevice = 12, + kDevGetAttr = 13, + kDevAllocData = 14, + kDevFreeData = 15, + kDevStreamSync = 16, + kCopyAmongRemote = 17, + kModuleLoad = 18, + kModuleImport = 19, + kModuleFree = 20, + kModuleGetFunc = 21, + kModuleGetSource = 22, + kNDArrayFree = 23 }; /*! diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 3da7453d875c..8864a6b3b33d 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -49,6 +49,8 @@ def create_micro_mod(c_mod, toolchain_prefix): temp_dir = util.tempdir() lib_obj_path = temp_dir.relpath("dev_lib.obj") print(c_mod.get_source()) + print(c_mod.entry_name) + input() c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) From 1b66dcbb65d1c766f0607b28fd4f802e48048253 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 28 Oct 2019 15:08:01 -0700 Subject: [PATCH 18/70] Add evaluation to tuning script --- 3rdparty/dlpack | 2 +- arm-auto-utvm-demo/tune_relay_utvm.py | 344 ++++++++------------------ 2 files changed, 98 insertions(+), 248 deletions(-) diff --git a/3rdparty/dlpack b/3rdparty/dlpack index 0acb731e0e43..87b968f91c1e 160000 --- a/3rdparty/dlpack +++ b/3rdparty/dlpack @@ -1 +1 @@ -Subproject commit 0acb731e0e43d15deee27b66f10e4c5b4e667913 +Subproject commit 87b968f91c1e5183fae0124c8f0238ba327b31ac diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 605570719641..ddd4bcbe0a20 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -14,45 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -""" -Auto-tuning a convolutional network on VTA -========================================== -**Author**: `Lianmin Zheng `_, `Thierry Moreau `_ - -Auto-tuning for a specific accelerator design is critical for getting the best -performance for any given operator. This is a tutorial showcases how to tune a -whole convolutional network on VTA. - -The operator implementation for VTA in TVM is written in template form. -The template has many tunable knobs (tile factor, virtual threads, etc). -We will tune all convolution operators in the neural network. After tuning, -we produce a log file which stores the best schedule parameters for all tuned -operators. When the TVM compiler compiles these operators, it will query this -log file to get the best knob parameters. - -""" - -###################################################################### -# Install dependencies -# -------------------- -# To use the autotvm package in tvm, we need to install some extra dependencies. -# (change "3" to "2" if you use python2): -# -# .. code-block:: bash -# -# pip3 install --user psutil xgboost tornado mxnet requests pillow -# -# To make TVM run faster during tuning, it is recommended to use cython -# as FFI of TVM. In the root directory of TVM, execute -# (change "3" to "2" if you use python2): -# -# .. code-block:: bash -# -# pip3 install --user cython -# sudo make cython3 -# -# Now return to python code. Import packages. - import os from mxnet.gluon.model_zoo import vision import numpy as np @@ -64,137 +25,78 @@ from tvm.contrib import graph_runtime, util, download from tvm.autotvm.measure.measure_methods import request_remote from tvm.autotvm.tuner import XGBTuner, GATuner, RandomTuner, GridSearchTuner +import tvm.micro as micro import vta from vta.testing import simulator from vta.top import graph_pack -################################################################# -# Compile network -# --------------- -# Perform vta-specific compilation with Relay from a Gluon model - -#def compile_network(env, target, model, start_pack, stop_pack): -# -# # Populate the shape and data type dictionary -# dtype_dict = {"data": 'float32'} -# shape_dict = {"data": (env.BATCH, 3, 224, 224)} -# -# # Get off the shelf gluon model, and convert to relay -# gluon_model = vision.get_model(model, pretrained=True) -# mod, params = relay.frontend.from_mxnet(gluon_model, shape_dict) -# -# # Update shape and type dictionary -# shape_dict.update({k: v.shape for k, v in params.items()}) -# dtype_dict.update({k: str(v.dtype) for k, v in params.items()}) -# -# # Perform quantization in Relay -# with relay.quantize.qconfig(global_scale=8.0, -# skip_conv_layers=[0]): -# relay_prog = relay.quantize.quantize(mod["main"], params=params) -# -# # Perform graph packing and constant folding for VTA target -# if target.device_name == "vta": -# assert env.BLOCK_IN == env.BLOCK_OUT -# relay_prog = graph_pack( -# relay_prog, -# env.BATCH, -# env.BLOCK_OUT, -# env.WGT_WIDTH, -# start_name=start_pack, -# stop_name=stop_pack) -# -# return relay_prog, params - - -################################################################# -# Start RPC Tracker -# ----------------- -# TVM uses an RPC session to communicate with Pynq boards. -# During tuning, the tuner will send the generated code to the board and -# measure the speed of code on the board. -# -# To scale up tuning, TVM uses an RPC Tracker to manage multiple devices. -# The RPC Tracker is a centralized master node. We can register all devices to -# the tracker. For example, if we have 10 Pynq boards, we can register all of them -# to the tracker, and run 10 measurements in parallel, accelerating the tuning process. -# -# To start an RPC tracker, run this command on the host machine. The tracker is -# required during the whole tuning process, so we need to open a new terminal for -# this command: -# -# .. code-block:: bash -# -# python -m tvm.exec.rpc_tracker --host=0.0.0.0 --port=9190 -# -# The expected output is: -# -# .. code-block:: bash -# -# INFO:RPCTracker:bind to 0.0.0.0:9190 +DEVICE_TYPE = 'openocd' +TOOLCHAIN_PREFIX = 'arm-none-eabi-' + +DEVICE = 'arm-cortex-m' +TARGET = tvm.target.create('c -device=micro_dev') + +N, L, M = 32, 32, 32 +N_TRIAL = 5 +N_PER_TRIAL = 2 +N_PARALLEL = 1 + +SERVER_ADDR = '0.0.0.0' +SERVER_PORT = 9190 + +LOG_FILE_NAME = '%s.%s.log' % (DEVICE, 'test') + +def create_micro_mod(c_mod, toolchain_prefix): + """Produces a micro module from a given module. + + Parameters + ---------- + c_mod : tvm.module.Module + module with "c" as its target backend + + toolchain_prefix : str + toolchain prefix to be used (see `tvm.micro.Session` docs) + + Return + ------ + micro_mod : tvm.module.Module + micro module for the target device + """ + temp_dir = util.tempdir() + lib_obj_path = temp_dir.relpath("dev_lib.obj") + print(c_mod.get_source()) + c_mod.export_library( + lib_obj_path, + fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) + micro_mod = tvm.module.load(lib_obj_path) + return micro_mod + + +def relay_micro_build(func, toolchain_prefix, params=None): + """Create a graph runtime module with a micro device context from a Relay function. + + Parameters + ---------- + func : relay.Function + function to compile + + params : dict + input parameters that do not change during inference + + Return + ------ + mod : tvm.module.Module + graph runtime module for the target device + """ + with tvm.build_config(disable_vectorize=True): + graph, c_mod, params = relay.build(func, target="c", params=params) + micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + ctx = tvm.micro_dev(0) + mod = graph_runtime.create(graph, micro_mod, ctx) + mod.set_input(**params) + return mod -################################################################# -# Register devices to RPC Tracker -# ----------------------------------- -# Now we can register our devices to the tracker. The first step is to -# build the TVM runtime for the Pynq devices. -# -# Follow `this section `_ -# to build the TVM runtime on the device. Then register the device to the tracker with: -# -# .. code-block:: bash -# -# python -m tvm.exec.rpc_server --tracker=[HOST_IP]:9190 --key=pynq -# -# (replace :code:`[HOST_IP]` with the IP address of your host machine) -# -# After registering devices, we can confirm it by querying the rpc_tracker: -# -# .. code-block:: bash -# -# python -m tvm.exec.query_rpc_tracker --host=0.0.0.0 --port=9190 -# -# For example, if we have 6 Pynq boards and 11 Raspberry Pi 3B, -# the output can be -# -# .. code-block:: bash -# -# Queue Status -# ---------------------------------- -# key total free pending -# ---------------------------------- -# pynq 6 6 0 -# rpi3b 11 11 0 -# ---------------------------------- -# -# You can register multiple devices to the tracker to accelerate tuning. - -########################################### -# Set Tuning Options -# ------------------ -# Before tuning, we should apply some configurations. -# Here we use an Pynq-Z1 board as an example. - -# Tracker host and port can be set by your environment -#tracker_host = os.environ.get("TVM_TRACKER_HOST", '0.0.0.0') -#tracker_port = int(os.environ.get("TVM_TRACKER_PORT", 9190)) - -# Load VTA parameters from the vta/config/vta_config.json file -#env = vta.get_env() - -# This target is used for cross compilation. You can query it by :code:`gcc -v` on your device. -# Set ``device=arm_cpu`` to run inference on the CPU -# or ``device=vta`` to run inference on the FPGA. -#device = "vta" -#target = env.target if device == "vta" else env.target_vta_cpu - -# Name of Gluon model to compile -# The ``start_pack`` and ``stop_pack`` labels indicate where -# to start and end the graph packing relay pass: in other words -# where to start and finish offloading to VTA. -#network = "resnet18_v1" -#start_pack="nn.max_pool2d" -#stop_pack="nn.global_avg_pool2d" @autotvm.template def matmul(N, L, M, dtype): @@ -225,110 +127,58 @@ def matmul(N, L, M, dtype): def tune(): - N, L, M = 32, 32, 32 - #task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target='c') - micro_target = tvm.target.create('c -device=micro_dev') - task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target=micro_target) - print(task.config_space) - - DEVICE_TYPE = 'openocd' - TOOLCHAIN_PREFIX = 'arm-none-eabi-' - DEVICE = 'arm-cortex-m' - SERVER_ADDR = '0.0.0.0' - SERVER_PORT = 9190 - import tvm.micro as micro - - log_filename = '%s.%s.log' % (DEVICE, 'test') - n_trial = 10 + task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target=TARGET) + early_stopping = None measure_option = autotvm.measure_option( builder=autotvm.LocalBuilder( build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR)), - runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=1, number=5) + runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=N_PARALLEL, number=N_PER_TRIAL) ) # create tmp log file - tmp_log_file = log_filename + ".tmp" + tmp_log_file = LOG_FILE_NAME + '.tmp' if os.path.exists(tmp_log_file): os.remove(tmp_log_file) tuner = RandomTuner(task) # do tuning - tuner.tune(n_trial=min(n_trial, len(task.config_space)), + tuner.tune(n_trial=min(N_TRIAL, len(task.config_space)), early_stopping=early_stopping, measure_option=measure_option, callbacks=[ - autotvm.callback.progress_bar(n_trial, prefix='[Matmul Task]'), + autotvm.callback.progress_bar(N_TRIAL, prefix='[Matmul Task]'), autotvm.callback.log_to_file(tmp_log_file)]) # pick best records to a cache file - autotvm.record.pick_best(tmp_log_file, log_filename) + autotvm.record.pick_best(tmp_log_file, LOG_FILE_NAME) os.remove(tmp_log_file) def evaluate(): # compile kernels with history best records - with autotvm.tophub.context(target, extra_files=[log_file]): - # Compile network - print("Compile...") - with relay.build_config(opt_level=3, disabled_pass={"AlterOpLayout"}): - if target.device_name != "vta": - graph, lib, params = relay.build( - relay_prog, target=target, - params=params, target_host=env.target_host) - else: - with vta.build_config(): - graph, lib, params = relay.build( - relay_prog, target=target, - params=params, target_host=env.target_host) - - # Export library - print("Upload...") - temp = util.tempdir() - lib.save(temp.relpath("graphlib.o")) - remote.upload(temp.relpath("graphlib.o")) - lib = remote.load_module("graphlib.o") - - # Generate the graph runtime - ctx = remote.ext_dev(0) if device == "vta" else remote.cpu(0) - m = graph_runtime.create(graph, lib, ctx) - - # upload parameters to device - image = tvm.nd.array( - (np.random.uniform(size=(1, 3, 224, 224))).astype('float32')) - m.set_input(**params) - m.set_input('data', image) - - # evaluate - print("Evaluate inference time cost...") - timer = m.module.time_evaluator("run", ctx, number=1, repeat=10) - tcost = timer() - prof_res = np.array(tcost.results) * 1000 # convert to millisecond - print("Mean inference time (std dev): %.2f ms (%.2f ms)" % - (np.mean(prof_res), np.std(prof_res))) - -#sess['exit']() - -## We should have extracted 10 convolution tasks -#assert len(tasks) == 10 -#print("Extracted {} conv2d tasks:".format(len(tasks))) -#for tsk in tasks: -# inp = tsk.args[0][1] -# wgt = tsk.args[1][1] -# batch = inp[0]*inp[4] -# in_filter = inp[1]*inp[5] -# out_filter = wgt[0]*wgt[4] -# height, width = inp[2], inp[3] -# hkernel, wkernel = wgt[2], wgt[3] -# hstride, wstride = tsk.args[2][0], tsk.args[2][1] -# hpad, wpad = tsk.args[3][0], tsk.args[3][1] -# print("({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})".format( -# batch, height, width, in_filter, out_filter, -# hkernel, wkernel, hpad, wpad, hstride, wstride -# )) - -# We do not run the tuning in our webpage server since it takes too long. -# Comment the following line to run it by yourself. -#return - + with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): + with TARGET: + sched, arg_bufs = matmul(N, L, M, 'float32') + c_mod = tvm.build(sched, arg_bufs, name='matmul') + + with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): + micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + micro_func = micro_mod['matmul'] + ctx = tvm.micro_dev(0) + + # check correctness + a_np = np.random.uniform(size=(N, L)).astype(np.float32) + b_np = np.random.uniform(size=(L, M)).astype(np.float32) + c_np = a_np.dot(b_np) + + c_tvm = tvm.nd.empty(c_np.shape, ctx=ctx) + micro_func(tvm.nd.array(a_np, ctx), tvm.nd.array(b_np, ctx), c_tvm) + + tvm.testing.assert_allclose(c_np, c_tvm.asnumpy(), rtol=1e-2) + + +if __name__ == '__main__': + tune() + evaluate() From dc0a34510fe0d21813b67ce761afa5fde961bd7d Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 28 Oct 2019 18:12:26 -0700 Subject: [PATCH 19/70] maybe using cycle counts now? --- arm-auto-utvm-demo/tune_relay_utvm.py | 4 +- python/tvm/autotvm/measure/measure_methods.py | 1 - python/tvm/module.py | 14 +++++-- src/runtime/micro/device/stm32f746/utvm_api.c | 2 +- src/runtime/micro/host_driven/utvm_runtime.c | 2 +- src/runtime/micro/host_driven/utvm_runtime.h | 2 +- src/runtime/micro/micro_module.cc | 20 +++++----- src/runtime/micro/micro_session.cc | 6 +-- src/runtime/micro/micro_session.h | 2 +- src/runtime/rpc/rpc_session.cc | 40 +++++++++++++++++++ 10 files changed, 69 insertions(+), 24 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index ddd4bcbe0a20..361e2343e810 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -39,7 +39,7 @@ N, L, M = 32, 32, 32 N_TRIAL = 5 -N_PER_TRIAL = 2 +N_PER_TRIAL = 1 N_PARALLEL = 1 SERVER_ADDR = '0.0.0.0' @@ -167,7 +167,7 @@ def evaluate(): micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) micro_func = micro_mod['matmul'] ctx = tvm.micro_dev(0) - + # check correctness a_np = np.random.uniform(size=(N, L)).astype(np.float32) b_np = np.random.uniform(size=(L, M)).astype(np.float32) diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index 294ac0b6b8bb..cfbf83efa371 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -464,7 +464,6 @@ def run_through_rpc(measure_input, build_result, from vta import program_fpga, reconfig_runtime program_fpga(remote, None) reconfig_runtime(remote) - print('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') remote.upload(build_result.filename) func = remote.load_module(os.path.split(build_result.filename)[1]) func.entry_name = 'default_function' diff --git a/python/tvm/module.py b/python/tvm/module.py index 765b664d1041..924e25a67d12 100644 --- a/python/tvm/module.py +++ b/python/tvm/module.py @@ -201,10 +201,16 @@ def evaluator(*args): """Internal wrapped evaluator.""" # Wrap feval so we can add more stats in future. blob = feval(*args) - fmt = "@" + ("d" * repeat) - results = struct.unpack(fmt, blob) - mean = sum(results) / float(repeat) - return ProfileResult(mean=mean, results=results) + if ctx.device_type == 13: # micro device + fmt = "@" + ("I" * repeat) + results = struct.unpack(fmt, blob) + mean = sum(results) / float(repeat) + return ProfileResult(mean=mean, results=results) + else: + fmt = "@" + ("d" * repeat) + results = struct.unpack(fmt, blob) + mean = sum(results) / float(repeat) + return ProfileResult(mean=mean, results=results) return evaluator except NameError: diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c index 459afe6a2bb0..f3a9de5c8b96 100644 --- a/src/runtime/micro/device/stm32f746/utvm_api.c +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -40,7 +40,7 @@ void UTVMTimerReset() { SYST_CVR = 0; } -int32_t UTVMTimerRead() { +uint32_t UTVMTimerRead() { if (!(SYST_CSR & SYST_COUNTFLAG)) { return start_time - stop_time; } else { diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 0ed996d0f246..40eecadb63c7 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -52,7 +52,7 @@ size_t utvm_num_active_allocs = 0; const char* utvm_last_error = NULL; // NOLINT(*) int32_t utvm_return_code = 0; // NOLINT(*) -int32_t utvm_task_time = 0; +uint32_t utvm_task_time = 0; // Gets called by UTVMInit, after device-specific initialization is finished. void UTVMMain() { diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index 8c789298d072..b5e44dfde38b 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -54,7 +54,7 @@ extern void UTVMTimerStart(); extern void UTVMTimerStop(); -extern int32_t UTVMTimerRead(); +extern uint32_t UTVMTimerRead(); void UTVMMain(); diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index f0ccb611564c..7de8717cfd30 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -72,15 +72,15 @@ class MicroModuleNode final : public ModuleNode { std::cout << " end" << std::endl; } - /*! - * \brief runs selected function on the micro device - * \param func_name name of the function to be run - * \param func_ptr offset of the function to be run - * \param args type-erased arguments passed to the function - */ - void RunFunction(DevPtr func_ptr, const TVMArgs& args) { - session_->PushToExecQueue(func_ptr, args); - } + ///*! + // * \brief runs selected function on the micro device + // * \param func_name name of the function to be run + // * \param func_ptr offset of the function to be run + // * \param args type-erased arguments passed to the function + // */ + //void RunFunction(DevPtr func_ptr, const TVMArgs& args) { + // session_->PushToExecQueue(func_ptr, args); + //} private: SymbolMap symbol_map_; @@ -98,7 +98,7 @@ class MicroWrappedFunc { void operator()(TVMArgs args, TVMRetValue* rv) const { std::cout << "[MicroWrappedFunc::operator()]" << std::endl; - session_->PushToExecQueue(func_ptr_, args); + *rv = (int) session_->PushToExecQueue(func_ptr_, args); } private: diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 174cfe9664ee..9cd515436c3f 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -268,7 +268,7 @@ void MicroSession::CreateSession(const std::string& device_type, // ARM and other manufacturers use the LSB of a function address to determine // whether it's a "thumb mode" function (TODO: figure out what that means). const bool kRequiresThumbModeBit = true; -void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { +uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "[MicroSession::PushToExecQueue]" << std::endl; // TODO: make this a parameter. if (kRequiresThumbModeBit) { @@ -343,10 +343,10 @@ void MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Check if there was an error during execution. If so, log it. CheckDeviceError(); - int32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); - std::cout << " TASK TIME WAS " << task_time << std::endl; + uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); + return task_time; } BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 8950e3850324..4cc6e03c7962 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -133,7 +133,7 @@ class MicroSession : public ModuleNode { * \param func address of the function to be executed * \param args args to the packed function */ - void PushToExecQueue(DevPtr func, const TVMArgs& args); + uint32_t PushToExecQueue(DevPtr func, const TVMArgs& args); //void EnqueueBinary(const std::string& binary_path); diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index 4658752bcf4c..d71169291960 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -1267,11 +1267,51 @@ void RPCSession::EventHandler::HandlePackedCall() { CHECK_EQ(state_, kRecvCode); } +PackedFunc MicroTimeEvaluator( + PackedFunc pf, + TVMContext ctx, + int number, + int repeat, + int min_repeat_ms) { + auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { + std::cout << "[WrapTimeEvaluator::MicroTimeEvaluator]" << std::endl; + TVMRetValue temp; + std::ostringstream os; + // skip first time call, to activate lazy compilation components. + pf.CallPacked(args, &temp); + DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); + + for (int i = 0; i < repeat; ++i) { + long speed = 0; + for (int j = 0; j < number; ++j) { + pf.CallPacked(args, &temp); + DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); + speed += (uint32_t) (temp.operator int()); + } + speed /= number; + std::cout << " [[TRIAL " << i << " AVERAGE IS " << speed << "]]" << std::endl; + os.write(reinterpret_cast(&speed), sizeof(speed)); + } + std::string blob = os.str(); + TVMByteArray arr; + arr.size = blob.length(); + arr.data = blob.data(); + // return the time. + *rv = arr; + }; + return PackedFunc(ftimer); +} + PackedFunc WrapTimeEvaluator(PackedFunc pf, TVMContext ctx, int number, int repeat, int min_repeat_ms) { + if (ctx.device_type == kDLMicroDev) { + return MicroTimeEvaluator(pf, ctx, number, repeat, min_repeat_ms); + } + CHECK(false) << "not using micro time eval"; + auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { TVMRetValue temp; std::ostringstream os; From 6908f70260bf92ddd8df8026619fefbbcffc8579 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 28 Oct 2019 18:51:37 -0700 Subject: [PATCH 20/70] Fix cycle count struct unpacking bug --- arm-auto-utvm-demo/tune_relay_utvm.py | 3 ++- python/tvm/autotvm/measure/measure_methods.py | 3 +++ python/tvm/module.py | 9 +++++++-- src/runtime/rpc/rpc_session.cc | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 361e2343e810..a1882696b8bb 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -174,7 +174,8 @@ def evaluate(): c_np = a_np.dot(b_np) c_tvm = tvm.nd.empty(c_np.shape, ctx=ctx) - micro_func(tvm.nd.array(a_np, ctx), tvm.nd.array(b_np, ctx), c_tvm) + res = micro_func(tvm.nd.array(a_np, ctx), tvm.nd.array(b_np, ctx), c_tvm) + print(f'cycle count: {res}') tvm.testing.assert_allclose(c_np, c_tvm.asnumpy(), rtol=1e-2) diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index cfbf83efa371..ad9367b38c25 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -247,6 +247,7 @@ def get_build_kwargs(self): return kwargs def run(self, measure_inputs, build_results): + print('[RPCRunner.run]') results = [] remote_args = (self.key, self.host, self.port, self.priority, self.timeout) @@ -271,7 +272,9 @@ def run(self, measure_inputs, build_results): if isinstance(res, Exception): # executor error or timeout results.append(MeasureResult((str(res),), MeasureErrorNo.RUN_TIMEOUT, self.timeout, time.time())) + raise Exception(f'encountered exception during measurement: {results}') else: + print(f' got a result: {res}') results.append(res) return results diff --git a/python/tvm/module.py b/python/tvm/module.py index 924e25a67d12..87a402e9cda8 100644 --- a/python/tvm/module.py +++ b/python/tvm/module.py @@ -199,12 +199,17 @@ def time_evaluator(self, func_name, ctx, number=10, repeat=1, min_repeat_ms=0): def evaluator(*args): """Internal wrapped evaluator.""" + print('[Module.time_evaluator.evaluator]') # Wrap feval so we can add more stats in future. blob = feval(*args) - if ctx.device_type == 13: # micro device - fmt = "@" + ("I" * repeat) + if ctx.device_type == 128 + 13: # RPC micro device + fmt = "@" + ("L" * repeat) results = struct.unpack(fmt, blob) + print(f' results: {results}') mean = sum(results) / float(repeat) + print(f' mean: {mean}') + results = list(map(float, results)) + print(f' floated results: {results}') return ProfileResult(mean=mean, results=results) else: fmt = "@" + ("d" * repeat) diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index d71169291960..b8b3939ce358 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -1282,7 +1282,7 @@ PackedFunc MicroTimeEvaluator( DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); for (int i = 0; i < repeat; ++i) { - long speed = 0; + unsigned long speed = 0; for (int j = 0; j < number; ++j) { pf.CallPacked(args, &temp); DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); From 75acf00a87fb23e23803c3f0936e6b6056082220 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 29 Oct 2019 15:54:39 -0700 Subject: [PATCH 21/70] simplify if --- src/runtime/micro/device/stm32f746/utvm_api.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c index f3a9de5c8b96..1929d38ff85a 100644 --- a/src/runtime/micro/device/stm32f746/utvm_api.c +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -41,11 +41,11 @@ void UTVMTimerReset() { } uint32_t UTVMTimerRead() { - if (!(SYST_CSR & SYST_COUNTFLAG)) { - return start_time - stop_time; - } else { + if (SYST_CSR & SYST_COUNTFLAG) { TVMAPISetLastError("timer overflowed"); return -1; + } else { + return start_time - stop_time; } } From 438e534b287c2348ee50a097ed926d5483f312eb Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 29 Oct 2019 15:55:48 -0700 Subject: [PATCH 22/70] remove old demo --- arm-auto-utvm-demo/demo.py | 93 -------------------------------------- 1 file changed, 93 deletions(-) delete mode 100644 arm-auto-utvm-demo/demo.py diff --git a/arm-auto-utvm-demo/demo.py b/arm-auto-utvm-demo/demo.py deleted file mode 100644 index f8386daa0adc..000000000000 --- a/arm-auto-utvm-demo/demo.py +++ /dev/null @@ -1,93 +0,0 @@ -import logging -import sys - -import numpy as np -import tvm - -from tvm import autotvm - -@autotvm.template -def matmul(N, L, M, dtype): - A = tvm.placeholder((N, L), name='A', dtype=dtype) - B = tvm.placeholder((L, M), name='B', dtype=dtype) - - k = tvm.reduce_axis((0, L), name='k') - C = tvm.compute((N, M), lambda i, j: tvm.sum(A[i, k] * B[k, j], axis=k), name='C') - s = tvm.create_schedule(C.op) - - # schedule - y, x = s[C].op.axis - k = s[C].op.reduce_axis[0] - - ##### define space begin ##### - cfg = autotvm.get_config() - cfg.define_split("tile_y", y, num_outputs=2) - cfg.define_split("tile_x", x, num_outputs=2) - ##### define space end ##### - - # schedule according to config - yo, yi = cfg["tile_y"].apply(s, C, y) - xo, xi = cfg["tile_x"].apply(s, C, x) - - s[C].reorder(yo, xo, k, yi, xi) - - return s, [A, B, C] - - -N, L, M = 512, 512, 512 -task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target='c') -print(task.config_space) - -# logging config (for printing tuning log to the screen) -logging.getLogger('autotvm').setLevel(logging.DEBUG) -logging.getLogger('autotvm').addHandler(logging.StreamHandler(sys.stdout)) - -TOOLCHAIN_PREFIX = 'arm-none-eabi-' -import tvm.micro as micro - -def test_build_func(obj_path, src_paths, **kwargs): - assert len(src_paths) == 1 - cross_compiler = tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR) - cross_compiler(obj_path, src_paths) - input('check obj') -test_build_func.output_format = 'obj' - -# TODO(weberlo): look at `tune_relay_vta.py` and `vta.exec.rpc_server` to -# figure out how to override the default rpc server with utvm infra. merge in -# what you've done in `test_micro_rpc.py`. - -# There are two steps for measuring a config: build and run. -# By default, we use all CPU cores to compile program. Then measure them sequentially. -# We measure 5 times and take average to reduce variance. - -#measure_option = autotvm.measure_option( -# builder=autotvm.LocalBuilder( -# build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR), n_parallel=1, do_fork=False), -# runner=autotvm.LocalRunner(number=5)) -measure_option = autotvm.measure_option( - builder=autotvm.LocalBuilder( - build_func=test_build_func, n_parallel=1, do_fork=False), - # TODO(webelrl)o: we need to make the local runner use utvm infra - runner=autotvm.LocalRunner(number=5)) - -# begin tuning, log records to file `matmul.log` -tuner = autotvm.tuner.RandomTuner(task) -tuner.tune(n_trial=10, - measure_option=measure_option, - callbacks=[autotvm.callback.log_to_file('matmul.log')]) - -# apply history best from log file -with autotvm.apply_history_best('matmul.log'): - with tvm.target.create("llvm"): - s, arg_bufs = matmul(N, L, M, 'float32') - func = tvm.build(s, arg_bufs) - -# check correctness -a_np = np.random.uniform(size=(N, L)).astype(np.float32) -b_np = np.random.uniform(size=(L, M)).astype(np.float32) -c_np = a_np.dot(b_np) - -c_tvm = tvm.nd.empty(c_np.shape) -func(tvm.nd.array(a_np), tvm.nd.array(b_np), c_tvm) - -tvm.testing.assert_allclose(c_np, c_tvm.asnumpy(), rtol=1e-2) From b3f3c38af5b946713c79541df24b8559ab47c306 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 1 Nov 2019 14:12:39 -0700 Subject: [PATCH 23/70] shit don't work and idk why --- arm-auto-utvm-demo/tune_relay_utvm.py | 17 +- python/tvm/autotvm/measure/measure.py | 6 - python/tvm/autotvm/measure/measure_methods.py | 5 +- python/tvm/contrib/binutil.py | 100 +- python/tvm/micro/base.py | 25 +- src/runtime/micro/device/stm32f746/core_cm7.h | 2671 +++ .../micro/device/stm32f746/stm32f746xx.h | 17598 ++++++++++++++++ .../device/stm32f746/stm32f7xx_hal_conf.h | 425 + .../micro/device/stm32f746/system_stm32f7xx.h | 123 + src/runtime/micro/device/stm32f746/utvm_api.c | 16 +- .../micro/device/stm32f746/utvm_init.c | 278 + .../micro/device/stm32f746/utvm_init.s | 475 +- .../micro/device/stm32f746/utvm_init.s.bak | 589 + .../micro/device/stm32f746/utvm_unit.c.bak | 278 + src/runtime/micro/micro_session.cc | 10 +- src/runtime/micro/tcl_socket.cc | 4 +- tests/python/unittest/test_runtime_micro.py | 4 +- 17 files changed, 22570 insertions(+), 54 deletions(-) create mode 100644 src/runtime/micro/device/stm32f746/core_cm7.h create mode 100644 src/runtime/micro/device/stm32f746/stm32f746xx.h create mode 100644 src/runtime/micro/device/stm32f746/stm32f7xx_hal_conf.h create mode 100644 src/runtime/micro/device/stm32f746/system_stm32f7xx.h create mode 100644 src/runtime/micro/device/stm32f746/utvm_init.c create mode 100644 src/runtime/micro/device/stm32f746/utvm_init.s.bak create mode 100644 src/runtime/micro/device/stm32f746/utvm_unit.c.bak diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index a1882696b8bb..874039f23951 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -45,7 +45,7 @@ SERVER_ADDR = '0.0.0.0' SERVER_PORT = 9190 -LOG_FILE_NAME = '%s.%s.log' % (DEVICE, 'test') +LOG_FILE_NAME = f'{DEVICE}.log' def create_micro_mod(c_mod, toolchain_prefix): """Produces a micro module from a given module. @@ -64,7 +64,7 @@ def create_micro_mod(c_mod, toolchain_prefix): micro module for the target device """ temp_dir = util.tempdir() - lib_obj_path = temp_dir.relpath("dev_lib.obj") + lib_obj_path = temp_dir.relpath('dev_lib.obj') print(c_mod.get_source()) c_mod.export_library( lib_obj_path, @@ -90,7 +90,7 @@ def relay_micro_build(func, toolchain_prefix, params=None): graph runtime module for the target device """ with tvm.build_config(disable_vectorize=True): - graph, c_mod, params = relay.build(func, target="c", params=params) + graph, c_mod, params = relay.build(func, target='c', params=params) micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) ctx = tvm.micro_dev(0) mod = graph_runtime.create(graph, micro_mod, ctx) @@ -111,15 +111,14 @@ def matmul(N, L, M, dtype): y, x = s[C].op.axis k = s[C].op.reduce_axis[0] - ##### define space begin ##### + # define schedule space cfg = autotvm.get_config() - cfg.define_split("tile_y", y, num_outputs=2) - cfg.define_split("tile_x", x, num_outputs=2) - ##### define space end ##### + cfg.define_split('tile_y', y, num_outputs=2) + cfg.define_split('tile_x', x, num_outputs=2) # schedule according to config - yo, yi = cfg["tile_y"].apply(s, C, y) - xo, xi = cfg["tile_x"].apply(s, C, x) + yo, yi = cfg['tile_y'].apply(s, C, y) + xo, xi = cfg['tile_x'].apply(s, C, x) s[C].reorder(yo, xo, k, yi, xi) diff --git a/python/tvm/autotvm/measure/measure.py b/python/tvm/autotvm/measure/measure.py index 29bd4148fa4e..0836fb741bd2 100644 --- a/python/tvm/autotvm/measure/measure.py +++ b/python/tvm/autotvm/measure/measure.py @@ -258,13 +258,7 @@ def create_measure_batch(task, option): def measure_batch(measure_inputs): build_results = builder.build(measure_inputs) - print(type(build_results)) - print(build_results) - #input('check em') results = runner.run(measure_inputs, build_results) - print(type(results)) - print(results) - #input('check em') return results measure_batch.n_parallel = builder.n_parallel diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index ad9367b38c25..b4aa8553e692 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -76,7 +76,7 @@ class LocalBuilder(Builder): If is 'ndk', use function for android ndk If is callable, use it as custom build function, expect lib_format field. """ - def __init__(self, timeout=10, n_parallel=None, build_func='default', do_fork=True): + def __init__(self, timeout=10, n_parallel=None, build_func='default'): super(LocalBuilder, self).__init__(timeout, n_parallel) if isinstance(build_func, str): @@ -87,7 +87,7 @@ def __init__(self, timeout=10, n_parallel=None, build_func='default', do_fork=Tr else: raise ValueError("Invalid build_func" + build_func) self.build_func = _wrap_build_func(build_func) - self.executor = LocalExecutor(timeout=timeout, do_fork=do_fork) + self.executor = LocalExecutor(timeout=timeout) self.tmp_dir = tempfile.mkdtemp() def build(self, measure_inputs): @@ -206,7 +206,6 @@ def set_task(self, task): self.task = task if check_remote(task.target, self.key, self.host, self.port): - print('Get devices for measurement successfully!') logger.info("Get devices for measurement successfully!") else: raise RuntimeError("Cannot get remote devices from the tracker. " diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 26dfa99789fe..4617c9932c11 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -60,7 +60,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): # 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"], + ".text": [".text", '.isr_vector'], ".rodata": [".rodata"], ".data": [".data", ".sdata"], ".bss": [".bss", ".sbss"], @@ -147,19 +147,73 @@ def tvm_callback_relocate_binary( #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 = """ + # TODO: this a fukn hack + #input(f'binary path: {binary_path}') + if 'utvm_runtime' in binary_path: + ld_script_contents = """ +ENTRY(UTVMInit) + /* Highest address of the user mode stack */ _estack = 0x20050000; /* end of RAM */ -/* Specify the memory areas */ /* -MEMORY + * Memory layout (for reference) + * RAM (xrw) : START = 0x20000000, LENGTH = 320K + * FLASH (rx) : START = 0x8000000, LENGTH = 1024K + */ + +/* Define output sections */ +SECTIONS { -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K -FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K + . = %s; + . = ALIGN(4); + .text : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + KEEP(*(.text)) + KEEP(*(.text*)) + . = ALIGN(4); + } + + . = %s; + . = ALIGN(4); + .rodata : + { + . = ALIGN(4); + KEEP(*(.rodata)) + KEEP(*(.rodata*)) + . = ALIGN(4); + } + + . = %s; + . = ALIGN(4); + .data : + { + . = ALIGN(4); + KEEP(*(.data)) + KEEP(*(.data*)) + . = ALIGN(4); + } + + . = %s; + . = ALIGN(4); + .bss : + { + . = ALIGN(4); + KEEP(*(.bss)) + KEEP(*(.bss*)) + . = ALIGN(4); + } } -*/ + """ % (text_addr, rodata_addr, data_addr, bss_addr) + else: + ld_script_contents = """ +/* + * Memory layout (for reference) + * RAM (xrw) : START = 0x20000000, LENGTH = 320K + * FLASH (rx) : START = 0x8000000, LENGTH = 1024K + */ /* Define output sections */ SECTIONS @@ -169,8 +223,8 @@ def tvm_callback_relocate_binary( .text : { . = ALIGN(4); - *(.text) - *(.text*) + KEEP(*(.text)) + KEEP(*(.text*)) . = ALIGN(4); } @@ -179,8 +233,8 @@ def tvm_callback_relocate_binary( .rodata : { . = ALIGN(4); - *(.rodata) - *(.rodata*) + KEEP(*(.rodata)) + KEEP(*(.rodata*)) . = ALIGN(4); } @@ -189,8 +243,8 @@ def tvm_callback_relocate_binary( .data : { . = ALIGN(4); - *(.data) - *(.data*) + KEEP(*(.data)) + KEEP(*(.data*)) . = ALIGN(4); } @@ -199,12 +253,22 @@ def tvm_callback_relocate_binary( .bss : { . = ALIGN(4); - *(.bss) - *(.bss*) + KEEP(*(.bss)) + KEEP(*(.bss*)) . = ALIGN(4); } } - """ % (text_addr, rodata_addr, data_addr, bss_addr) + """ % (text_addr, rodata_addr, data_addr, bss_addr) + print(f'relocing lib {binary_path}') + print(f' text_addr: {text_addr}') + print(f' rodata_addr: {rodata_addr}') + print(f' data_addr: {data_addr}') + print(f' bss_addr: {bss_addr}') + + # TODO(weberlo): Generate the script in a more procedural manner. + + # TODO: use the stm32-cube linker script as reference. set UTVMInit as + # entry point. add KEEP to sections to prevent garbage collection. #""" #SECTIONS @@ -262,7 +326,7 @@ def tvm_callback_relocate_binary( raise RuntimeError(msg) print(f'relocated obj path is {rel_obj_path}') - #input('check it out') + input('check it out') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 54c5fadf4127..b6b2fdba2376 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -248,7 +248,9 @@ def run_cmd(cmd): '-nodefaultlibs', '-nostdlib', '-fdata-sections', - '-ffunction-sections'] + '-ffunction-sections', + '-DSTM32F746xx' + ] if toolchain_prefix == 'arm-none-eabi-': device_id = 'stm32f746' @@ -268,6 +270,7 @@ def run_cmd(cmd): assert False src_paths = [] + include_paths = find_include_path() + [_get_micro_host_driven_dir()] ld_script_path = None tmp_dir = _util.tempdir() if lib_type == LibType.RUNTIME: @@ -275,8 +278,18 @@ def run_cmd(cmd): dev_dir = _get_micro_device_dir() + '/' + device_id dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + # there needs to at least be a utvm_timer.c file assert dev_src_paths + src_paths += dev_src_paths + # TODO: configure this + #include_paths += [dev_dir] + CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] + #include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] elif lib_type == LibType.OPERATOR: # Create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. @@ -285,7 +298,7 @@ def run_cmd(cmd): src_lines = f.read().splitlines() src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') with open(temp_src_path, 'w') as f: - f.write("\n".join(src_lines)) + f.write('\n'.join(src_lines)) src_path = temp_src_path base_compile_cmd += ['-c'] @@ -294,13 +307,18 @@ def run_cmd(cmd): src_paths += [src_path] - include_paths = find_include_path() + [_get_micro_host_driven_dir()] + print(f'include paths: {include_paths}') for path in include_paths: base_compile_cmd += ['-I', path] prereq_obj_paths = [] for src_path in src_paths: curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) + i = 2 + while curr_obj_path in prereq_obj_paths: + curr_obj_path = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) + i += 1 + prereq_obj_paths.append(curr_obj_path) curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] run_cmd(curr_compile_cmd) @@ -312,6 +330,7 @@ def run_cmd(cmd): ld_cmd += ['-o', obj_path] run_cmd(ld_cmd) print(f'compiled obj {obj_path}') + #input('check it') #if toolchain_prefix == '': # create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) diff --git a/src/runtime/micro/device/stm32f746/core_cm7.h b/src/runtime/micro/device/stm32f746/core_cm7.h new file mode 100644 index 000000000000..ada6c2a57ee8 --- /dev/null +++ b/src/runtime/micro/device/stm32f746/core_cm7.h @@ -0,0 +1,2671 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 04. June 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + * + * 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 defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (7U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void SCB_EnableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void SCB_DisableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void SCB_InvalidateICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void SCB_EnableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void SCB_DisableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ + __DSB(); + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void SCB_InvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void SCB_CleanDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void SCB_CleanInvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t)addr; + int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCIMVAC = op_addr; + op_addr += (uint32_t)linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCMVAC = op_addr; + op_addr += (uint32_t)linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCIMVAC = op_addr; + op_addr += (uint32_t)linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/src/runtime/micro/device/stm32f746/stm32f746xx.h b/src/runtime/micro/device/stm32f746/stm32f746xx.h new file mode 100644 index 000000000000..d97ad747b10c --- /dev/null +++ b/src/runtime/micro/device/stm32f746/stm32f746xx.h @@ -0,0 +1,17598 @@ +/** + ****************************************************************************** + * @file stm32f746xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +// NOTE: file from CMSIS/Device/ST/STM32F7xx/Include/stm32f746xx.h + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32f746xx + * @{ + */ + +#ifndef __STM32F746xx_H +#define __STM32F746xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief STM32F7xx Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M7 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M7 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M7 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M7 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M7 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M7 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M7 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M7 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */ + TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */ + TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_IRQn = 78, /*!< DCMI global interrupt */ + RNG_IRQn = 80, /*!< RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + LTDC_IRQn = 88, /*!< LTDC global Interrupt */ + LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ + DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ + SAI2_IRQn = 91, /*!< SAI2 global Interrupt */ + QUADSPI_IRQn = 92, /*!< Quad SPI global interrupt */ + LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ + CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ + I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ + SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +/** + * @brief Configuration of the Cortex-M7 Processor and Core Peripherals + */ +#define __CM7_REV 0x0001U /*!< Cortex-M7 revision r0p1 */ +#define __MPU_PRESENT 1 /*!< CM7 provides an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< CM7 uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ +#define __ICACHE_PRESENT 1 /*!< CM7 instruction cache present */ +#define __DCACHE_PRESENT 1 /*!< CM7 data cache present */ +#include "core_cm7.h" /*!< Cortex-M7 processor and core peripherals */ + + +#include "system_stm32f7xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t SR; /*!< ADC status register, Address offset: 0x00 */ + __IO uint32_t CR1; /*!< ADC control register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< ADC control register 2, Address offset: 0x08 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x0C */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x10 */ + __IO uint32_t JOFR1; /*!< ADC injected channel data offset register 1, Address offset: 0x14 */ + __IO uint32_t JOFR2; /*!< ADC injected channel data offset register 2, Address offset: 0x18 */ + __IO uint32_t JOFR3; /*!< ADC injected channel data offset register 3, Address offset: 0x1C */ + __IO uint32_t JOFR4; /*!< ADC injected channel data offset register 4, Address offset: 0x20 */ + __IO uint32_t HTR; /*!< ADC watchdog higher threshold register, Address offset: 0x24 */ + __IO uint32_t LTR; /*!< ADC watchdog lower threshold register, Address offset: 0x28 */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x2C */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x30 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x34 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x38*/ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x3C */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x40 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x44 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x48 */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x4C */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ + __IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CDR; /*!< ADC common regular data register for dual + AND triple modes, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; + + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + +/** + * @brief HDMI-CEC + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ +} DAC_TypeDef; + + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ +} DMA2D_TypeDef; + + +/** + * @brief Ethernet MAC + */ + +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACFFR; + __IO uint32_t MACHTHR; + __IO uint32_t MACHTLR; + __IO uint32_t MACMIIAR; + __IO uint32_t MACMIIDR; + __IO uint32_t MACFCR; + __IO uint32_t MACVLANTR; /* 8 */ + uint32_t RESERVED0[2]; + __IO uint32_t MACRWUFFR; /* 11 */ + __IO uint32_t MACPMTCSR; + uint32_t RESERVED1; + __IO uint32_t MACDBGR; + __IO uint32_t MACSR; /* 15 */ + __IO uint32_t MACIMR; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; /* 24 */ + uint32_t RESERVED2[40]; + __IO uint32_t MMCCR; /* 65 */ + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; /* 69 */ + uint32_t RESERVED3[14]; + __IO uint32_t MMCTGFSCCR; /* 84 */ + __IO uint32_t MMCTGFMSCCR; + uint32_t RESERVED4[5]; + __IO uint32_t MMCTGFCR; + uint32_t RESERVED5[10]; + __IO uint32_t MMCRFCECR; + __IO uint32_t MMCRFAECR; + uint32_t RESERVED6[10]; + __IO uint32_t MMCRGUFCR; + uint32_t RESERVED7[334]; + __IO uint32_t PTPTSCR; + __IO uint32_t PTPSSIR; + __IO uint32_t PTPTSHR; + __IO uint32_t PTPTSLR; + __IO uint32_t PTPTSHUR; + __IO uint32_t PTPTSLUR; + __IO uint32_t PTPTSAR; + __IO uint32_t PTPTTHR; + __IO uint32_t PTPTTLR; + __IO uint32_t RESERVED8; + __IO uint32_t PTPTSSR; + uint32_t RESERVED9[565]; + __IO uint32_t DMABMR; + __IO uint32_t DMATPDR; + __IO uint32_t DMARPDR; + __IO uint32_t DMARDLAR; + __IO uint32_t DMATDLAR; + __IO uint32_t DMASR; + __IO uint32_t DMAOMR; + __IO uint32_t DMAIER; + __IO uint32_t DMAMFBOCR; + __IO uint32_t DMARSWTR; + uint32_t RESERVED10[8]; + __IO uint32_t DMACHTDR; + __IO uint32_t DMACHRDR; + __IO uint32_t DMACHTBAR; + __IO uint32_t DMACHRBAR; +} ETH_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ + __IO uint32_t EMR; /*!< EXTI Event mask register, Address offset: 0x04 */ + __IO uint32_t RTSR; /*!< EXTI Rising trigger selection register, Address offset: 0x08 */ + __IO uint32_t FTSR; /*!< EXTI Falling trigger selection register, Address offset: 0x0C */ + __IO uint32_t SWIER; /*!< EXTI Software interrupt event register, Address offset: 0x10 */ + __IO uint32_t PR; /*!< EXTI Pending register, Address offset: 0x14 */ +} EXTI_TypeDef; + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x10 */ + __IO uint32_t OPTCR; /*!< FLASH option control register , Address offset: 0x14 */ + __IO uint32_t OPTCR1; /*!< FLASH option control register 1 , Address offset: 0x18 */ +} FLASH_TypeDef; + + + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */ + uint32_t RESERVED0; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief Flexible Memory Controller Bank5_6 + */ + +typedef struct +{ + __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ + __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ + __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ + __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ + __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ +} FMC_Bank5_6_TypeDef; + + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t PMC; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + uint32_t RESERVED[2]; /*!< Reserved, 0x18-0x1C */ + __IO uint32_t CMPCR; /*!< SYSCFG Compensation cell control register, Address offset: 0x20 */ +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + + +/** + * @brief LCD-TFT Display Controller + */ + +typedef struct +{ + uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ + __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ + __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ + __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ + __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ + __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ + __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ + uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ + __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ + uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ + __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ + __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ + __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ + __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ + __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ + __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ +} LTDC_TypeDef; + +/** + * @brief LCD-TFT Display layer x Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ + __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ + __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ + __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ + __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ + __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ + __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ + __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ + uint32_t RESERVED0[2]; /*!< Reserved */ + __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ + __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ + __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ + uint32_t RESERVED1[3]; /*!< Reserved */ + __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ + +} LTDC_Layer_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CSR1; /*!< PWR power control/status register 2, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ + __IO uint32_t CSR2; /*!< PWR power control/status register 2, Address offset: 0x0C */ +} PWR_TypeDef; + + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ + uint32_t RESERVED2; /*!< Reserved, 0x3C */ + __IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ + uint32_t RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, 0x5C */ + __IO uint32_t APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ + uint32_t RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ + __IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ + __IO uint32_t SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ + __IO uint32_t PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ + __IO uint32_t PLLSAICFGR; /*!< RCC PLLSAI configuration register, Address offset: 0x88 */ + __IO uint32_t DCKCFGR1; /*!< RCC Dedicated Clocks configuration register1, Address offset: 0x8C */ + __IO uint32_t DCKCFGR2; /*!< RCC Dedicated Clocks configuration register 2, Address offset: 0x90 */ + +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t reserved; /*!< Reserved */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SPDIF-RX Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ + __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ + __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ + __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ + __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ +} SPDIFRX_TypeDef; + +/** + * @brief SD host Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMClock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ +} SDMMC_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI control register 1 (not used in I2S mode), Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI control register 2, Address offset: 0x04 */ + __IO uint32_t SR; /*!< SPI status register, Address offset: 0x08 */ + __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ + __IO uint32_t CRCPR; /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */ + __IO uint32_t RXCRCR; /*!< SPI RX CRC register (not used in I2S mode), Address offset: 0x14 */ + __IO uint32_t TXCRCR; /*!< SPI TX CRC register (not used in I2S mode), Address offset: 0x18 */ + __IO uint32_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */ + __IO uint32_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */ +} SPI_TypeDef; + +/** + * @brief QUAD Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ + __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ + __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ + __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ + __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ + __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ + __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ + __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ + __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ + __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ +} QUADSPI_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + __IO uint32_t OR; /*!< TIM option register, Address offset: 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare mode register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare mode register6, Address offset: 0x5C */ + +} TIM_TypeDef; + +/** + * @brief LPTIMIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ +} LPTIM_TypeDef; + + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ +} USART_TypeDef; + + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @} + */ + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + uint32_t Reserved5[3]; /*!< Reserved 040h-048h */ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + uint32_t Reserved7; /*!< Reserved 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + uint32_t Reserved43[40]; /*!< Reserved 60h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO 104h-13Ch */ +} USB_OTG_GlobalTypeDef; + + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; +/** + * @} + */ + + + + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define RAMITCM_BASE 0x00000000UL /*!< Base address of : 16KB RAM reserved for CPU execution/instruction accessible over ITCM */ +#define FLASHITCM_BASE 0x00200000UL /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over ITCM */ +#define FLASHAXI_BASE 0x08000000UL /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ +#define RAMDTCM_BASE 0x20000000UL /*!< Base address of : 64KB system data RAM accessible over DTCM */ +#define PERIPH_BASE 0x40000000UL /*!< Base address of : AHB/ABP Peripherals */ +#define BKPSRAM_BASE 0x40024000UL /*!< Base address of : Backup SRAM(4 KB) */ +#define QSPI_BASE 0x90000000UL /*!< Base address of : QSPI memories accessible over AXI */ +#define FMC_R_BASE 0xA0000000UL /*!< Base address of : FMC Control registers */ +#define QSPI_R_BASE 0xA0001000UL /*!< Base address of : QSPI Control registers */ +#define SRAM1_BASE 0x20010000UL /*!< Base address of : 240KB RAM1 accessible over AXI/AHB */ +#define SRAM2_BASE 0x2004C000UL /*!< Base address of : 16KB RAM2 accessible over AXI/AHB */ +#define FLASH_END 0x080FFFFFUL /*!< FLASH end address */ +#define FLASH_OTP_BASE 0x1FF0F000UL /*!< Base address of : (up to 1024 Bytes) embedded FLASH OTP Area */ +#define FLASH_OTP_END 0x1FF0F41FUL /*!< End address of : (up to 1024 Bytes) embedded FLASH OTP Area */ + +/* Legacy define */ +#define FLASH_BASE FLASHAXI_BASE + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000UL) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (APB1PERIPH_BASE + 0x2400UL) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800UL) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) +#define SPDIFRX_BASE (APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) +#define I2C4_BASE (APB1PERIPH_BASE + 0x6000UL) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400UL) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800UL) +#define CEC_BASE (APB1PERIPH_BASE + 0x6C00UL) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000UL) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (APB1PERIPH_BASE + 0x7C00UL) + +/*!< APB2 peripherals */ +#define TIM1_BASE (APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (APB2PERIPH_BASE + 0x1400UL) +#define ADC1_BASE (APB2PERIPH_BASE + 0x2000UL) +#define ADC2_BASE (APB2PERIPH_BASE + 0x2100UL) +#define ADC3_BASE (APB2PERIPH_BASE + 0x2200UL) +#define ADC_BASE (APB2PERIPH_BASE + 0x2300UL) +#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2C00UL) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (APB2PERIPH_BASE + 0x3400UL) +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x3800UL) +#define EXTI_BASE (APB2PERIPH_BASE + 0x3C00UL) +#define TIM9_BASE (APB2PERIPH_BASE + 0x4000UL) +#define TIM10_BASE (APB2PERIPH_BASE + 0x4400UL) +#define TIM11_BASE (APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (APB2PERIPH_BASE + 0x5000UL) +#define SPI6_BASE (APB2PERIPH_BASE + 0x5400UL) +#define SAI1_BASE (APB2PERIPH_BASE + 0x5800UL) +#define SAI2_BASE (APB2PERIPH_BASE + 0x5C00UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) +#define SAI2_Block_A_BASE (SAI2_BASE + 0x004UL) +#define SAI2_Block_B_BASE (SAI2_BASE + 0x024UL) +#define LTDC_BASE (APB2PERIPH_BASE + 0x6800UL) +#define LTDC_Layer1_BASE (LTDC_BASE + 0x0084UL) +#define LTDC_Layer2_BASE (LTDC_BASE + 0x0104UL) +/*!< AHB1 peripherals */ +#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00UL) +#define GPIOI_BASE (AHB1PERIPH_BASE + 0x2000UL) +#define GPIOJ_BASE (AHB1PERIPH_BASE + 0x2400UL) +#define GPIOK_BASE (AHB1PERIPH_BASE + 0x2800UL) +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) +#define RCC_BASE (AHB1PERIPH_BASE + 0x3800UL) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x3C00UL) +#define UID_BASE 0x1FF0F420UL /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE 0x1FF0F442UL /*!< FLASH Size register base address */ +#define PACKAGE_BASE 0x1FF0F7E0UL /*!< Package size register base address */ +/* Legacy define */ +#define PACKAGESIZE_BASE PACKAGE_BASE + +#define DMA1_BASE (AHB1PERIPH_BASE + 0x6000UL) +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x6400UL) +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) +#define ETH_BASE (AHB1PERIPH_BASE + 0x8000UL) +#define ETH_MAC_BASE (ETH_BASE) +#define ETH_MMC_BASE (ETH_BASE + 0x0100UL) +#define ETH_PTP_BASE (ETH_BASE + 0x0700UL) +#define ETH_DMA_BASE (ETH_BASE + 0x1000UL) +#define DMA2D_BASE (AHB1PERIPH_BASE + 0xB000UL) +/*!< AHB2 peripherals */ +#define DCMI_BASE (AHB2PERIPH_BASE + 0x50000UL) +#define RNG_BASE (AHB2PERIPH_BASE + 0x60800UL) +/*!< FMC Bankx registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) +#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE 0xE0042000UL + +/*!< USB registers base address */ +#define USB_OTG_HS_PERIPH_BASE 0x40040000UL +#define USB_OTG_FS_PERIPH_BASE 0x50000000UL + +#define USB_OTG_GLOBAL_BASE 0x0000UL +#define USB_OTG_DEVICE_BASE 0x0800UL +#define USB_OTG_IN_ENDPOINT_BASE 0x0900UL +#define USB_OTG_OUT_ENDPOINT_BASE 0x0B00UL +#define USB_OTG_EP_REG_SIZE 0x0020UL +#define USB_OTG_HOST_BASE 0x0400UL +#define USB_OTG_HOST_PORT_BASE 0x0440UL +#define USB_OTG_HOST_CHANNEL_BASE 0x0500UL +#define USB_OTG_HOST_CHANNEL_SIZE 0x0020UL +#define USB_OTG_PCGCCTL_BASE 0x0E00UL +#define USB_OTG_FIFO_BASE 0x1000UL +#define USB_OTG_FIFO_SIZE 0x1000UL + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define CAN2 ((CAN_TypeDef *) CAN2_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC_BASE) +#define DAC ((DAC_TypeDef *) DAC_BASE) /* Kept for legacy purpose */ +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define ADC ((ADC_Common_TypeDef *) ADC_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC_BASE) +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define TIM9 ((TIM_TypeDef *) TIM9_BASE) +#define TIM10 ((TIM_TypeDef *) TIM10_BASE) +#define TIM11 ((TIM_TypeDef *) TIM11_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI2 ((SAI_TypeDef *) SAI2_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE) +#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE) +#define LTDC ((LTDC_TypeDef *)LTDC_BASE) +#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) +#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE) +#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) +#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) +#define ETH ((ETH_TypeDef *) ETH_BASE) +#define DMA2D ((DMA2D_TypeDef *)DMA2D_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define FMC_Bank1 ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank3 ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) +#define FMC_Bank5_6 ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) +#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) +#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) +#define USB_OTG_HS ((USB_OTG_GlobalTypeDef *) USB_OTG_HS_PERIPH_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************** Bit definition for ADC_SR register ********************/ +#define ADC_SR_AWD_Pos (0U) +#define ADC_SR_AWD_Msk (0x1UL << ADC_SR_AWD_Pos) /*!< 0x00000001 */ +#define ADC_SR_AWD ADC_SR_AWD_Msk /*!
© COPYRIGHT(c) 2016 STMicroelectronics
+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F7xx_HAL_CONF_H +#define __STM32F7xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +#define HAL_PWR_MODULE_ENABLED +/* #define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RCC_MODULE_ENABLED +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ + #define HAL_SPI_MODULE_ENABLED +/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +/* #define HAL_PCD_MODULE_ENABLED */ +/* #define HAL_HCD_MODULE_ENABLED */ + + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0x0FU) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define ART_ACCLERATOR_ENABLE 1U /* To enable instruction cache and prefetch */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## Ethernet peripheral configuration for NUCLEO 144 board ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ +/* LAN8742A PHY Address*/ +#define LAN8742A_PHY_ADDRESS 0x00 +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) + +#define PHY_READ_TO ((uint32_t)0x0000FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x1F) /*!< PHY special control/ status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< PHY Duplex mask */ + + +#define PHY_ISFR ((uint16_t)0x1D) /*!< PHY Interrupt Source Flag register Offset */ +#define PHY_ISFR_INT4 ((uint16_t)0x0010) /*!< PHY Link down inturrupt */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f7xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f7xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f7xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f7xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f7xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f7xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f7xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f7xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f7xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f7xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f7xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f7xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f7xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f7xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f7xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f7xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f7xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f7xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f7xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f7xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f7xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f7xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f7xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f7xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f7xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f7xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f7xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f7xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f7xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f7xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f7xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f7xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f7xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f7xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f7xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f7xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f7xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f7xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f7xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f7xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F7xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746/system_stm32f7xx.h b/src/runtime/micro/device/stm32f746/system_stm32f7xx.h new file mode 100644 index 000000000000..126ac71d7cfa --- /dev/null +++ b/src/runtime/micro/device/stm32f746/system_stm32f7xx.h @@ -0,0 +1,123 @@ +/** + ****************************************************************************** + * @file system_stm32f7xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device System Source File for STM32F7xx devices. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f7xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __SYSTEM_STM32F7XX_H +#define __SYSTEM_STM32F7XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32F7xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32F7xx_System_Exported_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ +extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ + + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32F7XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746/utvm_api.c index 1929d38ff85a..8a1d5df119cb 100644 --- a/src/runtime/micro/device/stm32f746/utvm_api.c +++ b/src/runtime/micro/device/stm32f746/utvm_api.c @@ -3,8 +3,18 @@ extern "C" { #endif +// TODO rename file to `utvm_timer.c` + #include "utvm_runtime.h" +// There are two implementations of cycle counters on the STM32F7X: SysTick and +// CYCCNT. SysTick is preferred, as it gives better error handling, but the +// counter is only 24 bits wide. If a larger timer is needed, use the CYCCNT +// implementation, which has a 32-bit counter. +#define USE_SYSTICK + +#ifdef USE_SYSTICK + #define SYST_CSR (*((volatile unsigned long *) 0xE000E010)) #define SYST_RVR (*((volatile unsigned long *) 0xE000E014)) #define SYST_CVR (*((volatile unsigned long *) 0xE000E018)) @@ -49,7 +59,8 @@ uint32_t UTVMTimerRead() { } } -/* +#else // !USE_SYSTICK + #define DWT_CTRL (*((volatile unsigned long *) 0xE0001000)) #define DWT_CYCCNT (*((volatile unsigned long *) 0xE0001004)) @@ -86,7 +97,8 @@ int32_t UTVMTimerRead() { return (largest - start_time) + stop_time; } } -*/ + +#endif // USE_SYSTICK #ifdef __cplusplus } // TVM_EXTERN_C diff --git a/src/runtime/micro/device/stm32f746/utvm_init.c b/src/runtime/micro/device/stm32f746/utvm_init.c new file mode 100644 index 000000000000..55ae5d42dc46 --- /dev/null +++ b/src/runtime/micro/device/stm32f746/utvm_init.c @@ -0,0 +1,278 @@ +/** + ****************************************************************************** + * @file system_stm32f7xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f7xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f7xx_system + * @{ + */ + +/** @addtogroup STM32F7xx_System_Private_Includes + * @{ + */ + +#include "stm32f7xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +#define VECT_TAB_SRAM +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 16000000; + const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void _UTVMInit(void) +{ +// /* FPU settings ------------------------------------------------------------*/ +// #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) +// SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ +// #endif +// /* Reset the RCC clock configuration to the default reset state ------------*/ +// /* Set HSION bit */ +// RCC->CR |= (uint32_t)0x00000001; +// +// /* Reset CFGR register */ +// RCC->CFGR = 0x00000000; +// +// /* Reset HSEON, CSSON and PLLON bits */ +// RCC->CR &= (uint32_t)0xFEF6FFFF; +// +// /* Reset PLLCFGR register */ +// RCC->PLLCFGR = 0x24003010; +// +// /* Reset HSEBYP bit */ +// RCC->CR &= (uint32_t)0xFFFBFFFF; +// +// /* Disable all interrupts */ +// RCC->CIR = 0x00000000; +// +// /* Configure the Vector Table location add offset address ------------------*/ +//#ifdef VECT_TAB_SRAM +// SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +//#else +// SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +//#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s b/src/runtime/micro/device/stm32f746/utvm_init.s index c78ae02c32f0..9bda879228db 100644 --- a/src/runtime/micro/device/stm32f746/utvm_init.s +++ b/src/runtime/micro/device/stm32f746/utvm_init.s @@ -47,11 +47,10 @@ .thumb .section .text.UTVMInit -.weak UTVMInit +/* .weak UTVMInit */ .type UTVMInit, %function UTVMInit: - /* ldr sp, =_estack */ /* set stack pointer */ - /* ldr sp, =0x20050000 */ /* set stack pointer */ + /* enable fpu */ ldr r0, =0xE000ED88 ldr r1, [r0] ldr r2, =0xF00000 @@ -60,8 +59,14 @@ UTVMInit: dsb isb /* set stack pointer */ + /* todo no hradcode */ ldr sp, =0x2004fffc + /* run init that's expressable in C */ + bl _UTVMInit + /* fix thumb-mode bit? */ bl UTVMMain +.size UTVMInit, .-UTVMInit + /** * @brief This is the code that gets called when the processor receives an @@ -73,5 +78,465 @@ UTVMInit: .section .text.Default_Handler,"ax",%progbits Default_Handler: Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler + b Infinite_Loop + .size Default_Handler, .-Default_Handler + + +/****************************************************************************** +* +* The minimal vector table for a Cortex M7. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ +.section .isr_vector,"a",%progbits +.type g_pfnVectors, %object +.size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word UTVMInit + + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDMMC1_IRQHandler /* SDMMC1 */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word 0 /* Reserved */ + .word RNG_IRQHandler /* Rng */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word SPI6_IRQHandler /* SPI6 */ + .word SAI1_IRQHandler /* SAI1 */ + .word LTDC_IRQHandler /* LTDC */ + .word LTDC_ER_IRQHandler /* LTDC error */ + .word DMA2D_IRQHandler /* DMA2D */ + .word SAI2_IRQHandler /* SAI2 */ + .word QUADSPI_IRQHandler /* QUADSPI */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word CEC_IRQHandler /* HDMI_CEC */ + .word I2C4_EV_IRQHandler /* I2C4 Event */ + .word I2C4_ER_IRQHandler /* I2C4 Error */ + .word SPDIF_RX_IRQHandler /* SPDIF_RX */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak LTDC_IRQHandler + .thumb_set LTDC_IRQHandler,Default_Handler + + .weak LTDC_ER_IRQHandler + .thumb_set LTDC_ER_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler + + .weak SAI2_IRQHandler + .thumb_set SAI2_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak SPDIF_RX_IRQHandler + .thumb_set SPDIF_RX_IRQHandler,Default_Handler diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s.bak b/src/runtime/micro/device/stm32f746/utvm_init.s.bak new file mode 100644 index 000000000000..5eda6ab09b4f --- /dev/null +++ b/src/runtime/micro/device/stm32f746/utvm_init.s.bak @@ -0,0 +1,589 @@ +/** + ****************************************************************************** + * @file startup_stm32f746xx.s + * @author MCD Application Team + * @brief STM32F746xx Devices vector table for GCC based toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M7 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m7 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system initialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M7. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDMMC1_IRQHandler /* SDMMC1 */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word 0 /* Reserved */ + .word RNG_IRQHandler /* Rng */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word SPI6_IRQHandler /* SPI6 */ + .word SAI1_IRQHandler /* SAI1 */ + .word LTDC_IRQHandler /* LTDC */ + .word LTDC_ER_IRQHandler /* LTDC error */ + .word DMA2D_IRQHandler /* DMA2D */ + .word SAI2_IRQHandler /* SAI2 */ + .word QUADSPI_IRQHandler /* QUADSPI */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word CEC_IRQHandler /* HDMI_CEC */ + .word I2C4_EV_IRQHandler /* I2C4 Event */ + .word I2C4_ER_IRQHandler /* I2C4 Error */ + .word SPDIF_RX_IRQHandler /* SPDIF_RX */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak LTDC_IRQHandler + .thumb_set LTDC_IRQHandler,Default_Handler + + .weak LTDC_ER_IRQHandler + .thumb_set LTDC_ER_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler + + .weak SAI2_IRQHandler + .thumb_set SAI2_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak SPDIF_RX_IRQHandler + .thumb_set SPDIF_RX_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/src/runtime/micro/device/stm32f746/utvm_unit.c.bak b/src/runtime/micro/device/stm32f746/utvm_unit.c.bak new file mode 100644 index 000000000000..1a362bdf618f --- /dev/null +++ b/src/runtime/micro/device/stm32f746/utvm_unit.c.bak @@ -0,0 +1,278 @@ +/** + ****************************************************************************** + * @file system_stm32f7xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f7xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f7xx_system + * @{ + */ + +/** @addtogroup STM32F7xx_System_Private_Includes + * @{ + */ + +#include "stm32f7xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 16000000; + const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000; + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x24003010; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 9cd515436c3f..a842cae9771b 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -335,10 +335,10 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; std::cout << " UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; - //std::cout << "do execution things: "; - //char tmp; - //std::cin >> tmp; - low_level_device()->Execute(utvm_init_loc, utvm_done_loc); + std::cout << "do execution things: "; + char tmp; + std::cin >> tmp; + //low_level_device()->Execute(utvm_init_loc, utvm_done_loc); // Check if there was an error during execution. If so, log it. CheckDeviceError(); @@ -438,7 +438,7 @@ std::tuple MicroSession::EncoderAppend( // Now, encode the unwrapped version. std::cout << " before array encode" << std::endl; void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); - std::cout << " after array encode" << num_args << std::endl; + std::cout << " after array encode" << std::endl; // And restore the original wrapped version. base_arr_handle->data = old_data; diff --git a/src/runtime/micro/tcl_socket.cc b/src/runtime/micro/tcl_socket.cc index 107fb1529498..4070e4bb3269 100644 --- a/src/runtime/micro/tcl_socket.cc +++ b/src/runtime/micro/tcl_socket.cc @@ -42,11 +42,13 @@ void TclSocket::Connect(tvm::common::SockAddr addr) { } void TclSocket::SendCommand() { + //std::cout << "[TclSocket::SendCommand]" << std::endl; + //std::cout << " cmd: " << cmd_builder_.str() << std::endl; cmd_builder_ << kCommandTerminateToken; std::string full_cmd = cmd_builder_.str(); + CHECK(tcp_socket_.Send(full_cmd.data(), full_cmd.length()) != -1) << "failed to send command"; - cmd_builder_.str(std::string()); reply_builder_.str(std::string()); char last_read = '\0'; diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 8864a6b3b33d..6230acd1603e 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -46,11 +46,11 @@ def create_micro_mod(c_mod, toolchain_prefix): micro_mod : tvm.module.Module micro module for the target device """ + print('[create_micro_mod]') temp_dir = util.tempdir() lib_obj_path = temp_dir.relpath("dev_lib.obj") print(c_mod.get_source()) - print(c_mod.entry_name) - input() + print(f' entry_name: {c_mod.entry_name}') c_mod.export_library( lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) From 1043b9d6d81278e684585a1b42cd3e004339cd31 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 1 Nov 2019 16:50:29 -0700 Subject: [PATCH 24/70] still no fokn clue --- python/tvm/contrib/binutil.py | 2 +- python/tvm/micro/base.py | 2 +- .../micro/device/stm32f746/utvm_init.c | 2 + .../micro/device/stm32f746/utvm_init.c.bad | 278 ++++++++++++++++++ .../micro/device/stm32f746/utvm_init.s | 1 - src/runtime/micro/micro_session.cc | 11 +- 6 files changed, 290 insertions(+), 6 deletions(-) create mode 100644 src/runtime/micro/device/stm32f746/utvm_init.c.bad diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 4617c9932c11..2077741a4ddd 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -169,7 +169,7 @@ def tvm_callback_relocate_binary( . = ALIGN(4); .text : { - . = ALIGN(4); + _stext = .; KEEP(*(.isr_vector)) KEEP(*(.text)) KEEP(*(.text*)) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index b6b2fdba2376..760c85f11e2f 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -288,7 +288,7 @@ def run_cmd(cmd): include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] - #include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] elif lib_type == LibType.OPERATOR: # Create a temporary copy of the source, so we can inject the dev lib diff --git a/src/runtime/micro/device/stm32f746/utvm_init.c b/src/runtime/micro/device/stm32f746/utvm_init.c index 55ae5d42dc46..da2084f6fd7e 100644 --- a/src/runtime/micro/device/stm32f746/utvm_init.c +++ b/src/runtime/micro/device/stm32f746/utvm_init.c @@ -147,6 +147,7 @@ * @param None * @retval None */ +extern char _stext; void _UTVMInit(void) { // /* FPU settings ------------------------------------------------------------*/ @@ -178,6 +179,7 @@ void _UTVMInit(void) //#else // SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ //#endif + SCB->VTOR = &_stext; /* Vector Table Relocation in Internal SRAM */ } /** diff --git a/src/runtime/micro/device/stm32f746/utvm_init.c.bad b/src/runtime/micro/device/stm32f746/utvm_init.c.bad new file mode 100644 index 000000000000..55ae5d42dc46 --- /dev/null +++ b/src/runtime/micro/device/stm32f746/utvm_init.c.bad @@ -0,0 +1,278 @@ +/** + ****************************************************************************** + * @file system_stm32f7xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f7xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f7xx_system + * @{ + */ + +/** @addtogroup STM32F7xx_System_Private_Includes + * @{ + */ + +#include "stm32f7xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +#define VECT_TAB_SRAM +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 16000000; + const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void _UTVMInit(void) +{ +// /* FPU settings ------------------------------------------------------------*/ +// #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) +// SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ +// #endif +// /* Reset the RCC clock configuration to the default reset state ------------*/ +// /* Set HSION bit */ +// RCC->CR |= (uint32_t)0x00000001; +// +// /* Reset CFGR register */ +// RCC->CFGR = 0x00000000; +// +// /* Reset HSEON, CSSON and PLLON bits */ +// RCC->CR &= (uint32_t)0xFEF6FFFF; +// +// /* Reset PLLCFGR register */ +// RCC->PLLCFGR = 0x24003010; +// +// /* Reset HSEBYP bit */ +// RCC->CR &= (uint32_t)0xFFFBFFFF; +// +// /* Disable all interrupts */ +// RCC->CIR = 0x00000000; +// +// /* Configure the Vector Table location add offset address ------------------*/ +//#ifdef VECT_TAB_SRAM +// SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +//#else +// SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +//#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s b/src/runtime/micro/device/stm32f746/utvm_init.s index 9bda879228db..56c7c891b933 100644 --- a/src/runtime/micro/device/stm32f746/utvm_init.s +++ b/src/runtime/micro/device/stm32f746/utvm_init.s @@ -63,7 +63,6 @@ UTVMInit: ldr sp, =0x2004fffc /* run init that's expressable in C */ bl _UTVMInit - /* fix thumb-mode bit? */ bl UTVMMain .size UTVMInit, .-UTVMInit diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index a842cae9771b..be09f42b9b5a 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,7 +57,8 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { - DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); + //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); + DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { size_t section_size = GetDefaultSectionSize(static_cast(i)); section_allocators_[i] = std::make_shared(DevMemRegion { @@ -335,15 +336,16 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; std::cout << " UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; - std::cout << "do execution things: "; + std::cout << " do execution things: "; char tmp; std::cin >> tmp; //low_level_device()->Execute(utvm_init_loc, utvm_done_loc); // Check if there was an error during execution. If so, log it. - CheckDeviceError(); + //CheckDeviceError(); uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); + std::cout << " task time was " << task_time << std::endl; GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); return task_time; @@ -525,7 +527,10 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr } void MicroSession::CheckDeviceError() { + std::cout << "[MicroSession::CheckDeviceError]" << std::endl; int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); + std::cout << " return_code: " << return_code << std::endl; + std::cout << " return_code loc: " << runtime_symbol_map_["utvm_return_code"].cast_to() << std::endl; if (return_code) { std::uintptr_t last_error = From 415df9bc1360685bc9d2ba9f18b7dd3cd16265d1 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 1 Nov 2019 17:05:04 -0700 Subject: [PATCH 25/70] i'm a moron --- python/tvm/contrib/binutil.py | 1 - src/runtime/micro/micro_session.cc | 12 ++++++------ src/runtime/micro/tcl_socket.cc | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 2077741a4ddd..e8767abba116 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -326,7 +326,6 @@ def tvm_callback_relocate_binary( raise RuntimeError(msg) print(f'relocated obj path is {rel_obj_path}') - input('check it out') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index be09f42b9b5a..79339240e101 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -57,8 +57,8 @@ void MicroSession::ExitWithScope() { } MicroSession::MicroSession() { - //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); - DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); + DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); + //DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { size_t section_size = GetDefaultSectionSize(static_cast(i)); section_allocators_[i] = std::make_shared(DevMemRegion { @@ -336,10 +336,10 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; std::cout << " UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; - std::cout << " do execution things: "; - char tmp; - std::cin >> tmp; - //low_level_device()->Execute(utvm_init_loc, utvm_done_loc); + //std::cout << " do execution things: "; + //char tmp; + //std::cin >> tmp; + low_level_device()->Execute(utvm_init_loc, utvm_done_loc); // Check if there was an error during execution. If so, log it. //CheckDeviceError(); diff --git a/src/runtime/micro/tcl_socket.cc b/src/runtime/micro/tcl_socket.cc index 4070e4bb3269..1f3f4922d2f4 100644 --- a/src/runtime/micro/tcl_socket.cc +++ b/src/runtime/micro/tcl_socket.cc @@ -49,6 +49,7 @@ void TclSocket::SendCommand() { CHECK(tcp_socket_.Send(full_cmd.data(), full_cmd.length()) != -1) << "failed to send command"; + cmd_builder_.str(std::string()); reply_builder_.str(std::string()); char last_read = '\0'; From edeafb3ea0c5a42becb465e4dedd5aa6bcb6e129 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 2 Nov 2019 13:55:34 -0700 Subject: [PATCH 26/70] Cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 5 +- python/tvm/autotvm/measure/measure_methods.py | 32 +- python/tvm/contrib/binutil.py | 13 + python/tvm/micro/base.py | 2 - python/tvm/micro/rpc_server.py | 21 - src/codegen/codegen_c_host.cc | 2 +- src/runtime/micro/device/stm32f746/core_cm7.h | 2671 --- .../micro/device/stm32f746/stm32f746xx.h | 17598 ---------------- .../micro/device/stm32f746/utvm_init.c | 244 - .../micro/device/stm32f746/utvm_init.s | 564 +- src/runtime/micro/micro_common.h | 16 + src/runtime/micro/micro_module.cc | 20 +- 12 files changed, 366 insertions(+), 20822 deletions(-) delete mode 100644 src/runtime/micro/device/stm32f746/core_cm7.h delete mode 100644 src/runtime/micro/device/stm32f746/stm32f746xx.h diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 874039f23951..6a05d47b907a 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -31,6 +31,9 @@ from vta.testing import simulator from vta.top import graph_pack +# first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal +# then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another + DEVICE_TYPE = 'openocd' TOOLCHAIN_PREFIX = 'arm-none-eabi-' @@ -38,7 +41,7 @@ TARGET = tvm.target.create('c -device=micro_dev') N, L, M = 32, 32, 32 -N_TRIAL = 5 +N_TRIAL = 1 N_PER_TRIAL = 1 N_PARALLEL = 1 diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index b4aa8553e692..0fa16e593f99 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -468,7 +468,37 @@ def run_through_rpc(measure_input, build_result, reconfig_runtime(remote) remote.upload(build_result.filename) func = remote.load_module(os.path.split(build_result.filename)[1]) - func.entry_name = 'default_function' + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + # TODO try running autotvm with the changes to micro module that grab + # the only function in the module if the requested name is + # __tvm_main__. + #func.entry_name = 'default_function' ctx = remote.context(str(measure_input.target), 0) time_f = func.time_evaluator( func.entry_name, ctx, number=number, repeat=repeat, min_repeat_ms=min_repeat_ms) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index e8767abba116..5d1e1bdc771f 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -23,6 +23,19 @@ from ..api import register_func +def run_cmd(cmd): + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + (out, _) = proc.communicate() + if proc.returncode != 0: + cmd_str = ' '.join(cmd) + error_msg = out.decode("utf-8") + msg = f"error while running command \"{cmd_str}\":\n{error_msg}" + raise RuntimeError(msg) + + @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. diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 760c85f11e2f..032dfcfdfc1e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -323,8 +323,6 @@ def run_cmd(cmd): curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] run_cmd(curr_compile_cmd) - # TODO(weberlo): adding '-fPIC' here causes the pc-relative data pools to - # not be updated when the obj is reloced. why? ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index dc45c64f0370..654e18d7c475 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -12,31 +12,10 @@ @tvm.register_func("tvm.rpc.server.start", override=True) def server_start(): - ## pylint: disable=unused-variable - #curr_path = os.path.dirname( - # os.path.abspath(os.path.expanduser(__file__))) - #proj_root = os.path.abspath(os.path.join(curr_path, "../../../../")) - #dll_path = find_libvta("libvta")[0] - #cfg_path = os.path.abspath(os.path.join(proj_root, "build/vta_config.json")) - #runtime_dll = [] session = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) session._enter() _load_module = tvm.get_global_func("tvm.rpc.server.load_module") - @tvm.register_func("tvm.rpc.server.load_module", override=True) - def load_module(file_name): - #load_vta_dll() - print(f'BEFORE MOD LOAD for {file_name}') - res = _load_module(file_name) - print(f'AFTER MOD LOAD: {res}') - return res - - - #@tvm.register_func("device_api.ext_dev") - #def ext_dev_callback(): - # load_vta_dll() - # return tvm.get_global_func("device_api.ext_dev")() - @tvm.register_func("tvm.rpc.server.shutdown", override=True) def server_shutdown(): session._exit() diff --git a/src/codegen/codegen_c_host.cc b/src/codegen/codegen_c_host.cc index 986c4f94ec94..063962a91ffe 100644 --- a/src/codegen/codegen_c_host.cc +++ b/src/codegen/codegen_c_host.cc @@ -109,7 +109,7 @@ void CodeGenCHost::PrintType(Type t, std::ostream& os) { // NOLINT(*) if (t.is_float()) { switch (t.bits()) { case 16: - os << "_Float16"; + os << "half"; break; case 32: os << "float"; break; case 64: diff --git a/src/runtime/micro/device/stm32f746/core_cm7.h b/src/runtime/micro/device/stm32f746/core_cm7.h deleted file mode 100644 index ada6c2a57ee8..000000000000 --- a/src/runtime/micro/device/stm32f746/core_cm7.h +++ /dev/null @@ -1,2671 +0,0 @@ -/**************************************************************************//** - * @file core_cm7.h - * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File - * @version V5.0.8 - * @date 04. June 2018 - ******************************************************************************/ -/* - * Copyright (c) 2009-2018 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed 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 - * - * 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 defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined (__clang__) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CORE_CM7_H_GENERIC -#define __CORE_CM7_H_GENERIC - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -/** - \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** - \ingroup Cortex_M7 - @{ - */ - -#include "cmsis_version.h" - -/* CMSIS CM7 definitions */ -#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ -#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ -#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ - __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ - -#define __CORTEX_M (7U) /*!< Cortex-M Core */ - -/** __FPU_USED indicates whether an FPU is used or not. - For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. -*/ -#if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) - #define __FPU_USED 1U - #else - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #define __FPU_USED 0U - #endif - #else - #define __FPU_USED 0U - #endif - -#endif - -#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM7_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM7_H_DEPENDANT -#define __CORE_CM7_H_DEPENDANT - -#ifdef __cplusplus - extern "C" { -#endif - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES - #ifndef __CM7_REV - #define __CM7_REV 0x0000U - #warning "__CM7_REV not defined in device header file; using default!" - #endif - - #ifndef __FPU_PRESENT - #define __FPU_PRESENT 0U - #warning "__FPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __ICACHE_PRESENT - #define __ICACHE_PRESENT 0U - #warning "__ICACHE_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __DCACHE_PRESENT - #define __DCACHE_PRESENT 0U - #warning "__DCACHE_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __DTCM_PRESENT - #define __DTCM_PRESENT 0U - #warning "__DTCM_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif - - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ -#else - #define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/* following defines should be used for structure members */ -#define __IM volatile const /*! Defines 'read only' structure member permissions */ -#define __OM volatile /*! Defines 'write only' structure member permissions */ -#define __IOM volatile /*! Defines 'read / write' structure member permissions */ - -/*@} end of group Cortex_M7 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - - Core FPU Register - ******************************************************************************/ -/** - \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** - \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union -{ - struct - { - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - -/* APSR Register Definitions */ -#define APSR_N_Pos 31U /*!< APSR: N Position */ -#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ - -#define APSR_Z_Pos 30U /*!< APSR: Z Position */ -#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ - -#define APSR_C_Pos 29U /*!< APSR: C Position */ -#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ - -#define APSR_V_Pos 28U /*!< APSR: V Position */ -#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ - -#define APSR_Q_Pos 27U /*!< APSR: Q Position */ -#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ - -#define APSR_GE_Pos 16U /*!< APSR: GE Position */ -#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ - - -/** - \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - -/* IPSR Register Definitions */ -#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ -#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ - - -/** - \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:1; /*!< bit: 9 Reserved */ - uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit */ - uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - -/* xPSR Register Definitions */ -#define xPSR_N_Pos 31U /*!< xPSR: N Position */ -#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ - -#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ -#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ - -#define xPSR_C_Pos 29U /*!< xPSR: C Position */ -#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ - -#define xPSR_V_Pos 28U /*!< xPSR: V Position */ -#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ - -#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ -#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ - -#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ -#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ - -#define xPSR_T_Pos 24U /*!< xPSR: T Position */ -#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ - -#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ -#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ - -#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ -#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ - -#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ -#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ - - -/** - \brief Union type to access the Control Registers (CONTROL). - */ -typedef union -{ - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/* CONTROL Register Definitions */ -#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ -#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ - -#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ -#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ - -#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ -#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ - -/*@} end of group CMSIS_CORE */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** - \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct -{ - __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24U]; - __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; - __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24U]; - __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24U]; - __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56U]; - __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** - \brief Structure type to access the System Control Block (SCB). - */ -typedef struct -{ - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[1U]; - __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ - __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ - __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ - __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ - uint32_t RESERVED3[93U]; - __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ - uint32_t RESERVED4[15U]; - __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ - __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ - uint32_t RESERVED5[1U]; - __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ - uint32_t RESERVED6[1U]; - __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ - __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ - __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ - __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ - __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ - __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ - __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ - __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ - uint32_t RESERVED7[6U]; - __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ - __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ - __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ - __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ - __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ - uint32_t RESERVED8[1U]; - __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ -#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ - -#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ -#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ - -#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ -#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ - -#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Register Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ -#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ - -#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ -#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ - -#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ -#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ - -#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ -#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ - -#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ -#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ - -#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ -#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ - -/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ -#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ - -#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ -#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ - -#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ -#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ - -#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ -#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ - -#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ -#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ - -#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ -#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ - -#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ -#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ - -/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ -#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ - -#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ -#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ - -#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ -#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ - -#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ -#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ - -#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ -#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ - -#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ -#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ - -/* SCB Hard Fault Status Register Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ - -/* SCB Cache Level ID Register Definitions */ -#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ -#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ - -#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ -#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ - -/* SCB Cache Type Register Definitions */ -#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ -#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ - -#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ -#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ - -#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ -#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ - -#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ -#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ - -#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ -#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ - -/* SCB Cache Size ID Register Definitions */ -#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ -#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ - -#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ -#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ - -#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ -#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ - -#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ -#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ - -#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ -#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ - -#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ -#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ - -#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ -#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ - -/* SCB Cache Size Selection Register Definitions */ -#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ -#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ - -#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ -#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ - -/* SCB Software Triggered Interrupt Register Definitions */ -#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ -#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ - -/* SCB D-Cache Invalidate by Set-way Register Definitions */ -#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ -#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ - -#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ -#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ - -/* SCB D-Cache Clean by Set-way Register Definitions */ -#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ -#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ - -#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ -#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ - -/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ -#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ -#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ - -#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ -#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ - -/* Instruction Tightly-Coupled Memory Control Register Definitions */ -#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ -#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ - -#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ -#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ - -#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ -#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ - -#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ -#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ - -/* Data Tightly-Coupled Memory Control Register Definitions */ -#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ -#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ - -#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ -#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ - -#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ -#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ - -#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ -#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ - -/* AHBP Control Register Definitions */ -#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ -#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ - -#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ -#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ - -/* L1 Cache Control Register Definitions */ -#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ -#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ - -#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ -#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ - -#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ -#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ - -/* AHBS Control Register Definitions */ -#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ -#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ - -#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ -#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ - -#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ -#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ - -/* Auxiliary Bus Fault Status Register Definitions */ -#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ -#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ - -#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ -#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ - -#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ -#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ - -#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ -#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ - -#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ -#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ - -#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ -#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** - \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct -{ - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ -#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ -#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ - -#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ -#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ - -#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ -#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ - -/*@} end of group CMSIS_SCnotSCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** - \brief Structure type to access the System Timer (SysTick). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** - \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct -{ - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** - \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ - uint32_t RESERVED3[981U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** - \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct -{ - __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ -#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ - -#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ -#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ -#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ - -#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ -#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ - -#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** - \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct -{ - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -#define MPU_TYPE_RALIASES 4U - -/* MPU Type Register Definitions */ -#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register Definitions */ -#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register Definitions */ -#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register Definitions */ -#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register Definitions */ -#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_FPU Floating Point Unit (FPU) - \brief Type definitions for the Floating Point Unit (FPU) - @{ - */ - -/** - \brief Structure type to access the Floating Point Unit (FPU). - */ -typedef struct -{ - uint32_t RESERVED0[1U]; - __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ - __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ - __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ - __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ - __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ - __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ -} FPU_Type; - -/* Floating-Point Context Control Register Definitions */ -#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ -#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ - -#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ -#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ - -#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ -#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ - -#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ -#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ - -#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ -#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ - -#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ -#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ - -#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ -#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ - -#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ -#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ - -#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ -#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ - -/* Floating-Point Context Address Register Definitions */ -#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ -#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ - -/* Floating-Point Default Status Control Register Definitions */ -#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ -#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ - -#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ -#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ - -#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ -#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ - -#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ -#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ - -/* Media and FP Feature Register 0 Definitions */ -#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ -#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ - -#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ -#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ - -#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ -#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ - -#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ -#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ - -#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ -#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ - -#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ -#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ - -#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ -#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ - -#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ -#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ - -/* Media and FP Feature Register 1 Definitions */ -#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ -#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ - -#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ -#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ - -#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ -#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ - -#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ -#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ - -/* Media and FP Feature Register 2 Definitions */ - -/*@} end of group CMSIS_FPU */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** - \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct -{ - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register Definitions */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register Definitions */ -#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register Definitions */ -#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_bitfield Core register bit field macros - \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). - @{ - */ - -/** - \brief Mask and shift a bit field value for use in a register bit range. - \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. - \return Masked and shifted value. -*/ -#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) - -/** - \brief Mask and shift a register value to extract a bit filed value. - \param[in] field Name of the register bit field. - \param[in] value Value of register. This parameter is interpreted as an uint32_t type. - \return Masked and shifted bit field value. -*/ -#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) - -/*@} end of group CMSIS_core_bitfield */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Core Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ -#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** - \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -#ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE -#else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset -#endif /* CMSIS_NVIC_VIRTUAL */ - -#ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE -#else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector -#endif /* (CMSIS_VECTAB_VIRTUAL) */ - -#define NVIC_USER_IRQ_OFFSET 16 - - -/* The following EXC_RETURN values are saved the LR on exception entry */ -#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ -#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ -#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ -#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ -#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ -#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ - - -/** - \brief Set Priority Grouping - \details Sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ - SCB->AIRCR = reg_value; -} - - -/** - \brief Get Priority Grouping - \details Reads the priority grouping field from the NVIC Interrupt Controller. - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) -{ - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); -} - - -/** - \brief Enable Interrupt - \details Enables a device specific interrupt in the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - } -} - - -/** - \brief Get Interrupt Enable status - \details Returns a device specific interrupt enable status from the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt is not enabled. - \return 1 Interrupt is enabled. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Disable Interrupt - \details Disables a device specific interrupt in the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } -} - - -/** - \brief Get Pending Interrupt - \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Set Pending Interrupt - \details Sets the pending bit of a device specific interrupt in the NVIC pending register. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - } -} - - -/** - \brief Clear Pending Interrupt - \details Clears the pending bit of a device specific interrupt in the NVIC pending register. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - } -} - - -/** - \brief Get Active Interrupt - \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Set Interrupt Priority - \details Sets the priority of a device specific interrupt or a processor exception. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - \note The priority cannot be set for every processor exception. - */ -__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } -} - - -/** - \brief Get Interrupt Priority - \details Reads the priority of a device specific interrupt or a processor exception. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \return Interrupt Priority. - Value is aligned automatically to the implemented priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) -{ - - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } -} - - -/** - \brief Encode Priority - \details Encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); -} - - -/** - \brief Decode Priority - \details Decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); -} - - -/** - \brief Set Interrupt Vector - \details Sets an interrupt vector in SRAM based interrupt vector table. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - VTOR must been relocated to SRAM before. - \param [in] IRQn Interrupt number - \param [in] vector Address of interrupt handler function - */ -__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) -{ - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; -} - - -/** - \brief Get Interrupt Vector - \details Reads an interrupt vector from interrupt vector table. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \return Address of interrupt handler function - */ -__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) -{ - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; -} - - -/** - \brief System Reset - \details Initiates a system reset request to reset the MCU. - */ -__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) -{ - __DSB(); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - - for(;;) /* wait until reset */ - { - __NOP(); - } -} - -/*@} end of CMSIS_Core_NVICFunctions */ - -/* ########################## MPU functions #################################### */ - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - -#include "mpu_armv7.h" - -#endif - -/* ########################## FPU functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_FpuFunctions FPU Functions - \brief Function that provides FPU type. - @{ - */ - -/** - \brief get FPU type - \details returns the FPU type - \returns - - \b 0: No FPU - - \b 1: Single precision FPU - - \b 2: Double + Single precision FPU - */ -__STATIC_INLINE uint32_t SCB_GetFPUType(void) -{ - uint32_t mvfr0; - - mvfr0 = SCB->MVFR0; - if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) - { - return 2U; /* Double + Single precision FPU */ - } - else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) - { - return 1U; /* Single precision FPU */ - } - else - { - return 0U; /* No FPU */ - } -} - - -/*@} end of CMSIS_Core_FpuFunctions */ - - - -/* ########################## Cache functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_CacheFunctions Cache Functions - \brief Functions that configure Instruction and Data cache. - @{ - */ - -/* Cache Size ID Register Macros */ -#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) -#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) - - -/** - \brief Enable I-Cache - \details Turns on I-Cache - */ -__STATIC_INLINE void SCB_EnableICache (void) -{ - #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) - __DSB(); - __ISB(); - SCB->ICIALLU = 0UL; /* invalidate I-Cache */ - __DSB(); - __ISB(); - SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Disable I-Cache - \details Turns off I-Cache - */ -__STATIC_INLINE void SCB_DisableICache (void) -{ - #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) - __DSB(); - __ISB(); - SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ - SCB->ICIALLU = 0UL; /* invalidate I-Cache */ - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Invalidate I-Cache - \details Invalidates I-Cache - */ -__STATIC_INLINE void SCB_InvalidateICache (void) -{ - #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) - __DSB(); - __ISB(); - SCB->ICIALLU = 0UL; - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Enable D-Cache - \details Turns on D-Cache - */ -__STATIC_INLINE void SCB_EnableDCache (void) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - uint32_t ccsidr; - uint32_t sets; - uint32_t ways; - - SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ - __DSB(); - - ccsidr = SCB->CCSIDR; - - /* invalidate D-Cache */ - sets = (uint32_t)(CCSIDR_SETS(ccsidr)); - do { - ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); - do { - SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | - ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); - #if defined ( __CC_ARM ) - __schedule_barrier(); - #endif - } while (ways-- != 0U); - } while(sets-- != 0U); - __DSB(); - - SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Disable D-Cache - \details Turns off D-Cache - */ -__STATIC_INLINE void SCB_DisableDCache (void) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - uint32_t ccsidr; - uint32_t sets; - uint32_t ways; - - SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ - __DSB(); - - SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ - __DSB(); - - ccsidr = SCB->CCSIDR; - - /* clean & invalidate D-Cache */ - sets = (uint32_t)(CCSIDR_SETS(ccsidr)); - do { - ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); - do { - SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | - ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); - #if defined ( __CC_ARM ) - __schedule_barrier(); - #endif - } while (ways-- != 0U); - } while(sets-- != 0U); - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Invalidate D-Cache - \details Invalidates D-Cache - */ -__STATIC_INLINE void SCB_InvalidateDCache (void) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - uint32_t ccsidr; - uint32_t sets; - uint32_t ways; - - SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ - __DSB(); - - ccsidr = SCB->CCSIDR; - - /* invalidate D-Cache */ - sets = (uint32_t)(CCSIDR_SETS(ccsidr)); - do { - ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); - do { - SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | - ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); - #if defined ( __CC_ARM ) - __schedule_barrier(); - #endif - } while (ways-- != 0U); - } while(sets-- != 0U); - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Clean D-Cache - \details Cleans D-Cache - */ -__STATIC_INLINE void SCB_CleanDCache (void) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - uint32_t ccsidr; - uint32_t sets; - uint32_t ways; - - SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ - __DSB(); - - ccsidr = SCB->CCSIDR; - - /* clean D-Cache */ - sets = (uint32_t)(CCSIDR_SETS(ccsidr)); - do { - ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); - do { - SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | - ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); - #if defined ( __CC_ARM ) - __schedule_barrier(); - #endif - } while (ways-- != 0U); - } while(sets-- != 0U); - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief Clean & Invalidate D-Cache - \details Cleans and Invalidates D-Cache - */ -__STATIC_INLINE void SCB_CleanInvalidateDCache (void) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - uint32_t ccsidr; - uint32_t sets; - uint32_t ways; - - SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ - __DSB(); - - ccsidr = SCB->CCSIDR; - - /* clean & invalidate D-Cache */ - sets = (uint32_t)(CCSIDR_SETS(ccsidr)); - do { - ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); - do { - SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | - ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); - #if defined ( __CC_ARM ) - __schedule_barrier(); - #endif - } while (ways-- != 0U); - } while(sets-- != 0U); - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief D-Cache Invalidate by address - \details Invalidates D-Cache for the given address - \param[in] addr address (aligned to 32-byte boundary) - \param[in] dsize size of memory block (in number of bytes) -*/ -__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t)addr; - int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ - - __DSB(); - - while (op_size > 0) { - SCB->DCIMVAC = op_addr; - op_addr += (uint32_t)linesize; - op_size -= linesize; - } - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief D-Cache Clean by address - \details Cleans D-Cache for the given address - \param[in] addr address (aligned to 32-byte boundary) - \param[in] dsize size of memory block (in number of bytes) -*/ -__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t) addr; - int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ - - __DSB(); - - while (op_size > 0) { - SCB->DCCMVAC = op_addr; - op_addr += (uint32_t)linesize; - op_size -= linesize; - } - - __DSB(); - __ISB(); - #endif -} - - -/** - \brief D-Cache Clean and Invalidate by address - \details Cleans and invalidates D_Cache for the given address - \param[in] addr address (aligned to 32-byte boundary) - \param[in] dsize size of memory block (in number of bytes) -*/ -__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) -{ - #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t) addr; - int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ - - __DSB(); - - while (op_size > 0) { - SCB->DCCIMVAC = op_addr; - op_addr += (uint32_t)linesize; - op_size -= linesize; - } - - __DSB(); - __ISB(); - #endif -} - - -/*@} end of CMSIS_Core_CacheFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) - -/** - \brief System Tick Configuration - \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - \param [in] ticks Number of ticks between two interrupts. - \return 0 Function succeeded. - \return 1 Function failed. - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } - - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** - \brief ITM Send Character - \details Transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - \param [in] ch Character to transmit. - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) - { - __NOP(); - } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); -} - - -/** - \brief ITM Receive Character - \details Inputs a character via the external variable \ref ITM_RxBuffer. - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) -{ - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** - \brief ITM Check Character - \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar (void) -{ - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - - - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM7_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ diff --git a/src/runtime/micro/device/stm32f746/stm32f746xx.h b/src/runtime/micro/device/stm32f746/stm32f746xx.h deleted file mode 100644 index d97ad747b10c..000000000000 --- a/src/runtime/micro/device/stm32f746/stm32f746xx.h +++ /dev/null @@ -1,17598 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f746xx.h - * @author MCD Application Team - * @brief CMSIS Cortex-M7 Device Peripheral Access Layer Header File. - * - * This file contains: - * - Data structures and the address mapping for all peripherals - * - Peripheral's registers declarations and bits definition - * - Macros to access peripheral’s registers hardware - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -// NOTE: file from CMSIS/Device/ST/STM32F7xx/Include/stm32f746xx.h - -/** @addtogroup CMSIS_Device - * @{ - */ - -/** @addtogroup stm32f746xx - * @{ - */ - -#ifndef __STM32F746xx_H -#define __STM32F746xx_H - -#ifdef __cplusplus - extern "C" { -#endif /* __cplusplus */ - -/** @addtogroup Configuration_section_for_CMSIS - * @{ - */ - -/** - * @brief STM32F7xx Interrupt Number Definition, according to the selected device - * in @ref Library_configuration_section - */ -typedef enum -{ -/****** Cortex-M7 Processor Exceptions Numbers ****************************************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M7 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M7 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M7 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M7 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M7 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M7 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M7 System Tick Interrupt */ -/****** STM32 specific Interrupt Numbers **********************************************************************/ - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ - PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ - TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ - RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ - FLASH_IRQn = 4, /*!< FLASH global Interrupt */ - RCC_IRQn = 5, /*!< RCC global Interrupt */ - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ - EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ - EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ - EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ - EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ - DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ - DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ - DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ - DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ - DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ - DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ - DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ - ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */ - CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ - CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */ - TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */ - TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ - TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ - TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ - TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ - TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ - USART1_IRQn = 37, /*!< USART1 global Interrupt */ - USART2_IRQn = 38, /*!< USART2 global Interrupt */ - USART3_IRQn = 39, /*!< USART3 global Interrupt */ - EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ - OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ - TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ - TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ - TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ - TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ - DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ - FMC_IRQn = 48, /*!< FMC global Interrupt */ - SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ - TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ - SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ - UART4_IRQn = 52, /*!< UART4 global Interrupt */ - UART5_IRQn = 53, /*!< UART5 global Interrupt */ - TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ - TIM7_IRQn = 55, /*!< TIM7 global interrupt */ - DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ - DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ - DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ - DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ - DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ - ETH_IRQn = 61, /*!< Ethernet global Interrupt */ - ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ - CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ - CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ - CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ - CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ - OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ - DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ - DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ - DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ - USART6_IRQn = 71, /*!< USART6 global interrupt */ - I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ - I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ - OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ - OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ - OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ - OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ - DCMI_IRQn = 78, /*!< DCMI global interrupt */ - RNG_IRQn = 80, /*!< RNG global interrupt */ - FPU_IRQn = 81, /*!< FPU global interrupt */ - UART7_IRQn = 82, /*!< UART7 global interrupt */ - UART8_IRQn = 83, /*!< UART8 global interrupt */ - SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ - SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ - SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ - SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ - LTDC_IRQn = 88, /*!< LTDC global Interrupt */ - LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ - DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ - SAI2_IRQn = 91, /*!< SAI2 global Interrupt */ - QUADSPI_IRQn = 92, /*!< Quad SPI global interrupt */ - LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ - CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ - I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ - I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ - SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ -} IRQn_Type; - -/** - * @} - */ - -/** - * @brief Configuration of the Cortex-M7 Processor and Core Peripherals - */ -#define __CM7_REV 0x0001U /*!< Cortex-M7 revision r0p1 */ -#define __MPU_PRESENT 1 /*!< CM7 provides an MPU */ -#define __NVIC_PRIO_BITS 4 /*!< CM7 uses 4 Bits for the Priority Levels */ -#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ -#define __FPU_PRESENT 1 /*!< FPU present */ -#define __ICACHE_PRESENT 1 /*!< CM7 instruction cache present */ -#define __DCACHE_PRESENT 1 /*!< CM7 data cache present */ -#include "core_cm7.h" /*!< Cortex-M7 processor and core peripherals */ - - -#include "system_stm32f7xx.h" -#include - -/** @addtogroup Peripheral_registers_structures - * @{ - */ - -/** - * @brief Analog to Digital Converter - */ - -typedef struct -{ - __IO uint32_t SR; /*!< ADC status register, Address offset: 0x00 */ - __IO uint32_t CR1; /*!< ADC control register 1, Address offset: 0x04 */ - __IO uint32_t CR2; /*!< ADC control register 2, Address offset: 0x08 */ - __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x0C */ - __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x10 */ - __IO uint32_t JOFR1; /*!< ADC injected channel data offset register 1, Address offset: 0x14 */ - __IO uint32_t JOFR2; /*!< ADC injected channel data offset register 2, Address offset: 0x18 */ - __IO uint32_t JOFR3; /*!< ADC injected channel data offset register 3, Address offset: 0x1C */ - __IO uint32_t JOFR4; /*!< ADC injected channel data offset register 4, Address offset: 0x20 */ - __IO uint32_t HTR; /*!< ADC watchdog higher threshold register, Address offset: 0x24 */ - __IO uint32_t LTR; /*!< ADC watchdog lower threshold register, Address offset: 0x28 */ - __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x2C */ - __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x30 */ - __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x34 */ - __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x38*/ - __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x3C */ - __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x40 */ - __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x44 */ - __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x48 */ - __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x4C */ -} ADC_TypeDef; - -typedef struct -{ - __IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ - __IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ - __IO uint32_t CDR; /*!< ADC common regular data register for dual - AND triple modes, Address offset: ADC1 base address + 0x308 */ -} ADC_Common_TypeDef; - - -/** - * @brief Controller Area Network TxMailBox - */ - -typedef struct -{ - __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ - __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ - __IO uint32_t TDLR; /*!< CAN mailbox data low register */ - __IO uint32_t TDHR; /*!< CAN mailbox data high register */ -} CAN_TxMailBox_TypeDef; - -/** - * @brief Controller Area Network FIFOMailBox - */ - -typedef struct -{ - __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ - __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ - __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ - __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ -} CAN_FIFOMailBox_TypeDef; - -/** - * @brief Controller Area Network FilterRegister - */ - -typedef struct -{ - __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ - __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ -} CAN_FilterRegister_TypeDef; - -/** - * @brief Controller Area Network - */ - -typedef struct -{ - __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ - __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ - __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ - __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ - __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ - __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ - __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ - __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ - uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ - CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ - CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ - uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ - __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ - __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ - uint32_t RESERVED2; /*!< Reserved, 0x208 */ - __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ - uint32_t RESERVED3; /*!< Reserved, 0x210 */ - __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ - uint32_t RESERVED4; /*!< Reserved, 0x218 */ - __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ - uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ - CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ -} CAN_TypeDef; - -/** - * @brief HDMI-CEC - */ - -typedef struct -{ - __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ - __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ - __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ - __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ - __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ - __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ -}CEC_TypeDef; - -/** - * @brief CRC calculation unit - */ - -typedef struct -{ - __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ - __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ - uint8_t RESERVED0; /*!< Reserved, 0x05 */ - uint16_t RESERVED1; /*!< Reserved, 0x06 */ - __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ - uint32_t RESERVED2; /*!< Reserved, 0x0C */ - __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ - __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ -} CRC_TypeDef; - -/** - * @brief Digital to Analog Converter - */ - -typedef struct -{ - __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ - __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ - __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ - __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ - __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ - __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ - __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ - __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ - __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ - __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ - __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ - __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ - __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ - __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ -} DAC_TypeDef; - - -/** - * @brief Debug MCU - */ - -typedef struct -{ - __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ - __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ - __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ - __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ -}DBGMCU_TypeDef; - -/** - * @brief DCMI - */ - -typedef struct -{ - __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ - __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ - __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ - __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ - __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ - __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ - __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ - __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ - __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ - __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ - __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ -} DCMI_TypeDef; - -/** - * @brief DMA Controller - */ - -typedef struct -{ - __IO uint32_t CR; /*!< DMA stream x configuration register */ - __IO uint32_t NDTR; /*!< DMA stream x number of data register */ - __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ - __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ - __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ - __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ -} DMA_Stream_TypeDef; - -typedef struct -{ - __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ - __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ - __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ - __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ -} DMA_TypeDef; - -/** - * @brief DMA2D Controller - */ - -typedef struct -{ - __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ - __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ - __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ - __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ - __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ - __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ - __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ - __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ - __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ - __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ - __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ - __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ - __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ - __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ - __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ - __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ - __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ - __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ - __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ - __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ - uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ - __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ - __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ -} DMA2D_TypeDef; - - -/** - * @brief Ethernet MAC - */ - -typedef struct -{ - __IO uint32_t MACCR; - __IO uint32_t MACFFR; - __IO uint32_t MACHTHR; - __IO uint32_t MACHTLR; - __IO uint32_t MACMIIAR; - __IO uint32_t MACMIIDR; - __IO uint32_t MACFCR; - __IO uint32_t MACVLANTR; /* 8 */ - uint32_t RESERVED0[2]; - __IO uint32_t MACRWUFFR; /* 11 */ - __IO uint32_t MACPMTCSR; - uint32_t RESERVED1; - __IO uint32_t MACDBGR; - __IO uint32_t MACSR; /* 15 */ - __IO uint32_t MACIMR; - __IO uint32_t MACA0HR; - __IO uint32_t MACA0LR; - __IO uint32_t MACA1HR; - __IO uint32_t MACA1LR; - __IO uint32_t MACA2HR; - __IO uint32_t MACA2LR; - __IO uint32_t MACA3HR; - __IO uint32_t MACA3LR; /* 24 */ - uint32_t RESERVED2[40]; - __IO uint32_t MMCCR; /* 65 */ - __IO uint32_t MMCRIR; - __IO uint32_t MMCTIR; - __IO uint32_t MMCRIMR; - __IO uint32_t MMCTIMR; /* 69 */ - uint32_t RESERVED3[14]; - __IO uint32_t MMCTGFSCCR; /* 84 */ - __IO uint32_t MMCTGFMSCCR; - uint32_t RESERVED4[5]; - __IO uint32_t MMCTGFCR; - uint32_t RESERVED5[10]; - __IO uint32_t MMCRFCECR; - __IO uint32_t MMCRFAECR; - uint32_t RESERVED6[10]; - __IO uint32_t MMCRGUFCR; - uint32_t RESERVED7[334]; - __IO uint32_t PTPTSCR; - __IO uint32_t PTPSSIR; - __IO uint32_t PTPTSHR; - __IO uint32_t PTPTSLR; - __IO uint32_t PTPTSHUR; - __IO uint32_t PTPTSLUR; - __IO uint32_t PTPTSAR; - __IO uint32_t PTPTTHR; - __IO uint32_t PTPTTLR; - __IO uint32_t RESERVED8; - __IO uint32_t PTPTSSR; - uint32_t RESERVED9[565]; - __IO uint32_t DMABMR; - __IO uint32_t DMATPDR; - __IO uint32_t DMARPDR; - __IO uint32_t DMARDLAR; - __IO uint32_t DMATDLAR; - __IO uint32_t DMASR; - __IO uint32_t DMAOMR; - __IO uint32_t DMAIER; - __IO uint32_t DMAMFBOCR; - __IO uint32_t DMARSWTR; - uint32_t RESERVED10[8]; - __IO uint32_t DMACHTDR; - __IO uint32_t DMACHRDR; - __IO uint32_t DMACHTBAR; - __IO uint32_t DMACHRBAR; -} ETH_TypeDef; - -/** - * @brief External Interrupt/Event Controller - */ - -typedef struct -{ - __IO uint32_t IMR; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ - __IO uint32_t EMR; /*!< EXTI Event mask register, Address offset: 0x04 */ - __IO uint32_t RTSR; /*!< EXTI Rising trigger selection register, Address offset: 0x08 */ - __IO uint32_t FTSR; /*!< EXTI Falling trigger selection register, Address offset: 0x0C */ - __IO uint32_t SWIER; /*!< EXTI Software interrupt event register, Address offset: 0x10 */ - __IO uint32_t PR; /*!< EXTI Pending register, Address offset: 0x14 */ -} EXTI_TypeDef; - -/** - * @brief FLASH Registers - */ - -typedef struct -{ - __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ - __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x04 */ - __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ - __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x0C */ - __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x10 */ - __IO uint32_t OPTCR; /*!< FLASH option control register , Address offset: 0x14 */ - __IO uint32_t OPTCR1; /*!< FLASH option control register 1 , Address offset: 0x18 */ -} FLASH_TypeDef; - - - -/** - * @brief Flexible Memory Controller - */ - -typedef struct -{ - __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ -} FMC_Bank1_TypeDef; - -/** - * @brief Flexible Memory Controller Bank1E - */ - -typedef struct -{ - __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ -} FMC_Bank1E_TypeDef; - -/** - * @brief Flexible Memory Controller Bank3 - */ - -typedef struct -{ - __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */ - __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */ - __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */ - __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */ - uint32_t RESERVED0; /*!< Reserved, 0x90 */ - __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */ -} FMC_Bank3_TypeDef; - -/** - * @brief Flexible Memory Controller Bank5_6 - */ - -typedef struct -{ - __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ - __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ - __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ - __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ - __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ -} FMC_Bank5_6_TypeDef; - - -/** - * @brief General Purpose I/O - */ - -typedef struct -{ - __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ - __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ - __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ - __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ - __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ - __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ - __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ - __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ - __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ -} GPIO_TypeDef; - -/** - * @brief System configuration controller - */ - -typedef struct -{ - __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ - __IO uint32_t PMC; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ - __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ - uint32_t RESERVED[2]; /*!< Reserved, 0x18-0x1C */ - __IO uint32_t CMPCR; /*!< SYSCFG Compensation cell control register, Address offset: 0x20 */ -} SYSCFG_TypeDef; - -/** - * @brief Inter-integrated Circuit Interface - */ - -typedef struct -{ - __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ - __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ - __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ - __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ - __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ - __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ - __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ - __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ - __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ - __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ - __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ -} I2C_TypeDef; - -/** - * @brief Independent WATCHDOG - */ - -typedef struct -{ - __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ - __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ - __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ - __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ - __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ -} IWDG_TypeDef; - - -/** - * @brief LCD-TFT Display Controller - */ - -typedef struct -{ - uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ - __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ - __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ - __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ - __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ - __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ - uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ - __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ - uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ - __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ - uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ - __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ - __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ - __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ - __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ - __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ - __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ -} LTDC_TypeDef; - -/** - * @brief LCD-TFT Display layer x Controller - */ - -typedef struct -{ - __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ - __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ - __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ - __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ - __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ - __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ - __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ - __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ - uint32_t RESERVED0[2]; /*!< Reserved */ - __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ - __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ - __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ - uint32_t RESERVED1[3]; /*!< Reserved */ - __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ - -} LTDC_Layer_TypeDef; - -/** - * @brief Power Control - */ - -typedef struct -{ - __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ - __IO uint32_t CSR1; /*!< PWR power control/status register 2, Address offset: 0x04 */ - __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ - __IO uint32_t CSR2; /*!< PWR power control/status register 2, Address offset: 0x0C */ -} PWR_TypeDef; - - -/** - * @brief Reset and Clock Control - */ - -typedef struct -{ - __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ - __IO uint32_t PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ - __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ - __IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ - __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ - __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ - __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ - uint32_t RESERVED0; /*!< Reserved, 0x1C */ - __IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ - __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ - uint32_t RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ - __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ - __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ - __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ - uint32_t RESERVED2; /*!< Reserved, 0x3C */ - __IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ - __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ - uint32_t RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ - __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ - __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ - __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ - uint32_t RESERVED4; /*!< Reserved, 0x5C */ - __IO uint32_t APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ - __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ - uint32_t RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ - __IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ - __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ - uint32_t RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ - __IO uint32_t SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ - __IO uint32_t PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ - __IO uint32_t PLLSAICFGR; /*!< RCC PLLSAI configuration register, Address offset: 0x88 */ - __IO uint32_t DCKCFGR1; /*!< RCC Dedicated Clocks configuration register1, Address offset: 0x8C */ - __IO uint32_t DCKCFGR2; /*!< RCC Dedicated Clocks configuration register 2, Address offset: 0x90 */ - -} RCC_TypeDef; - -/** - * @brief Real-Time Clock - */ - -typedef struct -{ - __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ - __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ - __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ - __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ - __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ - __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ - uint32_t reserved; /*!< Reserved */ - __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ - __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ - __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ - __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ - __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ - __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ - __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ - __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ - __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ - __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ - __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ - __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ - __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ - __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ - __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ - __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ - __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ - __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ - __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ - __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ - __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ - __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ - __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ - __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ - __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ - __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ - __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ - __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ - __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ - __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ - __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ - __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ - __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ - __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ - __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ - __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ - __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ - __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ - __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ - __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ - __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ - __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ - __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ - __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ - __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ -} RTC_TypeDef; - - -/** - * @brief Serial Audio Interface - */ - -typedef struct -{ - __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ -} SAI_TypeDef; - -typedef struct -{ - __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ - __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ - __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ - __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ - __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ - __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ - __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ - __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ -} SAI_Block_TypeDef; - -/** - * @brief SPDIF-RX Interface - */ - -typedef struct -{ - __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ - __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ - __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ - __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ - __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ - __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ - __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ -} SPDIFRX_TypeDef; - -/** - * @brief SD host Interface - */ - -typedef struct -{ - __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ - __IO uint32_t CLKCR; /*!< SDMMClock control register, Address offset: 0x04 */ - __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ - __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ - __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ - __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ - __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ - __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ - __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ - __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ - __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ - __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ - __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ - __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ - __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ - __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ - uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ - __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */ - uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ - __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ -} SDMMC_TypeDef; - -/** - * @brief Serial Peripheral Interface - */ - -typedef struct -{ - __IO uint32_t CR1; /*!< SPI control register 1 (not used in I2S mode), Address offset: 0x00 */ - __IO uint32_t CR2; /*!< SPI control register 2, Address offset: 0x04 */ - __IO uint32_t SR; /*!< SPI status register, Address offset: 0x08 */ - __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ - __IO uint32_t CRCPR; /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */ - __IO uint32_t RXCRCR; /*!< SPI RX CRC register (not used in I2S mode), Address offset: 0x14 */ - __IO uint32_t TXCRCR; /*!< SPI TX CRC register (not used in I2S mode), Address offset: 0x18 */ - __IO uint32_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */ - __IO uint32_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */ -} SPI_TypeDef; - -/** - * @brief QUAD Serial Peripheral Interface - */ - -typedef struct -{ - __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ - __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ - __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ - __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ - __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ - __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ - __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ - __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ - __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ - __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ - __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ - __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ - __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ -} QUADSPI_TypeDef; - -/** - * @brief TIM - */ - -typedef struct -{ - __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ - __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ - __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ - __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ - __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ - __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ - __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ - __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ - __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ - __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ - __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ - __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ - __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ - __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ - __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ - __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ - __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ - __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ - __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ - __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ - __IO uint32_t OR; /*!< TIM option register, Address offset: 0x50 */ - __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ - __IO uint32_t CCR5; /*!< TIM capture/compare mode register5, Address offset: 0x58 */ - __IO uint32_t CCR6; /*!< TIM capture/compare mode register6, Address offset: 0x5C */ - -} TIM_TypeDef; - -/** - * @brief LPTIMIMER - */ -typedef struct -{ - __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ - __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ - __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ - __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ - __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ - __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ - __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ - __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ -} LPTIM_TypeDef; - - -/** - * @brief Universal Synchronous Asynchronous Receiver Transmitter - */ - -typedef struct -{ - __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ - __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ - __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ - __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ - __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ - __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ - __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ - __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ - __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ - __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ - __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ -} USART_TypeDef; - - -/** - * @brief Window WATCHDOG - */ - -typedef struct -{ - __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ - __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ - __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ -} WWDG_TypeDef; - - -/** - * @brief RNG - */ - -typedef struct -{ - __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ - __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ - __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ -} RNG_TypeDef; - -/** - * @} - */ - -/** - * @brief USB_OTG_Core_Registers - */ -typedef struct -{ - __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ - __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ - __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ - __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ - __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ - __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ - __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ - __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ - __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ - __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ - __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ - __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ - uint32_t Reserved30[2]; /*!< Reserved 030h */ - __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ - __IO uint32_t CID; /*!< User ID Register 03Ch */ - uint32_t Reserved5[3]; /*!< Reserved 040h-048h */ - __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ - uint32_t Reserved6; /*!< Reserved 050h */ - __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ - uint32_t Reserved7; /*!< Reserved 058h */ - __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ - uint32_t Reserved43[40]; /*!< Reserved 60h-0FFh */ - __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ - __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO 104h-13Ch */ -} USB_OTG_GlobalTypeDef; - - -/** - * @brief USB_OTG_device_Registers - */ -typedef struct -{ - __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ - __IO uint32_t DCTL; /*!< dev Control Register 804h */ - __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ - uint32_t Reserved0C; /*!< Reserved 80Ch */ - __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ - __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ - __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ - __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ - uint32_t Reserved20; /*!< Reserved 820h */ - uint32_t Reserved9; /*!< Reserved 824h */ - __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ - __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ - __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ - __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ - __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ - __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ - uint32_t Reserved40; /*!< dedicated EP mask 840h */ - __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ - uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ - __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ -} USB_OTG_DeviceTypeDef; - - -/** - * @brief USB_OTG_IN_Endpoint-Specific_Register - */ -typedef struct -{ - __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ - uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ - __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ - uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ - __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ - __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ - __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ - uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ -} USB_OTG_INEndpointTypeDef; - - -/** - * @brief USB_OTG_OUT_Endpoint-Specific_Registers - */ -typedef struct -{ - __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ - uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ - __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ - uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ - __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ - __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ - uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ -} USB_OTG_OUTEndpointTypeDef; - - -/** - * @brief USB_OTG_Host_Mode_Register_Structures - */ -typedef struct -{ - __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ - __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ - __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ - uint32_t Reserved40C; /*!< Reserved 40Ch */ - __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ - __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ - __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ -} USB_OTG_HostTypeDef; - -/** - * @brief USB_OTG_Host_Channel_Specific_Registers - */ -typedef struct -{ - __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ - __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ - __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ - __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ - __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ - __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ - uint32_t Reserved[2]; /*!< Reserved */ -} USB_OTG_HostChannelTypeDef; -/** - * @} - */ - - - - -/** @addtogroup Peripheral_memory_map - * @{ - */ -#define RAMITCM_BASE 0x00000000UL /*!< Base address of : 16KB RAM reserved for CPU execution/instruction accessible over ITCM */ -#define FLASHITCM_BASE 0x00200000UL /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over ITCM */ -#define FLASHAXI_BASE 0x08000000UL /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ -#define RAMDTCM_BASE 0x20000000UL /*!< Base address of : 64KB system data RAM accessible over DTCM */ -#define PERIPH_BASE 0x40000000UL /*!< Base address of : AHB/ABP Peripherals */ -#define BKPSRAM_BASE 0x40024000UL /*!< Base address of : Backup SRAM(4 KB) */ -#define QSPI_BASE 0x90000000UL /*!< Base address of : QSPI memories accessible over AXI */ -#define FMC_R_BASE 0xA0000000UL /*!< Base address of : FMC Control registers */ -#define QSPI_R_BASE 0xA0001000UL /*!< Base address of : QSPI Control registers */ -#define SRAM1_BASE 0x20010000UL /*!< Base address of : 240KB RAM1 accessible over AXI/AHB */ -#define SRAM2_BASE 0x2004C000UL /*!< Base address of : 16KB RAM2 accessible over AXI/AHB */ -#define FLASH_END 0x080FFFFFUL /*!< FLASH end address */ -#define FLASH_OTP_BASE 0x1FF0F000UL /*!< Base address of : (up to 1024 Bytes) embedded FLASH OTP Area */ -#define FLASH_OTP_END 0x1FF0F41FUL /*!< End address of : (up to 1024 Bytes) embedded FLASH OTP Area */ - -/* Legacy define */ -#define FLASH_BASE FLASHAXI_BASE - -/*!< Peripheral memory map */ -#define APB1PERIPH_BASE PERIPH_BASE -#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) -#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) -#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000UL) - -/*!< APB1 peripherals */ -#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) -#define TIM3_BASE (APB1PERIPH_BASE + 0x0400UL) -#define TIM4_BASE (APB1PERIPH_BASE + 0x0800UL) -#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) -#define TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) -#define TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) -#define TIM12_BASE (APB1PERIPH_BASE + 0x1800UL) -#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00UL) -#define TIM14_BASE (APB1PERIPH_BASE + 0x2000UL) -#define LPTIM1_BASE (APB1PERIPH_BASE + 0x2400UL) -#define RTC_BASE (APB1PERIPH_BASE + 0x2800UL) -#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) -#define IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) -#define SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) -#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) -#define SPDIFRX_BASE (APB1PERIPH_BASE + 0x4000UL) -#define USART2_BASE (APB1PERIPH_BASE + 0x4400UL) -#define USART3_BASE (APB1PERIPH_BASE + 0x4800UL) -#define UART4_BASE (APB1PERIPH_BASE + 0x4C00UL) -#define UART5_BASE (APB1PERIPH_BASE + 0x5000UL) -#define I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) -#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) -#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) -#define I2C4_BASE (APB1PERIPH_BASE + 0x6000UL) -#define CAN1_BASE (APB1PERIPH_BASE + 0x6400UL) -#define CAN2_BASE (APB1PERIPH_BASE + 0x6800UL) -#define CEC_BASE (APB1PERIPH_BASE + 0x6C00UL) -#define PWR_BASE (APB1PERIPH_BASE + 0x7000UL) -#define DAC_BASE (APB1PERIPH_BASE + 0x7400UL) -#define UART7_BASE (APB1PERIPH_BASE + 0x7800UL) -#define UART8_BASE (APB1PERIPH_BASE + 0x7C00UL) - -/*!< APB2 peripherals */ -#define TIM1_BASE (APB2PERIPH_BASE + 0x0000UL) -#define TIM8_BASE (APB2PERIPH_BASE + 0x0400UL) -#define USART1_BASE (APB2PERIPH_BASE + 0x1000UL) -#define USART6_BASE (APB2PERIPH_BASE + 0x1400UL) -#define ADC1_BASE (APB2PERIPH_BASE + 0x2000UL) -#define ADC2_BASE (APB2PERIPH_BASE + 0x2100UL) -#define ADC3_BASE (APB2PERIPH_BASE + 0x2200UL) -#define ADC_BASE (APB2PERIPH_BASE + 0x2300UL) -#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2C00UL) -#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) -#define SPI4_BASE (APB2PERIPH_BASE + 0x3400UL) -#define SYSCFG_BASE (APB2PERIPH_BASE + 0x3800UL) -#define EXTI_BASE (APB2PERIPH_BASE + 0x3C00UL) -#define TIM9_BASE (APB2PERIPH_BASE + 0x4000UL) -#define TIM10_BASE (APB2PERIPH_BASE + 0x4400UL) -#define TIM11_BASE (APB2PERIPH_BASE + 0x4800UL) -#define SPI5_BASE (APB2PERIPH_BASE + 0x5000UL) -#define SPI6_BASE (APB2PERIPH_BASE + 0x5400UL) -#define SAI1_BASE (APB2PERIPH_BASE + 0x5800UL) -#define SAI2_BASE (APB2PERIPH_BASE + 0x5C00UL) -#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) -#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) -#define SAI2_Block_A_BASE (SAI2_BASE + 0x004UL) -#define SAI2_Block_B_BASE (SAI2_BASE + 0x024UL) -#define LTDC_BASE (APB2PERIPH_BASE + 0x6800UL) -#define LTDC_Layer1_BASE (LTDC_BASE + 0x0084UL) -#define LTDC_Layer2_BASE (LTDC_BASE + 0x0104UL) -/*!< AHB1 peripherals */ -#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000UL) -#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400UL) -#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800UL) -#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00UL) -#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000UL) -#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400UL) -#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800UL) -#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00UL) -#define GPIOI_BASE (AHB1PERIPH_BASE + 0x2000UL) -#define GPIOJ_BASE (AHB1PERIPH_BASE + 0x2400UL) -#define GPIOK_BASE (AHB1PERIPH_BASE + 0x2800UL) -#define CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) -#define RCC_BASE (AHB1PERIPH_BASE + 0x3800UL) -#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x3C00UL) -#define UID_BASE 0x1FF0F420UL /*!< Unique device ID register base address */ -#define FLASHSIZE_BASE 0x1FF0F442UL /*!< FLASH Size register base address */ -#define PACKAGE_BASE 0x1FF0F7E0UL /*!< Package size register base address */ -/* Legacy define */ -#define PACKAGESIZE_BASE PACKAGE_BASE - -#define DMA1_BASE (AHB1PERIPH_BASE + 0x6000UL) -#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) -#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) -#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) -#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) -#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) -#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) -#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) -#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) -#define DMA2_BASE (AHB1PERIPH_BASE + 0x6400UL) -#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) -#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) -#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) -#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) -#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) -#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) -#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) -#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) -#define ETH_BASE (AHB1PERIPH_BASE + 0x8000UL) -#define ETH_MAC_BASE (ETH_BASE) -#define ETH_MMC_BASE (ETH_BASE + 0x0100UL) -#define ETH_PTP_BASE (ETH_BASE + 0x0700UL) -#define ETH_DMA_BASE (ETH_BASE + 0x1000UL) -#define DMA2D_BASE (AHB1PERIPH_BASE + 0xB000UL) -/*!< AHB2 peripherals */ -#define DCMI_BASE (AHB2PERIPH_BASE + 0x50000UL) -#define RNG_BASE (AHB2PERIPH_BASE + 0x60800UL) -/*!< FMC Bankx registers base address */ -#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) -#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) -#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) -#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) - -/* Debug MCU registers base address */ -#define DBGMCU_BASE 0xE0042000UL - -/*!< USB registers base address */ -#define USB_OTG_HS_PERIPH_BASE 0x40040000UL -#define USB_OTG_FS_PERIPH_BASE 0x50000000UL - -#define USB_OTG_GLOBAL_BASE 0x0000UL -#define USB_OTG_DEVICE_BASE 0x0800UL -#define USB_OTG_IN_ENDPOINT_BASE 0x0900UL -#define USB_OTG_OUT_ENDPOINT_BASE 0x0B00UL -#define USB_OTG_EP_REG_SIZE 0x0020UL -#define USB_OTG_HOST_BASE 0x0400UL -#define USB_OTG_HOST_PORT_BASE 0x0440UL -#define USB_OTG_HOST_CHANNEL_BASE 0x0500UL -#define USB_OTG_HOST_CHANNEL_SIZE 0x0020UL -#define USB_OTG_PCGCCTL_BASE 0x0E00UL -#define USB_OTG_FIFO_BASE 0x1000UL -#define USB_OTG_FIFO_SIZE 0x1000UL - -/** - * @} - */ - -/** @addtogroup Peripheral_declaration - * @{ - */ -#define TIM2 ((TIM_TypeDef *) TIM2_BASE) -#define TIM3 ((TIM_TypeDef *) TIM3_BASE) -#define TIM4 ((TIM_TypeDef *) TIM4_BASE) -#define TIM5 ((TIM_TypeDef *) TIM5_BASE) -#define TIM6 ((TIM_TypeDef *) TIM6_BASE) -#define TIM7 ((TIM_TypeDef *) TIM7_BASE) -#define TIM12 ((TIM_TypeDef *) TIM12_BASE) -#define TIM13 ((TIM_TypeDef *) TIM13_BASE) -#define TIM14 ((TIM_TypeDef *) TIM14_BASE) -#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) -#define RTC ((RTC_TypeDef *) RTC_BASE) -#define WWDG ((WWDG_TypeDef *) WWDG_BASE) -#define IWDG ((IWDG_TypeDef *) IWDG_BASE) -#define SPI2 ((SPI_TypeDef *) SPI2_BASE) -#define SPI3 ((SPI_TypeDef *) SPI3_BASE) -#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) -#define USART2 ((USART_TypeDef *) USART2_BASE) -#define USART3 ((USART_TypeDef *) USART3_BASE) -#define UART4 ((USART_TypeDef *) UART4_BASE) -#define UART5 ((USART_TypeDef *) UART5_BASE) -#define I2C1 ((I2C_TypeDef *) I2C1_BASE) -#define I2C2 ((I2C_TypeDef *) I2C2_BASE) -#define I2C3 ((I2C_TypeDef *) I2C3_BASE) -#define I2C4 ((I2C_TypeDef *) I2C4_BASE) -#define CAN1 ((CAN_TypeDef *) CAN1_BASE) -#define CAN2 ((CAN_TypeDef *) CAN2_BASE) -#define CEC ((CEC_TypeDef *) CEC_BASE) -#define PWR ((PWR_TypeDef *) PWR_BASE) -#define DAC1 ((DAC_TypeDef *) DAC_BASE) -#define DAC ((DAC_TypeDef *) DAC_BASE) /* Kept for legacy purpose */ -#define UART7 ((USART_TypeDef *) UART7_BASE) -#define UART8 ((USART_TypeDef *) UART8_BASE) -#define TIM1 ((TIM_TypeDef *) TIM1_BASE) -#define TIM8 ((TIM_TypeDef *) TIM8_BASE) -#define USART1 ((USART_TypeDef *) USART1_BASE) -#define USART6 ((USART_TypeDef *) USART6_BASE) -#define ADC ((ADC_Common_TypeDef *) ADC_BASE) -#define ADC1 ((ADC_TypeDef *) ADC1_BASE) -#define ADC2 ((ADC_TypeDef *) ADC2_BASE) -#define ADC3 ((ADC_TypeDef *) ADC3_BASE) -#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC_BASE) -#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) -#define SPI1 ((SPI_TypeDef *) SPI1_BASE) -#define SPI4 ((SPI_TypeDef *) SPI4_BASE) -#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) -#define EXTI ((EXTI_TypeDef *) EXTI_BASE) -#define TIM9 ((TIM_TypeDef *) TIM9_BASE) -#define TIM10 ((TIM_TypeDef *) TIM10_BASE) -#define TIM11 ((TIM_TypeDef *) TIM11_BASE) -#define SPI5 ((SPI_TypeDef *) SPI5_BASE) -#define SPI6 ((SPI_TypeDef *) SPI6_BASE) -#define SAI1 ((SAI_TypeDef *) SAI1_BASE) -#define SAI2 ((SAI_TypeDef *) SAI2_BASE) -#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) -#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) -#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE) -#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE) -#define LTDC ((LTDC_TypeDef *)LTDC_BASE) -#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) -#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) -#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) -#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) -#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) -#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) -#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) -#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) -#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) -#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) -#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE) -#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) -#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) -#define CRC ((CRC_TypeDef *) CRC_BASE) -#define RCC ((RCC_TypeDef *) RCC_BASE) -#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) -#define DMA1 ((DMA_TypeDef *) DMA1_BASE) -#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) -#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) -#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) -#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) -#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) -#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) -#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) -#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) -#define DMA2 ((DMA_TypeDef *) DMA2_BASE) -#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) -#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) -#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) -#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) -#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) -#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) -#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) -#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) -#define ETH ((ETH_TypeDef *) ETH_BASE) -#define DMA2D ((DMA2D_TypeDef *)DMA2D_BASE) -#define DCMI ((DCMI_TypeDef *) DCMI_BASE) -#define RNG ((RNG_TypeDef *) RNG_BASE) -#define FMC_Bank1 ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) -#define FMC_Bank1E ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) -#define FMC_Bank3 ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) -#define FMC_Bank5_6 ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) -#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) -#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) -#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) -#define USB_OTG_HS ((USB_OTG_GlobalTypeDef *) USB_OTG_HS_PERIPH_BASE) - -/** - * @} - */ - -/** @addtogroup Exported_constants - * @{ - */ - - /** @addtogroup Peripheral_Registers_Bits_Definition - * @{ - */ - -/******************************************************************************/ -/* Peripheral Registers_Bits_Definition */ -/******************************************************************************/ - -/******************************************************************************/ -/* */ -/* Analog to Digital Converter */ -/* */ -/******************************************************************************/ -/******************** Bit definition for ADC_SR register ********************/ -#define ADC_SR_AWD_Pos (0U) -#define ADC_SR_AWD_Msk (0x1UL << ADC_SR_AWD_Pos) /*!< 0x00000001 */ -#define ADC_SR_AWD ADC_SR_AWD_Msk /*!
© COPYRIGHT 2016 STMicroelectronics
- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f7xx_system - * @{ - */ - -/** @addtogroup STM32F7xx_System_Private_Includes - * @{ - */ - #include "stm32f7xx.h" -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Defines - * @{ - */ - -/************************* Miscellaneous Configuration ************************/ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -#define VECT_TAB_SRAM -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Variables - * @{ - */ - - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ - uint32_t SystemCoreClock = 16000000; - const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemFrequency variable. - * @param None - * @retval None - */ extern char _stext; void _UTVMInit(void) { @@ -181,100 +34,3 @@ void _UTVMInit(void) //#endif SCB->VTOR = &_stext; /* Vector Table Relocation in Internal SRAM */ } - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 25 MHz), user has to ensure that HSE_VALUE is same as the real - * frequency of the crystal used. Otherwise, this function may - * have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s b/src/runtime/micro/device/stm32f746/utvm_init.s index 56c7c891b933..1da26a18a98a 100644 --- a/src/runtime/micro/device/stm32f746/utvm_init.s +++ b/src/runtime/micro/device/stm32f746/utvm_init.s @@ -86,7 +86,7 @@ Infinite_Loop: * The minimal vector table for a Cortex M7. Note that the proper constructs * must be placed on this to ensure that it ends up at physical address * 0x0000.0000. -* +* *******************************************************************************/ .section .isr_vector,"a",%progbits .type g_pfnVectors, %object @@ -111,91 +111,91 @@ g_pfnVectors: .word 0 .word PendSV_Handler .word SysTick_Handler - + /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDMMC1_IRQHandler /* SDMMC1 */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* Reserved */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word 0 /* Reserved */ .word RNG_IRQHandler /* Rng */ .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ + .word UART7_IRQHandler /* UART7 */ .word UART8_IRQHandler /* UART8 */ .word SPI4_IRQHandler /* SPI4 */ .word SPI5_IRQHandler /* SPI5 */ @@ -210,24 +210,24 @@ g_pfnVectors: .word CEC_IRQHandler /* HDMI_CEC */ .word I2C4_EV_IRQHandler /* I2C4 Event */ .word I2C4_ER_IRQHandler /* I2C4 Error */ - .word SPDIF_RX_IRQHandler /* SPDIF_RX */ - + .word SPDIF_RX_IRQHandler /* SPDIF_RX */ + /******************************************************************************* * -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override * this definition. -* +* *******************************************************************************/ .weak NMI_Handler .thumb_set NMI_Handler,Default_Handler - + .weak HardFault_Handler .thumb_set HardFault_Handler,Default_Handler - + .weak MemManage_Handler .thumb_set MemManage_Handler,Default_Handler - + .weak BusFault_Handler .thumb_set BusFault_Handler,Default_Handler @@ -244,298 +244,298 @@ g_pfnVectors: .thumb_set PendSV_Handler,Default_Handler .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler + + .weak TAMP_STAMP_IRQHandler .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler + + .weak RTC_WKUP_IRQHandler .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler + + .weak FLASH_IRQHandler .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler + + .weak RCC_IRQHandler .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler + + .weak EXTI0_IRQHandler .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler + + .weak EXTI1_IRQHandler .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler + + .weak EXTI4_IRQHandler .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler + + .weak DMA1_Stream0_IRQHandler .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler + + .weak DMA1_Stream1_IRQHandler .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler + + .weak DMA1_Stream2_IRQHandler .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler + + .weak DMA1_Stream5_IRQHandler .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler + + .weak DMA1_Stream6_IRQHandler .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler + + .weak ADC_IRQHandler .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler + + .weak CAN1_TX_IRQHandler .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler + + .weak CAN1_RX0_IRQHandler .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler + + .weak CAN1_RX1_IRQHandler .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler + + .weak CAN1_SCE_IRQHandler .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler + + .weak EXTI9_5_IRQHandler .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler + + .weak TIM1_BRK_TIM9_IRQHandler .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler + + .weak TIM1_UP_TIM10_IRQHandler .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - .weak TIM1_TRG_COM_TIM11_IRQHandler + .weak TIM1_TRG_COM_TIM11_IRQHandler .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler + + .weak TIM1_CC_IRQHandler .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler + + .weak TIM2_IRQHandler .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler + + .weak TIM3_IRQHandler .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler + + .weak TIM4_IRQHandler .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler + + .weak I2C1_EV_IRQHandler .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler + + .weak I2C1_ER_IRQHandler .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler + + .weak I2C2_EV_IRQHandler .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler + + .weak I2C2_ER_IRQHandler .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler + + .weak SPI1_IRQHandler .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler + + .weak SPI2_IRQHandler .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler + + .weak USART1_IRQHandler .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler + + .weak USART2_IRQHandler .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler + + .weak USART3_IRQHandler .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler + + .weak EXTI15_10_IRQHandler .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler + + .weak RTC_Alarm_IRQHandler .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler + + .weak OTG_FS_WKUP_IRQHandler .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler + + .weak TIM8_BRK_TIM12_IRQHandler .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler + + .weak TIM8_UP_TIM13_IRQHandler .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler + + .weak TIM8_TRG_COM_TIM14_IRQHandler .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler + + .weak TIM8_CC_IRQHandler .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler + + .weak DMA1_Stream7_IRQHandler .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler + + .weak FMC_IRQHandler .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler + + .weak SDMMC1_IRQHandler .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler + + .weak TIM5_IRQHandler .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler + + .weak SPI3_IRQHandler .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler + + .weak UART4_IRQHandler .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler + + .weak UART5_IRQHandler .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler + + .weak TIM6_DAC_IRQHandler .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler + + .weak TIM7_IRQHandler .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler + + .weak DMA2_Stream0_IRQHandler .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler + + .weak DMA2_Stream1_IRQHandler .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler + + .weak DMA2_Stream2_IRQHandler .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler + + .weak DMA2_Stream3_IRQHandler .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - .weak ETH_IRQHandler + .weak ETH_IRQHandler .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler + + .weak ETH_WKUP_IRQHandler .thumb_set ETH_WKUP_IRQHandler,Default_Handler - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler + + .weak CAN2_RX1_IRQHandler .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler + + .weak CAN2_SCE_IRQHandler .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler + + .weak OTG_FS_IRQHandler .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler + + .weak DMA2_Stream5_IRQHandler .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler + + .weak DMA2_Stream6_IRQHandler .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler + + .weak DMA2_Stream7_IRQHandler .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler + + .weak USART6_IRQHandler .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler + + .weak I2C3_EV_IRQHandler .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler + + .weak I2C3_ER_IRQHandler .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler + + .weak OTG_HS_EP1_OUT_IRQHandler .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler + + .weak OTG_HS_EP1_IN_IRQHandler .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler + + .weak OTG_HS_WKUP_IRQHandler .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler + + .weak OTG_HS_IRQHandler .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler + + .weak DCMI_IRQHandler .thumb_set DCMI_IRQHandler,Default_Handler - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler - .weak FPU_IRQHandler + .weak FPU_IRQHandler .thumb_set FPU_IRQHandler,Default_Handler - .weak UART7_IRQHandler + .weak UART7_IRQHandler .thumb_set UART7_IRQHandler,Default_Handler - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler - .weak SPI4_IRQHandler + .weak SPI4_IRQHandler .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler + + .weak SPI5_IRQHandler .thumb_set SPI5_IRQHandler,Default_Handler - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler - .weak SAI1_IRQHandler + .weak SAI1_IRQHandler .thumb_set SAI1_IRQHandler,Default_Handler - - .weak LTDC_IRQHandler + + .weak LTDC_IRQHandler .thumb_set LTDC_IRQHandler,Default_Handler - .weak LTDC_ER_IRQHandler + .weak LTDC_ER_IRQHandler .thumb_set LTDC_ER_IRQHandler,Default_Handler - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler - .weak SAI2_IRQHandler + .weak SAI2_IRQHandler .thumb_set SAI2_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler + + .weak QUADSPI_IRQHandler .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler + + .weak LPTIM1_IRQHandler .thumb_set LPTIM1_IRQHandler,Default_Handler - .weak CEC_IRQHandler + .weak CEC_IRQHandler .thumb_set CEC_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak SPDIF_RX_IRQHandler - .thumb_set SPDIF_RX_IRQHandler,Default_Handler + + .weak SPDIF_RX_IRQHandler + .thumb_set SPDIF_RX_IRQHandler,Default_Handler diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 77f16a31813d..0781e3bbacdc 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -211,6 +211,22 @@ class SymbolMap { return result->second; } + bool HasSymbol(const std::string& name) const { + return map_.find(name) != map_.end(); + } + + std::vector GetSymbols() const { + std::vector res; + for (const auto& it : map_) { + res.push_back(it.first); + } + return res; + } + + size_t size() const { + return map_.size(); + } + private: /*! \brief backing map */ std::unordered_map map_; diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 7de8717cfd30..558986085dcf 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -112,7 +112,25 @@ PackedFunc MicroModuleNode::GetFunction( const std::string& name, const ObjectPtr& sptr_to_self) { std::cout << "[MicroModuleNode::GetFunction(name=" << name << ")]" << std::endl; - DevPtr func_ptr = symbol_map_[name]; + DevPtr func_ptr; + if (name == tvm::runtime::symbol::tvm_module_main) { + std::cout << " here" << std::endl; + if (symbol_map_.HasSymbol(tvm::runtime::symbol::tvm_module_main)) { + std::cout << " ayy" << std::endl; + func_ptr = symbol_map_[tvm::runtime::symbol::tvm_module_main]; + } else { + std::cout << " lmao" << std::endl; + func_ptr = symbol_map_["default_function"]; + } + //std::cout << " symbols:" << std::endl; + //for (const auto& sym_name : symbol_map_.GetSymbols()) { + // std::cout << " " << sym_name << std::endl; + //} + //CHECK(symbol_map_.size() == 1) << "entry point requested with multiple functions in module"; + //func_ptr = symbol_map_[symbol_map_.GetSymbols()[0]]; + } else { + func_ptr = symbol_map_[name]; + } MicroWrappedFunc f(session_, func_ptr); return PackedFunc(f); } From 68b511365b446707a5568d2749202260a72b2f22 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 2 Nov 2019 16:37:53 -0700 Subject: [PATCH 27/70] Still works --- arm-auto-utvm-demo/tune_relay_utvm.py | 45 +--- python/tvm/micro/__init__.py | 3 +- python/tvm/micro/base.py | 96 +++++--- python/tvm/micro/binutil/__init__.py | 233 ++++++++++++++++++ python/tvm/micro/binutil/host.py | 0 python/tvm/micro/binutil/riscv_spike.py | 0 python/tvm/micro/binutil/stm32f746xx.py | 0 python/tvm/micro/rpc_server.py | 6 +- .../stm32f7xx_hal_conf.h | 0 .../system_stm32f7xx.h | 0 .../{stm32f746 => stm32f746xx}/utvm_api.c | 0 .../{stm32f746 => stm32f746xx}/utvm_init.c | 0 .../utvm_init.c.bad | 0 .../{stm32f746 => stm32f746xx}/utvm_init.s | 0 .../utvm_init.s.bak | 0 .../{stm32f746 => stm32f746xx}/utvm_link.ld | 0 .../utvm_unit.c.bak | 0 tests/python/unittest/test_runtime_micro.py | 86 ++++--- 18 files changed, 347 insertions(+), 122 deletions(-) create mode 100644 python/tvm/micro/binutil/__init__.py create mode 100644 python/tvm/micro/binutil/host.py create mode 100644 python/tvm/micro/binutil/riscv_spike.py create mode 100644 python/tvm/micro/binutil/stm32f746xx.py rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/stm32f7xx_hal_conf.h (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/system_stm32f7xx.h (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_api.c (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_init.c (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_init.c.bad (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_init.s (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_init.s.bak (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_link.ld (100%) rename src/runtime/micro/device/{stm32f746 => stm32f746xx}/utvm_unit.c.bak (100%) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 6a05d47b907a..b192aa4aadea 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -34,8 +34,10 @@ # first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal # then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another -DEVICE_TYPE = 'openocd' -TOOLCHAIN_PREFIX = 'arm-none-eabi-' +DEV_BINUTIL = micro.binutil.ArmBinutil() +DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) +#DEVICE_TYPE = 'openocd' +#TOOLCHAIN_PREFIX = 'arm-none-eabi-' DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') @@ -50,7 +52,7 @@ LOG_FILE_NAME = f'{DEVICE}.log' -def create_micro_mod(c_mod, toolchain_prefix): +def create_micro_mod(c_mod, dev_binutil): """Produces a micro module from a given module. Parameters @@ -66,41 +68,16 @@ def create_micro_mod(c_mod, toolchain_prefix): micro_mod : tvm.module.Module micro module for the target device """ + print('[create_micro_mod]') temp_dir = util.tempdir() - lib_obj_path = temp_dir.relpath('dev_lib.obj') - print(c_mod.get_source()) + lib_obj_path = temp_dir.relpath("dev_lib.obj") c_mod.export_library( lib_obj_path, - fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) + fcompile=tvm.micro.cross_compiler(dev_binutil, micro.LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path) return micro_mod -def relay_micro_build(func, toolchain_prefix, params=None): - """Create a graph runtime module with a micro device context from a Relay function. - - Parameters - ---------- - func : relay.Function - function to compile - - params : dict - input parameters that do not change during inference - - Return - ------ - mod : tvm.module.Module - graph runtime module for the target device - """ - with tvm.build_config(disable_vectorize=True): - graph, c_mod, params = relay.build(func, target='c', params=params) - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) - ctx = tvm.micro_dev(0) - mod = graph_runtime.create(graph, micro_mod, ctx) - mod.set_input(**params) - return mod - - @autotvm.template def matmul(N, L, M, dtype): A = tvm.placeholder((N, L), name='A', dtype=dtype) @@ -134,7 +111,7 @@ def tune(): early_stopping = None measure_option = autotvm.measure_option( builder=autotvm.LocalBuilder( - build_func=tvm.micro.cross_compiler(TOOLCHAIN_PREFIX, micro.LibType.OPERATOR)), + build_func=tvm.micro.cross_compiler(DEV_BINUTIL, micro.LibType.OPERATOR)), runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=N_PARALLEL, number=N_PER_TRIAL) ) @@ -165,8 +142,8 @@ def evaluate(): sched, arg_bufs = matmul(N, L, M, 'float32') c_mod = tvm.build(sched, arg_bufs, name='matmul') - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) micro_func = micro_mod['matmul'] ctx = tvm.micro_dev(0) diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 1162dc804c0f..84c821a4e374 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,4 +23,5 @@ """ from ..contrib import binutil -from .base import LibType, Session, cross_compiler, create_micro_lib +from .base import LibType, OpenOcdComm, HostComm, Session, cross_compiler, create_micro_lib +from .binutil import HostBinutil, ArmBinutil diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 032dfcfdfc1e..1be1a1cb3e52 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -22,27 +22,37 @@ import logging import os import sys +from collections import namedtuple from enum import Enum from pathlib import Path import tvm from tvm.contrib import util as _util from tvm.contrib import cc as _cc - from .._ffi.function import _init_api from .._ffi.libinfo import find_include_path - -SUPPORTED_DEVICE_TYPES = ["host", "openocd"] +from tvm.contrib.binutil import run_cmd class LibType(Enum): RUNTIME = 0 OPERATOR = 1 -@tvm.register_func('micro.create_session') -def create_session(device_type, toolchain_prefix, **kwargs): - res = Session(device_type, toolchain_prefix, **kwargs) - return res.module +class OpenOcdComm: + def __init__(self, server_addr, server_port): + self.server_addr = server_addr + self.server_port = server_port + + def name(self): + return 'openocd' + + +class HostComm: + def __init__(self): + pass + + def name(self): + return 'host' class Session: @@ -76,29 +86,38 @@ class Session: """ # TODO(weberlo): remove required trailing dash in toolchain_prefix - def __init__(self, device_type, toolchain_prefix, **kwargs): - if device_type not in SUPPORTED_DEVICE_TYPES: - raise RuntimeError("unknown micro device type \"{}\"".format(device_type)) - #self._check_system() + def __init__(self, dev_binutil, dev_communicator): + self._check_system() #self._check_args(device_type, kwargs) + self.binutil = dev_binutil + self.communicator = dev_communicator + # First, find and compile runtime library. runtime_src_path = os.path.join(_get_micro_host_driven_dir(), "utvm_runtime.c") tmp_dir = _util.tempdir() runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") - create_micro_lib( - runtime_obj_path, runtime_src_path, toolchain_prefix, LibType.RUNTIME) + self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) - self.op_modules = [] + if isinstance(self.communicator, OpenOcdComm): + server_addr = self.communicator.server_addr + server_port = self.communicator.server_port + elif isinstance(self.communicator, HostComm): + server_addr = '' + server_port = 0 + else: + raise RuntimeError(f'unknown communication method: f{self.communicator}') - self.device_type = device_type - self.toolchain_prefix = toolchain_prefix - self.base_addr = kwargs.get("base_addr", 0) - self.server_addr = kwargs.get("server_addr", "") - self.port = kwargs.get("port", 0) + # todo remove use of base addrs everywhere + base_addr = 0 self.module = _CreateSession( - self.device_type, runtime_obj_path, self.toolchain_prefix, self.base_addr, self.server_addr, self.port) + self.communicator.name(), + runtime_obj_path, + self.binutil.toolchain_prefix(), + base_addr, + server_addr, + server_port) self._enter = self.module["enter"] self._exit = self.module["exit"] @@ -159,7 +178,7 @@ def _get_micro_device_dir(): return micro_device_dir -def cross_compiler(toolchain_prefix, lib_type): +def cross_compiler(dev_binutil, lib_type): """Creates a cross compile function that wraps `create_micro_lib`. For use in `tvm.module.Module.export_library`. @@ -192,8 +211,9 @@ def compile_func(obj_path, src_path, **kwargs): obj_path = obj_path[0] if isinstance(src_path, list): src_path = src_path[0] - create_micro_lib(obj_path, src_path, toolchain_prefix, - lib_type, kwargs.get("options", None)) + dev_binutil.create_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) + #create_micro_lib(obj_path, src_path, toolchain_prefix, + # lib_type, kwargs.get("options", None)) return _cc.cross_compiler(compile_func, output_format='obj') @@ -216,24 +236,20 @@ def create_micro_lib( whether to include the device library header containing definitions of library functions. """ - import subprocess + #import subprocess import os - import copy - from shutil import copyfile - - from tvm._ffi.libinfo import find_include_path - from tvm.contrib import binutil - - def run_cmd(cmd): - proc = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - (out, _) = proc.communicate() - if proc.returncode != 0: - msg = "Compilation error:\n" - msg += out.decode("utf-8") - raise RuntimeError(msg) + + #def run_cmd(cmd): + # proc = subprocess.Popen( + # cmd, + # stdout=subprocess.PIPE, + # stderr=subprocess.STDOUT) + # (out, _) = proc.communicate() + # if proc.returncode != 0: + # cmd_str = ' '.join(cmd) + # msg = f"error while running command \"{' '.join(cmd)}\":\n" + # msg += out.decode("utf-8") + # raise RuntimeError(msg) base_compile_cmd = [ f'{toolchain_prefix}gcc', diff --git a/python/tvm/micro/binutil/__init__.py b/python/tvm/micro/binutil/__init__.py new file mode 100644 index 000000000000..07384d28e0ec --- /dev/null +++ b/python/tvm/micro/binutil/__init__.py @@ -0,0 +1,233 @@ +import os +import sys +from enum import Enum +from pathlib import Path + +from tvm.contrib import util as _util +from tvm.contrib.binutil import run_cmd +from tvm._ffi.libinfo import find_include_path +from tvm.micro import LibType + +#from . import host +#from . import riscv_spike +#from . import stm32f746xx + +#class Device(Enum): +# HOST = 0 +# RISCV_SPIKE = 1 +# STM32F746XX = 2 + + +class MicroBinutil: + def __init__(self, toolchain_prefix): + print(f'creating microbinutil with {toolchain_prefix}') + self._toolchain_prefix = toolchain_prefix + + def create_lib(self, obj_path, src_path, lib_type, options=None): + """Compiles code into a binary for the target micro device. + + Parameters + ---------- + obj_path : Optional[str] + path to generated object file (defaults to same directory as `src_path`) + + src_path : str + path to source file + + toolchain_prefix : str + toolchain prefix to be used + + include_dev_lib_header : bool + whether to include the device library header containing definitions of + library functions. + """ + print('OPTIONS') + print(f'{obj_path}') + print(f'{src_path}') + print(f'{lib_type}') + print(f'{options}') + base_compile_cmd = [ + f'{self.toolchain_prefix()}gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-c', + '-O0', + '-g', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + ] + if options is not None: + base_compile_cmd += options + + #if toolchain_prefix == 'arm-none-eabi-': + # device_id = 'stm32f746' + # base_compile_cmd += [ + # '-mcpu=cortex-m7', + # '-mlittle-endian', + # '-mfloat-abi=hard', + # '-mfpu=fpv5-sp-d16', + # '-mthumb', + # '-gdwarf-5' + # ] + #elif toolchain_prefix == '': + # device_id = 'host' + # if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + # base_compile_cmd += ['-mcmodel=large'] + #else: + # assert False + + src_paths = [] + include_paths = find_include_path() + [_get_micro_host_driven_dir()] + ld_script_path = None + tmp_dir = _util.tempdir() + if lib_type == LibType.RUNTIME: + import glob + dev_dir = _get_micro_device_dir() + '/' + self.device_id() + + print(dev_dir) + dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + print(dev_src_paths) + # there needs to at least be a utvm_timer.c file + assert dev_src_paths + + src_paths += dev_src_paths + # TODO: configure this + #include_paths += [dev_dir] + CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] + elif lib_type == LibType.OPERATOR: + # Create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath('temp.c') + with open(src_path, 'r') as f: + src_lines = f.read().splitlines() + src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') + with open(temp_src_path, 'w') as f: + f.write('\n'.join(src_lines)) + src_path = temp_src_path + + base_compile_cmd += ['-c'] + else: + raise RuntimeError('unknown lib type') + + src_paths += [src_path] + + print(f'include paths: {include_paths}') + for path in include_paths: + base_compile_cmd += ['-I', path] + + prereq_obj_paths = [] + for src_path in src_paths: + curr_obj_path = self._get_unique_obj_name(src_path, prereq_obj_paths, tmp_dir) + prereq_obj_paths.append(curr_obj_path) + curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + run_cmd(curr_compile_cmd) + + ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] + ld_cmd += prereq_obj_paths + ld_cmd += ['-o', obj_path] + run_cmd(ld_cmd) + print(f'compiled obj {obj_path}') + + def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): + res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) + i = 2 + # if the name collides, try increasing numeric suffixes until the name doesn't collide + while res in obj_paths: + res = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) + i += 1 + return res + + def device_id(self): + raise RuntimeError('no device ID for abstract MicroBinutil') + + def toolchain_prefix(self): + return self._toolchain_prefix + + +class HostBinutil(MicroBinutil): + def __init__(self): + super(HostBinutil, self).__init__('') + + def create_lib(self, obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + options += ['-mcmodel=large'] + super(HostBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) + + def device_id(self): + return 'host' + + +class ArmBinutil(MicroBinutil): + def __init__(self): + super(ArmBinutil, self).__init__('arm-none-eabi-') + + def create_lib(self, obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + options += [ + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-mthumb', + '-gdwarf-5', + '-DSTM32F746xx' + ] + super(ArmBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) + + def device_id(self): + return 'stm32f746xx' + + +#def get_device_binutil(device): +# # TODO make all binutils singletons if they remain stateless +# if device_id == Device.HOST: +# return HostBinutil() +# elif device_id == Device.RISCV_SPIKE: +# return SpikeBinutil() +# elif device_id == Device.STM32F746XX: +# return ArmBinutil() +# else: +# raise RuntimeError(f'invalid device: {device}') + + +def _get_micro_host_driven_dir(): + """Get directory path for uTVM host-driven runtime source files. + + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", "..", + "src", "runtime", "micro", "host_driven") + return micro_host_driven_dir + + +def _get_micro_device_dir(): + """Get directory path for TODO + + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_device_dir = os.path.join(micro_dir, "..", "..", "..", "..", + "src", "runtime", "micro", "device") + return micro_device_dir + + diff --git a/python/tvm/micro/binutil/host.py b/python/tvm/micro/binutil/host.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/tvm/micro/binutil/riscv_spike.py b/python/tvm/micro/binutil/riscv_spike.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/tvm/micro/binutil/stm32f746xx.py b/python/tvm/micro/binutil/stm32f746xx.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 654e18d7c475..de881ba32079 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -7,12 +7,12 @@ from tvm import rpc from tvm import micro -DEVICE_TYPE = 'openocd' -TOOLCHAIN_PREFIX = 'arm-none-eabi-' +DEV_BINUTIL = micro.binutil.ArmBinutil() +DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) @tvm.register_func("tvm.rpc.server.start", override=True) def server_start(): - session = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) + session = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) session._enter() _load_module = tvm.get_global_func("tvm.rpc.server.load_module") diff --git a/src/runtime/micro/device/stm32f746/stm32f7xx_hal_conf.h b/src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h similarity index 100% rename from src/runtime/micro/device/stm32f746/stm32f7xx_hal_conf.h rename to src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h diff --git a/src/runtime/micro/device/stm32f746/system_stm32f7xx.h b/src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h similarity index 100% rename from src/runtime/micro/device/stm32f746/system_stm32f7xx.h rename to src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h diff --git a/src/runtime/micro/device/stm32f746/utvm_api.c b/src/runtime/micro/device/stm32f746xx/utvm_api.c similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_api.c rename to src/runtime/micro/device/stm32f746xx/utvm_api.c diff --git a/src/runtime/micro/device/stm32f746/utvm_init.c b/src/runtime/micro/device/stm32f746xx/utvm_init.c similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_init.c rename to src/runtime/micro/device/stm32f746xx/utvm_init.c diff --git a/src/runtime/micro/device/stm32f746/utvm_init.c.bad b/src/runtime/micro/device/stm32f746xx/utvm_init.c.bad similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_init.c.bad rename to src/runtime/micro/device/stm32f746xx/utvm_init.c.bad diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s b/src/runtime/micro/device/stm32f746xx/utvm_init.s similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_init.s rename to src/runtime/micro/device/stm32f746xx/utvm_init.s diff --git a/src/runtime/micro/device/stm32f746/utvm_init.s.bak b/src/runtime/micro/device/stm32f746xx/utvm_init.s.bak similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_init.s.bak rename to src/runtime/micro/device/stm32f746xx/utvm_init.s.bak diff --git a/src/runtime/micro/device/stm32f746/utvm_link.ld b/src/runtime/micro/device/stm32f746xx/utvm_link.ld similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_link.ld rename to src/runtime/micro/device/stm32f746xx/utvm_link.ld diff --git a/src/runtime/micro/device/stm32f746/utvm_unit.c.bak b/src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak similarity index 100% rename from src/runtime/micro/device/stm32f746/utvm_unit.c.bak rename to src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 6230acd1603e..24bd9308e961 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,12 +25,16 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -DEVICE_TYPE = "openocd" -TOOLCHAIN_PREFIX = "arm-none-eabi-" #DEVICE_TYPE = "host" #TOOLCHAIN_PREFIX = "" +#DEVICE_TYPE = "openocd" +#TOOLCHAIN_PREFIX = "arm-none-eabi-" -def create_micro_mod(c_mod, toolchain_prefix): +DEV_BINUTIL = micro.binutil.ArmBinutil() +# todo make a micro.comm namespace? +DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) + +def create_micro_mod(c_mod, dev_binutil): """Produces a micro module from a given module. Parameters @@ -49,16 +53,14 @@ def create_micro_mod(c_mod, toolchain_prefix): print('[create_micro_mod]') temp_dir = util.tempdir() lib_obj_path = temp_dir.relpath("dev_lib.obj") - print(c_mod.get_source()) - print(f' entry_name: {c_mod.entry_name}') c_mod.export_library( lib_obj_path, - fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) + fcompile=tvm.micro.cross_compiler(dev_binutil, micro.LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path) return micro_mod -def relay_micro_build(func, toolchain_prefix, params=None): +def relay_micro_build(func, dev_binutil, params=None): """Create a graph runtime module with a micro device context from a Relay function. Parameters @@ -76,7 +78,7 @@ def relay_micro_build(func, toolchain_prefix, params=None): """ with tvm.build_config(disable_vectorize=True): graph, c_mod, params = relay.build(func, target="c", params=params) - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + micro_mod = create_micro_mod(c_mod, dev_binutil) ctx = tvm.micro_dev(0) mod = graph_runtime.create(graph, micro_mod, ctx) mod.set_input(**params) @@ -113,7 +115,7 @@ def test_alloc(): return shape = (1024,) dtype = "float32" - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): ctx = tvm.micro_dev(0) np_tensor = np.random.uniform(size=shape).astype(dtype) micro_tensor = tvm.nd.array(np_tensor, ctx) @@ -143,20 +145,16 @@ def test_add(): func_name = "fadd" c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) - def run_func(): - a = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) - b = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) - #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - micro_func(a, b, c) - - for _ in range(10): - run_func() + a = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) + b = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) + #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + micro_func(a, b, c) #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -188,8 +186,8 @@ def test_int_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.randint(1, 50, size=shape).astype(dtype), ctx) @@ -223,8 +221,8 @@ def test_float_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -251,8 +249,8 @@ def test_graph_runtime(): z = relay.add(xx, relay.const(1.0)) func = relay.Function([x], z) - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - mod = relay_micro_build(func, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + mod = relay_micro_build(func, DEV_BINUTIL) x_in = np.random.uniform(size=shape[0]).astype(dtype) mod.run(x=x_in) @@ -291,8 +289,8 @@ def test_conv2d(): with tvm.build_config(disable_vectorize=True): graph, c_mod, params = relay.build(mod, target="c") - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - micro_mod = create_micro_mod(c_mod, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) @@ -325,9 +323,9 @@ def test_multiple_modules(): ret = relay.subtract(x, relay.const(1.0)) sub_const_func = relay.Function([x], ret) - with micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX): - add_const_mod = relay_micro_build(add_const_func, TOOLCHAIN_PREFIX) - sub_const_mod = relay_micro_build(sub_const_func, TOOLCHAIN_PREFIX) + with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) + sub_const_mod = relay_micro_build(sub_const_func, DEV_BINUTIL) x_in = np.random.uniform(size=shape[0]).astype(dtype) add_const_mod.run(x=x_in) @@ -353,8 +351,8 @@ def test_interleave_sessions(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) - sess_b = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) + sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) @@ -362,13 +360,13 @@ def test_interleave_sessions(): np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) with sess_a: - add_const_mod = relay_micro_build(add_const_func, TOOLCHAIN_PREFIX) + add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( add_result, np_tensor_a + 1.0) with sess_b: - add_const_mod = relay_micro_build(add_const_func, TOOLCHAIN_PREFIX) + add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) add_const_mod.run(x=micro_tensor_b) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -387,15 +385,15 @@ def test_nested_sessions(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) - sess_b = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) + sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) with sess_b: np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, TOOLCHAIN_PREFIX) + add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -414,12 +412,12 @@ def test_inactive_session_use(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) - sess_b = micro.Session(DEVICE_TYPE, TOOLCHAIN_PREFIX) + sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, TOOLCHAIN_PREFIX) + add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) with sess_b: # These objects belong to `sess_a`. @@ -431,7 +429,7 @@ def test_inactive_session_use(): if __name__ == "__main__": #test_alloc() - test_add() + #test_add() #test_int_workspace_add() #test_float_workspace_add() @@ -440,7 +438,7 @@ def test_inactive_session_use(): #test_conv2d() - #test_multiple_modules() + test_multiple_modules() #test_interleave_sessions() #test_nested_sessions() #test_inactive_session_use() From 0f7577e0d4cb665640b3be65d613c397ba01fa1a Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 4 Nov 2019 17:41:59 -0800 Subject: [PATCH 28/70] Refactor part 1 --- 3rdparty/dlpack | 2 +- arm-auto-utvm-demo/tune_relay_utvm.py | 2 + python/tvm/contrib/binutil.py | 63 ++- python/tvm/micro/base.py | 16 + src/runtime/micro/device/host/utvm_api.c | 2 +- src/runtime/micro/micro_session.cc | 358 +++++++++--------- src/runtime/micro/micro_session.h | 42 +- .../micro/target_data_layout_encoder.h | 12 +- tests/python/unittest/test_runtime_micro.py | 4 +- 9 files changed, 251 insertions(+), 250 deletions(-) diff --git a/3rdparty/dlpack b/3rdparty/dlpack index 87b968f91c1e..0acb731e0e43 160000 --- a/3rdparty/dlpack +++ b/3rdparty/dlpack @@ -1 +1 @@ -Subproject commit 87b968f91c1e5183fae0124c8f0238ba327b31ac +Subproject commit 0acb731e0e43d15deee27b66f10e4c5b4e667913 diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index b192aa4aadea..aa8d9cda6fc2 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -106,6 +106,7 @@ def matmul(N, L, M, dtype): def tune(): + print('[TUNE]') task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target=TARGET) early_stopping = None @@ -136,6 +137,7 @@ def tune(): def evaluate(): + print('[EVALUATE]') # compile kernels with history best records with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): with TARGET: diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 5d1e1bdc771f..66065831cc99 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -28,12 +28,14 @@ def run_cmd(cmd): cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - (out, _) = proc.communicate() + (output, _) = proc.communicate() + # todo need to use py_str? + output = output.decode('utf-8') if proc.returncode != 0: cmd_str = ' '.join(cmd) - error_msg = out.decode("utf-8") - msg = f"error while running command \"{cmd_str}\":\n{error_msg}" + msg = f"error while running command \"{cmd_str}\":\n{output}" raise RuntimeError(msg) + return output @register_func("tvm_callback_get_section_size") @@ -61,14 +63,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): 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(size_output) - raise RuntimeError(msg) + size_output = run_cmd(["{}size".format(toolchain_prefix), "-A", binary_path]) # TODO(weberlo): Refactor this method and `*relocate_binary` so they are # both aware of [".bss", ".sbss", ".sdata"] being relocated to ".bss". @@ -327,17 +322,11 @@ def tvm_callback_relocate_binary( 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) - + run_cmd([ + "{}ld".format(toolchain_prefix), + binary_path, + "-T", rel_ld_script_path, + "-o", rel_obj_path]) print(f'relocated obj path is {rel_obj_path}') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) @@ -369,16 +358,11 @@ def tvm_callback_read_binary_section(binary, section, toolchain_prefix): 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) + run_cmd([ + "{}objcopy".format(toolchain_prefix), + "--dump-section", + ".{}={}".format(section, tmp_section), + tmp_bin]) if os.path.isfile(tmp_section): # Get section content if it exists. with open(tmp_section, "rb") as f: @@ -411,15 +395,12 @@ def tvm_callback_get_symbol_map(binary, toolchain_prefix): 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() + nm_output = run_cmd([ + "{}nm".format(toolchain_prefix), + "-C", + "--defined-only", + tmp_obj]) + nm_output = nm_output.splitlines() map_str = "" for line in nm_output: line = line.split() diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 1be1a1cb3e52..147417a1187d 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -115,6 +115,22 @@ def __init__(self, dev_binutil, dev_communicator): self.communicator.name(), runtime_obj_path, self.binutil.toolchain_prefix(), + 0x20000180, + 20480, + 0x20005180, + 20480, + 0x2000a180, + 768, + 0x2000a480, + 768, + 0x2000a780, + 1280, + 0x2000ac80, + 262144, + 0x2004ac80, + 20480, + 0x2004fc80, + 80, base_addr, server_addr, server_port) diff --git a/src/runtime/micro/device/host/utvm_api.c b/src/runtime/micro/device/host/utvm_api.c index 53a9c83bc72a..1b6f17607c9e 100644 --- a/src/runtime/micro/device/host/utvm_api.c +++ b/src/runtime/micro/device/host/utvm_api.c @@ -15,7 +15,7 @@ void UTVMTimerStop() { } void UTVMTimerReset() { } -int32_t UTVMTimerRead() { +uint32_t UTVMTimerRead() { return 420; } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 79339240e101..f6e9b3ab9086 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -33,6 +33,12 @@ namespace tvm { namespace runtime { +// ARM and other manufacturers use the lowest bit of a function address to determine +// whether it's a "thumb mode" function. The Thumb ISA is more restricted, but +// results in more compact binaries. +const bool kRequiresThumbModeBit = true; +const size_t kWordSize = 4; + struct TVMMicroSessionThreadLocalEntry { std::stack> session_stack; }; @@ -56,20 +62,73 @@ void MicroSession::ExitWithScope() { entry->session_stack.pop(); } -MicroSession::MicroSession() { - DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); +MicroSession::MicroSession( + const std::string& comms_method, + const std::string& binary_path, + const std::string& toolchain_prefix, + uint64_t text_start, + size_t text_size, + uint64_t rodata_start, + size_t rodata_size, + uint64_t data_start, + size_t data_size, + uint64_t bss_start, + size_t bss_size, + uint64_t args_start, + size_t args_size, + uint64_t heap_start, + size_t heap_size, + uint64_t workspace_start, + size_t workspace_size, + uint64_t stack_start, + size_t stack_size, + std::uintptr_t base_addr, + const std::string& server_addr, + int port) { + //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); //DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); - for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - size_t section_size = GetDefaultSectionSize(static_cast(i)); - section_allocators_[i] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = section_size, - }); - curr_start_offset += section_size; - } - + //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + // size_t section_size = GetDefaultSectionSize(static_cast(i)); + // section_allocators_[i] = std::make_shared(DevMemRegion { + // .start = curr_start_offset, + // .size = section_size, + // }); + // curr_start_offset += section_size; + //} + section_allocators_[0] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(text_start), + .size = text_size, + }); + section_allocators_[1] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(rodata_start), + .size = rodata_size, + }); + section_allocators_[2] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(data_start), + .size = data_size, + }); + section_allocators_[3] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(bss_start), + .size = bss_size, + }); + section_allocators_[4] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(args_start), + .size = args_size, + }); + section_allocators_[5] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(heap_start), + .size = heap_size, + }); + section_allocators_[6] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(workspace_start), + .size = workspace_size, + }); + section_allocators_[7] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(stack_start), + .size = stack_size, + }); - CHECK(curr_start_offset.value() < 0x20050000) << "exceeded available RAM on device (" << std::endl; + //CHECK(curr_start_offset.value() < 0x20050000) << "exceeded available RAM on device (" << std::endl; std::cout << "[Memory Layout]" << std::endl; std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_offset().cast_to() << std::endl; @@ -84,151 +143,11 @@ MicroSession::MicroSession() { // NOTE: we don't use this for openocd memory_size_ = 0; //memory_size_ = curr_start_offset.cast_to(); - - /* Linker script sample - * #if !defined(MBED_APP_START) - * #define MBED_APP_START 0x08000000 - * #endif - * - * #if !defined(MBED_APP_SIZE) - * #define MBED_APP_SIZE 1024K - * #endif - * - * MEMORY - * { - * FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE - * RAM (rwx) : ORIGIN = 0x200001C8, LENGTH = 320K - 0x1C8 - * } - */ - - /* - size_t half_flash_size = 512000; // 0.5 MB - DevBaseOffset curr_start_offset = DevBaseOffset(0x08000000); - section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = half_flash_size, - }); - curr_start_offset += half_flash_size; - section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = half_flash_size, - }); - curr_start_offset += half_flash_size; - - curr_start_offset = DevBaseOffset(0x200001C8); - size_t one_sixth_ram_size = 53256; - section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_sixth_ram_size, - }); - curr_start_offset += one_sixth_ram_size; - - memory_size_ = 0; - */ - - /* - // TODO: why do we need to start 0x1c8 bytes after the start of ram? - //curr_start_offset = DevBaseOffset(0x200001C8); - size_t one_eighth_ram_size = 40000; - DevBaseOffset curr_start_offset = DevBaseOffset(0x200001C8); - - std::cout << "[Memory Layout]" << std::endl; - std::cout << "text start: " << curr_start_offset.cast_to() << std::endl; - size_t text_size - section_allocators_[static_cast(SectionKind::kText)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "rodata start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kRodata)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "data start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kData)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "bss start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kBss)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "args start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kArgs)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "stack start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kStack)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "heap start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kHeap)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "workspace start: " << curr_start_offset.cast_to() << std::endl; - section_allocators_[static_cast(SectionKind::kWorkspace)] = std::make_shared(DevMemRegion { - .start = curr_start_offset, - .size = one_eighth_ram_size, - }); - curr_start_offset += one_eighth_ram_size; - std::cout << "WHAT THE FUCK" << std::endl; - */ -} - -MicroSession::~MicroSession() { - for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - section_allocators_[i] = nullptr; - } - low_level_device_ = nullptr; -} - -void MicroSession::CreateSession(const std::string& device_type, - const std::string& binary_path, - const std::string& toolchain_prefix, - std::uintptr_t base_addr, - const std::string& server_addr, - int port) { // TODO(weberlo): make device type enum toolchain_prefix_ = toolchain_prefix; - if (device_type == "host") { + if (comms_method == "host") { low_level_device_ = HostLowLevelDeviceCreate(memory_size_); - } else if (device_type == "openocd") { + } else if (comms_method == "openocd") { // TODO(weberlo): We need a better way of configuring devices. low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); } else { @@ -239,7 +158,7 @@ void MicroSession::CreateSession(const std::string& device_type, std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; - //if (device_type == "openocd") { + //if (comms_method == "openocd") { // // Set OpenOCD device's stack pointer. // auto stack_section = GetAllocator(SectionKind::kStack); // low_level_device_->SetStackTop(stack_section->max_end_offset()); @@ -259,6 +178,13 @@ void MicroSession::CreateSession(const std::string& device_type, DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); } +MicroSession::~MicroSession() { + for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { + section_allocators_[i] = nullptr; + } + low_level_device_ = nullptr; +} + //void MicroSession::BakeSession(const std::string& binary_path) { // //runtime_symbol_map_ = SymbolMap(binary, toolchain_prefix_); // runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; @@ -266,9 +192,6 @@ void MicroSession::CreateSession(const std::string& device_type, // std::cout << runtime_symbol_map_["utvm_task"].value() << std::endl; //} -// ARM and other manufacturers use the LSB of a function address to determine -// whether it's a "thumb mode" function (TODO: figure out what that means). -const bool kRequiresThumbModeBit = true; uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "[MicroSession::PushToExecQueue]" << std::endl; // TODO: make this a parameter. @@ -282,7 +205,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // allocation in the args section. DevPtr args_addr = low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); - TargetDataLayoutEncoder encoder(args_addr); + TargetDataLayoutEncoder encoder(args_addr, kWordSize); std::cout << " after encoder alloc" << std::endl; @@ -304,26 +227,51 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), // .num_args = args.num_args, //}; - typedef struct StructARMUTVMTask { - /*! \brief Pointer to function to call for this task */ - uint32_t func; - /*! \brief Array of argument values */ - uint32_t arg_values; - /*! \brief Array of type codes for each argument value */ - uint32_t arg_type_codes; - /*! \brief Number of arguments */ - uint32_t num_args; - } ARMUTVMTask; - TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); - ARMUTVMTask task = { - .func = *((uint32_t*) &func_dev_addr), - .arg_values = *((uint32_t*) &arg_values_dev_addr), - .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), - .num_args = (uint32_t) args.num_args, - }; - // Write the task. - DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); + if (kWordSize == 4) { + typedef struct StructUTVMTask32 { + /*! \brief Pointer to function to call for this task */ + uint32_t func; + /*! \brief Array of argument values */ + uint32_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint32_t arg_type_codes; + /*! \brief Number of arguments */ + int32_t num_args; + } UTVMTask32; + TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + UTVMTask32 task = { + .func = *((uint32_t*) &func_dev_addr), + .arg_values = *((uint32_t*) &arg_values_dev_addr), + .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), + .num_args = args.num_args, + }; + // Write the task. + DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); + } else if (kWordSize == 8) { + typedef struct StructUTVMTask64 { + /*! \brief Pointer to function to call for this task */ + uint64_t func; + /*! \brief Array of argument values */ + uint64_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint64_t arg_type_codes; + /*! \brief Number of arguments */ + int32_t num_args; + } UTVMTask64; + TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + UTVMTask64 task = { + .func = *((uint64_t*) &func_dev_addr), + .arg_values = *((uint64_t*) &arg_values_dev_addr), + .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), + .num_args = args.num_args, + }; + // Write the task. + DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); + } else { + CHECK(false) << "unsupported word size " << kWordSize; + } std::cout << " after task write" << std::endl; @@ -620,17 +568,53 @@ PackedFunc MicroSession::GetFunction( // create micro session and low-level device from Python frontend TVM_REGISTER_GLOBAL("micro._CreateSession") .set_body([](TVMArgs args, TVMRetValue* rv) { - const std::string& device_type = args[0]; + const std::string& comms_method = args[0]; const std::string& binary_path = args[1]; const std::string& toolchain_prefix = args[2]; - uint64_t base_addr = args[3]; - const std::string& server_addr = args[4]; - int port = args[5]; - ObjectPtr session = make_object(); + uint64_t text_start = args[3]; + size_t text_size = args[4]; + uint64_t rodata_start = args[5]; + size_t rodata_size = args[6]; + uint64_t data_start = args[7]; + size_t data_size = args[8]; + uint64_t bss_start = args[9]; + size_t bss_size = args[10]; + uint64_t args_start = args[11]; + size_t args_size = args[12]; + uint64_t heap_start = args[13]; + size_t heap_size = args[14]; + uint64_t workspace_start = args[15]; + size_t workspace_size = args[16]; + uint64_t stack_start = args[17]; + size_t stack_size = args[18]; + uint64_t base_addr = args[19]; + const std::string& server_addr = args[20]; + int port = args[21]; + ObjectPtr session = make_object( + comms_method, + binary_path, + toolchain_prefix, + text_start, + text_size, + rodata_start, + rodata_size, + data_start, + data_size, + bss_start, + bss_size, + args_start, + args_size, + heap_start, + heap_size, + workspace_start, + workspace_size, + stack_start, + stack_size, + base_addr, + server_addr, + port); //session->CreateSession( - // device_type, binary_path, toolchain_prefix, base_addr, server_addr, port); - session->CreateSession( - "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); + // "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); *rv = Module(session); }); diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 4cc6e03c7962..e1e43ce03b08 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -47,7 +47,7 @@ #include #include "low_level_device.h" -#include "host_driven/utvm_runtime.h" +//#include "host_driven/utvm_runtime.h" #include "target_data_layout_encoder.h" namespace tvm { @@ -74,10 +74,35 @@ class MicroSession : public ModuleNode { return "MicroSession"; } + // TODO make a micro session config object /*! - * \brief constructor + * \brief creates session by setting up a low-level device and initting allocators for it + * \param args TVMArgs passed into the micro.init packedfunc + * TODO rewrite docs */ - MicroSession(); + MicroSession( + const std::string& comms_method, + const std::string& binary_path, + const std::string& toolchain_prefix, + uint64_t text_start, + size_t text_size, + uint64_t rodata_start, + size_t rodata_size, + uint64_t data_start, + size_t data_size, + uint64_t bss_start, + size_t bss_size, + uint64_t args_start, + size_t args_size, + uint64_t heap_start, + size_t heap_size, + uint64_t workspace_start, + size_t workspace_size, + uint64_t stack_start, + size_t stack_size, + std::uintptr_t base_addr, + const std::string& server_addr, + int port); /*! * \brief destructor @@ -86,16 +111,7 @@ class MicroSession : public ModuleNode { static ObjectPtr& Current(); - /*! - * \brief creates session by setting up a low-level device and initting allocators for it - * \param args TVMArgs passed into the micro.init packedfunc - */ - void CreateSession(const std::string& device_type, - const std::string& binary_path, - const std::string& toolchain_prefix, - std::uintptr_t base_addr, - const std::string& server_addr, - int port); + void CreateSession(); //void BakeSession(const std::string& binary_path); diff --git a/src/runtime/micro/target_data_layout_encoder.h b/src/runtime/micro/target_data_layout_encoder.h index b3b992809e3f..e443e6a6bbeb 100644 --- a/src/runtime/micro/target_data_layout_encoder.h +++ b/src/runtime/micro/target_data_layout_encoder.h @@ -33,8 +33,6 @@ namespace runtime { // TODO(weberlo): Handle endianness. // TODO: make this parameterizable -static const int kWordSize = 4; - /*! * \brief data encoder for uTVM that builds a host-side buffer */ @@ -99,9 +97,9 @@ class TargetDataLayoutEncoder { * \brief constructor * \param start_addr start address of the encoder in device memory */ - explicit TargetDataLayoutEncoder(DevPtr start_addr) - : buf_(std::vector()), curr_offset_(0) { - start_addr_ = DevPtr(UpperAlignValue(start_addr.value(), kWordSize)); + explicit TargetDataLayoutEncoder(DevPtr start_addr, size_t word_size) + : buf_(std::vector()), curr_offset_(0), word_size_(word_size) { + start_addr_ = DevPtr(UpperAlignValue(start_addr.value(), word_size_)); } /*! @@ -111,7 +109,7 @@ class TargetDataLayoutEncoder { */ template Slot Alloc(size_t num_elems = 1) { - curr_offset_ = UpperAlignValue(curr_offset_, kWordSize); + curr_offset_ = UpperAlignValue(curr_offset_, word_size_); size_t size = sizeof(T) * num_elems; if (curr_offset_ + size > buf_.size()) { buf_.resize(curr_offset_ + size); @@ -144,6 +142,8 @@ class TargetDataLayoutEncoder { size_t curr_offset_; /*! \brief start address of the encoder in device memory */ DevPtr start_addr_; + /*! \brief TODO */ + size_t word_size_; }; template diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 24bd9308e961..015006e27708 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -31,9 +31,11 @@ #TOOLCHAIN_PREFIX = "arm-none-eabi-" DEV_BINUTIL = micro.binutil.ArmBinutil() -# todo make a micro.comm namespace? DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) +#DEV_BINUTIL = micro.binutil.HostBinutil() +#DEV_COMMUNICATOR = micro.HostComm() + def create_micro_mod(c_mod, dev_binutil): """Produces a micro module from a given module. From 37c9ee374fe8cedeef48825c609735fd04dd77c4 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 09:45:27 -0800 Subject: [PATCH 29/70] Host works again --- python/tvm/contrib/binutil.py | 104 ++------ python/tvm/micro/__init__.py | 4 +- python/tvm/micro/base.py | 77 +++--- python/tvm/micro/device/__init__.py | 194 ++++++++++++++ python/tvm/micro/device/host.py | 52 ++++ python/tvm/micro/device/riscv_spike.py | 0 python/tvm/micro/device/stm32f746xx.py | 65 +++++ src/runtime/micro/device/host/utvm_api.c | 4 +- src/runtime/micro/host_driven/utvm_runtime.c | 11 + src/runtime/micro/host_low_level_device.cc | 16 +- src/runtime/micro/low_level_device.h | 2 +- src/runtime/micro/micro_common.cc | 18 +- src/runtime/micro/micro_common.h | 9 +- src/runtime/micro/micro_session.cc | 255 ++++++++++++++----- src/runtime/micro/micro_session.h | 17 +- tests/python/unittest/test_runtime_micro.py | 146 +++++------ 16 files changed, 683 insertions(+), 291 deletions(-) create mode 100644 python/tvm/micro/device/__init__.py create mode 100644 python/tvm/micro/device/host.py create mode 100644 python/tvm/micro/device/riscv_spike.py create mode 100644 python/tvm/micro/device/stm32f746xx.py diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 66065831cc99..c4eb509dd6fa 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -107,7 +107,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): @register_func("tvm_callback_relocate_binary") def tvm_callback_relocate_binary( - binary_path, text_addr, rodata_addr, data_addr, bss_addr, toolchain_prefix): + binary_path, word_size, text_addr, rodata_addr, data_addr, bss_addr, toolchain_prefix): """Relocates sections in the binary to new addresses Parameters @@ -115,6 +115,9 @@ def tvm_callback_relocate_binary( binary_path : str path of the binary file + word_size : int + TODO + text_addr : str text section absolute address @@ -138,7 +141,7 @@ def tvm_callback_relocate_binary( global TEMPDIR_REFS tmp_dir = util.tempdir() TEMPDIR_REFS.append(tmp_dir) - rel_obj_path = tmp_dir.relpath("relocated.o") + rel_obj_path = tmp_dir.relpath("relocated.obj") #rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_relocated.o' with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'r') as f: gdbinit_contents = f.read().split('\n') @@ -157,10 +160,7 @@ def tvm_callback_relocate_binary( # TODO: this a fukn hack #input(f'binary path: {binary_path}') - if 'utvm_runtime' in binary_path: - ld_script_contents = """ -ENTRY(UTVMInit) - + ld_script_contents = """ /* Highest address of the user mode stack */ _estack = 0x20050000; /* end of RAM */ @@ -174,104 +174,56 @@ def tvm_callback_relocate_binary( SECTIONS { . = %s; - . = ALIGN(4); + . = ALIGN(?); .text : { _stext = .; - KEEP(*(.isr_vector)) + /*KEEP(*(.isr_vector))*/ KEEP(*(.text)) KEEP(*(.text*)) - . = ALIGN(4); + . = ALIGN(?); } . = %s; - . = ALIGN(4); + . = ALIGN(?); .rodata : { - . = ALIGN(4); + . = ALIGN(?); KEEP(*(.rodata)) KEEP(*(.rodata*)) - . = ALIGN(4); + . = ALIGN(?); } . = %s; - . = ALIGN(4); + . = ALIGN(?); .data : { - . = ALIGN(4); + . = ALIGN(?); KEEP(*(.data)) KEEP(*(.data*)) - . = ALIGN(4); + . = ALIGN(?); } . = %s; - . = ALIGN(4); + . = ALIGN(?); .bss : { - . = ALIGN(4); + . = ALIGN(?); KEEP(*(.bss)) KEEP(*(.bss*)) - . = ALIGN(4); + . = ALIGN(?); } } - """ % (text_addr, rodata_addr, data_addr, bss_addr) - else: - ld_script_contents = """ -/* - * Memory layout (for reference) - * RAM (xrw) : START = 0x20000000, LENGTH = 320K - * FLASH (rx) : START = 0x8000000, LENGTH = 1024K - */ - -/* Define output sections */ -SECTIONS -{ - . = %s; - . = ALIGN(4); - .text : - { - . = ALIGN(4); - KEEP(*(.text)) - KEEP(*(.text*)) - . = ALIGN(4); - } - - . = %s; - . = ALIGN(4); - .rodata : - { - . = ALIGN(4); - KEEP(*(.rodata)) - KEEP(*(.rodata*)) - . = ALIGN(4); - } - - . = %s; - . = ALIGN(4); - .data : - { - . = ALIGN(4); - KEEP(*(.data)) - KEEP(*(.data*)) - . = ALIGN(4); - } - - . = %s; - . = ALIGN(4); - .bss : - { - . = ALIGN(4); - KEEP(*(.bss)) - KEEP(*(.bss*)) - . = ALIGN(4); - } -} - """ % (text_addr, rodata_addr, data_addr, bss_addr) - print(f'relocing lib {binary_path}') - print(f' text_addr: {text_addr}') - print(f' rodata_addr: {rodata_addr}') - print(f' data_addr: {data_addr}') - print(f' bss_addr: {bss_addr}') + """ + ld_script_contents = ld_script_contents.replace('ALIGN(?)', f'ALIGN({word_size})') + print(ld_script_contents) + ld_script_contents = ld_script_contents % (text_addr, rodata_addr, data_addr, bss_addr) + print(ld_script_contents) + print(f'relocing lib {binary_path}') + print(f' text_addr: {text_addr}') + print(f' rodata_addr: {rodata_addr}') + print(f' data_addr: {data_addr}') + print(f' bss_addr: {bss_addr}') # TODO(weberlo): Generate the script in a more procedural manner. diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 84c821a4e374..92ca0f105b64 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,5 +23,5 @@ """ from ..contrib import binutil -from .base import LibType, OpenOcdComm, HostComm, Session, cross_compiler, create_micro_lib -from .binutil import HostBinutil, ArmBinutil +from .base import LibType, Session, cross_compiler, create_micro_lib +from . import device diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 147417a1187d..e0cb1ca7b95e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -38,23 +38,6 @@ class LibType(Enum): OPERATOR = 1 -class OpenOcdComm: - def __init__(self, server_addr, server_port): - self.server_addr = server_addr - self.server_port = server_port - - def name(self): - return 'openocd' - - -class HostComm: - def __init__(self): - pass - - def name(self): - return 'host' - - class Session: """MicroTVM Device Session @@ -86,51 +69,56 @@ class Session: """ # TODO(weberlo): remove required trailing dash in toolchain_prefix - def __init__(self, dev_binutil, dev_communicator): + def __init__(self, config): self._check_system() #self._check_args(device_type, kwargs) - self.binutil = dev_binutil - self.communicator = dev_communicator + self.binutil = config['binutil'] + self.mem_layout = config['mem_layout'] + self.word_size = config['word_size'] + self.thumb_mode = config['thumb_mode'] + self.comms_method = config['comms_method'] # First, find and compile runtime library. - runtime_src_path = os.path.join(_get_micro_host_driven_dir(), "utvm_runtime.c") + runtime_src_path = os.path.join(_get_micro_host_driven_dir(), 'utvm_runtime.c') tmp_dir = _util.tempdir() - runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") + runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) - if isinstance(self.communicator, OpenOcdComm): - server_addr = self.communicator.server_addr - server_port = self.communicator.server_port - elif isinstance(self.communicator, HostComm): + if isinstance(self.comms_method, tvm.micro.device.OpenOcdComm): + server_addr = self.comms_method.server_addr + server_port = self.comms_method.server_port + elif isinstance(self.comms_method, tvm.micro.device.HostComm): server_addr = '' server_port = 0 else: - raise RuntimeError(f'unknown communication method: f{self.communicator}') + raise RuntimeError(f'unknown communication method: f{self.comms_method}') # todo remove use of base addrs everywhere base_addr = 0 self.module = _CreateSession( - self.communicator.name(), + self.comms_method.name(), runtime_obj_path, self.binutil.toolchain_prefix(), - 0x20000180, - 20480, - 0x20005180, - 20480, - 0x2000a180, - 768, - 0x2000a480, - 768, - 0x2000a780, - 1280, - 0x2000ac80, - 262144, - 0x2004ac80, - 20480, - 0x2004fc80, - 80, + self.mem_layout['text'].get('start', 0), + self.mem_layout['text']['size'], + self.mem_layout['rodata'].get('start', 0), + self.mem_layout['rodata']['size'], + self.mem_layout['data'].get('start', 0), + self.mem_layout['data']['size'], + self.mem_layout['bss'].get('start', 0), + self.mem_layout['bss']['size'], + self.mem_layout['args'].get('start', 0), + self.mem_layout['args']['size'], + self.mem_layout['heap'].get('start', 0), + self.mem_layout['heap']['size'], + self.mem_layout['workspace'].get('start', 0), + self.mem_layout['workspace']['size'], + self.mem_layout['stack'].get('start', 0), + self.mem_layout['stack']['size'], + self.word_size, + self.thumb_mode, base_addr, server_addr, server_port) @@ -254,6 +242,7 @@ def create_micro_lib( """ #import subprocess import os + assert False #def run_cmd(cmd): # proc = subprocess.Popen( diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py new file mode 100644 index 000000000000..d6e5dce96430 --- /dev/null +++ b/python/tvm/micro/device/__init__.py @@ -0,0 +1,194 @@ +import os +import sys +from enum import Enum +from pathlib import Path + +from tvm.contrib import util as _util +from tvm.contrib.binutil import run_cmd +from tvm._ffi.libinfo import find_include_path +from tvm.micro import LibType + +class MicroBinutil: + def __init__(self, toolchain_prefix): + print(f'creating microbinutil with {toolchain_prefix}') + self._toolchain_prefix = toolchain_prefix + + def create_lib(self, obj_path, src_path, lib_type, options=None): + """Compiles code into a binary for the target micro device. + + Parameters + ---------- + obj_path : Optional[str] + path to generated object file (defaults to same directory as `src_path`) + + src_path : str + path to source file + + toolchain_prefix : str + toolchain prefix to be used + + include_dev_lib_header : bool + whether to include the device library header containing definitions of + library functions. + """ + print('OPTIONS') + print(f'{obj_path}') + print(f'{src_path}') + print(f'{lib_type}') + print(f'{options}') + base_compile_cmd = [ + f'{self.toolchain_prefix()}gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-c', + '-O0', + '-g', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + ] + if options is not None: + base_compile_cmd += options + + #if toolchain_prefix == 'arm-none-eabi-': + # device_id = 'stm32f746' + # base_compile_cmd += [ + # '-mcpu=cortex-m7', + # '-mlittle-endian', + # '-mfloat-abi=hard', + # '-mfpu=fpv5-sp-d16', + # '-mthumb', + # '-gdwarf-5' + # ] + #elif toolchain_prefix == '': + # device_id = 'host' + # if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + # base_compile_cmd += ['-mcmodel=large'] + #else: + # assert False + + src_paths = [] + include_paths = find_include_path() + [_get_micro_host_driven_dir()] + ld_script_path = None + tmp_dir = _util.tempdir() + if lib_type == LibType.RUNTIME: + import glob + dev_dir = _get_micro_device_dir() + '/' + self.device_id() + + print(dev_dir) + dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + print(dev_src_paths) + # there needs to at least be a utvm_timer.c file + assert dev_src_paths + + src_paths += dev_src_paths + # TODO: configure this + #include_paths += [dev_dir] + CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] + include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] + include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] + elif lib_type == LibType.OPERATOR: + # Create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath('temp.c') + with open(src_path, 'r') as f: + src_lines = f.read().splitlines() + src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') + with open(temp_src_path, 'w') as f: + f.write('\n'.join(src_lines)) + src_path = temp_src_path + + base_compile_cmd += ['-c'] + else: + raise RuntimeError('unknown lib type') + + src_paths += [src_path] + + print(f'include paths: {include_paths}') + for path in include_paths: + base_compile_cmd += ['-I', path] + + prereq_obj_paths = [] + for src_path in src_paths: + curr_obj_path = self._get_unique_obj_name(src_path, prereq_obj_paths, tmp_dir) + prereq_obj_paths.append(curr_obj_path) + curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + run_cmd(curr_compile_cmd) + + ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] + ld_cmd += prereq_obj_paths + ld_cmd += ['-o', obj_path] + run_cmd(ld_cmd) + print(f'compiled obj {obj_path}') + + def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): + res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) + i = 2 + # if the name collides, try increasing numeric suffixes until the name doesn't collide + while res in obj_paths: + res = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) + i += 1 + return res + + def device_id(self): + raise RuntimeError('no device ID for abstract MicroBinutil') + + def toolchain_prefix(self): + return self._toolchain_prefix + + +class OpenOcdComm: + def __init__(self, server_addr, server_port): + self.server_addr = server_addr + self.server_port = server_port + + def name(self): + return 'openocd' + + +class HostComm: + def __init__(self): + pass + + def name(self): + return 'host' + + +def _get_micro_host_driven_dir(): + """Get directory path for uTVM host-driven runtime source files. + + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", "..", + "src", "runtime", "micro", "host_driven") + return micro_host_driven_dir + + +def _get_micro_device_dir(): + """Get directory path for TODO + + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_device_dir = os.path.join(micro_dir, "..", "..", "..", "..", + "src", "runtime", "micro", "device") + return micro_device_dir + + +from . import host +from . import riscv_spike +from . import stm32f746xx diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py new file mode 100644 index 000000000000..3cc9603709c1 --- /dev/null +++ b/python/tvm/micro/device/host.py @@ -0,0 +1,52 @@ +import sys + +from . import MicroBinutil, HostComm + +class HostBinutil(MicroBinutil): + def __init__(self): + super(HostBinutil, self).__init__('') + + def create_lib(self, obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + options += ['-mcmodel=large'] + super(HostBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) + + def device_id(self): + return 'host' + + +def get_config(): + return { + 'binutil': HostBinutil(), + 'mem_layout': { + 'text': { + 'size': 20480, + }, + 'rodata': { + 'size': 20480, + }, + 'data': { + 'size': 768, + }, + 'bss': { + 'size': 768, + }, + 'args': { + 'size': 1280, + }, + 'heap': { + 'size': 262144, + }, + 'workspace': { + 'size': 20480, + }, + 'stack': { + 'size': 80, + }, + }, + 'word_size': 8 if sys.maxsize > 2**32 else 4, + 'thumb_mode': False, + 'comms_method': HostComm(), + } diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/tvm/micro/device/stm32f746xx.py b/python/tvm/micro/device/stm32f746xx.py new file mode 100644 index 000000000000..743e8ee2295c --- /dev/null +++ b/python/tvm/micro/device/stm32f746xx.py @@ -0,0 +1,65 @@ +from . import MicroBinutil, OpenOcdComm + +class ArmBinutil(MicroBinutil): + def __init__(self): + super(ArmBinutil, self).__init__('arm-none-eabi-') + + def create_lib(self, obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + options += [ + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-mthumb', + '-gdwarf-5', + '-DSTM32F746xx' + ] + super(ArmBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) + + def device_id(self): + return 'stm32f746xx' + + +def get_config(server_addr, server_port): + return { + 'binutil': ArmBinutil(), + 'mem_layout': { + 'text': { + 'start': 0x20000180, + 'size': 20480, + }, + 'rodata': { + 'start': 0x20005180, + 'size': 20480, + }, + 'data': { + 'start': 0x2000a180, + 'size': 768, + }, + 'bss': { + 'start': 0x2000a480, + 'size': 768, + }, + 'args': { + 'start': 0x2000a780, + 'size': 1280, + }, + 'heap': { + 'start': 0x2000ac80, + 'size': 262144, + }, + 'workspace': { + 'start': 0x2004ac80, + 'size': 20480, + }, + 'stack': { + 'start': 0x2004fc80, + 'size': 80, + }, + }, + 'word_size': 4, + 'thumb_mode': True, + 'comms_method': OpenOcdComm(server_addr, server_port), + } diff --git a/src/runtime/micro/device/host/utvm_api.c b/src/runtime/micro/device/host/utvm_api.c index 1b6f17607c9e..c88c98a80561 100644 --- a/src/runtime/micro/device/host/utvm_api.c +++ b/src/runtime/micro/device/host/utvm_api.c @@ -7,7 +7,9 @@ extern "C" { // TODO(weberlo): use this? https://stackoverflow.com/questions/5141960/get-the-current-time-in-c -void UTVMInit() { } +void UTVMInit() { + UTVMMain(); +} void UTVMTimerStart() { } diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 40eecadb63c7..76c5ddf1c1bc 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -56,10 +56,21 @@ uint32_t utvm_task_time = 0; // Gets called by UTVMInit, after device-specific initialization is finished. void UTVMMain() { + /* + utvm_workspace_begin = (char*) 420; // NOLINT(*) + utvm_workspace_end = (char*) 420; // NOLINT(*) + utvm_workspace_curr = (char*) 420; // NOLINT(*) + utvm_num_active_allocs = 420; + utvm_last_error = (const char*) 420; // NOLINT(*) + utvm_return_code = 0; // NOLINT(*) + utvm_task_time = 420; + UTVMDone(); + */ utvm_workspace_curr = utvm_workspace_begin; utvm_num_active_allocs = 0; utvm_last_error = NULL; // NOLINT(*) utvm_return_code = 0; + utvm_task_time = 0; UTVMTimerReset(); UTVMTimerStart(); utvm_return_code = utvm_task.func((void*) utvm_task.arg_values, (void*) utvm_task.arg_type_codes, // NOLINT(*) diff --git a/src/runtime/micro/host_low_level_device.cc b/src/runtime/micro/host_low_level_device.cc index 4eea88aaaffd..643efdd95429 100644 --- a/src/runtime/micro/host_low_level_device.cc +++ b/src/runtime/micro/host_low_level_device.cc @@ -40,21 +40,21 @@ class HostLowLevelDevice final : public LowLevelDevice { * \brief constructor to initialize on-host memory region to act as device * \param num_bytes size of the emulated on-device memory region */ - explicit HostLowLevelDevice(size_t num_bytes) : size_(num_bytes) { + explicit HostLowLevelDevice(size_t num_bytes, void** base_addr) : size_(num_bytes) { size_t size_in_pages = (num_bytes + kPageSize - 1) / kPageSize; // TODO(weberlo): Set permissions per section (e.g., read-write perms for // the heap, execute perms for text, etc.). int mmap_prot = PROT_READ | PROT_WRITE | PROT_EXEC; int mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE; - base_addr_ = reinterpret_cast( - mmap(nullptr, size_in_pages * kPageSize, mmap_prot, mmap_flags, -1, 0)); + base_addr_ = mmap(nullptr, size_in_pages * kPageSize, mmap_prot, mmap_flags, -1, 0); + *base_addr = base_addr_; } /*! * \brief destructor to deallocate on-host device region */ virtual ~HostLowLevelDevice() { - munmap(reinterpret_cast(base_addr_), size_); + munmap(base_addr_, size_); } void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { @@ -73,7 +73,7 @@ class HostLowLevelDevice final : public LowLevelDevice { } std::uintptr_t base_addr() const final { - return base_addr_; + return 0; } const char* device_type() const final { @@ -82,14 +82,14 @@ class HostLowLevelDevice final : public LowLevelDevice { private: /*! \brief base address of the micro device memory region */ - std::uintptr_t base_addr_; + void* base_addr_; /*! \brief size of memory region */ size_t size_; }; -const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes) { +const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes, void** base_addr) { std::shared_ptr lld = - std::make_shared(num_bytes); + std::make_shared(num_bytes, base_addr); return lld; } diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index 3cdfa77d30bc..cc2d6d66bb04 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -113,7 +113,7 @@ class LowLevelDevice { * \brief create a host low-level device * \param num_bytes size of the memory region */ -const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes); +const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes, void** base_addr); /*! * \brief connect to OpenOCD and create an OpenOCD low-level device diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 3779b957fc9a..e84ac6b9fd8a 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -84,19 +84,21 @@ static std::string AddrToString(void* addr) { } std::string RelocateBinarySections(const std::string& binary_path, - DevPtr text, - DevPtr rodata, - DevPtr data, - DevPtr bss, + size_t word_size, + DevPtr text_addr, + DevPtr rodata_addr, + DevPtr data_addr, + DevPtr bss_addr, const std::string& toolchain_prefix) { const auto* f = Registry::Get("tvm_callback_relocate_binary"); CHECK(f != nullptr) << "Require tvm_callback_relocate_binary to exist in registry"; std::string relocated_bin = (*f)(binary_path, - AddrToString(text.cast_to()), - AddrToString(rodata.cast_to()), - AddrToString(data.cast_to()), - AddrToString(bss.cast_to()), + word_size, + AddrToString(text_addr.cast_to()), + AddrToString(rodata_addr.cast_to()), + AddrToString(data_addr.cast_to()), + AddrToString(bss_addr.cast_to()), toolchain_prefix); return relocated_bin; } diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 0781e3bbacdc..afd8b3e77f9b 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -301,10 +301,11 @@ const char* SectionToString(SectionKind section); * \return relocated binary file contents */ std::string RelocateBinarySections(const std::string& binary_name, - DevPtr text, - DevPtr rodata, - DevPtr data, - DevPtr bss, + size_t word_size, + DevPtr text_addr, + DevPtr rodata_addr, + DevPtr data_addr, + DevPtr bss_addr, const std::string& toolchain_prefix); /*! diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index f6e9b3ab9086..9052e01dc8ef 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -23,6 +23,9 @@ #include #include +#include +#include +#include #include #include #include @@ -33,12 +36,6 @@ namespace tvm { namespace runtime { -// ARM and other manufacturers use the lowest bit of a function address to determine -// whether it's a "thumb mode" function. The Thumb ISA is more restricted, but -// results in more compact binaries. -const bool kRequiresThumbModeBit = true; -const size_t kWordSize = 4; - struct TVMMicroSessionThreadLocalEntry { std::stack> session_stack; }; @@ -82,9 +79,11 @@ MicroSession::MicroSession( size_t workspace_size, uint64_t stack_start, size_t stack_size, + size_t word_size, + bool thumb_mode, std::uintptr_t base_addr, const std::string& server_addr, - int port) { + int port) : word_size_(word_size), thumb_mode_(thumb_mode) { //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); //DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { @@ -95,69 +94,139 @@ MicroSession::MicroSession( // }); // curr_start_offset += section_size; //} - section_allocators_[0] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(text_start), - .size = text_size, - }); - section_allocators_[1] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(rodata_start), - .size = rodata_size, - }); - section_allocators_[2] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(data_start), - .size = data_size, - }); - section_allocators_[3] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(bss_start), - .size = bss_size, - }); - section_allocators_[4] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(args_start), - .size = args_size, - }); - section_allocators_[5] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(heap_start), - .size = heap_size, - }); - section_allocators_[6] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(workspace_start), - .size = workspace_size, - }); - section_allocators_[7] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(stack_start), - .size = stack_size, - }); //CHECK(curr_start_offset.value() < 0x20050000) << "exceeded available RAM on device (" << std::endl; - std::cout << "[Memory Layout]" << std::endl; - std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_offset().cast_to() << std::endl; - std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_offset().cast_to() << std::endl; - std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_offset().cast_to() << std::endl; - std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_offset().cast_to() << std::endl; - std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_offset().cast_to() << std::endl; - std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_offset().cast_to() << std::endl; - std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_offset().cast_to() << std::endl; - std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_offset().cast_to() << std::endl; - // NOTE: we don't use this for openocd memory_size_ = 0; //memory_size_ = curr_start_offset.cast_to(); // TODO(weberlo): make device type enum toolchain_prefix_ = toolchain_prefix; if (comms_method == "host") { - low_level_device_ = HostLowLevelDeviceCreate(memory_size_); + CHECK( + text_start == 0 && + rodata_start == 0 && + data_start == 0 && + bss_start == 0 && + args_start == 0 && + heap_start == 0 && + workspace_start == 0 && + stack_start == 0) << "unable to specify section addresses for host device"; + size_t memory_size = text_size + rodata_size + data_size + bss_size + args_size + heap_size + workspace_size + stack_size; + void* base_addr; + low_level_device_ = HostLowLevelDeviceCreate(memory_size, &base_addr); + std::cout << "base addr is " << base_addr << std::endl; + DevBaseOffset curr_offset = DevBaseOffset(reinterpret_cast(base_addr)); + + section_allocators_[0] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = text_size, + }); + curr_offset += text_size; + section_allocators_[1] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = rodata_size, + }); + curr_offset += rodata_size; + section_allocators_[2] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = data_size, + }); + curr_offset += data_size; + section_allocators_[3] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = bss_size, + }); + curr_offset += bss_size; + section_allocators_[4] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = args_size, + }); + curr_offset += args_size; + section_allocators_[5] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = heap_size, + }); + curr_offset += heap_size; + section_allocators_[6] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = workspace_size, + }); + curr_offset += workspace_size; + section_allocators_[7] = std::make_shared(DevMemRegion { + .start = curr_offset, + .size = stack_size, + }); + curr_offset += stack_size; } else if (comms_method == "openocd") { // TODO(weberlo): We need a better way of configuring devices. low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); + section_allocators_[0] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(text_start), + .size = text_size, + }); + section_allocators_[1] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(rodata_start), + .size = rodata_size, + }); + section_allocators_[2] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(data_start), + .size = data_size, + }); + section_allocators_[3] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(bss_start), + .size = bss_size, + }); + section_allocators_[4] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(args_start), + .size = args_size, + }); + section_allocators_[5] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(heap_start), + .size = heap_size, + }); + section_allocators_[6] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(workspace_start), + .size = workspace_size, + }); + section_allocators_[7] = std::make_shared(DevMemRegion { + .start = DevBaseOffset(stack_start), + .size = stack_size, + }); } else { LOG(FATAL) << "unsupported micro low-level device"; } + std::cout << "[Memory Layout]" << std::endl; + std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_offset().cast_to() << std::endl; + std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_offset().cast_to() << std::endl; + std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_offset().cast_to() << std::endl; + std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_offset().cast_to() << std::endl; + std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_offset().cast_to() << std::endl; + std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_offset().cast_to() << std::endl; + std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_offset().cast_to() << std::endl; + std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_offset().cast_to() << std::endl; + runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; + std::uintptr_t workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); + std::cout << " workspace begin: " << (void*) workspace_begin << std::endl; + std::uintptr_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); + std::cout << " workspace end: " << (void*) workspace_end << std::endl; + std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); + std::cout << " workspace curr: " << (void*) workspace_curr << std::endl; + size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); + std::cout << " num active allocs: " << (void*) num_active_allocs << std::endl; + std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); + std::cout << " last error: " << (void*) last_error << std::endl; + int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); + std::cout << " return code: " << return_code << std::endl; + uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); + std::cout << " task time was " << task_time << std::endl; + std::cout << " --------------------------------------------------------------------------------" << std::endl; + //if (comms_method == "openocd") { // // Set OpenOCD device's stack pointer. // auto stack_section = GetAllocator(SectionKind::kStack); @@ -195,7 +264,7 @@ MicroSession::~MicroSession() { uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "[MicroSession::PushToExecQueue]" << std::endl; // TODO: make this a parameter. - if (kRequiresThumbModeBit) { + if (thumb_mode_) { func_ptr += 1; } int32_t (*func_dev_addr)(void*, void*, int32_t) = @@ -205,7 +274,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // allocation in the args section. DevPtr args_addr = low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); - TargetDataLayoutEncoder encoder(args_addr, kWordSize); + TargetDataLayoutEncoder encoder(args_addr, word_size_); std::cout << " after encoder alloc" << std::endl; @@ -227,7 +296,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), // .num_args = args.num_args, //}; - if (kWordSize == 4) { + if (word_size_ == 4) { typedef struct StructUTVMTask32 { /*! \brief Pointer to function to call for this task */ uint32_t func; @@ -248,7 +317,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { }; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); - } else if (kWordSize == 8) { + } else if (word_size_ == 8) { typedef struct StructUTVMTask64 { /*! \brief Pointer to function to call for this task */ uint64_t func; @@ -270,7 +339,8 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else { - CHECK(false) << "unsupported word size " << kWordSize; + // TODO hoist word size check to initialization + CHECK(false) << "unsupported word size " << word_size_; } std::cout << " after task write" << std::endl; @@ -278,7 +348,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); DevBaseOffset utvm_init_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); - if (kRequiresThumbModeBit) { + if (thumb_mode_) { utvm_init_loc += 1; } @@ -287,12 +357,41 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { //std::cout << " do execution things: "; //char tmp; //std::cin >> tmp; + //DevSymbolWrite(runtime_symbol_map_, "utvm_task_time", 0); + std::uintptr_t workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); + std::cout << " workspace begin: " << workspace_begin << std::endl; + std::uintptr_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); + std::cout << " workspace end: " << workspace_end << std::endl; + std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); + std::cout << " workspace curr: " << workspace_curr << std::endl; + size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); + std::cout << " num active allocs: " << num_active_allocs << std::endl; + std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); + std::cout << " last error: " << last_error << std::endl; + int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); + std::cout << " return code: " << return_code << std::endl; + uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); + std::cout << " task time was " << task_time << std::endl; + std::cout << " --------------------------------------------------------------------------------" << std::endl; + low_level_device()->Execute(utvm_init_loc, utvm_done_loc); // Check if there was an error during execution. If so, log it. //CheckDeviceError(); - uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); + workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); + std::cout << " workspace begin: " << workspace_begin << std::endl; + workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); + std::cout << " workspace end: " << workspace_end << std::endl; + workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); + std::cout << " workspace curr: " << workspace_curr << std::endl; + num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); + std::cout << " num active allocs: " << num_active_allocs << std::endl; + last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); + std::cout << " last error: " << last_error << std::endl; + return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); + std::cout << " return code: " << return_code << std::endl; + task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); std::cout << " task time was " << task_time << std::endl; GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); @@ -305,10 +404,10 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d DevMemRegion data_section; DevMemRegion bss_section; - text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, kWordSize); - rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, kWordSize); - data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, kWordSize); - bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, kWordSize); + text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, word_size_); + rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, word_size_); + data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, word_size_); + bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, word_size_); std::cout << "text size: " << std::hex << text_section.size << std::endl; std::cout << "rodata size: " << std::hex << rodata_section.size << std::endl; std::cout << "data size: " << std::hex << data_section.size << std::endl; @@ -328,6 +427,7 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::cout << "bss start: " << std::hex << bss_section.start.value() << std::endl; std::string relocated_bin = RelocateBinarySections( binary_path, + word_size_, low_level_device_->ToDevPtr(text_section.start), low_level_device_->ToDevPtr(rodata_section.start), low_level_device_->ToDevPtr(data_section.start), @@ -415,6 +515,7 @@ std::tuple MicroSession::EncoderAppend( } DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { + /* typedef struct StructARMTVMArray { uint32_t data; DLContext ctx; @@ -426,9 +527,10 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr uint32_t byte_offset; uint32_t pad2; } ARMTVMArray; + */ - //auto tvm_arr_slot = encoder->Alloc(); - auto tvm_arr_slot = encoder->Alloc(); + auto tvm_arr_slot = encoder->Alloc(); + //auto tvm_arr_slot = encoder->Alloc(); auto shape_slot = encoder->Alloc(arr.ndim); // `shape` and `strides` are stored on the host, so we need to write them to @@ -445,6 +547,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); + /* ARMTVMArray dev_arr = { .data = *((uint32_t*) &arr.data), .ctx = arr.ctx, @@ -456,10 +559,11 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr .byte_offset = *((uint32_t*) &arr.byte_offset), .pad2 = 0, }; + */ // Copy `arr`, update the copy's pointers to be device pointers, then // write the copy to `tvm_arr_slot`. - //TVMArray dev_arr = arr; + TVMArray dev_arr = arr; // Update the device type to look like a host, because codegen generates // checks that it is a host array. CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; @@ -498,13 +602,19 @@ void MicroSession::CheckDeviceError() { void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { //void* runtime_impl_addr = runtime_symbol_map_[func_name].cast_to(); DevPtr runtime_impl_addr = runtime_symbol_map_[func_name]; - if (kRequiresThumbModeBit) { + if (thumb_mode_) { runtime_impl_addr += 1; } std::cout << "patching " << func_name << " with addr " << runtime_impl_addr.cast_to() << std::endl; std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; - DevSymbolWrite(symbol_map, func_name_underscore.str(), (int32_t) runtime_impl_addr.value()); + if (word_size_ == 4) { + DevSymbolWrite(symbol_map, func_name_underscore.str(), (int32_t) runtime_impl_addr.value()); + } else if (word_size_ == 8) { + DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr.value()); + } else { + CHECK(false) << "ayy"; + } } std::string MicroSession::ReadString(DevBaseOffset str_offset) { @@ -536,6 +646,8 @@ void MicroSession::FreeInSection(SectionKind type, DevBaseOffset ptr) { template T MicroSession::DevSymbolRead(const SymbolMap& symbol_map, const std::string& symbol) { DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); + //sym_offset -= 6; + std::cout << "SYM OFFSET FOR " << symbol << " IS " << sym_offset.cast_to() << std::endl; T result; low_level_device()->Read(sym_offset, &result, sizeof(T)); return result; @@ -546,6 +658,7 @@ void MicroSession::DevSymbolWrite(const SymbolMap& symbol_map, const std::string& symbol, const T& value) { DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); + //sym_offset -= 6; low_level_device()->Write(sym_offset, &value, sizeof(T)); } @@ -587,9 +700,11 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") size_t workspace_size = args[16]; uint64_t stack_start = args[17]; size_t stack_size = args[18]; - uint64_t base_addr = args[19]; - const std::string& server_addr = args[20]; - int port = args[21]; + size_t word_size = args[19]; + bool thumb_mode = args[20]; + uint64_t base_addr = args[21]; + const std::string& server_addr = args[22]; + int port = args[23]; ObjectPtr session = make_object( comms_method, binary_path, @@ -610,6 +725,8 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") workspace_size, stack_start, stack_size, + word_size, + thumb_mode, base_addr, server_addr, port); diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index e1e43ce03b08..ccef1fa84783 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -100,6 +100,8 @@ class MicroSession : public ModuleNode { size_t workspace_size, uint64_t stack_start, size_t stack_size, + size_t word_size, + bool thumb_mode, std::uintptr_t base_addr, const std::string& server_addr, int port); @@ -113,8 +115,6 @@ class MicroSession : public ModuleNode { void CreateSession(); - //void BakeSession(const std::string& binary_path); - BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers); /*! @@ -192,15 +192,18 @@ class MicroSession : public ModuleNode { section_allocators_[static_cast(SectionKind::kNumKinds)]; /*! \brief total number of bytes of usable device memory for this session */ size_t memory_size_; - ///*! \brief uTVM runtime binary info */ - //BinaryInfo runtime_bin_info_; - /*! \brief path to uTVM runtime source code */ - std::string runtime_binary_path_; + /*! \brief TODO */ + size_t word_size_; + /*! \brief TODO */ + // ARM and other manufacturers use the lowest bit of a function address to determine + // whether it's a "thumb mode" function. The Thumb ISA is more restricted, but + // results in more compact binaries. + bool thumb_mode_; /*! \brief offset of the runtime entry function */ DevBaseOffset utvm_main_symbol_; /*! \brief offset of the runtime exit breakpoint */ DevBaseOffset utvm_done_symbol_; - + /*! \brief TODO */ SymbolMap runtime_symbol_map_; /*! diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 015006e27708..ec533d804286 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -30,13 +30,10 @@ #DEVICE_TYPE = "openocd" #TOOLCHAIN_PREFIX = "arm-none-eabi-" -DEV_BINUTIL = micro.binutil.ArmBinutil() -DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) +DEV_CONFIG = micro.device.host.get_config() +#DEV_CONFIG = micro.device.stm32f746xx.get_config('127.0.0.1', 6666) -#DEV_BINUTIL = micro.binutil.HostBinutil() -#DEV_COMMUNICATOR = micro.HostComm() - -def create_micro_mod(c_mod, dev_binutil): +def create_micro_mod(c_mod, dev_config): """Produces a micro module from a given module. Parameters @@ -57,7 +54,7 @@ def create_micro_mod(c_mod, dev_binutil): lib_obj_path = temp_dir.relpath("dev_lib.obj") c_mod.export_library( lib_obj_path, - fcompile=tvm.micro.cross_compiler(dev_binutil, micro.LibType.OPERATOR)) + fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path) return micro_mod @@ -117,7 +114,7 @@ def test_alloc(): return shape = (1024,) dtype = "float32" - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): + with micro.Session(DEV_CONFIG): ctx = tvm.micro_dev(0) np_tensor = np.random.uniform(size=shape).astype(dtype) micro_tensor = tvm.nd.array(np_tensor, ctx) @@ -147,8 +144,8 @@ def test_add(): func_name = "fadd" c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) @@ -156,14 +153,18 @@ def test_add(): #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) + print(a) + print(b) + print(c) micro_func(a, b, c) + print(c) #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) #c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) #micro_func(a, b, c) - #tvm.testing.assert_allclose( - # c.asnumpy(), a.asnumpy() + b.asnumpy()) + tvm.testing.assert_allclose( + c.asnumpy(), a.asnumpy() + b.asnumpy()) def test_int_workspace_add(): @@ -188,8 +189,8 @@ def test_int_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.randint(1, 50, size=shape).astype(dtype), ctx) @@ -223,8 +224,8 @@ def test_float_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -251,12 +252,14 @@ def test_graph_runtime(): z = relay.add(xx, relay.const(1.0)) func = relay.Function([x], z) - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - mod = relay_micro_build(func, DEV_BINUTIL) + with micro.Session(DEV_CONFIG): + mod = relay_micro_build(func, DEV_CONFIG) x_in = np.random.uniform(size=shape[0]).astype(dtype) + print(x_in) mod.run(x=x_in) result = mod.get_output(0).asnumpy() + print(result) tvm.testing.assert_allclose( result, x_in * x_in + 1.0) @@ -270,43 +273,45 @@ def test_conv2d(): from tvm.relay import transform dshape = (1, 4, 16, 16) - for dtype, func_name in [('float32', 'fused_nn_conv2d'), ('int8', 'fused_nn_conv2d_2')]: - reset_gdbinit() + dtype = 'float32' + func_name = 'fused_nn_conv2d' - # Construct Relay program. - x = relay.var("x", shape=dshape, dtype=dtype) - conv_expr = relay.nn.conv2d( - x, relay.var("w"), - kernel_size=(3, 3), - padding=(1, 1), - channels=4) - func = relay.Function(relay.analysis.free_vars(conv_expr), conv_expr) - mod = relay.Module.from_expr(func) - mod = transform.InferType()(mod) + reset_gdbinit() - x_shape = list(map(lambda x: x.value, mod['main'].params[0].checked_type.shape)) - w_shape = list(map(lambda x: x.value, mod['main'].params[1].checked_type.shape)) - out_shape = list(map(lambda x: x.value, mod['main'].ret_type.shape)) + # Construct Relay program. + x = relay.var("x", shape=dshape, dtype=dtype) + conv_expr = relay.nn.conv2d( + x, relay.var("w"), + kernel_size=(3, 3), + padding=(1, 1), + channels=4) + func = relay.Function(relay.analysis.free_vars(conv_expr), conv_expr) + mod = relay.Module.from_expr(func) + mod = transform.InferType()(mod) + + x_shape = list(map(lambda x: x.value, mod['main'].params[0].checked_type.shape)) + w_shape = list(map(lambda x: x.value, mod['main'].params[1].checked_type.shape)) + out_shape = list(map(lambda x: x.value, mod['main'].ret_type.shape)) - with tvm.build_config(disable_vectorize=True): - graph, c_mod, params = relay.build(mod, target="c") + with tvm.build_config(disable_vectorize=True): + graph, c_mod, params = relay.build(mod, target="c") - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) - micro_func = micro_mod[func_name] - ctx = tvm.micro_dev(0) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) + micro_func = micro_mod[func_name] + ctx = tvm.micro_dev(0) - x_data = tvm.nd.array(np.random.uniform(size=x_shape).astype(dtype), ctx) - w_data = tvm.nd.array(np.random.uniform(size=w_shape).astype(dtype), ctx) - result = tvm.nd.array(np.zeros(shape=out_shape, dtype=dtype), ctx) - micro_func(x_data, w_data, result) + x_data = tvm.nd.array(np.random.uniform(size=x_shape).astype(dtype), ctx) + w_data = tvm.nd.array(np.random.uniform(size=w_shape).astype(dtype), ctx) + result = tvm.nd.array(np.zeros(shape=out_shape, dtype=dtype), ctx) + micro_func(x_data, w_data, result) - out_data = np.zeros(out_shape, dtype=dtype) - params = { 'x': x_data.asnumpy(), 'w': w_data.asnumpy() } - intrp = create_executor('debug') - expected_result = intrp.evaluate(mod['main'])(x_data, w_data).data + out_data = np.zeros(out_shape, dtype=dtype) + params = { 'x': x_data.asnumpy(), 'w': w_data.asnumpy() } + intrp = create_executor('debug') + expected_result = intrp.evaluate(mod['main'])(x_data, w_data).data - tvm.testing.assert_allclose(result.asnumpy(), expected_result.asnumpy()) + tvm.testing.assert_allclose(result.asnumpy(), expected_result.asnumpy()) def test_multiple_modules(): @@ -325,9 +330,9 @@ def test_multiple_modules(): ret = relay.subtract(x, relay.const(1.0)) sub_const_func = relay.Function([x], ret) - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) - sub_const_mod = relay_micro_build(sub_const_func, DEV_BINUTIL) + with micro.Session(DEV_CONFIG): + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + sub_const_mod = relay_micro_build(sub_const_func, DEV_CONFIG) x_in = np.random.uniform(size=shape[0]).astype(dtype) add_const_mod.run(x=x_in) @@ -353,8 +358,8 @@ def test_interleave_sessions(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) - sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_a = micro.Session(DEV_CONFIG) + sess_b = micro.Session(DEV_CONFIG) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) @@ -362,13 +367,13 @@ def test_interleave_sessions(): np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) with sess_a: - add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( add_result, np_tensor_a + 1.0) with sess_b: - add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_b) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -387,15 +392,15 @@ def test_nested_sessions(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) - sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_a = micro.Session(DEV_CONFIG) + sess_b = micro.Session(DEV_CONFIG) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) with sess_b: np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -414,12 +419,12 @@ def test_inactive_session_use(): ret = relay.add(x, relay.const(1.0)) add_const_func = relay.Function([x], ret) - sess_a = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) - sess_b = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) + sess_a = micro.Session(DEV_CONFIG) + sess_b = micro.Session(DEV_CONFIG) with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, DEV_BINUTIL) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) with sess_b: # These objects belong to `sess_a`. @@ -430,18 +435,17 @@ def test_inactive_session_use(): if __name__ == "__main__": - #test_alloc() - #test_add() + test_alloc() + test_add() - #test_int_workspace_add() - #test_float_workspace_add() + test_int_workspace_add() + test_float_workspace_add() - #test_graph_runtime() + test_graph_runtime() - #test_conv2d() + test_conv2d() test_multiple_modules() - #test_interleave_sessions() - #test_nested_sessions() - #test_inactive_session_use() - #test_arm_add() + test_interleave_sessions() + test_nested_sessions() + test_inactive_session_use() From 4df83c8025e7c512fee764f61ae3bc6a635ece63 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 10:13:58 -0800 Subject: [PATCH 30/70] ARM and host work simultaneously --- src/runtime/micro/micro_session.cc | 172 +++++++++++--------- src/runtime/micro/micro_session.h | 25 +++ tests/python/unittest/test_runtime_micro.py | 55 +------ 3 files changed, 123 insertions(+), 129 deletions(-) diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 9052e01dc8ef..031bb2399f4e 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -297,16 +297,6 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // .num_args = args.num_args, //}; if (word_size_ == 4) { - typedef struct StructUTVMTask32 { - /*! \brief Pointer to function to call for this task */ - uint32_t func; - /*! \brief Array of argument values */ - uint32_t arg_values; - /*! \brief Array of type codes for each argument value */ - uint32_t arg_type_codes; - /*! \brief Number of arguments */ - int32_t num_args; - } UTVMTask32; TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); UTVMTask32 task = { @@ -318,24 +308,30 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else if (word_size_ == 8) { - typedef struct StructUTVMTask64 { - /*! \brief Pointer to function to call for this task */ - uint64_t func; - /*! \brief Array of argument values */ - uint64_t arg_values; - /*! \brief Array of type codes for each argument value */ - uint64_t arg_type_codes; - /*! \brief Number of arguments */ - int32_t num_args; - } UTVMTask64; - TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); - UTVMTask64 task = { - .func = *((uint64_t*) &func_dev_addr), - .arg_values = *((uint64_t*) &arg_values_dev_addr), - .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), + //typedef struct StructUTVMTask64 { + // /*! \brief Pointer to function to call for this task */ + // uint64_t func; + // /*! \brief Array of argument values */ + // uint64_t arg_values; + // /*! \brief Array of type codes for each argument value */ + // uint64_t arg_type_codes; + // /*! \brief Number of arguments */ + // int32_t num_args; + //} UTVMTask64; + UTVMTask task = { + .func = func_dev_addr, + .arg_values = std::get<0>(arg_field_addrs).cast_to(), + .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), .num_args = args.num_args, }; + //TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + //int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + //UTVMTask64 task = { + // .func = *((uint64_t*) &func_dev_addr), + // .arg_values = *((uint64_t*) &arg_values_dev_addr), + // .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), + // .num_args = args.num_args, + //}; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else { @@ -473,7 +469,6 @@ std::tuple MicroSession::EncoderAppend( auto tvm_vals_slot = encoder->Alloc(num_args); auto type_codes_slot = encoder->Alloc(num_args); - std::cout << " num_args: " << num_args << std::endl; for (int i = 0; i < num_args; i++) { switch (type_codes[i]) { case kNDArrayContainer: @@ -486,9 +481,7 @@ std::tuple MicroSession::EncoderAppend( // Mutate the array to unwrap the `data` field. base_arr_handle->data = reinterpret_cast(old_data)->data; // Now, encode the unwrapped version. - std::cout << " before array encode" << std::endl; void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); - std::cout << " after array encode" << std::endl; // And restore the original wrapped version. base_arr_handle->data = old_data; @@ -506,15 +499,12 @@ std::tuple MicroSession::EncoderAppend( break; } } - std::cout << " past args loop" << std::endl; type_codes_slot.WriteArray(type_codes, num_args); - std::cout << " tvm_vals_slot.start_addr(): " << tvm_vals_slot.start_addr().cast_to() << std::endl; - std::cout << " type_codes_slot.start_addr(): " << type_codes_slot.start_addr().cast_to() << std::endl; - return std::make_tuple(tvm_vals_slot.start_addr(), type_codes_slot.start_addr()); } DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { + // TODO make this code mux on the word size /* typedef struct StructARMTVMArray { uint32_t data; @@ -529,53 +519,79 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr } ARMTVMArray; */ - auto tvm_arr_slot = encoder->Alloc(); - //auto tvm_arr_slot = encoder->Alloc(); - auto shape_slot = encoder->Alloc(arr.ndim); - - // `shape` and `strides` are stored on the host, so we need to write them to - // the device first. The `data` field is already allocated on the device and - // is a device pointer, so we don't need to write it. - shape_slot.WriteArray(arr.shape, arr.ndim); - DevPtr shape_addr = shape_slot.start_addr(); - DevPtr strides_addr = DevPtr(nullptr); - if (arr.strides != nullptr) { - auto stride_slot = encoder->Alloc(arr.ndim); - stride_slot.WriteArray(arr.strides, arr.ndim); - strides_addr = stride_slot.start_addr(); - } + if (word_size_ == 4) { + auto tvm_arr_slot = encoder->Alloc(); + //CHECK(false) << "should we be allocing int32_t?"; + auto shape_slot = encoder->Alloc(arr.ndim); + + // `shape` and `strides` are stored on the host, so we need to write them to + // the device first. The `data` field is already allocated on the device and + // is a device pointer, so we don't need to write it. + shape_slot.WriteArray(arr.shape, arr.ndim); + DevPtr shape_addr = shape_slot.start_addr(); + DevPtr strides_addr = DevPtr(nullptr); + if (arr.strides != nullptr) { + auto stride_slot = encoder->Alloc(arr.ndim); + stride_slot.WriteArray(arr.strides, arr.ndim); + strides_addr = stride_slot.start_addr(); + } - int64_t* dev_shape = shape_addr.cast_to(); - int64_t* dev_strides = strides_addr.cast_to(); - /* - ARMTVMArray dev_arr = { - .data = *((uint32_t*) &arr.data), - .ctx = arr.ctx, - .ndim = arr.ndim, - .dtype = arr.dtype, - .shape = *((uint32_t*) &dev_shape), - .strides = *((uint32_t*) &dev_strides), - .pad1 = 0, - .byte_offset = *((uint32_t*) &arr.byte_offset), - .pad2 = 0, - }; - */ + int64_t* dev_shape = shape_addr.cast_to(); + int64_t* dev_strides = strides_addr.cast_to(); + TVMArray32 dev_arr = { + .data = *((uint32_t*) &arr.data), + .ctx = arr.ctx, + .ndim = arr.ndim, + .dtype = arr.dtype, + .shape = *((uint32_t*) &dev_shape), + .strides = *((uint32_t*) &dev_strides), + .pad1 = 0, + .byte_offset = *((uint32_t*) &arr.byte_offset), + .pad2 = 0, + }; + // Update the device type to look like a host, because codegen generates + // checks that it is a host array. + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; + dev_arr.ctx.device_type = DLDeviceType::kDLCPU; + tvm_arr_slot.WriteValue(dev_arr); + return tvm_arr_slot.start_addr(); + } else if (word_size_ == 8) { + auto tvm_arr_slot = encoder->Alloc(); + auto shape_slot = encoder->Alloc(arr.ndim); + + // `shape` and `strides` are stored on the host, so we need to write them to + // the device first. The `data` field is already allocated on the device and + // is a device pointer, so we don't need to write it. + shape_slot.WriteArray(arr.shape, arr.ndim); + DevPtr shape_addr = shape_slot.start_addr(); + DevPtr strides_addr = DevPtr(nullptr); + if (arr.strides != nullptr) { + auto stride_slot = encoder->Alloc(arr.ndim); + stride_slot.WriteArray(arr.strides, arr.ndim); + strides_addr = stride_slot.start_addr(); + } - // Copy `arr`, update the copy's pointers to be device pointers, then - // write the copy to `tvm_arr_slot`. - TVMArray dev_arr = arr; - // Update the device type to look like a host, because codegen generates - // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; - dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - // Add the base address of the device to the array's data's device offset to - // get a device address. - //DevBaseOffset arr_offset(reinterpret_cast(arr.data)); - //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); - //dev_arr.shape = shape_addr.cast_to(); - //dev_arr.strides = strides_addr.cast_to(); - tvm_arr_slot.WriteValue(dev_arr); - return tvm_arr_slot.start_addr(); + int64_t* dev_shape = shape_addr.cast_to(); + int64_t* dev_strides = strides_addr.cast_to(); + + // Copy `arr`, update the copy's pointers to be device pointers, then + // write the copy to `tvm_arr_slot`. + TVMArray dev_arr = arr; + // Update the device type to look like a host, because codegen generates + // checks that it is a host array. + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; + dev_arr.ctx.device_type = DLDeviceType::kDLCPU; + // Add the base address of the device to the array's data's device offset to + // get a device address. + DevBaseOffset arr_offset(reinterpret_cast(arr.data)); + dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); + dev_arr.shape = shape_addr.cast_to(); + dev_arr.strides = strides_addr.cast_to(); + tvm_arr_slot.WriteValue(dev_arr); + return tvm_arr_slot.start_addr(); + } else { + CHECK(false) << "invalid word size"; + } } void MicroSession::CheckDeviceError() { diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index ccef1fa84783..d31ebc29b41b 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -273,6 +273,31 @@ struct MicroDevSpace { ObjectPtr session; }; +// tvm array for serialization to 32-bit devices +typedef struct StructTVMArray32 { + uint32_t data; + DLContext ctx; + int ndim; + DLDataType dtype; + uint32_t shape; + uint32_t strides; + uint32_t pad1; + uint32_t byte_offset; + uint32_t pad2; +} TVMArray32; + +// utvm task for serialization to 32-bit devices +typedef struct StructUTVMTask32 { + /*! \brief Pointer to function to call for this task */ + uint32_t func; + /*! \brief Array of argument values */ + uint32_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint32_t arg_type_codes; + /*! \brief Number of arguments */ + int32_t num_args; +} UTVMTask32; + } // namespace runtime } // namespace tvm #endif // TVM_RUNTIME_MICRO_MICRO_SESSION_H_ diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index ec533d804286..24d0f3b64deb 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,11 +25,6 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -#DEVICE_TYPE = "host" -#TOOLCHAIN_PREFIX = "" -#DEVICE_TYPE = "openocd" -#TOOLCHAIN_PREFIX = "arm-none-eabi-" - DEV_CONFIG = micro.device.host.get_config() #DEV_CONFIG = micro.device.stm32f746xx.get_config('127.0.0.1', 6666) @@ -167,43 +162,6 @@ def test_add(): c.asnumpy(), a.asnumpy() + b.asnumpy()) -def test_int_workspace_add(): - """Test a module which uses a workspace to compute an intermediate value.""" - if not tvm.module.enabled("micro_dev"): - return - shape = (1024,) - dtype = "int32" - - reset_gdbinit() - - # Construct TVM expression. - tvm_shape = tvm.convert(shape) - A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) - B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) - B = tvm.compute(A.shape, lambda *i: A(*i) + 1, name="B") - # TODO: need to force the dtype of `C` to be int8 instead of int32 somehow, - # if we want to benchmark int8. - C = tvm.compute(A.shape, lambda *i: B(*i) + 1, name="C") - s = tvm.create_schedule(C.op) - - func_name = "fadd_two_workspace" - c_mod = tvm.build(s, [A, C], target="c", name=func_name) - - with micro.Session(DEV_CONFIG): - micro_mod = create_micro_mod(c_mod, DEV_CONFIG) - micro_func = micro_mod[func_name] - ctx = tvm.micro_dev(0) - a = tvm.nd.array(np.random.randint(1, 50, size=shape).astype(dtype), ctx) - print(a) - c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print(c) - micro_func(a, c) - print(c) - - tvm.testing.assert_allclose( - c.asnumpy(), a.asnumpy() + 2) - - def test_float_workspace_add(): """Test a module which uses a workspace to compute an intermediate value.""" if not tvm.module.enabled("micro_dev"): @@ -437,15 +395,10 @@ def test_inactive_session_use(): if __name__ == "__main__": test_alloc() test_add() - - test_int_workspace_add() - test_float_workspace_add() - + test_workspace_add() test_graph_runtime() - test_conv2d() - test_multiple_modules() - test_interleave_sessions() - test_nested_sessions() - test_inactive_session_use() + #test_interleave_sessions() + #test_nested_sessions() + #test_inactive_session_use() From bf10c430f067761d5b6ff0127968d88be1c6822a Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 13:18:52 -0800 Subject: [PATCH 31/70] refactor yo life --- arm-auto-utvm-demo/tune_relay_utvm.py | 67 +-- python/tvm/micro/__init__.py | 2 +- python/tvm/micro/base.py | 488 ++++++++++-------- python/tvm/micro/device/__init__.py | 41 +- .../micro/device/{stm32f746xx.py => arm.py} | 10 +- python/tvm/micro/device/host.py | 8 +- python/tvm/micro/rpc_server.py | 30 +- src/runtime/micro/micro_session.cc | 77 +-- src/runtime/micro/micro_session.h | 13 + tests/python/unittest/test_runtime_micro.py | 115 ++--- 10 files changed, 434 insertions(+), 417 deletions(-) rename python/tvm/micro/device/{stm32f746xx.py => arm.py} (88%) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index aa8d9cda6fc2..e8d94c3de12f 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -34,16 +34,13 @@ # first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal # then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another -DEV_BINUTIL = micro.binutil.ArmBinutil() -DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) -#DEVICE_TYPE = 'openocd' -#TOOLCHAIN_PREFIX = 'arm-none-eabi-' +DEV_CONFIG = micro.device.arm.default_config('127.0.0.1', 6666) DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') N, L, M = 32, 32, 32 -N_TRIAL = 1 +N_TRIAL = 3 N_PER_TRIAL = 1 N_PARALLEL = 1 @@ -51,31 +48,33 @@ SERVER_PORT = 9190 LOG_FILE_NAME = f'{DEVICE}.log' +if os.path.exists(LOG_FILE_NAME): + os.remove(LOG_FILE_NAME) -def create_micro_mod(c_mod, dev_binutil): - """Produces a micro module from a given module. - - Parameters - ---------- - c_mod : tvm.module.Module - module with "c" as its target backend - - toolchain_prefix : str - toolchain prefix to be used (see `tvm.micro.Session` docs) - - Return - ------ - micro_mod : tvm.module.Module - micro module for the target device - """ - print('[create_micro_mod]') - temp_dir = util.tempdir() - lib_obj_path = temp_dir.relpath("dev_lib.obj") - c_mod.export_library( - lib_obj_path, - fcompile=tvm.micro.cross_compiler(dev_binutil, micro.LibType.OPERATOR)) - micro_mod = tvm.module.load(lib_obj_path) - return micro_mod +#def create_micro_mod(c_mod, dev_config): +# """Produces a micro module from a given module. +# +# Parameters +# ---------- +# c_mod : tvm.module.Module +# module with "c" as its target backend +# +# toolchain_prefix : str +# toolchain prefix to be used (see `tvm.micro.Session` docs) +# +# Return +# ------ +# micro_mod : tvm.module.Module +# micro module for the target device +# """ +# print('[create_micro_mod]') +# temp_dir = util.tempdir() +# lib_obj_path = temp_dir.relpath("dev_lib.obj") +# c_mod.export_library( +# lib_obj_path, +# fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) +# micro_mod = tvm.module.load(lib_obj_path) +# return micro_mod @autotvm.template @@ -112,7 +111,7 @@ def tune(): early_stopping = None measure_option = autotvm.measure_option( builder=autotvm.LocalBuilder( - build_func=tvm.micro.cross_compiler(DEV_BINUTIL, micro.LibType.OPERATOR)), + build_func=tvm.micro.cross_compiler(DEV_CONFIG['binutil'], micro.LibType.OPERATOR)), runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=N_PARALLEL, number=N_PER_TRIAL) ) @@ -139,13 +138,14 @@ def tune(): def evaluate(): print('[EVALUATE]') # compile kernels with history best records - with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): + #with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): + with autotvm.apply_history_best(LOG_FILE_NAME): with TARGET: sched, arg_bufs = matmul(N, L, M, 'float32') c_mod = tvm.build(sched, arg_bufs, name='matmul') - with micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR): - micro_mod = create_micro_mod(c_mod, DEV_BINUTIL) + with micro.Session(DEV_CONFIG) as sess: + micro_mod = sess.create_micro_mod(c_mod) micro_func = micro_mod['matmul'] ctx = tvm.micro_dev(0) @@ -163,4 +163,5 @@ def evaluate(): if __name__ == '__main__': tune() + input('finished tuning...') evaluate() diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 92ca0f105b64..0d86867f5404 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,5 +23,5 @@ """ from ..contrib import binutil -from .base import LibType, Session, cross_compiler, create_micro_lib +from .base import LibType, Session, cross_compiler from . import device diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index e0cb1ca7b95e..82c5dd2e3e81 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -57,15 +57,10 @@ class Session: .. code-block:: python c_mod = ... # some module generated with "c" as the target - device_type = "openocd" - toolchain_prefix = "riscv64-unknown-elf-" - with tvm.micro.Session(device_type, - toolchain_prefix, - base_addr=0x10010000, - server_addr="127.0.0.1", - port=6666): - c_mod.export_library(lib_obj_path, fcompile=tvm.micro.cross_compiler(toolchain_prefix)) - micro_mod = tvm.module.load(lib_obj_path, "micro_dev") + dev_config = micro.device.stm32f746xx.default_config('127.0.0.1', 6666) + with tvm.micro.Session(dev_config): + c_mod.export_library(lib_obj_path, fcompile=tvm.micro.cross_compiler(dev_config)) + micro_mod = tvm.module.load(lib_obj_path, 'micro_dev') """ # TODO(weberlo): remove required trailing dash in toolchain_prefix @@ -73,7 +68,8 @@ def __init__(self, config): self._check_system() #self._check_args(device_type, kwargs) - self.binutil = config['binutil'] + #self.binutil = config['binutil'] + self.binutil = tvm.micro.device.get_binutil(config['binutil']) self.mem_layout = config['mem_layout'] self.word_size = config['word_size'] self.thumb_mode = config['thumb_mode'] @@ -85,10 +81,11 @@ def __init__(self, config): runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) - if isinstance(self.comms_method, tvm.micro.device.OpenOcdComm): - server_addr = self.comms_method.server_addr - server_port = self.comms_method.server_port - elif isinstance(self.comms_method, tvm.micro.device.HostComm): + comms_method = config['comms_method'] + if comms_method == 'openocd': + server_addr = config['server_addr'] + server_port = config['server_port'] + elif comms_method == 'host': server_addr = '' server_port = 0 else: @@ -98,7 +95,7 @@ def __init__(self, config): base_addr = 0 self.module = _CreateSession( - self.comms_method.name(), + comms_method, runtime_obj_path, self.binutil.toolchain_prefix(), self.mem_layout['text'].get('start', 0), @@ -125,6 +122,28 @@ def __init__(self, config): self._enter = self.module["enter"] self._exit = self.module["exit"] + def create_micro_mod(self, c_mod): + """Produces a micro module from a given module. + + Parameters + ---------- + c_mod : tvm.module.Module + module with "c" as its target backend + + Return + ------ + micro_mod : tvm.module.Module + micro module for the target device + """ + print('[create_micro_mod]') + temp_dir = _util.tempdir() + lib_obj_path = temp_dir.relpath('dev_lib.obj') + c_mod.export_library( + lib_obj_path, + fcompile=cross_compiler(self.binutil, LibType.OPERATOR)) + micro_mod = tvm.module.load(lib_obj_path) + return micro_mod + def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -154,34 +173,6 @@ def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() -def _get_micro_host_driven_dir(): - """Get directory path for uTVM host-driven runtime source files. - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "host_driven") - return micro_host_driven_dir - - -def _get_micro_device_dir(): - """Get directory path for TODO - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "device") - return micro_device_dir - - def cross_compiler(dev_binutil, lib_type): """Creates a cross compile function that wraps `create_micro_lib`. @@ -189,12 +180,7 @@ def cross_compiler(dev_binutil, lib_type): Parameters ---------- - toolchain_prefix : str - toolchain prefix to be used - - include_dev_lib_header : Optional[bool] - whether to include the device library header containing definitions of - library functions. + lib_type: DFSDF Return ------ @@ -207,189 +193,257 @@ def cross_compiler(dev_binutil, lib_type): .. code-block:: python c_mod = ... # some module generated with "c" as the target - fcompile = tvm.micro.cross_compiler(toolchain_prefix="") - c_mod.export_library("dev_lib.obj", fcompile=fcompile) + fcompile = tvm.micro.cross_compiler(lib_type=LibType.OPERATOR) + c_mod.export_library('dev_lib.obj', fcompile=fcompile) """ + if isinstance(dev_binutil, str): + dev_binutil = tvm.micro.device.get_binutil(dev_binutil) + def compile_func(obj_path, src_path, **kwargs): if isinstance(obj_path, list): obj_path = obj_path[0] if isinstance(src_path, list): src_path = src_path[0] dev_binutil.create_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) - #create_micro_lib(obj_path, src_path, toolchain_prefix, - # lib_type, kwargs.get("options", None)) return _cc.cross_compiler(compile_func, output_format='obj') -def create_micro_lib( - obj_path, src_path, toolchain_prefix, lib_type, options=None): - """Compiles code into a binary for the target micro device. +def _get_micro_host_driven_dir(): + """Get directory path for uTVM host-driven runtime source files. - Parameters - ---------- - obj_path : Optional[str] - path to generated object file (defaults to same directory as `src_path`) + Return + ------ + micro_device_dir : str + directory path + """ + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", + "src", "runtime", "micro", "host_driven") + return micro_host_driven_dir - src_path : str - path to source file - toolchain_prefix : str - toolchain prefix to be used +def _get_micro_device_dir(): + """Get directory path for TODO - include_dev_lib_header : bool - whether to include the device library header containing definitions of - library functions. + Return + ------ + micro_device_dir : str + directory path """ - #import subprocess - import os - assert False - - #def run_cmd(cmd): - # proc = subprocess.Popen( - # cmd, - # stdout=subprocess.PIPE, - # stderr=subprocess.STDOUT) - # (out, _) = proc.communicate() - # if proc.returncode != 0: - # cmd_str = ' '.join(cmd) - # msg = f"error while running command \"{' '.join(cmd)}\":\n" - # msg += out.decode("utf-8") - # raise RuntimeError(msg) - - base_compile_cmd = [ - f'{toolchain_prefix}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - '-DSTM32F746xx' - ] - - if toolchain_prefix == 'arm-none-eabi-': - device_id = 'stm32f746' - base_compile_cmd += [ - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-mthumb', - '-gdwarf-5' - ] - elif toolchain_prefix == '': - device_id = 'host' - if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - base_compile_cmd += ['-mcmodel=large'] - else: - assert False - - src_paths = [] - include_paths = find_include_path() + [_get_micro_host_driven_dir()] - ld_script_path = None - tmp_dir = _util.tempdir() - if lib_type == LibType.RUNTIME: - import glob - dev_dir = _get_micro_device_dir() + '/' + device_id - - dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') - # there needs to at least be a utvm_timer.c file - assert dev_src_paths - - src_paths += dev_src_paths - # TODO: configure this - #include_paths += [dev_dir] - CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] - elif lib_type == LibType.OPERATOR: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - temp_src_path = tmp_dir.relpath('temp.c') - with open(src_path, 'r') as f: - src_lines = f.read().splitlines() - src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') - with open(temp_src_path, 'w') as f: - f.write('\n'.join(src_lines)) - src_path = temp_src_path - - base_compile_cmd += ['-c'] - else: - raise RuntimeError('unknown lib type') - - src_paths += [src_path] - - print(f'include paths: {include_paths}') - for path in include_paths: - base_compile_cmd += ['-I', path] - - prereq_obj_paths = [] - for src_path in src_paths: - curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) - i = 2 - while curr_obj_path in prereq_obj_paths: - curr_obj_path = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) - i += 1 - - prereq_obj_paths.append(curr_obj_path) - curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] - run_cmd(curr_compile_cmd) - - ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] - ld_cmd += prereq_obj_paths - ld_cmd += ['-o', obj_path] - run_cmd(ld_cmd) - print(f'compiled obj {obj_path}') - #input('check it') - - #if toolchain_prefix == '': - # create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) - #elif toolchain_prefix == 'arm-none-eabi-': - # create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) - - -def create_host_micro_lib( - obj_path, src_path, toolchain_prefix, lib_type, options): - # uTVM object files cannot have an ".o" suffix, because it triggers the - # code path for creating shared objects in `tvm.module.load`. So we replace - # ".o" suffixes with ".obj". - if obj_path.endswith(".o"): - logging.warning( - "\".o\" suffix in \"%s\" has been replaced with \".obj\"", obj_path) - obj_path = str(Path(obj_path).with_suffix("obj")) - - options = ["-I" + path for path in find_include_path()] - options += ["-I{}".format(_get_micro_host_driven_dir())] - options += ["-fno-stack-protector"] - # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host - # device. - if toolchain_prefix == "" and sys.maxsize > 2**32 and sys.platform.startswith("linux"): - # Only add this option if the host is a 64-bit Linux. - options += ["-mcmodel=large"] - compile_cmd = "{}gcc".format(toolchain_prefix) - - if lib_type == LibType.OPERATOR: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - tmp_dir = _util.tempdir() - temp_src_path = tmp_dir.relpath("temp.c") - with open(src_path, "r") as f: - src_lines = f.read().splitlines() - src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") - with open(temp_src_path, "w") as f: - f.write("\n".join(src_lines)) - src_path = temp_src_path - - _cc.create_shared(obj_path, src_path, options, compile_cmd) + micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) + micro_device_dir = os.path.join(micro_dir, "..", "..", "..", + "src", "runtime", "micro", "device") + return micro_device_dir + + +#def cross_compiler(dev_config, lib_type): +# """Creates a cross compile function that wraps `create_micro_lib`. +# +# For use in `tvm.module.Module.export_library`. +# +# Parameters +# ---------- +# toolchain_prefix : str +# toolchain prefix to be used +# +# include_dev_lib_header : Optional[bool] +# whether to include the device library header containing definitions of +# library functions. +# +# Return +# ------ +# func : Callable[[str, str, Optional[str]], None] +# cross compile function taking a destination path for the object file +# and a path for the input source file. +# +# Example +# -------- +# .. code-block:: python +# +# c_mod = ... # some module generated with "c" as the target +# fcompile = tvm.micro.cross_compiler(toolchain_prefix="") +# c_mod.export_library("dev_lib.obj", fcompile=fcompile) +# """ +# def compile_func(obj_path, src_path, **kwargs): +# if isinstance(obj_path, list): +# obj_path = obj_path[0] +# if isinstance(src_path, list): +# src_path = src_path[0] +# dev_config['binutil'].create_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) +# #create_micro_lib(obj_path, src_path, toolchain_prefix, +# # lib_type, kwargs.get("options", None)) +# return _cc.cross_compiler(compile_func, output_format='obj') + + +#def create_micro_lib( +# obj_path, src_path, toolchain_prefix, lib_type, options=None): +# """Compiles code into a binary for the target micro device. +# +# Parameters +# ---------- +# obj_path : Optional[str] +# path to generated object file (defaults to same directory as `src_path`) +# +# src_path : str +# path to source file +# +# toolchain_prefix : str +# toolchain prefix to be used +# +# include_dev_lib_header : bool +# whether to include the device library header containing definitions of +# library functions. +# """ +# #import subprocess +# import os +# assert False +# +# #def run_cmd(cmd): +# # proc = subprocess.Popen( +# # cmd, +# # stdout=subprocess.PIPE, +# # stderr=subprocess.STDOUT) +# # (out, _) = proc.communicate() +# # if proc.returncode != 0: +# # cmd_str = ' '.join(cmd) +# # msg = f"error while running command \"{' '.join(cmd)}\":\n" +# # msg += out.decode("utf-8") +# # raise RuntimeError(msg) +# +# base_compile_cmd = [ +# f'{toolchain_prefix}gcc', +# '-std=c11', +# '-Wall', +# '-Wextra', +# '--pedantic', +# '-c', +# '-O0', +# '-g', +# '-nostartfiles', +# '-nodefaultlibs', +# '-nostdlib', +# '-fdata-sections', +# '-ffunction-sections', +# '-DSTM32F746xx' +# ] +# +# if toolchain_prefix == 'arm-none-eabi-': +# device_id = 'stm32f746' +# base_compile_cmd += [ +# '-mcpu=cortex-m7', +# '-mlittle-endian', +# '-mfloat-abi=hard', +# '-mfpu=fpv5-sp-d16', +# '-mthumb', +# '-gdwarf-5' +# ] +# elif toolchain_prefix == '': +# device_id = 'host' +# if sys.maxsize > 2**32 and sys.platform.startswith('linux'): +# base_compile_cmd += ['-mcmodel=large'] +# else: +# assert False +# +# src_paths = [] +# include_paths = find_include_path() + [_get_micro_host_driven_dir()] +# ld_script_path = None +# tmp_dir = _util.tempdir() +# if lib_type == LibType.RUNTIME: +# import glob +# dev_dir = _get_micro_device_dir() + '/' + device_id +# +# dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') +# # there needs to at least be a utvm_timer.c file +# assert dev_src_paths +# +# src_paths += dev_src_paths +# # TODO: configure this +# #include_paths += [dev_dir] +# CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' +# include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] +# include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] +# include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] +# include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] +# include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] +# elif lib_type == LibType.OPERATOR: +# # Create a temporary copy of the source, so we can inject the dev lib +# # header without modifying the original. +# temp_src_path = tmp_dir.relpath('temp.c') +# with open(src_path, 'r') as f: +# src_lines = f.read().splitlines() +# src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') +# with open(temp_src_path, 'w') as f: +# f.write('\n'.join(src_lines)) +# src_path = temp_src_path +# +# base_compile_cmd += ['-c'] +# else: +# raise RuntimeError('unknown lib type') +# +# src_paths += [src_path] +# +# print(f'include paths: {include_paths}') +# for path in include_paths: +# base_compile_cmd += ['-I', path] +# +# prereq_obj_paths = [] +# for src_path in src_paths: +# curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) +# i = 2 +# while curr_obj_path in prereq_obj_paths: +# curr_obj_path = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) +# i += 1 +# +# prereq_obj_paths.append(curr_obj_path) +# curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] +# run_cmd(curr_compile_cmd) +# +# ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] +# ld_cmd += prereq_obj_paths +# ld_cmd += ['-o', obj_path] +# run_cmd(ld_cmd) +# print(f'compiled obj {obj_path}') +# #input('check it') +# +# #if toolchain_prefix == '': +# # create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) +# #elif toolchain_prefix == 'arm-none-eabi-': +# # create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) +# +# +#def create_host_micro_lib( +# obj_path, src_path, toolchain_prefix, lib_type, options): +# # uTVM object files cannot have an ".o" suffix, because it triggers the +# # code path for creating shared objects in `tvm.module.load`. So we replace +# # ".o" suffixes with ".obj". +# if obj_path.endswith(".o"): +# logging.warning( +# "\".o\" suffix in \"%s\" has been replaced with \".obj\"", obj_path) +# obj_path = str(Path(obj_path).with_suffix("obj")) +# +# options = ["-I" + path for path in find_include_path()] +# options += ["-I{}".format(_get_micro_host_driven_dir())] +# options += ["-fno-stack-protector"] +# # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host +# # device. +# if toolchain_prefix == "" and sys.maxsize > 2**32 and sys.platform.startswith("linux"): +# # Only add this option if the host is a 64-bit Linux. +# options += ["-mcmodel=large"] +# compile_cmd = "{}gcc".format(toolchain_prefix) +# +# if lib_type == LibType.OPERATOR: +# # Create a temporary copy of the source, so we can inject the dev lib +# # header without modifying the original. +# tmp_dir = _util.tempdir() +# temp_src_path = tmp_dir.relpath("temp.c") +# with open(src_path, "r") as f: +# src_lines = f.read().splitlines() +# src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") +# with open(temp_src_path, "w") as f: +# f.write("\n".join(src_lines)) +# src_path = temp_src_path +# +# _cc.create_shared(obj_path, src_path, options, compile_cmd) #def create_arm_micro_lib( diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index d6e5dce96430..c8340151dafd 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -144,21 +144,33 @@ def toolchain_prefix(self): return self._toolchain_prefix -class OpenOcdComm: - def __init__(self, server_addr, server_port): - self.server_addr = server_addr - self.server_port = server_port +#class OpenOcdComm: +# def __init__(self, server_addr, server_port): +# self.server_addr = server_addr +# self.server_port = server_port +# +# def name(self): +# return 'openocd' +# +# +#class HostComm: +# def __init__(self): +# pass +# +# def name(self): +# return 'host' - def name(self): - return 'openocd' - - -class HostComm: - def __init__(self): - pass +from . import host +from . import arm +from . import riscv_spike - def name(self): - return 'host' +def get_binutil(name): + if name == 'host': + return host.HostBinutil() + elif name == 'arm': + return arm.ArmBinutil() + else: + assert False def _get_micro_host_driven_dir(): @@ -189,6 +201,3 @@ def _get_micro_device_dir(): return micro_device_dir -from . import host -from . import riscv_spike -from . import stm32f746xx diff --git a/python/tvm/micro/device/stm32f746xx.py b/python/tvm/micro/device/arm.py similarity index 88% rename from python/tvm/micro/device/stm32f746xx.py rename to python/tvm/micro/device/arm.py index 743e8ee2295c..52e170a5a7be 100644 --- a/python/tvm/micro/device/stm32f746xx.py +++ b/python/tvm/micro/device/arm.py @@ -1,4 +1,4 @@ -from . import MicroBinutil, OpenOcdComm +from . import MicroBinutil class ArmBinutil(MicroBinutil): def __init__(self): @@ -22,9 +22,9 @@ def device_id(self): return 'stm32f746xx' -def get_config(server_addr, server_port): +def default_config(server_addr, server_port): return { - 'binutil': ArmBinutil(), + 'binutil': 'arm', 'mem_layout': { 'text': { 'start': 0x20000180, @@ -61,5 +61,7 @@ def get_config(server_addr, server_port): }, 'word_size': 4, 'thumb_mode': True, - 'comms_method': OpenOcdComm(server_addr, server_port), + 'comms_method': 'openocd', + 'server_addr': server_addr, + 'server_port': server_port, } diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 3cc9603709c1..6bcc1760b6f8 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -1,6 +1,6 @@ import sys -from . import MicroBinutil, HostComm +from . import MicroBinutil class HostBinutil(MicroBinutil): def __init__(self): @@ -17,9 +17,9 @@ def device_id(self): return 'host' -def get_config(): +def default_config(): return { - 'binutil': HostBinutil(), + 'binutil': 'host', 'mem_layout': { 'text': { 'size': 20480, @@ -48,5 +48,5 @@ def get_config(): }, 'word_size': 8 if sys.maxsize > 2**32 else 4, 'thumb_mode': False, - 'comms_method': HostComm(), + 'comms_method': 'host', } diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index de881ba32079..9db82cec3ea9 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -7,20 +7,6 @@ from tvm import rpc from tvm import micro -DEV_BINUTIL = micro.binutil.ArmBinutil() -DEV_COMMUNICATOR = micro.OpenOcdComm('127.0.0.1', 6666) - -@tvm.register_func("tvm.rpc.server.start", override=True) -def server_start(): - session = micro.Session(DEV_BINUTIL, DEV_COMMUNICATOR) - session._enter() - _load_module = tvm.get_global_func("tvm.rpc.server.load_module") - - @tvm.register_func("tvm.rpc.server.shutdown", override=True) - def server_shutdown(): - session._exit() - - def main(): """Main function""" parser = argparse.ArgumentParser() @@ -34,6 +20,8 @@ def main(): help="RPC key used to identify the connection type.") parser.add_argument('--tracker', type=str, default="", help="Report to RPC tracker") + parser.add_argument('--dev-config', type=str, + help="JSON config file for the target device") args = parser.parse_args() logging.basicConfig(level=logging.INFO) @@ -47,6 +35,20 @@ def main(): else: tracker_addr = None + #with open(args.dev_config, 'r') as dev_conf_file: + # dev_config = json.read(dev_conf_file) + dev_config = micro.device.arm.default_config('127.0.0.1', 6666) + + @tvm.register_func("tvm.rpc.server.start", override=True) + def server_start(): + session = micro.Session(dev_config) + session._enter() + #_load_module = tvm.get_global_func("tvm.rpc.server.load_module") + + @tvm.register_func("tvm.rpc.server.shutdown", override=True) + def server_shutdown(): + session._exit() + server = rpc.Server(args.host, args.port, args.port_end, diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 031bb2399f4e..1e0f0d5484dc 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -211,22 +211,6 @@ MicroSession::MicroSession( std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; - std::uintptr_t workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); - std::cout << " workspace begin: " << (void*) workspace_begin << std::endl; - std::uintptr_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); - std::cout << " workspace end: " << (void*) workspace_end << std::endl; - std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); - std::cout << " workspace curr: " << (void*) workspace_curr << std::endl; - size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); - std::cout << " num active allocs: " << (void*) num_active_allocs << std::endl; - std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); - std::cout << " last error: " << (void*) last_error << std::endl; - int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); - std::cout << " return code: " << return_code << std::endl; - uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); - std::cout << " task time was " << task_time << std::endl; - std::cout << " --------------------------------------------------------------------------------" << std::endl; - //if (comms_method == "openocd") { // // Set OpenOCD device's stack pointer. // auto stack_section = GetAllocator(SectionKind::kStack); @@ -290,12 +274,6 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { encoder.buf_size()); std::cout << " after encoder write" << std::endl; - //UTVMTask task = { - // .func = func_dev_addr, - // .arg_values = std::get<0>(arg_field_addrs).cast_to(), - // .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), - // .num_args = args.num_args, - //}; if (word_size_ == 4) { TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); @@ -308,30 +286,14 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else if (word_size_ == 8) { - //typedef struct StructUTVMTask64 { - // /*! \brief Pointer to function to call for this task */ - // uint64_t func; - // /*! \brief Array of argument values */ - // uint64_t arg_values; - // /*! \brief Array of type codes for each argument value */ - // uint64_t arg_type_codes; - // /*! \brief Number of arguments */ - // int32_t num_args; - //} UTVMTask64; - UTVMTask task = { - .func = func_dev_addr, - .arg_values = std::get<0>(arg_field_addrs).cast_to(), - .arg_type_codes = std::get<1>(arg_field_addrs).cast_to(), + TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); + int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); + UTVMTask64 task = { + .func = *((uint64_t*) &func_dev_addr), + .arg_values = *((uint64_t*) &arg_values_dev_addr), + .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), .num_args = args.num_args, }; - //TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - //int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); - //UTVMTask64 task = { - // .func = *((uint64_t*) &func_dev_addr), - // .arg_values = *((uint64_t*) &arg_values_dev_addr), - // .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), - // .num_args = args.num_args, - //}; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else { @@ -353,7 +315,12 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { //std::cout << " do execution things: "; //char tmp; //std::cin >> tmp; - //DevSymbolWrite(runtime_symbol_map_, "utvm_task_time", 0); + + low_level_device()->Execute(utvm_init_loc, utvm_done_loc); + + // Check if there was an error during execution. If so, log it. + CheckDeviceError(); + std::uintptr_t workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); std::cout << " workspace begin: " << workspace_begin << std::endl; std::uintptr_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); @@ -370,26 +337,6 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " task time was " << task_time << std::endl; std::cout << " --------------------------------------------------------------------------------" << std::endl; - low_level_device()->Execute(utvm_init_loc, utvm_done_loc); - - // Check if there was an error during execution. If so, log it. - //CheckDeviceError(); - - workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); - std::cout << " workspace begin: " << workspace_begin << std::endl; - workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); - std::cout << " workspace end: " << workspace_end << std::endl; - workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); - std::cout << " workspace curr: " << workspace_curr << std::endl; - num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); - std::cout << " num active allocs: " << num_active_allocs << std::endl; - last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); - std::cout << " last error: " << last_error << std::endl; - return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); - std::cout << " return code: " << return_code << std::endl; - task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); - std::cout << " task time was " << task_time << std::endl; - GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); return task_time; } diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index d31ebc29b41b..817b3ad5f392 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -277,6 +277,7 @@ struct MicroDevSpace { typedef struct StructTVMArray32 { uint32_t data; DLContext ctx; + // todo make int32? int ndim; DLDataType dtype; uint32_t shape; @@ -298,6 +299,18 @@ typedef struct StructUTVMTask32 { int32_t num_args; } UTVMTask32; +// utvm task for serialization to 64-bit devices +typedef struct StructUTVMTask64 { + /*! \brief Pointer to function to call for this task */ + uint64_t func; + /*! \brief Array of argument values */ + uint64_t arg_values; + /*! \brief Array of type codes for each argument value */ + uint64_t arg_type_codes; + /*! \brief Number of arguments */ + int32_t num_args; +} UTVMTask64; + } // namespace runtime } // namespace tvm #endif // TVM_RUNTIME_MICRO_MICRO_SESSION_H_ diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 24d0f3b64deb..005e2818b2d1 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,36 +25,36 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -DEV_CONFIG = micro.device.host.get_config() -#DEV_CONFIG = micro.device.stm32f746xx.get_config('127.0.0.1', 6666) +DEV_CONFIG = micro.device.host.default_config() +#DEV_CONFIG = micro.device.stm32f746xx.default_config('127.0.0.1', 6666) -def create_micro_mod(c_mod, dev_config): - """Produces a micro module from a given module. - - Parameters - ---------- - c_mod : tvm.module.Module - module with "c" as its target backend - - toolchain_prefix : str - toolchain prefix to be used (see `tvm.micro.Session` docs) - - Return - ------ - micro_mod : tvm.module.Module - micro module for the target device - """ - print('[create_micro_mod]') - temp_dir = util.tempdir() - lib_obj_path = temp_dir.relpath("dev_lib.obj") - c_mod.export_library( - lib_obj_path, - fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) - micro_mod = tvm.module.load(lib_obj_path) - return micro_mod - - -def relay_micro_build(func, dev_binutil, params=None): +#def create_micro_mod(c_mod, dev_config): +# """Produces a micro module from a given module. +# +# Parameters +# ---------- +# c_mod : tvm.module.Module +# module with "c" as its target backend +# +# toolchain_prefix : str +# toolchain prefix to be used (see `tvm.micro.Session` docs) +# +# Return +# ------ +# micro_mod : tvm.module.Module +# micro module for the target device +# """ +# print('[create_micro_mod]') +# temp_dir = util.tempdir() +# lib_obj_path = temp_dir.relpath("dev_lib.obj") +# c_mod.export_library( +# lib_obj_path, +# fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) +# micro_mod = tvm.module.load(lib_obj_path) +# return micro_mod + + +def relay_micro_build(func, sess, params=None): """Create a graph runtime module with a micro device context from a Relay function. Parameters @@ -72,7 +72,7 @@ def relay_micro_build(func, dev_binutil, params=None): """ with tvm.build_config(disable_vectorize=True): graph, c_mod, params = relay.build(func, target="c", params=params) - micro_mod = create_micro_mod(c_mod, dev_binutil) + micro_mod = sess.create_micro_mod(c_mod) ctx = tvm.micro_dev(0) mod = graph_runtime.create(graph, micro_mod, ctx) mod.set_input(**params) @@ -121,11 +121,7 @@ def test_add(): if not tvm.module.enabled("micro_dev"): return shape = (1024,) - #dtype = "float32" - dtype = "int32" - - # int32: 47049, 46780, 46780, 46780, 46780, 46780, 46780, 46780, 46780, 46780 - # float32: 46803 46780 46780 46780 46780 46780 46780 46780 46780 46780 + dtype = "float32" reset_gdbinit() @@ -139,30 +135,23 @@ def test_add(): func_name = "fadd" c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) - with micro.Session(DEV_CONFIG): - micro_mod = create_micro_mod(c_mod, DEV_CONFIG) + with micro.Session(DEV_CONFIG) as sess: + micro_mod = sess.create_micro_mod(c_mod) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) - a = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) - b = tvm.nd.array(np.random.randint(1, 10000, size=shape).astype(dtype), ctx) - #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) + b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) print(a) print(b) print(c) micro_func(a, b, c) print(c) - - #a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - #c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - #micro_func(a, b, c) tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + b.asnumpy()) -def test_float_workspace_add(): +def test_workspace_add(): """Test a module which uses a workspace to compute an intermediate value.""" if not tvm.module.enabled("micro_dev"): return @@ -182,8 +171,8 @@ def test_float_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEV_CONFIG): - micro_mod = create_micro_mod(c_mod, DEV_CONFIG) + with micro.Session(DEV_CONFIG) as sess: + micro_mod = sess.create_micro_mod(c_mod) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -210,8 +199,8 @@ def test_graph_runtime(): z = relay.add(xx, relay.const(1.0)) func = relay.Function([x], z) - with micro.Session(DEV_CONFIG): - mod = relay_micro_build(func, DEV_CONFIG) + with micro.Session(DEV_CONFIG) as sess: + mod = relay_micro_build(func, sess) x_in = np.random.uniform(size=shape[0]).astype(dtype) print(x_in) @@ -254,8 +243,8 @@ def test_conv2d(): with tvm.build_config(disable_vectorize=True): graph, c_mod, params = relay.build(mod, target="c") - with micro.Session(DEV_CONFIG): - micro_mod = create_micro_mod(c_mod, DEV_CONFIG) + with micro.Session(DEV_CONFIG) as sess: + micro_mod = sess.create_micro_mod(c_mod) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) @@ -288,9 +277,9 @@ def test_multiple_modules(): ret = relay.subtract(x, relay.const(1.0)) sub_const_func = relay.Function([x], ret) - with micro.Session(DEV_CONFIG): - add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) - sub_const_mod = relay_micro_build(sub_const_func, DEV_CONFIG) + with micro.Session(DEV_CONFIG) as sess: + add_const_mod = relay_micro_build(add_const_func, sess) + sub_const_mod = relay_micro_build(sub_const_func, sess) x_in = np.random.uniform(size=shape[0]).astype(dtype) add_const_mod.run(x=x_in) @@ -325,13 +314,13 @@ def test_interleave_sessions(): np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) with sess_a: - add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + add_const_mod = relay_micro_build(add_const_func, sess_a) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( add_result, np_tensor_a + 1.0) with sess_b: - add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + add_const_mod = relay_micro_build(add_const_func, sess_b) add_const_mod.run(x=micro_tensor_b) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -358,7 +347,7 @@ def test_nested_sessions(): with sess_b: np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + add_const_mod = relay_micro_build(add_const_func, sess_a) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -382,7 +371,7 @@ def test_inactive_session_use(): with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + add_const_mod = relay_micro_build(add_const_func, sess_a) with sess_b: # These objects belong to `sess_a`. @@ -399,6 +388,6 @@ def test_inactive_session_use(): test_graph_runtime() test_conv2d() test_multiple_modules() - #test_interleave_sessions() - #test_nested_sessions() - #test_inactive_session_use() + test_interleave_sessions() + test_nested_sessions() + test_inactive_session_use() From face9cef3a3e05ff0c7602d6392652bc83a870b1 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 13:50:08 -0800 Subject: [PATCH 32/70] More cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 36 +- python/tvm/contrib/binutil.py | 2 - python/tvm/micro/base.py | 343 +------------- python/tvm/micro/binutil/__init__.py | 233 ---------- python/tvm/micro/binutil/host.py | 0 python/tvm/micro/binutil/riscv_spike.py | 0 python/tvm/micro/binutil/stm32f746xx.py | 0 python/tvm/micro/device/__init__.py | 51 +-- python/tvm/micro/device/arm/__init__.py | 1 + .../device/{arm.py => arm/stm32f746xx.py} | 11 +- .../device/stm32f746xx/stm32f7xx_hal_conf.h | 425 ------------------ .../device/stm32f746xx/system_stm32f7xx.h | 123 ----- .../micro/device/stm32f746xx/utvm_api.c | 1 - .../micro/device/stm32f746xx/utvm_init.c | 6 +- .../micro/device/stm32f746xx/utvm_init.c.bad | 278 ------------ .../micro/device/stm32f746xx/utvm_init.s | 2 - tests/python/unittest/test_runtime_micro.py | 10 +- 17 files changed, 45 insertions(+), 1477 deletions(-) delete mode 100644 python/tvm/micro/binutil/__init__.py delete mode 100644 python/tvm/micro/binutil/host.py delete mode 100644 python/tvm/micro/binutil/riscv_spike.py delete mode 100644 python/tvm/micro/binutil/stm32f746xx.py create mode 100644 python/tvm/micro/device/arm/__init__.py rename python/tvm/micro/device/{arm.py => arm/stm32f746xx.py} (85%) delete mode 100644 src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h delete mode 100644 src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h delete mode 100644 src/runtime/micro/device/stm32f746xx/utvm_init.c.bad diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index e8d94c3de12f..0b2efb6de760 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -34,13 +34,14 @@ # first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal # then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another -DEV_CONFIG = micro.device.arm.default_config('127.0.0.1', 6666) +DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') N, L, M = 32, 32, 32 -N_TRIAL = 3 +DTYPE = 'float32' +N_TRIAL = 2 N_PER_TRIAL = 1 N_PARALLEL = 1 @@ -51,32 +52,6 @@ if os.path.exists(LOG_FILE_NAME): os.remove(LOG_FILE_NAME) -#def create_micro_mod(c_mod, dev_config): -# """Produces a micro module from a given module. -# -# Parameters -# ---------- -# c_mod : tvm.module.Module -# module with "c" as its target backend -# -# toolchain_prefix : str -# toolchain prefix to be used (see `tvm.micro.Session` docs) -# -# Return -# ------ -# micro_mod : tvm.module.Module -# micro module for the target device -# """ -# print('[create_micro_mod]') -# temp_dir = util.tempdir() -# lib_obj_path = temp_dir.relpath("dev_lib.obj") -# c_mod.export_library( -# lib_obj_path, -# fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) -# micro_mod = tvm.module.load(lib_obj_path) -# return micro_mod - - @autotvm.template def matmul(N, L, M, dtype): A = tvm.placeholder((N, L), name='A', dtype=dtype) @@ -106,7 +81,7 @@ def matmul(N, L, M, dtype): def tune(): print('[TUNE]') - task = autotvm.task.create(matmul, args=(N, L, M, 'float32'), target=TARGET) + task = autotvm.task.create(matmul, args=(N, L, M, DTYPE), target=TARGET) early_stopping = None measure_option = autotvm.measure_option( @@ -141,7 +116,7 @@ def evaluate(): #with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): with autotvm.apply_history_best(LOG_FILE_NAME): with TARGET: - sched, arg_bufs = matmul(N, L, M, 'float32') + sched, arg_bufs = matmul(N, L, M, DTYPE) c_mod = tvm.build(sched, arg_bufs, name='matmul') with micro.Session(DEV_CONFIG) as sess: @@ -163,5 +138,4 @@ def evaluate(): if __name__ == '__main__': tune() - input('finished tuning...') evaluate() diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index c4eb509dd6fa..b5132cda1cb7 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -177,8 +177,6 @@ def tvm_callback_relocate_binary( . = ALIGN(?); .text : { - _stext = .; - /*KEEP(*(.isr_vector))*/ KEEP(*(.text)) KEEP(*(.text*)) . = ALIGN(?); diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 82c5dd2e3e81..0c455c3fc56c 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -59,16 +59,17 @@ class Session: c_mod = ... # some module generated with "c" as the target dev_config = micro.device.stm32f746xx.default_config('127.0.0.1', 6666) with tvm.micro.Session(dev_config): - c_mod.export_library(lib_obj_path, fcompile=tvm.micro.cross_compiler(dev_config)) + c_mod.export_library( + lib_obj_path, + fcompile=tvm.micro.cross_compiler(dev_config['binutil'], + tvm.micro.LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path, 'micro_dev') """ - # TODO(weberlo): remove required trailing dash in toolchain_prefix def __init__(self, config): self._check_system() - #self._check_args(device_type, kwargs) + self._check_config(config) - #self.binutil = config['binutil'] self.binutil = tvm.micro.device.get_binutil(config['binutil']) self.mem_layout = config['mem_layout'] self.word_size = config['word_size'] @@ -119,8 +120,8 @@ def __init__(self, config): base_addr, server_addr, server_port) - self._enter = self.module["enter"] - self._exit = self.module["exit"] + self._enter = self.module['enter'] + self._exit = self.module['exit'] def create_micro_mod(self, c_mod): """Produces a micro module from a given module. @@ -149,21 +150,21 @@ def _check_system(self): Raises error if not supported. """ - if not sys.platform.startswith("linux"): - raise RuntimeError("MicroTVM is currently only supported on Linux") + if not sys.platform.startswith('linux'): + raise RuntimeError('MicroTVM is currently only supported on Linux') # TODO(weberlo): Add 32-bit support. # It's primarily the compilation pipeline that isn't compatible. if sys.maxsize <= 2**32: - raise RuntimeError("MicroTVM is currently only supported on 64-bit platforms") + raise RuntimeError('MicroTVM is currently only supported on 64-bit platforms') - def _check_args(self, device_type, args): + def _check_config(self, config): """Check if the given configuration is valid.""" - if device_type == "host": - pass - elif device_type == "openocd": - assert "base_addr" in args - assert "server_addr" in args - assert "port" in args + #if device_type == "host": + # pass + #elif device_type == "openocd": + # assert "base_addr" in args + # assert "server_addr" in args + # assert "port" in args def __enter__(self): self._enter() @@ -217,8 +218,8 @@ def _get_micro_host_driven_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "host_driven") + micro_host_driven_dir = os.path.join(micro_dir, '..', '..', '..', + 'src', 'runtime', 'micro', 'host_driven') return micro_host_driven_dir @@ -231,309 +232,9 @@ def _get_micro_device_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, "..", "..", "..", - "src", "runtime", "micro", "device") + micro_device_dir = os.path.join(micro_dir, '..', '..', '..', + 'src', 'runtime', 'micro', 'device') return micro_device_dir -#def cross_compiler(dev_config, lib_type): -# """Creates a cross compile function that wraps `create_micro_lib`. -# -# For use in `tvm.module.Module.export_library`. -# -# Parameters -# ---------- -# toolchain_prefix : str -# toolchain prefix to be used -# -# include_dev_lib_header : Optional[bool] -# whether to include the device library header containing definitions of -# library functions. -# -# Return -# ------ -# func : Callable[[str, str, Optional[str]], None] -# cross compile function taking a destination path for the object file -# and a path for the input source file. -# -# Example -# -------- -# .. code-block:: python -# -# c_mod = ... # some module generated with "c" as the target -# fcompile = tvm.micro.cross_compiler(toolchain_prefix="") -# c_mod.export_library("dev_lib.obj", fcompile=fcompile) -# """ -# def compile_func(obj_path, src_path, **kwargs): -# if isinstance(obj_path, list): -# obj_path = obj_path[0] -# if isinstance(src_path, list): -# src_path = src_path[0] -# dev_config['binutil'].create_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) -# #create_micro_lib(obj_path, src_path, toolchain_prefix, -# # lib_type, kwargs.get("options", None)) -# return _cc.cross_compiler(compile_func, output_format='obj') - - -#def create_micro_lib( -# obj_path, src_path, toolchain_prefix, lib_type, options=None): -# """Compiles code into a binary for the target micro device. -# -# Parameters -# ---------- -# obj_path : Optional[str] -# path to generated object file (defaults to same directory as `src_path`) -# -# src_path : str -# path to source file -# -# toolchain_prefix : str -# toolchain prefix to be used -# -# include_dev_lib_header : bool -# whether to include the device library header containing definitions of -# library functions. -# """ -# #import subprocess -# import os -# assert False -# -# #def run_cmd(cmd): -# # proc = subprocess.Popen( -# # cmd, -# # stdout=subprocess.PIPE, -# # stderr=subprocess.STDOUT) -# # (out, _) = proc.communicate() -# # if proc.returncode != 0: -# # cmd_str = ' '.join(cmd) -# # msg = f"error while running command \"{' '.join(cmd)}\":\n" -# # msg += out.decode("utf-8") -# # raise RuntimeError(msg) -# -# base_compile_cmd = [ -# f'{toolchain_prefix}gcc', -# '-std=c11', -# '-Wall', -# '-Wextra', -# '--pedantic', -# '-c', -# '-O0', -# '-g', -# '-nostartfiles', -# '-nodefaultlibs', -# '-nostdlib', -# '-fdata-sections', -# '-ffunction-sections', -# '-DSTM32F746xx' -# ] -# -# if toolchain_prefix == 'arm-none-eabi-': -# device_id = 'stm32f746' -# base_compile_cmd += [ -# '-mcpu=cortex-m7', -# '-mlittle-endian', -# '-mfloat-abi=hard', -# '-mfpu=fpv5-sp-d16', -# '-mthumb', -# '-gdwarf-5' -# ] -# elif toolchain_prefix == '': -# device_id = 'host' -# if sys.maxsize > 2**32 and sys.platform.startswith('linux'): -# base_compile_cmd += ['-mcmodel=large'] -# else: -# assert False -# -# src_paths = [] -# include_paths = find_include_path() + [_get_micro_host_driven_dir()] -# ld_script_path = None -# tmp_dir = _util.tempdir() -# if lib_type == LibType.RUNTIME: -# import glob -# dev_dir = _get_micro_device_dir() + '/' + device_id -# -# dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') -# # there needs to at least be a utvm_timer.c file -# assert dev_src_paths -# -# src_paths += dev_src_paths -# # TODO: configure this -# #include_paths += [dev_dir] -# CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' -# include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] -# include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] -# include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] -# include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] -# include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] -# elif lib_type == LibType.OPERATOR: -# # Create a temporary copy of the source, so we can inject the dev lib -# # header without modifying the original. -# temp_src_path = tmp_dir.relpath('temp.c') -# with open(src_path, 'r') as f: -# src_lines = f.read().splitlines() -# src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') -# with open(temp_src_path, 'w') as f: -# f.write('\n'.join(src_lines)) -# src_path = temp_src_path -# -# base_compile_cmd += ['-c'] -# else: -# raise RuntimeError('unknown lib type') -# -# src_paths += [src_path] -# -# print(f'include paths: {include_paths}') -# for path in include_paths: -# base_compile_cmd += ['-I', path] -# -# prereq_obj_paths = [] -# for src_path in src_paths: -# curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) -# i = 2 -# while curr_obj_path in prereq_obj_paths: -# curr_obj_path = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) -# i += 1 -# -# prereq_obj_paths.append(curr_obj_path) -# curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] -# run_cmd(curr_compile_cmd) -# -# ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] -# ld_cmd += prereq_obj_paths -# ld_cmd += ['-o', obj_path] -# run_cmd(ld_cmd) -# print(f'compiled obj {obj_path}') -# #input('check it') -# -# #if toolchain_prefix == '': -# # create_host_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) -# #elif toolchain_prefix == 'arm-none-eabi-': -# # create_arm_micro_lib(obj_path, src_path, toolchain_prefix, lib_type, options) -# -# -#def create_host_micro_lib( -# obj_path, src_path, toolchain_prefix, lib_type, options): -# # uTVM object files cannot have an ".o" suffix, because it triggers the -# # code path for creating shared objects in `tvm.module.load`. So we replace -# # ".o" suffixes with ".obj". -# if obj_path.endswith(".o"): -# logging.warning( -# "\".o\" suffix in \"%s\" has been replaced with \".obj\"", obj_path) -# obj_path = str(Path(obj_path).with_suffix("obj")) -# -# options = ["-I" + path for path in find_include_path()] -# options += ["-I{}".format(_get_micro_host_driven_dir())] -# options += ["-fno-stack-protector"] -# # TODO(weberlo): Don't rely on the toolchain prefix to identify if this is the host -# # device. -# if toolchain_prefix == "" and sys.maxsize > 2**32 and sys.platform.startswith("linux"): -# # Only add this option if the host is a 64-bit Linux. -# options += ["-mcmodel=large"] -# compile_cmd = "{}gcc".format(toolchain_prefix) -# -# if lib_type == LibType.OPERATOR: -# # Create a temporary copy of the source, so we can inject the dev lib -# # header without modifying the original. -# tmp_dir = _util.tempdir() -# temp_src_path = tmp_dir.relpath("temp.c") -# with open(src_path, "r") as f: -# src_lines = f.read().splitlines() -# src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") -# with open(temp_src_path, "w") as f: -# f.write("\n".join(src_lines)) -# src_path = temp_src_path -# -# _cc.create_shared(obj_path, src_path, options, compile_cmd) - - -#def create_arm_micro_lib( -# obj_path, src_path, toolchain_prefix, lib_type, options): -# import subprocess -# import os -# import copy -# from shutil import copyfile -# -# from tvm._ffi.libinfo import find_include_path -# from tvm.contrib import binutil -# -# def run_cmd(cmd): -# proc = subprocess.Popen( -# cmd, -# stdout=subprocess.PIPE, -# stderr=subprocess.STDOUT) -# (out, _) = proc.communicate() -# if proc.returncode != 0: -# msg = "Compilation error:\n" -# msg += out.decode("utf-8") -# raise RuntimeError(msg) -# -# base_compile_cmd = [ -# 'arm-none-eabi-gcc', -# '-std=c11', -# '-Wall', -# '-Wextra', -# '--pedantic', -# '-mcpu=cortex-m7', -# '-mlittle-endian', -# '-mfloat-abi=hard', -# '-mfpu=fpv5-sp-d16', -# '-mthumb', -# '-c', -# '-O0', -# '-g', -# '-gdwarf-5', -# '-nostartfiles', -# '-nodefaultlibs', -# '-nostdlib', -# '-fdata-sections', -# '-ffunction-sections'] -# -# src_paths = [] -# ld_script_path = None -# tmp_dir = _util.tempdir() -# if lib_type == LibType.RUNTIME: -# import glob -# DEVICE_ID = 'stm32f746' -# dev_dir = _get_micro_device_dir() + '/' + DEVICE_ID -# -# dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') -# assert dev_src_paths -# src_paths += dev_src_paths -# elif lib_type == LibType.OPERATOR: -# # Create a temporary copy of the source, so we can inject the dev lib -# # header without modifying the original. -# temp_src_path = tmp_dir.relpath("temp.c") -# with open(src_path, "r") as f: -# src_lines = f.read().splitlines() -# src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") -# with open(temp_src_path, "w") as f: -# f.write("\n".join(src_lines)) -# src_path = temp_src_path -# -# base_compile_cmd += ['-c'] -# else: -# raise RuntimeError('unknown lib type') -# -# src_paths += [src_path] -# -# include_paths = find_include_path() + [_get_micro_host_driven_dir()] -# for path in include_paths: -# base_compile_cmd += ['-I', path] -# -# prereq_obj_paths = [] -# for src_path in src_paths: -# curr_obj_path = tmp_dir.relpath(Path(src_path).with_suffix('o').name) -# prereq_obj_paths.append(curr_obj_path) -# curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] -# run_cmd(curr_compile_cmd) -# -# # TODO(weberlo): adding '-fPIC' here causes the pc-relative data pools to -# # not be updated when the obj is reloced. why? -# ld_cmd = ['arm-none-eabi-ld', '-relocatable'] -# ld_cmd += prereq_obj_paths -# ld_cmd += ['-o', obj_path] -# run_cmd(ld_cmd) -# print(f'compiled obj {obj_path}') - - -_init_api("tvm.micro", "tvm.micro.base") +_init_api('tvm.micro', 'tvm.micro.base') diff --git a/python/tvm/micro/binutil/__init__.py b/python/tvm/micro/binutil/__init__.py deleted file mode 100644 index 07384d28e0ec..000000000000 --- a/python/tvm/micro/binutil/__init__.py +++ /dev/null @@ -1,233 +0,0 @@ -import os -import sys -from enum import Enum -from pathlib import Path - -from tvm.contrib import util as _util -from tvm.contrib.binutil import run_cmd -from tvm._ffi.libinfo import find_include_path -from tvm.micro import LibType - -#from . import host -#from . import riscv_spike -#from . import stm32f746xx - -#class Device(Enum): -# HOST = 0 -# RISCV_SPIKE = 1 -# STM32F746XX = 2 - - -class MicroBinutil: - def __init__(self, toolchain_prefix): - print(f'creating microbinutil with {toolchain_prefix}') - self._toolchain_prefix = toolchain_prefix - - def create_lib(self, obj_path, src_path, lib_type, options=None): - """Compiles code into a binary for the target micro device. - - Parameters - ---------- - obj_path : Optional[str] - path to generated object file (defaults to same directory as `src_path`) - - src_path : str - path to source file - - toolchain_prefix : str - toolchain prefix to be used - - include_dev_lib_header : bool - whether to include the device library header containing definitions of - library functions. - """ - print('OPTIONS') - print(f'{obj_path}') - print(f'{src_path}') - print(f'{lib_type}') - print(f'{options}') - base_compile_cmd = [ - f'{self.toolchain_prefix()}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - ] - if options is not None: - base_compile_cmd += options - - #if toolchain_prefix == 'arm-none-eabi-': - # device_id = 'stm32f746' - # base_compile_cmd += [ - # '-mcpu=cortex-m7', - # '-mlittle-endian', - # '-mfloat-abi=hard', - # '-mfpu=fpv5-sp-d16', - # '-mthumb', - # '-gdwarf-5' - # ] - #elif toolchain_prefix == '': - # device_id = 'host' - # if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - # base_compile_cmd += ['-mcmodel=large'] - #else: - # assert False - - src_paths = [] - include_paths = find_include_path() + [_get_micro_host_driven_dir()] - ld_script_path = None - tmp_dir = _util.tempdir() - if lib_type == LibType.RUNTIME: - import glob - dev_dir = _get_micro_device_dir() + '/' + self.device_id() - - print(dev_dir) - dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') - print(dev_src_paths) - # there needs to at least be a utvm_timer.c file - assert dev_src_paths - - src_paths += dev_src_paths - # TODO: configure this - #include_paths += [dev_dir] - CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] - elif lib_type == LibType.OPERATOR: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - temp_src_path = tmp_dir.relpath('temp.c') - with open(src_path, 'r') as f: - src_lines = f.read().splitlines() - src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') - with open(temp_src_path, 'w') as f: - f.write('\n'.join(src_lines)) - src_path = temp_src_path - - base_compile_cmd += ['-c'] - else: - raise RuntimeError('unknown lib type') - - src_paths += [src_path] - - print(f'include paths: {include_paths}') - for path in include_paths: - base_compile_cmd += ['-I', path] - - prereq_obj_paths = [] - for src_path in src_paths: - curr_obj_path = self._get_unique_obj_name(src_path, prereq_obj_paths, tmp_dir) - prereq_obj_paths.append(curr_obj_path) - curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] - run_cmd(curr_compile_cmd) - - ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] - ld_cmd += prereq_obj_paths - ld_cmd += ['-o', obj_path] - run_cmd(ld_cmd) - print(f'compiled obj {obj_path}') - - def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): - res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) - i = 2 - # if the name collides, try increasing numeric suffixes until the name doesn't collide - while res in obj_paths: - res = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) - i += 1 - return res - - def device_id(self): - raise RuntimeError('no device ID for abstract MicroBinutil') - - def toolchain_prefix(self): - return self._toolchain_prefix - - -class HostBinutil(MicroBinutil): - def __init__(self): - super(HostBinutil, self).__init__('') - - def create_lib(self, obj_path, src_path, lib_type, options=None): - if options is None: - options = [] - if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - options += ['-mcmodel=large'] - super(HostBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) - - def device_id(self): - return 'host' - - -class ArmBinutil(MicroBinutil): - def __init__(self): - super(ArmBinutil, self).__init__('arm-none-eabi-') - - def create_lib(self, obj_path, src_path, lib_type, options=None): - if options is None: - options = [] - options += [ - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-mthumb', - '-gdwarf-5', - '-DSTM32F746xx' - ] - super(ArmBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) - - def device_id(self): - return 'stm32f746xx' - - -#def get_device_binutil(device): -# # TODO make all binutils singletons if they remain stateless -# if device_id == Device.HOST: -# return HostBinutil() -# elif device_id == Device.RISCV_SPIKE: -# return SpikeBinutil() -# elif device_id == Device.STM32F746XX: -# return ArmBinutil() -# else: -# raise RuntimeError(f'invalid device: {device}') - - -def _get_micro_host_driven_dir(): - """Get directory path for uTVM host-driven runtime source files. - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", "..", - "src", "runtime", "micro", "host_driven") - return micro_host_driven_dir - - -def _get_micro_device_dir(): - """Get directory path for TODO - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, "..", "..", "..", "..", - "src", "runtime", "micro", "device") - return micro_device_dir - - diff --git a/python/tvm/micro/binutil/host.py b/python/tvm/micro/binutil/host.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/python/tvm/micro/binutil/riscv_spike.py b/python/tvm/micro/binutil/riscv_spike.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/python/tvm/micro/binutil/stm32f746xx.py b/python/tvm/micro/binutil/stm32f746xx.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index c8340151dafd..d6b9268eda84 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -10,7 +10,6 @@ class MicroBinutil: def __init__(self, toolchain_prefix): - print(f'creating microbinutil with {toolchain_prefix}') self._toolchain_prefix = toolchain_prefix def create_lib(self, obj_path, src_path, lib_type, options=None): @@ -54,23 +53,6 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): if options is not None: base_compile_cmd += options - #if toolchain_prefix == 'arm-none-eabi-': - # device_id = 'stm32f746' - # base_compile_cmd += [ - # '-mcpu=cortex-m7', - # '-mlittle-endian', - # '-mfloat-abi=hard', - # '-mfpu=fpv5-sp-d16', - # '-mthumb', - # '-gdwarf-5' - # ] - #elif toolchain_prefix == '': - # device_id = 'host' - # if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - # base_compile_cmd += ['-mcmodel=large'] - #else: - # assert False - src_paths = [] include_paths = find_include_path() + [_get_micro_host_driven_dir()] ld_script_path = None @@ -86,14 +68,6 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): assert dev_src_paths src_paths += dev_src_paths - # TODO: configure this - #include_paths += [dev_dir] - CMSIS_PATH = '/home/pratyush/Code/nucleo-interaction-from-scratch/stm32-cube' - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/CMSIS/Device/ST/STM32F7xx/Include'] - include_paths += [f'{CMSIS_PATH}/Drivers/STM32F7xx_HAL_Driver/Inc'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32F7xx_Nucleo_144'] - include_paths += [f'{CMSIS_PATH}/Drivers/BSP/STM32746G-Discovery'] elif lib_type == LibType.OPERATOR: # Create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. @@ -144,22 +118,6 @@ def toolchain_prefix(self): return self._toolchain_prefix -#class OpenOcdComm: -# def __init__(self, server_addr, server_port): -# self.server_addr = server_addr -# self.server_port = server_port -# -# def name(self): -# return 'openocd' -# -# -#class HostComm: -# def __init__(self): -# pass -# -# def name(self): -# return 'host' - from . import host from . import arm from . import riscv_spike @@ -167,8 +125,8 @@ def toolchain_prefix(self): def get_binutil(name): if name == 'host': return host.HostBinutil() - elif name == 'arm': - return arm.ArmBinutil() + elif name == 'stm32f746xx': + return arm.stm32f746xx.Stm32F746XXBinutil() else: assert False @@ -182,8 +140,8 @@ def _get_micro_host_driven_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", "..", - "src", "runtime", "micro", "host_driven") + micro_host_driven_dir = os.path.join(micro_dir, '..', '..', '..', '..', + 'src', 'runtime', 'micro', 'host_driven') return micro_host_driven_dir @@ -200,4 +158,3 @@ def _get_micro_device_dir(): "src", "runtime", "micro", "device") return micro_device_dir - diff --git a/python/tvm/micro/device/arm/__init__.py b/python/tvm/micro/device/arm/__init__.py new file mode 100644 index 000000000000..c0f979b4c02a --- /dev/null +++ b/python/tvm/micro/device/arm/__init__.py @@ -0,0 +1 @@ +from . import stm32f746xx diff --git a/python/tvm/micro/device/arm.py b/python/tvm/micro/device/arm/stm32f746xx.py similarity index 85% rename from python/tvm/micro/device/arm.py rename to python/tvm/micro/device/arm/stm32f746xx.py index 52e170a5a7be..4e6ee237ca30 100644 --- a/python/tvm/micro/device/arm.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -1,8 +1,8 @@ -from . import MicroBinutil +from .. import MicroBinutil -class ArmBinutil(MicroBinutil): +class Stm32F746XXBinutil(MicroBinutil): def __init__(self): - super(ArmBinutil, self).__init__('arm-none-eabi-') + super(Stm32F746XXBinutil, self).__init__('arm-none-eabi-') def create_lib(self, obj_path, src_path, lib_type, options=None): if options is None: @@ -14,9 +14,8 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): '-mfpu=fpv5-sp-d16', '-mthumb', '-gdwarf-5', - '-DSTM32F746xx' ] - super(ArmBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) + super(Stm32F746XXBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) def device_id(self): return 'stm32f746xx' @@ -24,7 +23,7 @@ def device_id(self): def default_config(server_addr, server_port): return { - 'binutil': 'arm', + 'binutil': 'stm32f746xx', 'mem_layout': { 'text': { 'start': 0x20000180, diff --git a/src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h b/src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h deleted file mode 100644 index f40ee7173d06..000000000000 --- a/src/runtime/micro/device/stm32f746xx/stm32f7xx_hal_conf.h +++ /dev/null @@ -1,425 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f7xx_hal_conf.h - * @author MCD Application Team - * @version V1.0.1 - * @date 30-December-2016 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F7xx_HAL_CONF_H -#define __STM32F7xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -/* #define HAL_CAN_MODULE_ENABLED */ -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -/* #define HAL_RNG_MODULE_ENABLED */ -/* #define HAL_RTC_MODULE_ENABLED */ -/* #define HAL_SAI_MODULE_ENABLED */ -/* #define HAL_SD_MODULE_ENABLED */ -/* #define HAL_SPDIFRX_MODULE_ENABLED */ - #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_PCD_MODULE_ENABLED */ -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x0FU) /*!< tick interrupt priority */ -#define USE_RTOS 0U -#define PREFETCH_ENABLE 1U -#define ART_ACCLERATOR_ENABLE 1U /* To enable instruction cache and prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration for NUCLEO 144 board ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2U -#define MAC_ADDR1 0U -#define MAC_ADDR2 0U -#define MAC_ADDR3 0U -#define MAC_ADDR4 0U -#define MAC_ADDR5 0U - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x1F) /*!< PHY special control/ status register Offset */ - -#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< PHY Duplex mask */ - - -#define PHY_ISFR ((uint16_t)0x1D) /*!< PHY Interrupt Source Flag register Offset */ -#define PHY_ISFR_INT4 ((uint16_t)0x0010) /*!< PHY Link down inturrupt */ - -/* ################## SPI peripheral configuration ########################## */ - -/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver -* Activated: CRC code is present inside driver -* Deactivated: CRC code cleaned from driver -*/ - -#define USE_SPI_CRC 1U - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f7xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32f7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h b/src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h deleted file mode 100644 index 126ac71d7cfa..000000000000 --- a/src/runtime/micro/device/stm32f746xx/system_stm32f7xx.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32f7xx.h - * @author MCD Application Team - * @brief CMSIS Cortex-M7 Device System Source File for STM32F7xx devices. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f7xx_system - * @{ - */ - -/** - * @brief Define to prevent recursive inclusion - */ -#ifndef __SYSTEM_STM32F7XX_H -#define __SYSTEM_STM32F7XX_H - -#ifdef __cplusplus - extern "C" { -#endif - -/** @addtogroup STM32F7xx_System_Includes - * @{ - */ - -/** - * @} - */ - - -/** @addtogroup STM32F7xx_System_Exported_Variables - * @{ - */ - /* The SystemCoreClock variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetSysClockFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ -extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ - -extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ -extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ - - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Exported_Constants - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Exported_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Exported_Functions - * @{ - */ - -extern void SystemInit(void); -extern void SystemCoreClockUpdate(void); -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /*__SYSTEM_STM32F7XX_H */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746xx/utvm_api.c b/src/runtime/micro/device/stm32f746xx/utvm_api.c index 8a1d5df119cb..0ae1016e2a31 100644 --- a/src/runtime/micro/device/stm32f746xx/utvm_api.c +++ b/src/runtime/micro/device/stm32f746xx/utvm_api.c @@ -1,4 +1,3 @@ - #ifdef __cplusplus extern "C" { #endif diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.c b/src/runtime/micro/device/stm32f746xx/utvm_init.c index 9cffdaf95d2c..306bc34b0c0f 100644 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.c +++ b/src/runtime/micro/device/stm32f746xx/utvm_init.c @@ -1,6 +1,6 @@ -#include "stm32f7xx.h" +//#include "stm32f7xx.h" -extern char _stext; +//extern char _stext; void _UTVMInit(void) { // /* FPU settings ------------------------------------------------------------*/ @@ -32,5 +32,5 @@ void _UTVMInit(void) //#else // SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ //#endif - SCB->VTOR = &_stext; /* Vector Table Relocation in Internal SRAM */ + //SCB->VTOR = &_stext; /* Vector Table Relocation in Internal SRAM */ } diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.c.bad b/src/runtime/micro/device/stm32f746xx/utvm_init.c.bad deleted file mode 100644 index 55ae5d42dc46..000000000000 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.c.bad +++ /dev/null @@ -1,278 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32f7xx.c - * @author MCD Application Team - * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. - * - * This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f7xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f7xx_system - * @{ - */ - -/** @addtogroup STM32F7xx_System_Private_Includes - * @{ - */ - -#include "stm32f7xx.h" - -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Defines - * @{ - */ - -/************************* Miscellaneous Configuration ************************/ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -#define VECT_TAB_SRAM -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Variables - * @{ - */ - - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ - uint32_t SystemCoreClock = 16000000; - const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemFrequency variable. - * @param None - * @retval None - */ -void _UTVMInit(void) -{ -// /* FPU settings ------------------------------------------------------------*/ -// #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) -// SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ -// #endif -// /* Reset the RCC clock configuration to the default reset state ------------*/ -// /* Set HSION bit */ -// RCC->CR |= (uint32_t)0x00000001; -// -// /* Reset CFGR register */ -// RCC->CFGR = 0x00000000; -// -// /* Reset HSEON, CSSON and PLLON bits */ -// RCC->CR &= (uint32_t)0xFEF6FFFF; -// -// /* Reset PLLCFGR register */ -// RCC->PLLCFGR = 0x24003010; -// -// /* Reset HSEBYP bit */ -// RCC->CR &= (uint32_t)0xFFFBFFFF; -// -// /* Disable all interrupts */ -// RCC->CIR = 0x00000000; -// -// /* Configure the Vector Table location add offset address ------------------*/ -//#ifdef VECT_TAB_SRAM -// SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -//#else -// SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -//#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 25 MHz), user has to ensure that HSE_VALUE is same as the real - * frequency of the crystal used. Otherwise, this function may - * have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.s b/src/runtime/micro/device/stm32f746xx/utvm_init.s index 1da26a18a98a..ea0737369542 100644 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/stm32f746xx/utvm_init.s @@ -61,8 +61,6 @@ UTVMInit: /* set stack pointer */ /* todo no hradcode */ ldr sp, =0x2004fffc - /* run init that's expressable in C */ - bl _UTVMInit bl UTVMMain .size UTVMInit, .-UTVMInit diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 005e2818b2d1..2abf207dc675 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,8 +25,8 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -DEV_CONFIG = micro.device.host.default_config() -#DEV_CONFIG = micro.device.stm32f746xx.default_config('127.0.0.1', 6666) +#DEV_CONFIG = micro.device.host.default_config() +DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) #def create_micro_mod(c_mod, dev_config): # """Produces a micro module from a given module. @@ -388,6 +388,6 @@ def test_inactive_session_use(): test_graph_runtime() test_conv2d() test_multiple_modules() - test_interleave_sessions() - test_nested_sessions() - test_inactive_session_use() + #test_interleave_sessions() + #test_nested_sessions() + #test_inactive_session_use() From 277cbe8a4483bcde6e7d72c5566e63a5ff02370c Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 15:41:49 -0800 Subject: [PATCH 33/70] big refactor but now host no work --- python/tvm/contrib/binutil.py | 104 ++++------ python/tvm/micro/base.py | 4 - python/tvm/micro/device/arm/stm32f746xx.py | 5 + .../micro/device/stm32f746xx/utvm_init.s | 6 +- src/runtime/micro/host_driven/utvm_runtime.c | 23 +- src/runtime/micro/host_low_level_device.cc | 20 +- src/runtime/micro/low_level_device.h | 85 ++++---- src/runtime/micro/micro_common.cc | 29 ++- src/runtime/micro/micro_common.h | 95 +++++---- src/runtime/micro/micro_device_api.cc | 26 ++- src/runtime/micro/micro_section_allocator.h | 40 ++-- src/runtime/micro/micro_session.cc | 196 +++++++++--------- src/runtime/micro/micro_session.h | 19 +- src/runtime/micro/openocd_low_level_device.cc | 56 ++--- tests/python/unittest/test_runtime_micro.py | 14 +- 15 files changed, 331 insertions(+), 391 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index b5132cda1cb7..55d20a1c8d07 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -107,7 +107,16 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): @register_func("tvm_callback_relocate_binary") def tvm_callback_relocate_binary( - binary_path, word_size, text_addr, rodata_addr, data_addr, bss_addr, toolchain_prefix): + binary_path, + word_size, + text_start, + rodata_start, + data_start, + bss_start, + workspace_start, + workspace_end, + stack_end, + toolchain_prefix): """Relocates sections in the binary to new addresses Parameters @@ -118,16 +127,16 @@ def tvm_callback_relocate_binary( word_size : int TODO - text_addr : str + text_start : str text section absolute address - rodata_addr : str + rodata_start : str rodata section absolute address - data_addr : str + data_start : str data section absolute address - bss_addr : str + bss_start : str bss section absolute address toolchain_prefix : str @@ -160,17 +169,14 @@ def tvm_callback_relocate_binary( # TODO: this a fukn hack #input(f'binary path: {binary_path}') + stack_pointer_init = stack_end - word_size ld_script_contents = """ -/* Highest address of the user mode stack */ -_estack = 0x20050000; /* end of RAM */ - -/* - * Memory layout (for reference) - * RAM (xrw) : START = 0x20000000, LENGTH = 320K - * FLASH (rx) : START = 0x8000000, LENGTH = 1024K - */ +/* linker symbols for use in C source */ +_utvm_stack_pointer_init = %s; +_utvm_workspace_start = %s; +_utvm_workspace_end = %s; +_utvm_word_size = %s; -/* Define output sections */ SECTIONS { . = %s; @@ -213,62 +219,26 @@ def tvm_callback_relocate_binary( } } """ + # first, fill in ALIGN args with the target word size ld_script_contents = ld_script_contents.replace('ALIGN(?)', f'ALIGN({word_size})') + # then fill in addrs for linker symbols and section starts + ld_script_contents = ld_script_contents % ( + f'0x{stack_pointer_init:x}', + f'0x{workspace_start:x}', + f'0x{workspace_end:x}', + word_size, + f'0x{text_start:x}', + f'0x{rodata_start:x}', + f'0x{data_start:x}', + f'0x{bss_start:x}') print(ld_script_contents) - ld_script_contents = ld_script_contents % (text_addr, rodata_addr, data_addr, bss_addr) - print(ld_script_contents) + input() print(f'relocing lib {binary_path}') - print(f' text_addr: {text_addr}') - print(f' rodata_addr: {rodata_addr}') - print(f' data_addr: {data_addr}') - print(f' bss_addr: {bss_addr}') - - # TODO(weberlo): Generate the script in a more procedural manner. - - # TODO: use the stm32-cube linker script as reference. set UTVMInit as - # entry point. add KEEP to sections to prevent garbage collection. - -#""" -#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) + print(f' text_start: {text_start}') + print(f' rodata_start: {rodata_start}') + print(f' data_start: {data_start}') + print(f' bss_start: {bss_start}') + rel_ld_script_path = tmp_dir.relpath("relocated.lds") with open(rel_ld_script_path, "w") as f: f.write(ld_script_contents) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 0c455c3fc56c..6f85c87d82a8 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -92,9 +92,6 @@ def __init__(self, config): else: raise RuntimeError(f'unknown communication method: f{self.comms_method}') - # todo remove use of base addrs everywhere - base_addr = 0 - self.module = _CreateSession( comms_method, runtime_obj_path, @@ -117,7 +114,6 @@ def __init__(self, config): self.mem_layout['stack']['size'], self.word_size, self.thumb_mode, - base_addr, server_addr, server_port) self._enter = self.module['enter'] diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 4e6ee237ca30..3c941f6223bb 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -1,5 +1,10 @@ from .. import MicroBinutil +# +# Memory layout +# RAM (rwx) : START = 0x20000000, LENGTH = 320K +# FLASH (rx) : START = 0x8000000, LENGTH = 1024K + class Stm32F746XXBinutil(MicroBinutil): def __init__(self): super(Stm32F746XXBinutil, self).__init__('arm-none-eabi-') diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.s b/src/runtime/micro/device/stm32f746xx/utvm_init.s index ea0737369542..947918e0d183 100644 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/stm32f746xx/utvm_init.s @@ -47,7 +47,6 @@ .thumb .section .text.UTVMInit -/* .weak UTVMInit */ .type UTVMInit, %function UTVMInit: /* enable fpu */ @@ -59,8 +58,7 @@ UTVMInit: dsb isb /* set stack pointer */ - /* todo no hradcode */ - ldr sp, =0x2004fffc + ldr sp, =_utvm_stack_pointer_init bl UTVMMain .size UTVMInit, .-UTVMInit @@ -92,7 +90,7 @@ Infinite_Loop: g_pfnVectors: - .word _estack + .word _utvm_stack_pointer_init .word UTVMInit .word NMI_Handler diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 76c5ddf1c1bc..ef83dfc49588 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -43,8 +43,15 @@ UTVMTask utvm_task = { }; // These pointers are patched at load time to point to the workspace section. -char* utvm_workspace_begin = NULL; // NOLINT(*) -char* utvm_workspace_end = NULL; // NOLINT(*) + + +// linker-provided symbols +extern char _utvm_workspace_start; +extern char _utvm_workspace_end; +extern char _utvm_word_size; + +//char* utvm_workspace_begin = NULL; // NOLINT(*) +//char* utvm_workspace_end = NULL; // NOLINT(*) char* utvm_workspace_curr = NULL; // NOLINT(*) // Keep track of how many active allocations there are on the workspace. size_t utvm_num_active_allocs = 0; @@ -66,7 +73,7 @@ void UTVMMain() { utvm_task_time = 420; UTVMDone(); */ - utvm_workspace_curr = utvm_workspace_begin; + utvm_workspace_curr = &_utvm_workspace_start; utvm_num_active_allocs = 0; utvm_last_error = NULL; // NOLINT(*) utvm_return_code = 0; @@ -86,9 +93,11 @@ void UTVMDone() { } void* TVMBackendAllocWorkspace(int device_type, int device_id, uint64_t size, int dtype_code_hint, int dtype_bits_hint) { + size_t word_size = (size_t) &_utvm_word_size; // Align up to 8 bytes. - utvm_workspace_curr += (8 - ((uintptr_t) utvm_workspace_curr % 8)) % 8; // NOLINT(*) - if (utvm_workspace_curr + size > utvm_workspace_end) { + utvm_workspace_curr += + (word_size - ((uintptr_t) utvm_workspace_curr % word_size)) % word_size; // NOLINT(*) + if (utvm_workspace_curr + size > &_utvm_workspace_end) { // Out of space in workspace. return NULL; } @@ -104,11 +113,11 @@ int TVMBackendFreeWorkspace(int device_type, int device_id, void* ptr) { TVMAPISetLastError("free called with no active workspace allocations"); // Reset allocations and workspace (for future task executions). utvm_num_active_allocs = 0; - utvm_workspace_curr = utvm_workspace_begin; + utvm_workspace_curr = &_utvm_workspace_start; return -1; } else if (utvm_num_active_allocs == 0) { // No more allocations. Reset workspace. - utvm_workspace_curr = utvm_workspace_begin; + utvm_workspace_curr = &_utvm_workspace_start; return 0; } else { return 0; diff --git a/src/runtime/micro/host_low_level_device.cc b/src/runtime/micro/host_low_level_device.cc index 643efdd95429..17590770e440 100644 --- a/src/runtime/micro/host_low_level_device.cc +++ b/src/runtime/micro/host_low_level_device.cc @@ -31,6 +31,9 @@ namespace tvm { namespace runtime { +/*! \brief number of bytes in each page */ +constexpr int kPageSize = 4096; + /*! * \brief emulated low-level device on host machine */ @@ -57,25 +60,18 @@ class HostLowLevelDevice final : public LowLevelDevice { munmap(base_addr_, size_); } - void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { - void* addr = ToDevPtr(offset).cast_to(); - std::memcpy(buf, addr, num_bytes); + void Read(DevPtr addr, void* buf, size_t num_bytes) { + std::memcpy(buf, addr.cast_to(), num_bytes); } - void Write(DevBaseOffset offset, const void* buf, size_t num_bytes) { - void* addr = ToDevPtr(offset).cast_to(); - std::memcpy(addr, buf, num_bytes); + void Write(DevPtr addr, const void* buf, size_t num_bytes) { + std::memcpy(addr.cast_to(), buf, num_bytes); } - void Execute(DevBaseOffset func_offset, DevBaseOffset breakpoint) { - DevPtr func_addr = ToDevPtr(func_offset); + void Execute(DevPtr func_addr, DevPtr breakpoint_addr) { reinterpret_cast(func_addr.value())(); } - std::uintptr_t base_addr() const final { - return 0; - } - const char* device_type() const final { return "host"; } diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index cc2d6d66bb04..eab99606381c 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -40,73 +40,66 @@ class LowLevelDevice { virtual ~LowLevelDevice() {} /*! - * \brief reads num_bytes from device memory at base_addr + offset into buffer - * \param offset on-device memory offset pointer to be read from + * \brief reads num_bytes from device memory at addr into buffer + * \param addr on-device memory address to read from * \param buffer on-host buffer to be read into - * \param num_bytes number of bytes to be read + * \param num_bytes number of bytes to read */ - virtual void Read(DevBaseOffset offset, + virtual void Read(DevPtr addr, void* buffer, size_t num_bytes) = 0; /*! - * \brief writes num_bytes from buffer to device memory at base_addr + offset - * \param offset on-device memory offset pointer to be written to - * \param buffer on-host buffer to be written - * \param num_bytes number of bytes to be written + * \brief writes num_bytes from buffer to device memory at addr + * \param addr on-device memory address to write into + * \param buffer host buffer to write from + * \param num_bytes number of bytes to write */ - virtual void Write(DevBaseOffset offset, + virtual void Write(DevPtr addr, const void* buffer, size_t num_bytes) = 0; /*! - * \brief starts execution of device at offset + * \brief starts execution of device at func_addr * \param func_addr offset of the init stub function - * \param breakpoint breakpoint at which to stop function execution + * \param breakpoint_addr address at which to stop function execution */ - virtual void Execute(DevBaseOffset func_offset, DevBaseOffset breakpoint) = 0; + virtual void Execute(DevPtr func_addr, DevPtr breakpoint_addr) = 0; // TODO(weberlo): Should we just give the device the *entire* memory layout // decided by the session? - /*! - * \brief sets the offset of the top of the stack section - * \param stack_top offset of the stack top - */ - virtual void SetStackTop(DevBaseOffset stack_top) { - LOG(FATAL) << "unimplemented"; - } - - /*! - * \brief convert from base offset to absolute address - * \param offset base offset - * \return absolute address - */ - DevPtr ToDevPtr(DevBaseOffset offset) { - return DevPtr(base_addr() + offset.value()); - } - - /*! - * \brief convert from absolute address to base offset - * \param ptr absolute address - * \return base offset - */ - DevBaseOffset ToDevOffset(DevPtr ptr) { - return DevBaseOffset(ptr.value() - base_addr()); - } + ///*! + // * \brief sets the offset of the top of the stack section + // * \param stack_top offset of the stack top + // */ + //virtual void SetStackTop(DevBaseOffset stack_top) { + // LOG(FATAL) << "unimplemented"; + //} + + ///*! + // * \brief convert from base offset to absolute address + // * \param offset base offset + // * \return absolute address + // */ + //DevPtr ToDevPtr(DevBaseOffset offset) { + // return DevPtr(base_addr() + offset.value()); + //} + + ///*! + // * \brief convert from absolute address to base offset + // * \param ptr absolute address + // * \return base offset + // */ + //DevBaseOffset ToDevOffset(DevPtr ptr) { + // return DevBaseOffset(ptr.value() - base_addr()); + //} /*! * \brief getter function for low-level device type * \return string containing device type */ virtual const char* device_type() const = 0; - - protected: - /*! - * \brief getter function for base_addr - * \return the base address of the device memory region - */ - virtual std::uintptr_t base_addr() const = 0; }; /*! @@ -117,10 +110,10 @@ const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes, /*! * \brief connect to OpenOCD and create an OpenOCD low-level device + * \param addr address of the OpenOCD server to connect to * \param port port of the OpenOCD server to connect to */ -const std::shared_ptr OpenOCDLowLevelDeviceCreate(std::uintptr_t base_addr, - const std::string& addr, +const std::shared_ptr OpenOCDLowLevelDeviceCreate(const std::string& addr, int port); } // namespace runtime diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index e84ac6b9fd8a..683571d6fda8 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -83,22 +83,29 @@ static std::string AddrToString(void* addr) { return string_addr; } -std::string RelocateBinarySections(const std::string& binary_path, - size_t word_size, - DevPtr text_addr, - DevPtr rodata_addr, - DevPtr data_addr, - DevPtr bss_addr, - const std::string& toolchain_prefix) { +std::string RelocateBinarySections( + const std::string& binary_path, + size_t word_size, + DevPtr text_start, + DevPtr rodata_start, + DevPtr data_start, + DevPtr bss_start, + DevPtr workspace_start, + DevPtr workspace_end, + DevPtr stack_end_start, + const std::string& toolchain_prefix) { const auto* f = Registry::Get("tvm_callback_relocate_binary"); CHECK(f != nullptr) << "Require tvm_callback_relocate_binary to exist in registry"; std::string relocated_bin = (*f)(binary_path, word_size, - AddrToString(text_addr.cast_to()), - AddrToString(rodata_addr.cast_to()), - AddrToString(data_addr.cast_to()), - AddrToString(bss_addr.cast_to()), + text_start.cast_to(), + rodata_start.cast_to(), + data_start.cast_to(), + bss_start.cast_to(), + workspace_start.cast_to(), + workspace_end.cast_to(), + stack_end_start.cast_to(), toolchain_prefix); return relocated_bin; } diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index afd8b3e77f9b..f9b3c59b1879 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -128,40 +128,40 @@ class DevPtr : public DeviceLocation { } }; -/*! \brief offset from device base address */ -class DevBaseOffset : public DeviceLocation { - public: - /*! \brief construct a base offset with value `value` */ - explicit DevBaseOffset(std::uintptr_t value) : DeviceLocation(value) {} - - /*! \brief default constructor */ - DevBaseOffset() : DeviceLocation() {} - - /*! \brief construct a null base offset */ - explicit DevBaseOffset(std::nullptr_t value) : DeviceLocation(value) {} - - /*! \brief add an integer to this base offset to get a larger base offset */ - DevBaseOffset operator+(size_t n) const { - return DevBaseOffset(value_ + n); - } - - /*! \brief mutably add an integer to this base offset */ - DevBaseOffset& operator+=(size_t n) { - value_ += n; - return *this; - } - - /*! \brief subtract an integer from this base offset to get a smaller base offset */ - DevBaseOffset operator-(size_t n) const { - return DevBaseOffset(value_ - n); - } - - /*! \brief mutably subtract an integer from this base offset */ - DevBaseOffset& operator-=(size_t n) { - value_ -= n; - return *this; - } -}; +///*! \brief offset from device base address */ +//class DevBaseOffset : public DeviceLocation { +// public: +// /*! \brief construct a base offset with value `value` */ +// explicit DevBaseOffset(std::uintptr_t value) : DeviceLocation(value) {} +// +// /*! \brief default constructor */ +// DevBaseOffset() : DeviceLocation() {} +// +// /*! \brief construct a null base offset */ +// explicit DevBaseOffset(std::nullptr_t value) : DeviceLocation(value) {} +// +// /*! \brief add an integer to this base offset to get a larger base offset */ +// DevBaseOffset operator+(size_t n) const { +// return DevBaseOffset(value_ + n); +// } +// +// /*! \brief mutably add an integer to this base offset */ +// DevBaseOffset& operator+=(size_t n) { +// value_ += n; +// return *this; +// } +// +// /*! \brief subtract an integer from this base offset to get a smaller base offset */ +// DevBaseOffset operator-(size_t n) const { +// return DevBaseOffset(value_ - n); +// } +// +// /*! \brief mutably subtract an integer from this base offset */ +// DevBaseOffset& operator-=(size_t n) { +// value_ -= n; +// return *this; +// } +//}; /*! * \brief map from symbols to their on-device offsets @@ -235,7 +235,7 @@ class SymbolMap { /*! \brief struct containing start and size of a device memory region */ struct DevMemRegion { /*! \brief section start offset */ - DevBaseOffset start; + DevPtr start; /*! \brief size of section */ size_t size; }; @@ -262,12 +262,6 @@ struct BinaryContents { std::string bss_contents; }; -// TODO(weberlo): should this be here? -/*! \brief number of bytes in each page */ -constexpr int kPageSize = 4096; - -const DevBaseOffset kDeviceStart = DevBaseOffset(64); - /*! * \brief return default size of given section kind in bytes */ @@ -290,6 +284,7 @@ inline size_t UpperAlignValue(size_t value, size_t align) { */ const char* SectionToString(SectionKind section); +// todo new docs /*! * \brief links binary by repositioning section addresses * \param binary_name input binary filename @@ -300,13 +295,17 @@ const char* SectionToString(SectionKind section); * \param toolchain_prefix prefix of compiler toolchain to use * \return relocated binary file contents */ -std::string RelocateBinarySections(const std::string& binary_name, - size_t word_size, - DevPtr text_addr, - DevPtr rodata_addr, - DevPtr data_addr, - DevPtr bss_addr, - const std::string& toolchain_prefix); +std::string RelocateBinarySections( + const std::string& binary_path, + size_t word_size, + DevPtr text_start, + DevPtr rodata_start, + DevPtr data_start, + DevPtr bss_start, + DevPtr workspace_start, + DevPtr workspace_end, + DevPtr stack_end_start, + const std::string& toolchain_prefix); /*! * \brief reads section from binary diff --git a/src/runtime/micro/micro_device_api.cc b/src/runtime/micro/micro_device_api.cc index d1df67f00d9b..de2e03155a04 100644 --- a/src/runtime/micro/micro_device_api.cc +++ b/src/runtime/micro/micro_device_api.cc @@ -61,7 +61,7 @@ class MicroDeviceAPI final : public DeviceAPI { void FreeDataSpace(TVMContext ctx, void* ptr) final { MicroDevSpace* dev_space = static_cast(ptr); dev_space->session->FreeInSection( - SectionKind::kHeap, DevBaseOffset(reinterpret_cast(dev_space->data))); + SectionKind::kHeap, DevPtr(reinterpret_cast(dev_space->data))); delete dev_space; } @@ -89,12 +89,12 @@ class MicroDeviceAPI final : public DeviceAPI { ObjectPtr& session = from_space->session; const std::shared_ptr& lld = session->low_level_device(); - DevBaseOffset from_dev_offset = GetDevLoc(from_space, from_offset); - DevBaseOffset to_dev_offset = GetDevLoc(to_space, to_offset); + DevPtr from_dev_addr = GetDevLoc(from_space, from_offset); + DevPtr to_dev_addr = GetDevLoc(to_space, to_offset); std::vector buffer(size); - lld->Read(from_dev_offset, static_cast(buffer.data()), size); - lld->Write(to_dev_offset, static_cast(buffer.data()), size); + lld->Read(from_dev_addr, static_cast(buffer.data()), size); + lld->Write(to_dev_addr, static_cast(buffer.data()), size); } else if (type_from_to == std::make_tuple(kDLMicroDev, kDLCPU)) { // Reading from the device. @@ -102,9 +102,9 @@ class MicroDeviceAPI final : public DeviceAPI { ObjectPtr& session = from_space->session; const std::shared_ptr& lld = session->low_level_device(); - DevBaseOffset from_dev_offset = GetDevLoc(from_space, from_offset); + DevPtr from_dev_addr = GetDevLoc(from_space, from_offset); void* to_host_ptr = GetHostLoc(to, to_offset); - lld->Read(from_dev_offset, to_host_ptr, size); + lld->Read(from_dev_addr, to_host_ptr, size); } else if (type_from_to == std::make_tuple(kDLCPU, kDLMicroDev)) { // Writing to the device. @@ -113,8 +113,8 @@ class MicroDeviceAPI final : public DeviceAPI { const std::shared_ptr& lld = session->low_level_device(); void* from_host_ptr = GetHostLoc(from, from_offset); - DevBaseOffset to_dev_offset = GetDevLoc(to_space, to_offset); - lld->Write(to_dev_offset, from_host_ptr, size); + DevPtr to_dev_addr = GetDevLoc(to_space, to_offset); + lld->Write(to_dev_addr, from_host_ptr, size); } else { LOG(FATAL) << "Expect copy from/to micro device or between micro device\n"; } @@ -138,7 +138,7 @@ class MicroDeviceAPI final : public DeviceAPI { MicroDevSpace* dev_space = static_cast(data); ObjectPtr& session = dev_space->session; session->FreeInSection(SectionKind::kWorkspace, - DevBaseOffset(reinterpret_cast(dev_space->data))); + DevPtr(reinterpret_cast(dev_space->data))); delete dev_space; } @@ -152,10 +152,8 @@ class MicroDeviceAPI final : public DeviceAPI { } private: - DevBaseOffset GetDevLoc(MicroDevSpace* dev_space, size_t offset) { - DevBaseOffset dev_offset = - DevBaseOffset(reinterpret_cast(dev_space->data) + offset); - return dev_offset; + DevPtr GetDevLoc(MicroDevSpace* dev_space, size_t offset) { + return DevPtr(reinterpret_cast(dev_space->data) + offset); } void* GetHostLoc(const void* ptr, size_t offset) { diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index 5443d042dfed..e5e83930dd9f 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -38,11 +38,12 @@ class MicroSectionAllocator { * \brief constructor that specifies section boundaries * \param region location and size of the section on the device */ - explicit MicroSectionAllocator(DevMemRegion region) - : start_offset_(region.start), + explicit MicroSectionAllocator(DevMemRegion region, size_t word_size) + : start_addr_(region.start), size_(0), - capacity_(region.size) { - CHECK_EQ(start_offset_.value() % 8, 0) << "micro section not aligned to 8 bytes"; + capacity_(region.size), + word_size_(word_size) { + CHECK_EQ(start_addr_.value() % word_size, 0) << "micro section not aligned to " << word_size << " bytes"; } /*! @@ -55,15 +56,15 @@ class MicroSectionAllocator { * \param size size of allocated memory in bytes * \return pointer to allocated memory region in section, nullptr if out of space */ - DevBaseOffset Allocate(size_t size) { + DevPtr Allocate(size_t size) { size_ = UpperAlignValue(size_, 8); CHECK(size_ + size < capacity_) << "cannot alloc " << size << " bytes in section with start_addr " << - start_offset_.cast_to(); - DevBaseOffset alloc_ptr = start_offset_ + size_; + start_addr_.cast_to(); + DevPtr alloc_addr = start_addr_ + size_; size_ += size; - alloc_map_[alloc_ptr.value()] = size; - return alloc_ptr; + alloc_map_[alloc_addr.value()] = size; + return alloc_addr; } /*! @@ -71,10 +72,9 @@ class MicroSectionAllocator { * \param offs offset to allocated memory * \note simple allocator scheme, more complex versions will be implemented later */ - void Free(DevBaseOffset offs) { - std::uintptr_t ptr = offs.value(); - CHECK(alloc_map_.find(ptr) != alloc_map_.end()) << "freed pointer was never allocated"; - alloc_map_.erase(ptr); + void Free(DevPtr addr) { + CHECK(alloc_map_.find(addr.value()) != alloc_map_.end()) << "freed pointer was never allocated"; + alloc_map_.erase(addr.value()); if (alloc_map_.empty()) { size_ = 0; } @@ -83,17 +83,17 @@ class MicroSectionAllocator { /*! * \brief start offset of the memory region managed by this allocator */ - DevBaseOffset start_offset() const { return start_offset_; } + DevPtr start_addr() const { return start_addr_; } /*! - * \brief current end offset of the space being used in this memory region + * \brief current end addr of the space being used in this memory region */ - DevBaseOffset curr_end_offset() const { return start_offset_ + size_; } + DevPtr curr_end_addr() const { return start_addr_ + size_; } /*! - * \brief end offset of the memory region managed by this allocator + * \brief end addr of the memory region managed by this allocator */ - DevBaseOffset max_end_offset() const { return start_offset_ + capacity_; } + DevPtr max_addr() const { return start_addr_ + capacity_; } /*! * \brief size of the section @@ -107,11 +107,13 @@ class MicroSectionAllocator { private: /*! \brief start address of the section */ - DevBaseOffset start_offset_; + DevPtr start_addr_; /*! \brief current size of the section */ size_t size_; /*! \brief total storage capacity of the section */ size_t capacity_; + /*! \brief TODO */ + size_t word_size_; /*! \brief allocation map for allocation sizes */ std::unordered_map alloc_map_; }; diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 1e0f0d5484dc..d55957e85b35 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -81,7 +81,6 @@ MicroSession::MicroSession( size_t stack_size, size_t word_size, bool thumb_mode, - std::uintptr_t base_addr, const std::string& server_addr, int port) : word_size_(word_size), thumb_mode_(thumb_mode) { //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); @@ -115,97 +114,98 @@ MicroSession::MicroSession( size_t memory_size = text_size + rodata_size + data_size + bss_size + args_size + heap_size + workspace_size + stack_size; void* base_addr; low_level_device_ = HostLowLevelDeviceCreate(memory_size, &base_addr); + CHECK(reinterpret_cast(base_addr) % word_size_ == 0) << "base address not aligned to " << word_size_ << " bytes"; std::cout << "base addr is " << base_addr << std::endl; - DevBaseOffset curr_offset = DevBaseOffset(reinterpret_cast(base_addr)); + DevPtr curr_addr = DevPtr(reinterpret_cast(base_addr)); section_allocators_[0] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = text_size, - }); - curr_offset += text_size; + }, word_size_); + curr_addr += text_size; section_allocators_[1] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = rodata_size, - }); - curr_offset += rodata_size; + }, word_size_); + curr_addr += rodata_size; section_allocators_[2] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = data_size, - }); - curr_offset += data_size; + }, word_size_); + curr_addr += data_size; section_allocators_[3] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = bss_size, - }); - curr_offset += bss_size; + }, word_size_); + curr_addr += bss_size; section_allocators_[4] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = args_size, - }); - curr_offset += args_size; + }, word_size_); + curr_addr += args_size; section_allocators_[5] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = heap_size, - }); - curr_offset += heap_size; + }, word_size_); + curr_addr += heap_size; section_allocators_[6] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = workspace_size, - }); - curr_offset += workspace_size; + }, word_size_); + curr_addr += workspace_size; section_allocators_[7] = std::make_shared(DevMemRegion { - .start = curr_offset, + .start = curr_addr, .size = stack_size, - }); - curr_offset += stack_size; + }, word_size_); + curr_addr += stack_size; } else if (comms_method == "openocd") { // TODO(weberlo): We need a better way of configuring devices. - low_level_device_ = OpenOCDLowLevelDeviceCreate(base_addr, server_addr, port); + low_level_device_ = OpenOCDLowLevelDeviceCreate(server_addr, port); section_allocators_[0] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(text_start), + .start = DevPtr(text_start), .size = text_size, - }); + }, word_size_); section_allocators_[1] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(rodata_start), + .start = DevPtr(rodata_start), .size = rodata_size, - }); + }, word_size_); section_allocators_[2] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(data_start), + .start = DevPtr(data_start), .size = data_size, - }); + }, word_size_); section_allocators_[3] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(bss_start), + .start = DevPtr(bss_start), .size = bss_size, - }); + }, word_size_); section_allocators_[4] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(args_start), + .start = DevPtr(args_start), .size = args_size, - }); + }, word_size_); section_allocators_[5] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(heap_start), + .start = DevPtr(heap_start), .size = heap_size, - }); + }, word_size_); section_allocators_[6] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(workspace_start), + .start = DevPtr(workspace_start), .size = workspace_size, - }); + }, word_size_); section_allocators_[7] = std::make_shared(DevMemRegion { - .start = DevBaseOffset(stack_start), + .start = DevPtr(stack_start), .size = stack_size, - }); + }, word_size_); } else { LOG(FATAL) << "unsupported micro low-level device"; } std::cout << "[Memory Layout]" << std::endl; - std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_offset().cast_to() << std::endl; - std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_offset().cast_to() << std::endl; - std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_offset().cast_to() << std::endl; - std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_offset().cast_to() << std::endl; - std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_offset().cast_to() << std::endl; - std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_offset().cast_to() << std::endl; - std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_offset().cast_to() << std::endl; - std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_offset().cast_to() << std::endl; + std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_addr().cast_to() << std::endl; + std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_addr().cast_to() << std::endl; + std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_addr().cast_to() << std::endl; + std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_addr().cast_to() << std::endl; + std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_addr().cast_to() << std::endl; + std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_addr().cast_to() << std::endl; + std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_addr().cast_to() << std::endl; + std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_addr().cast_to() << std::endl; runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; @@ -214,21 +214,17 @@ MicroSession::MicroSession( //if (comms_method == "openocd") { // // Set OpenOCD device's stack pointer. // auto stack_section = GetAllocator(SectionKind::kStack); - // low_level_device_->SetStackTop(stack_section->max_end_offset()); + // low_level_device_->SetStackTop(stack_section->max_end_addr()); //} // Patch workspace pointers to the start of the workspace section. - DevBaseOffset workspace_start_offset = GetAllocator(SectionKind::kWorkspace)->start_offset(); - DevBaseOffset workspace_end_offset = GetAllocator(SectionKind::kWorkspace)->max_end_offset(); - void* workspace_start_addr = - low_level_device_->ToDevPtr(workspace_start_offset).cast_to(); - void* workspace_end_addr = - low_level_device_->ToDevPtr(workspace_end_offset).cast_to(); + //void* workspace_start_addr = GetAllocator(SectionKind::kWorkspace)->start_addr().cast_to(); + //void* workspace_end_addr = GetAllocator(SectionKind::kWorkspace)->max_addr().cast_to(); // TODO(weberlo): A lot of these symbol writes can be converted into symbols // in the C source, where the symbols are created by the linker script we // generate in python. - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_begin", workspace_start_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); + //DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_begin", workspace_start_addr); + //DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); } MicroSession::~MicroSession() { @@ -256,8 +252,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { // Create an allocator stream for the memory region after the most recent // allocation in the args section. - DevPtr args_addr = - low_level_device()->ToDevPtr(GetAllocator(SectionKind::kArgs)->curr_end_offset()); + DevPtr args_addr = GetAllocator(SectionKind::kArgs)->curr_end_addr(); TargetDataLayoutEncoder encoder(args_addr, word_size_); std::cout << " after encoder alloc" << std::endl; @@ -266,10 +261,10 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " after encoder append" << std::endl; // Flush `stream` to device memory. - DevBaseOffset stream_dev_offset = + DevPtr stream_dev_addr = GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); std::cout << " low-level device: " << low_level_device() << std::endl; - low_level_device()->Write(stream_dev_offset, + low_level_device()->Write(stream_dev_addr, reinterpret_cast(encoder.data()), encoder.buf_size()); std::cout << " after encoder write" << std::endl; @@ -303,28 +298,23 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " after task write" << std::endl; - //DevBaseOffset utvm_main_loc = DevBaseOffset(runtime_symbol_map_["UTVMMain"].value()); - DevBaseOffset utvm_init_loc = DevBaseOffset(runtime_symbol_map_["UTVMInit"].value()); - DevBaseOffset utvm_done_loc = DevBaseOffset(runtime_symbol_map_["UTVMDone"].value()); + DevPtr utvm_init_addr = runtime_symbol_map_["UTVMInit"]; + DevPtr utvm_done_addr = runtime_symbol_map_["UTVMDone"]; if (thumb_mode_) { - utvm_init_loc += 1; + utvm_init_addr += 1; } - std::cout << " UTVMInit loc: " << utvm_init_loc.cast_to() << std::endl; - std::cout << " UTVMDone loc: " << utvm_done_loc.cast_to() << std::endl; + std::cout << " UTVMInit loc: " << utvm_init_addr.cast_to() << std::endl; + std::cout << " UTVMDone loc: " << utvm_done_addr.cast_to() << std::endl; //std::cout << " do execution things: "; //char tmp; //std::cin >> tmp; - low_level_device()->Execute(utvm_init_loc, utvm_done_loc); + low_level_device()->Execute(utvm_init_addr, utvm_done_addr); // Check if there was an error during execution. If so, log it. CheckDeviceError(); - std::uintptr_t workspace_begin = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_begin"); - std::cout << " workspace begin: " << workspace_begin << std::endl; - std::uintptr_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); - std::cout << " workspace end: " << workspace_end << std::endl; std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); std::cout << " workspace curr: " << workspace_curr << std::endl; size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); @@ -337,7 +327,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " task time was " << task_time << std::endl; std::cout << " --------------------------------------------------------------------------------" << std::endl; - GetAllocator(SectionKind::kArgs)->Free(stream_dev_offset); + GetAllocator(SectionKind::kArgs)->Free(stream_dev_addr); return task_time; } @@ -371,10 +361,14 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::string relocated_bin = RelocateBinarySections( binary_path, word_size_, - low_level_device_->ToDevPtr(text_section.start), - low_level_device_->ToDevPtr(rodata_section.start), - low_level_device_->ToDevPtr(data_section.start), - low_level_device_->ToDevPtr(bss_section.start), + // TODO fill in new args + text_section.start, + rodata_section.start, + data_section.start, + bss_section.start, + GetAllocator(SectionKind::kWorkspace)->start_addr(), + GetAllocator(SectionKind::kWorkspace)->max_addr(), + GetAllocator(SectionKind::kStack)->max_addr(), toolchain_prefix_); std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); std::string rodata_contents = ReadSection(relocated_bin, SectionKind::kRodata, toolchain_prefix_); @@ -528,10 +522,10 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr // checks that it is a host array. CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - // Add the base address of the device to the array's data's device offset to - // get a device address. - DevBaseOffset arr_offset(reinterpret_cast(arr.data)); - dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); + //// Add the base address of the device to the array's data's device offset to + //// get a device address. + //DevPtr arr_offset(reinterpret_cast(arr.data)); + //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); dev_arr.shape = shape_addr.cast_to(); dev_arr.strides = strides_addr.cast_to(); tvm_arr_slot.WriteValue(dev_arr); @@ -552,8 +546,8 @@ void MicroSession::CheckDeviceError() { DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); std::string last_error_str; if (last_error) { - DevBaseOffset last_err_offset = low_level_device()->ToDevOffset(DevPtr(last_error)); - last_error_str = ReadString(last_err_offset); + DevPtr last_err_addr = DevPtr(last_error); + last_error_str = ReadString(last_err_addr); } LOG(FATAL) << "error during micro function execution:\n" << " return code: " << std::dec << return_code << "\n" @@ -580,39 +574,38 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& } } -std::string MicroSession::ReadString(DevBaseOffset str_offset) { +std::string MicroSession::ReadString(DevPtr str_addr) { std::ostringstream result; const size_t buf_size = 256; std::vector buf(buf_size, 0); size_t i = buf_size; while (i == buf_size) { - low_level_device()->Read(str_offset, buf.data(), buf_size); + low_level_device()->Read(str_addr, buf.data(), buf_size); i = 0; while (i < buf_size) { if (buf[i] == 0) break; result << buf[i]; i++; } - str_offset = str_offset + i; + str_addr = str_addr + i; } return result.str(); } -DevBaseOffset MicroSession::AllocateInSection(SectionKind type, size_t size) { +DevPtr MicroSession::AllocateInSection(SectionKind type, size_t size) { return GetAllocator(type)->Allocate(size); } -void MicroSession::FreeInSection(SectionKind type, DevBaseOffset ptr) { - return GetAllocator(type)->Free(ptr); +void MicroSession::FreeInSection(SectionKind type, DevPtr addr) { + return GetAllocator(type)->Free(addr); } template T MicroSession::DevSymbolRead(const SymbolMap& symbol_map, const std::string& symbol) { - DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); - //sym_offset -= 6; - std::cout << "SYM OFFSET FOR " << symbol << " IS " << sym_offset.cast_to() << std::endl; + DevPtr sym_addr = symbol_map[symbol]; + std::cout << "sym offset for " << symbol << " is " << sym_addr.cast_to() << std::endl; T result; - low_level_device()->Read(sym_offset, &result, sizeof(T)); + low_level_device()->Read(sym_addr, &result, sizeof(T)); return result; } @@ -620,9 +613,8 @@ template void MicroSession::DevSymbolWrite(const SymbolMap& symbol_map, const std::string& symbol, const T& value) { - DevBaseOffset sym_offset = low_level_device()->ToDevOffset(symbol_map[symbol]); - //sym_offset -= 6; - low_level_device()->Write(sym_offset, &value, sizeof(T)); + DevPtr sym_addr = symbol_map[symbol]; + low_level_device()->Write(sym_addr, &value, sizeof(T)); } PackedFunc MicroSession::GetFunction( @@ -665,9 +657,8 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") size_t stack_size = args[18]; size_t word_size = args[19]; bool thumb_mode = args[20]; - uint64_t base_addr = args[21]; - const std::string& server_addr = args[22]; - int port = args[23]; + const std::string& server_addr = args[21]; + int port = args[22]; ObjectPtr session = make_object( comms_method, binary_path, @@ -690,7 +681,6 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") stack_size, word_size, thumb_mode, - base_addr, server_addr, port); //session->CreateSession( diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 817b3ad5f392..ba66ed06db39 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -102,7 +102,6 @@ class MicroSession : public ModuleNode { size_t stack_size, size_t word_size, bool thumb_mode, - std::uintptr_t base_addr, const std::string& server_addr, int port); @@ -128,21 +127,21 @@ class MicroSession : public ModuleNode { * \param size size of allocated memory in bytes * \return pointer to allocated memory region in section, nullptr if out of space */ - DevBaseOffset AllocateInSection(SectionKind type, size_t size); + DevPtr AllocateInSection(SectionKind type, size_t size); /*! * \brief free prior allocation from section * \param type type of section to allocate in - * \param ptr pointer to allocated memory + * \param addr device address of allocated memory */ - void FreeInSection(SectionKind type, DevBaseOffset ptr); + void FreeInSection(SectionKind type, DevPtr addr); /*! * \brief read string from device to host - * \param str_offset device offset of first character of string + * \param str_addr device address of first character of string * \return host copy of device string that was read */ - std::string ReadString(DevBaseOffset str_offset); + std::string ReadString(DevPtr str_addr); /*! * \brief sets up runtime metadata for `func` and copies arguments for on-device execution @@ -151,10 +150,6 @@ class MicroSession : public ModuleNode { */ uint32_t PushToExecQueue(DevPtr func, const TVMArgs& args); - //void EnqueueBinary(const std::string& binary_path); - - //void FlushBinary(const BinaryContents& bin_contents); - /*! * \brief read value of symbol from device memory * \param symbol_map symbol map to read location of symbol from @@ -199,10 +194,6 @@ class MicroSession : public ModuleNode { // whether it's a "thumb mode" function. The Thumb ISA is more restricted, but // results in more compact binaries. bool thumb_mode_; - /*! \brief offset of the runtime entry function */ - DevBaseOffset utvm_main_symbol_; - /*! \brief offset of the runtime exit breakpoint */ - DevBaseOffset utvm_done_symbol_; /*! \brief TODO */ SymbolMap runtime_symbol_map_; diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index ffdfc958ef4a..c973dc3c0bb6 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -37,18 +37,14 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { public: /*! * \brief constructor to initialize connection to openocd device - * \param base_addr base address of the device * \param server_addr address of the OpenOCD server to connect to * \param port port of the OpenOCD server to connect to */ - explicit OpenOCDLowLevelDevice(std::uintptr_t base_addr, - const std::string& server_addr, + explicit OpenOCDLowLevelDevice(const std::string& server_addr, int port) : socket_() { std::cout << "[OpenOCDLowLevelDevice]" << std::endl; server_addr_ = server_addr; port_ = port; - base_addr_ = base_addr; - CHECK(base_addr_ % 8 == 0) << "base address not aligned to 8 bytes"; socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); socket_.cmd_builder() << "halt 0"; @@ -56,7 +52,7 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { std::cout << " finished init" << std::endl; } - void Read(DevBaseOffset offset, void* buf, size_t num_bytes) { + void Read(DevPtr addr, void* buf, size_t num_bytes) { if (num_bytes == 0) { return; } @@ -64,7 +60,6 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { // TODO(weberlo): Refactor between read and write. // Check if we need to chunk this write request. if (num_bytes > kMemTransferLimit) { - DevBaseOffset curr_offset = offset; char* curr_buf_ptr = reinterpret_cast(buf); while (num_bytes != 0) { size_t amount_to_read; @@ -73,8 +68,8 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } else { amount_to_read = num_bytes; } - Read(offset, reinterpret_cast(curr_buf_ptr), amount_to_read); - offset += amount_to_read; + Read(addr, reinterpret_cast(curr_buf_ptr), amount_to_read); + addr += amount_to_read; curr_buf_ptr += amount_to_read; num_bytes -= amount_to_read; } @@ -84,7 +79,6 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.cmd_builder() << "array unset output"; socket_.SendCommand(); - DevPtr addr = DevPtr(base_addr_ + offset.value()); socket_.cmd_builder() << "mem2array output" << " " << std::dec << kWordSize @@ -127,14 +121,13 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } } - void Write(DevBaseOffset offset, const void* buf, size_t num_bytes) { + void Write(DevPtr addr, const void* buf, size_t num_bytes) { if (num_bytes == 0) { return; } // Check if we need to chunk this write request. if (num_bytes > kMemTransferLimit) { - DevBaseOffset curr_offset = offset; const char* curr_buf_ptr = reinterpret_cast(buf); while (num_bytes != 0) { size_t amount_to_write; @@ -143,8 +136,8 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } else { amount_to_write = num_bytes; } - Write(offset, reinterpret_cast(curr_buf_ptr), amount_to_write); - offset += amount_to_write; + Write(addr, reinterpret_cast(curr_buf_ptr), amount_to_write); + addr += amount_to_write; curr_buf_ptr += amount_to_write; num_bytes -= amount_to_write; } @@ -171,7 +164,6 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.SendCommand(); } { - DevPtr addr = DevPtr(base_addr_ + offset.value()); socket_.cmd_builder() << "array2mem input" << " " << std::dec << kWordSize @@ -181,15 +173,14 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { } } - void Execute(DevBaseOffset func_offset, DevBaseOffset breakpoint) { + void Execute(DevPtr func_addr, DevPtr breakpoint_addr) { socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); // Set a breakpoint at the beginning of `UTVMDone`. - socket_.cmd_builder() << "bp " << ToDevPtr(breakpoint).cast_to() << " 2"; + socket_.cmd_builder() << "bp " << breakpoint_addr.cast_to() << " 2"; socket_.SendCommand(); - DevPtr func_addr = DevPtr(base_addr_ + func_offset.value()); socket_.cmd_builder() << "resume " << func_addr.cast_to(); socket_.SendCommand(); @@ -200,30 +191,26 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.SendCommand(); // Remove the breakpoint. - socket_.cmd_builder() << "rbp " << ToDevPtr(breakpoint).cast_to(); + socket_.cmd_builder() << "rbp " << breakpoint_addr.cast_to(); socket_.SendCommand(); } - void SetStackTop(DevBaseOffset stack_top) { - stack_top_ = DevPtr(base_addr_ + stack_top.value()); - } - - std::uintptr_t base_addr() const final { - return base_addr_; - } + //std::uintptr_t base_addr() const final { + // return base_addr_; + //} - DevPtr stack_top() const { - CHECK(stack_top_ != nullptr) << "stack top was never initialized"; - return stack_top_; - } + //DevPtr stack_top() const { + // CHECK(stack_top_ != nullptr) << "stack top was never initialized"; + // return stack_top_; + //} const char* device_type() const final { return "openocd"; } private: - /*! \brief base address of the micro device memory region */ - std::uintptr_t base_addr_; + ///*! \brief base address of the micro device memory region */ + //std::uintptr_t base_addr_; /*! \brief top of the stack section */ DevPtr stack_top_; /*! \brief socket used to communicate with the device through Tcl */ @@ -242,11 +229,10 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { static const constexpr int kWaitTime = 10000; }; -const std::shared_ptr OpenOCDLowLevelDeviceCreate(std::uintptr_t base_addr, - const std::string& server_addr, +const std::shared_ptr OpenOCDLowLevelDeviceCreate(const std::string& server_addr, int port) { std::shared_ptr lld = - std::make_shared(base_addr, server_addr, port); + std::make_shared(server_addr, port); return lld; } diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 2abf207dc675..ffdc1eddbedb 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,8 +25,8 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -#DEV_CONFIG = micro.device.host.default_config() -DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +DEV_CONFIG = micro.device.host.default_config() +#DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) #def create_micro_mod(c_mod, dev_config): # """Produces a micro module from a given module. @@ -382,12 +382,12 @@ def test_inactive_session_use(): if __name__ == "__main__": - test_alloc() - test_add() + #test_alloc() + #test_add() test_workspace_add() - test_graph_runtime() - test_conv2d() - test_multiple_modules() + #test_graph_runtime() + #test_conv2d() + #test_multiple_modules() #test_interleave_sessions() #test_nested_sessions() #test_inactive_session_use() From 2669d1c9ad9605ddd4add81e24b95a6c6b09c361 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 5 Nov 2019 21:32:38 -0800 Subject: [PATCH 34/70] Host works again --- python/tvm/contrib/binutil.py | 4 +- python/tvm/micro/base.py | 1 + python/tvm/micro/device/__init__.py | 1 - src/runtime/micro/host_driven/utvm_runtime.c | 40 +++++--------- src/runtime/micro/micro_session.cc | 57 +++++++++----------- tests/python/unittest/test_runtime_micro.py | 16 +++--- 6 files changed, 49 insertions(+), 70 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 55d20a1c8d07..992907d0682b 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -232,7 +232,7 @@ def tvm_callback_relocate_binary( f'0x{data_start:x}', f'0x{bss_start:x}') print(ld_script_contents) - input() + #input('check script: ') print(f'relocing lib {binary_path}') print(f' text_start: {text_start}') print(f' rodata_start: {rodata_start}') @@ -247,7 +247,7 @@ def tvm_callback_relocate_binary( binary_path, "-T", rel_ld_script_path, "-o", rel_obj_path]) - print(f'relocated obj path is {rel_obj_path}') + #input(f'relocated obj path is {rel_obj_path}') with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 6f85c87d82a8..d318e792395d 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -81,6 +81,7 @@ def __init__(self, config): tmp_dir = _util.tempdir() runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) + #input(f'check {runtime_obj_path}: ') comms_method = config['comms_method'] if comms_method == 'openocd': diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index d6b9268eda84..488bf227a6a9 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -100,7 +100,6 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): ld_cmd += prereq_obj_paths ld_cmd += ['-o', obj_path] run_cmd(ld_cmd) - print(f'compiled obj {obj_path}') def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index ef83dfc49588..2bbd6015f9c7 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -42,16 +42,11 @@ UTVMTask utvm_task = { .num_args = 0, }; -// These pointers are patched at load time to point to the workspace section. - - -// linker-provided symbols -extern char _utvm_workspace_start; -extern char _utvm_workspace_end; -extern char _utvm_word_size; +size_t utvm_word_size = 0; // NOLINT(*) -//char* utvm_workspace_begin = NULL; // NOLINT(*) -//char* utvm_workspace_end = NULL; // NOLINT(*) +// These pointers are patched at load time to point to the workspace section. +char* utvm_workspace_start = NULL; // NOLINT(*) +char* utvm_workspace_end = NULL; // NOLINT(*) char* utvm_workspace_curr = NULL; // NOLINT(*) // Keep track of how many active allocations there are on the workspace. size_t utvm_num_active_allocs = 0; @@ -63,25 +58,17 @@ uint32_t utvm_task_time = 0; // Gets called by UTVMInit, after device-specific initialization is finished. void UTVMMain() { - /* - utvm_workspace_begin = (char*) 420; // NOLINT(*) - utvm_workspace_end = (char*) 420; // NOLINT(*) - utvm_workspace_curr = (char*) 420; // NOLINT(*) - utvm_num_active_allocs = 420; - utvm_last_error = (const char*) 420; // NOLINT(*) - utvm_return_code = 0; // NOLINT(*) - utvm_task_time = 420; - UTVMDone(); - */ - utvm_workspace_curr = &_utvm_workspace_start; + utvm_workspace_curr = utvm_workspace_start; utvm_num_active_allocs = 0; utvm_last_error = NULL; // NOLINT(*) utvm_return_code = 0; utvm_task_time = 0; UTVMTimerReset(); UTVMTimerStart(); - utvm_return_code = utvm_task.func((void*) utvm_task.arg_values, (void*) utvm_task.arg_type_codes, // NOLINT(*) - utvm_task.num_args); + utvm_return_code = utvm_task.func( + (void*) utvm_task.arg_values, // NOLINT(*) + (void*) utvm_task.arg_type_codes, // NOLINT(*) + utvm_task.num_args); UTVMTimerStop(); utvm_task_time = UTVMTimerRead(); UTVMDone(); @@ -93,11 +80,10 @@ void UTVMDone() { } void* TVMBackendAllocWorkspace(int device_type, int device_id, uint64_t size, int dtype_code_hint, int dtype_bits_hint) { - size_t word_size = (size_t) &_utvm_word_size; // Align up to 8 bytes. utvm_workspace_curr += - (word_size - ((uintptr_t) utvm_workspace_curr % word_size)) % word_size; // NOLINT(*) - if (utvm_workspace_curr + size > &_utvm_workspace_end) { + (utvm_word_size - ((uintptr_t) utvm_workspace_curr % utvm_word_size)) % utvm_word_size; // NOLINT(*) + if (utvm_workspace_curr + size > utvm_workspace_end) { // Out of space in workspace. return NULL; } @@ -113,11 +99,11 @@ int TVMBackendFreeWorkspace(int device_type, int device_id, void* ptr) { TVMAPISetLastError("free called with no active workspace allocations"); // Reset allocations and workspace (for future task executions). utvm_num_active_allocs = 0; - utvm_workspace_curr = &_utvm_workspace_start; + utvm_workspace_curr = utvm_workspace_start; return -1; } else if (utvm_num_active_allocs == 0) { // No more allocations. Reset workspace. - utvm_workspace_curr = &_utvm_workspace_start; + utvm_workspace_curr = utvm_workspace_start; return 0; } else { return 0; diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index d55957e85b35..c321c6056d3d 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -211,20 +211,15 @@ MicroSession::MicroSession( std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; - //if (comms_method == "openocd") { - // // Set OpenOCD device's stack pointer. - // auto stack_section = GetAllocator(SectionKind::kStack); - // low_level_device_->SetStackTop(stack_section->max_end_addr()); - //} - + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); // Patch workspace pointers to the start of the workspace section. - //void* workspace_start_addr = GetAllocator(SectionKind::kWorkspace)->start_addr().cast_to(); - //void* workspace_end_addr = GetAllocator(SectionKind::kWorkspace)->max_addr().cast_to(); + void* workspace_start_addr = GetAllocator(SectionKind::kWorkspace)->start_addr().cast_to(); + void* workspace_end_addr = GetAllocator(SectionKind::kWorkspace)->max_addr().cast_to(); // TODO(weberlo): A lot of these symbol writes can be converted into symbols // in the C source, where the symbols are created by the linker script we // generate in python. - //DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_begin", workspace_start_addr); - //DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); } MicroSession::~MicroSession() { @@ -234,16 +229,8 @@ MicroSession::~MicroSession() { low_level_device_ = nullptr; } -//void MicroSession::BakeSession(const std::string& binary_path) { -// //runtime_symbol_map_ = SymbolMap(binary, toolchain_prefix_); -// runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; -// std::cout << runtime_symbol_map_["UTVMMain"].value() << std::endl; -// std::cout << runtime_symbol_map_["utvm_task"].value() << std::endl; -//} - uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "[MicroSession::PushToExecQueue]" << std::endl; - // TODO: make this a parameter. if (thumb_mode_) { func_ptr += 1; } @@ -312,17 +299,24 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { low_level_device()->Execute(utvm_init_addr, utvm_done_addr); - // Check if there was an error during execution. If so, log it. - CheckDeviceError(); - - std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); - std::cout << " workspace curr: " << workspace_curr << std::endl; - size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); - std::cout << " num active allocs: " << num_active_allocs << std::endl; - std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); - std::cout << " last error: " << last_error << std::endl; - int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); - std::cout << " return code: " << return_code << std::endl; + //// Check if there was an error during execution. If so, log it. + //CheckDeviceError(); + + uint64_t workspace_start = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_start"); + std::cout << " workspace start: " << workspace_start << std::endl; + uint64_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); + std::cout << " workspace end: " << workspace_end << std::endl; + uint64_t word_size = DevSymbolRead(runtime_symbol_map_, "utvm_word_size"); + std::cout << " word size: " << word_size << std::endl; + + //std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); + //std::cout << " workspace curr: " << workspace_curr << std::endl; + //size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); + //std::cout << " num active allocs: " << num_active_allocs << std::endl; + //std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); + //std::cout << " last error: " << last_error << std::endl; + //int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); + //std::cout << " return code: " << return_code << std::endl; uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); std::cout << " task time was " << task_time << std::endl; std::cout << " --------------------------------------------------------------------------------" << std::endl; @@ -557,7 +551,6 @@ void MicroSession::CheckDeviceError() { } void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name) { - //void* runtime_impl_addr = runtime_symbol_map_[func_name].cast_to(); DevPtr runtime_impl_addr = runtime_symbol_map_[func_name]; if (thumb_mode_) { runtime_impl_addr += 1; @@ -566,9 +559,9 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; if (word_size_ == 4) { - DevSymbolWrite(symbol_map, func_name_underscore.str(), (int32_t) runtime_impl_addr.value()); + DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint32_t) runtime_impl_addr.value()); } else if (word_size_ == 8) { - DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr.value()); + DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint64_t) runtime_impl_addr.value()); } else { CHECK(false) << "ayy"; } diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index ffdc1eddbedb..312d7fdbfc4d 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -382,12 +382,12 @@ def test_inactive_session_use(): if __name__ == "__main__": - #test_alloc() - #test_add() + test_alloc() + test_add() test_workspace_add() - #test_graph_runtime() - #test_conv2d() - #test_multiple_modules() - #test_interleave_sessions() - #test_nested_sessions() - #test_inactive_session_use() + test_graph_runtime() + test_conv2d() + test_multiple_modules() + test_interleave_sessions() + test_nested_sessions() + test_inactive_session_use() From cf84064a5642900309a84c3a9ea092f2e645d8ce Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 12:27:40 -0800 Subject: [PATCH 35/70] more cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 5 ++- include/tvm/runtime/c_runtime_api.h | 2 +- python/tvm/autotvm/measure/measure_methods.py | 31 ------------------ python/tvm/autotvm/task/task.py | 5 +-- python/tvm/contrib/binutil.py | 32 ++++++++----------- python/tvm/micro/base.py | 2 -- python/tvm/micro/device/__init__.py | 11 ++++--- python/tvm/micro/rpc_server.py | 9 ++++-- python/tvm/rpc/client.py | 8 +---- src/codegen/build_module.cc | 7 +++- src/runtime/micro/low_level_device.h | 29 ----------------- src/runtime/micro/micro_common.cc | 4 --- src/runtime/micro/micro_common.h | 2 -- src/runtime/micro/micro_session.cc | 19 ----------- 14 files changed, 41 insertions(+), 125 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 0b2efb6de760..2db938303554 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -34,10 +34,12 @@ # first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal # then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another -DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +#DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +DEV_CONFIG = micro.device.host.default_config() DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') +#TARGET = tvm.target.create('micro_dev') N, L, M = 32, 32, 32 DTYPE = 'float32' @@ -138,4 +140,5 @@ def evaluate(): if __name__ == '__main__': tune() + input('finished tuning...') evaluate() diff --git a/include/tvm/runtime/c_runtime_api.h b/include/tvm/runtime/c_runtime_api.h index d6f9f19af4c0..5053326058bc 100644 --- a/include/tvm/runtime/c_runtime_api.h +++ b/include/tvm/runtime/c_runtime_api.h @@ -81,7 +81,7 @@ typedef enum { kDLAOCL = 5, kDLSDAccel = 6, kOpenGL = 11, - //kDLMicroDev = 13, + kDLMicroDev = 13, // AddExtraTVMType which is not in DLPack here } TVMDeviceExtType; diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index 0fa16e593f99..436134c1d8d6 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -468,37 +468,6 @@ def run_through_rpc(measure_input, build_result, reconfig_runtime(remote) remote.upload(build_result.filename) func = remote.load_module(os.path.split(build_result.filename)[1]) - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - # TODO try running autotvm with the changes to micro module that grab - # the only function in the module if the requested name is - # __tvm_main__. - #func.entry_name = 'default_function' ctx = remote.context(str(measure_input.target), 0) time_f = func.time_evaluator( func.entry_name, ctx, number=number, repeat=repeat, min_repeat_ms=min_repeat_ms) diff --git a/python/tvm/autotvm/task/task.py b/python/tvm/autotvm/task/task.py index 97828101260f..8abf20f37a3b 100644 --- a/python/tvm/autotvm/task/task.py +++ b/python/tvm/autotvm/task/task.py @@ -178,10 +178,11 @@ def create(func_name, args, target, target_host=None, template_key=None): func = TASK_TABLE[func_name] ret = Task(func_name, args) + print('[autotvm.task.create]') + print(f' target before: {target}') if isinstance(target, str): target = _target.create(target) - print('[autotvm.task.create]') - print(f' target: {target}') + print(f' target after: {target}') # init config space ret.config_space = ConfigSpace() diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 992907d0682b..1264ab4d6e84 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -113,8 +113,6 @@ def tvm_callback_relocate_binary( rodata_start, data_start, bss_start, - workspace_start, - workspace_end, stack_end, toolchain_prefix): """Relocates sections in the binary to new addresses @@ -125,19 +123,22 @@ def tvm_callback_relocate_binary( path of the binary file word_size : int - TODO + word size on the target machine - text_start : str - text section absolute address + text_start : int + text section address - rodata_start : str - rodata section absolute address + rodata_start : int + rodata section address - data_start : str - data section absolute address + data_start : int + data section address - bss_start : str - bss section absolute address + bss_start : int + bss section address + + stack_end : int + stack section end address toolchain_prefix : str prefix for binary names in target compiler toolchain @@ -171,11 +172,8 @@ def tvm_callback_relocate_binary( #input(f'binary path: {binary_path}') stack_pointer_init = stack_end - word_size ld_script_contents = """ -/* linker symbols for use in C source */ +/* linker symbol for use in UTVMInit */ _utvm_stack_pointer_init = %s; -_utvm_workspace_start = %s; -_utvm_workspace_end = %s; -_utvm_word_size = %s; SECTIONS { @@ -183,6 +181,7 @@ def tvm_callback_relocate_binary( . = ALIGN(?); .text : { + . = ALIGN(?); KEEP(*(.text)) KEEP(*(.text*)) . = ALIGN(?); @@ -224,9 +223,6 @@ def tvm_callback_relocate_binary( # then fill in addrs for linker symbols and section starts ld_script_contents = ld_script_contents % ( f'0x{stack_pointer_init:x}', - f'0x{workspace_start:x}', - f'0x{workspace_end:x}', - word_size, f'0x{text_start:x}', f'0x{rodata_start:x}', f'0x{data_start:x}', diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index d318e792395d..789971bff447 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -22,7 +22,6 @@ import logging import os import sys -from collections import namedtuple from enum import Enum from pathlib import Path @@ -31,7 +30,6 @@ from tvm.contrib import cc as _cc from .._ffi.function import _init_api from .._ffi.libinfo import find_include_path -from tvm.contrib.binutil import run_cmd class LibType(Enum): RUNTIME = 0 diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index 488bf227a6a9..cceb3a90ae5a 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -30,11 +30,12 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): whether to include the device library header containing definitions of library functions. """ - print('OPTIONS') - print(f'{obj_path}') - print(f'{src_path}') - print(f'{lib_type}') - print(f'{options}') + print('[MicroBinutil.create_lib]') + print(' EXTENDED OPTIONS') + print(f' {obj_path}') + print(f' {src_path}') + print(f' {lib_type}') + print(f' {options}') base_compile_cmd = [ f'{self.toolchain_prefix()}gcc', '-std=c11', diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 9db82cec3ea9..bd8a1aafe325 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -35,9 +35,12 @@ def main(): else: tracker_addr = None - #with open(args.dev_config, 'r') as dev_conf_file: - # dev_config = json.read(dev_conf_file) - dev_config = micro.device.arm.default_config('127.0.0.1', 6666) + with open(args.dev_config, 'r') as dev_conf_file: + dev_config = json.load(dev_conf_file) + #dev_config = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) + #dev_config = micro.device.host.default_config() + # TODO remove line above + #assert False @tvm.register_func("tvm.rpc.server.start", override=True) def server_start(): diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index 9c992e6bb000..c30d5396ee60 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -73,13 +73,11 @@ def context(self, dev_type, dev_id=0): print('[RPCSession.context]') print(f' dev_type: {dev_type}') print(f' dev_id: {dev_id}') - if 'micro_dev' in dev_type: - print(' IS MICRO_DEV') + if '-device=micro_dev' in dev_type: dev_type = 'micro_dev' ctx = nd.context(dev_type, dev_id) encode = (self._tbl_index + 1) * base.RPC_SESS_MASK ctx.device_type += encode - print(f' encoded dev_type: {ctx.device_type}') ctx._rpc_sess = self return ctx @@ -235,13 +233,9 @@ def __del__(self): self.close() def _connect(self): - print('AYY ' + str(self._addr)) self._sock = base.connect_with_retry(self._addr) - print('LMAO') self._sock.sendall(struct.pack("device_type = kDLCPU; t->thread_warp_size = 1; - if (target_name == "c" || target_name == "llvm") { + if (target_name == "c" and t->device_name == "micro_dev") { + t->device_type = kDLMicroDev; + } else if (target_name == "c" || target_name == "llvm") { t->keys_array.push_back(ir::StringImm::make("cpu")); } else if (target_name == "cuda" || target_name == "nvptx") { t->device_type = kDLGPU; @@ -214,6 +216,7 @@ std::string GetDeviceName(const std::string& target_str) { } Target Target::Create(const std::string& target_str) { + std::cout << "[Target::Create]" << std::endl; if (target_str.length() == 0) { LOG(ERROR) << "target_str must not be empty"; } @@ -223,11 +226,13 @@ Target Target::Create(const std::string& target_str) { ss >> target_name; auto device_name = GetDeviceName(target_str); + std::cout << " device_name: " << device_name << std::endl; std::vector options; std::string item; while (ss >> item) { options.push_back(item); + std::cout << " option: " << item << std::endl; } return CreateTarget(target_name, options); diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index eab99606381c..fd78790f3672 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -66,35 +66,6 @@ class LowLevelDevice { */ virtual void Execute(DevPtr func_addr, DevPtr breakpoint_addr) = 0; - // TODO(weberlo): Should we just give the device the *entire* memory layout - // decided by the session? - - ///*! - // * \brief sets the offset of the top of the stack section - // * \param stack_top offset of the stack top - // */ - //virtual void SetStackTop(DevBaseOffset stack_top) { - // LOG(FATAL) << "unimplemented"; - //} - - ///*! - // * \brief convert from base offset to absolute address - // * \param offset base offset - // * \return absolute address - // */ - //DevPtr ToDevPtr(DevBaseOffset offset) { - // return DevPtr(base_addr() + offset.value()); - //} - - ///*! - // * \brief convert from absolute address to base offset - // * \param ptr absolute address - // * \return base offset - // */ - //DevBaseOffset ToDevOffset(DevPtr ptr) { - // return DevBaseOffset(ptr.value() - base_addr()); - //} - /*! * \brief getter function for low-level device type * \return string containing device type diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 683571d6fda8..54936085ee9b 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -90,8 +90,6 @@ std::string RelocateBinarySections( DevPtr rodata_start, DevPtr data_start, DevPtr bss_start, - DevPtr workspace_start, - DevPtr workspace_end, DevPtr stack_end_start, const std::string& toolchain_prefix) { const auto* f = Registry::Get("tvm_callback_relocate_binary"); @@ -103,8 +101,6 @@ std::string RelocateBinarySections( rodata_start.cast_to(), data_start.cast_to(), bss_start.cast_to(), - workspace_start.cast_to(), - workspace_end.cast_to(), stack_end_start.cast_to(), toolchain_prefix); return relocated_bin; diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index f9b3c59b1879..3f1394bfd568 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -302,8 +302,6 @@ std::string RelocateBinarySections( DevPtr rodata_start, DevPtr data_start, DevPtr bss_start, - DevPtr workspace_start, - DevPtr workspace_end, DevPtr stack_end_start, const std::string& toolchain_prefix); diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index c321c6056d3d..afc652741b85 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -83,23 +83,6 @@ MicroSession::MicroSession( bool thumb_mode, const std::string& server_addr, int port) : word_size_(word_size), thumb_mode_(thumb_mode) { - //DevBaseOffset curr_start_offset = DevBaseOffset(0x20000180); - //DevBaseOffset curr_start_offset = DevBaseOffset(0x200001c8); - //for (size_t i = 0; i < static_cast(SectionKind::kNumKinds); i++) { - // size_t section_size = GetDefaultSectionSize(static_cast(i)); - // section_allocators_[i] = std::make_shared(DevMemRegion { - // .start = curr_start_offset, - // .size = section_size, - // }); - // curr_start_offset += section_size; - //} - - //CHECK(curr_start_offset.value() < 0x20050000) << "exceeded available RAM on device (" << std::endl; - - // NOTE: we don't use this for openocd - memory_size_ = 0; - //memory_size_ = curr_start_offset.cast_to(); - // TODO(weberlo): make device type enum toolchain_prefix_ = toolchain_prefix; if (comms_method == "host") { CHECK( @@ -360,8 +343,6 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d rodata_section.start, data_section.start, bss_section.start, - GetAllocator(SectionKind::kWorkspace)->start_addr(), - GetAllocator(SectionKind::kWorkspace)->max_addr(), GetAllocator(SectionKind::kStack)->max_addr(), toolchain_prefix_); std::string text_contents = ReadSection(relocated_bin, SectionKind::kText, toolchain_prefix_); From 838054a1f38efe941b101c3f215ff4d38e7d4956 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 14:34:07 -0800 Subject: [PATCH 36/70] More cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 1 - python/tvm/contrib/binutil.py | 145 +++++++++----------- python/tvm/micro/base.py | 25 ++-- python/tvm/micro/device/__init__.py | 27 +++- python/tvm/micro/device/arm/stm32f746xx.py | 3 +- python/tvm/micro/rpc_server.py | 5 +- python/tvm/module.py | 20 +-- src/runtime/micro/micro_common.cc | 34 ----- src/runtime/micro/micro_common.h | 5 - src/runtime/micro/micro_module.cc | 2 +- src/runtime/micro/micro_session.cc | 8 +- src/runtime/micro/micro_session.h | 23 ++-- src/runtime/rpc/rpc_session.cc | 6 +- tests/python/unittest/test_runtime_micro.py | 10 +- 14 files changed, 127 insertions(+), 187 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 2db938303554..ed4b38da04b2 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -39,7 +39,6 @@ DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') -#TARGET = tvm.target.create('micro_dev') N, L, M = 32, 32, 32 DTYPE = 'float32' diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 1264ab4d6e84..dd00378a3e74 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -33,7 +33,7 @@ def run_cmd(cmd): output = output.decode('utf-8') if proc.returncode != 0: cmd_str = ' '.join(cmd) - msg = f"error while running command \"{cmd_str}\":\n{output}" + msg = f'error while running command \"{cmd_str}\":\n{output}' raise RuntimeError(msg) return output @@ -60,18 +60,18 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): size of the section in bytes """ if not os.path.isfile(binary_path): - raise RuntimeError("no such file \"{}\"".format(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_output = run_cmd(["{}size".format(toolchain_prefix), "-A", binary_path]) + size_output = run_cmd(['{}size'.format(toolchain_prefix), '-A', binary_path]) # 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", '.isr_vector'], - ".rodata": [".rodata"], - ".data": [".data", ".sdata"], - ".bss": [".bss", ".sbss"], + '.text': ['.text'], + '.rodata': ['.rodata'], + '.data': ['.data', '.sdata'], + '.bss': ['.bss', '.sbss'], } sections_to_sum = section_mapping["." + section_name] section_size = 0 @@ -90,7 +90,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): # NOTE: For some reason, the size of the BSS section on the RISC-V # GCC is sometimes reported to be smaller than it is, so we need to adjust # for this. - if "riscv" in toolchain_prefix and section_name == 'bss': + if 'riscv' in toolchain_prefix and section_name == 'bss': # TODO(weberlo): Figure out why 32 is the minimum constant that works. # # The current hypothesis is that the last symbols in the ".bss" and @@ -105,7 +105,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): return section_size -@register_func("tvm_callback_relocate_binary") +@register_func('tvm_callback_relocate_binary') def tvm_callback_relocate_binary( binary_path, word_size, @@ -151,7 +151,7 @@ def tvm_callback_relocate_binary( global TEMPDIR_REFS tmp_dir = util.tempdir() TEMPDIR_REFS.append(tmp_dir) - rel_obj_path = tmp_dir.relpath("relocated.obj") + rel_obj_path = tmp_dir.relpath('relocated.obj') #rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_relocated.o' with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'r') as f: gdbinit_contents = f.read().split('\n') @@ -163,70 +163,59 @@ def tvm_callback_relocate_binary( with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: f.write('\n'.join(new_contents)) - #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: this a fukn hack - #input(f'binary path: {binary_path}') stack_pointer_init = stack_end - word_size - ld_script_contents = """ + + 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' + ld_script_contents += f""" /* linker symbol for use in UTVMInit */ -_utvm_stack_pointer_init = %s; +_utvm_stack_pointer_init = 0x{stack_pointer_init:x}; SECTIONS -{ - . = %s; - . = ALIGN(?); +{{ + . = 0x{text_start:x}; + . = ALIGN({word_size}); .text : - { - . = ALIGN(?); + {{ + . = ALIGN({word_size}); KEEP(*(.text)) KEEP(*(.text*)) - . = ALIGN(?); - } + . = ALIGN({word_size}); + }} - . = %s; - . = ALIGN(?); + . = 0x{rodata_start:x}; + . = ALIGN({word_size}); .rodata : - { - . = ALIGN(?); + {{ + . = ALIGN({word_size}); KEEP(*(.rodata)) KEEP(*(.rodata*)) - . = ALIGN(?); - } + . = ALIGN({word_size}); + }} - . = %s; - . = ALIGN(?); + . = 0x{data_start:x}; + . = ALIGN({word_size}); .data : - { - . = ALIGN(?); + {{ + . = ALIGN({word_size}); KEEP(*(.data)) KEEP(*(.data*)) - . = ALIGN(?); - } + . = ALIGN({word_size}); + }} - . = %s; - . = ALIGN(?); + . = 0x{bss_start:x}; + . = ALIGN({word_size}); .bss : - { - . = ALIGN(?); + {{ + . = ALIGN({word_size}); KEEP(*(.bss)) KEEP(*(.bss*)) - . = ALIGN(?); - } -} + . = ALIGN({word_size}); + }} +}} """ - # first, fill in ALIGN args with the target word size - ld_script_contents = ld_script_contents.replace('ALIGN(?)', f'ALIGN({word_size})') - # then fill in addrs for linker symbols and section starts - ld_script_contents = ld_script_contents % ( - f'0x{stack_pointer_init:x}', - f'0x{text_start:x}', - f'0x{rodata_start:x}', - f'0x{data_start:x}', - f'0x{bss_start:x}') print(ld_script_contents) #input('check script: ') print(f'relocing lib {binary_path}') @@ -235,21 +224,21 @@ def tvm_callback_relocate_binary( print(f' data_start: {data_start}') print(f' bss_start: {bss_start}') - rel_ld_script_path = tmp_dir.relpath("relocated.lds") - with open(rel_ld_script_path, "w") as f: + rel_ld_script_path = tmp_dir.relpath('relocated.lds') + with open(rel_ld_script_path, 'w') as f: f.write(ld_script_contents) run_cmd([ - "{}ld".format(toolchain_prefix), + '{}ld'.format(toolchain_prefix), binary_path, - "-T", rel_ld_script_path, - "-o", rel_obj_path]) + '-T', rel_ld_script_path, + '-o', rel_obj_path]) #input(f'relocated obj path is {rel_obj_path}') - with open(rel_obj_path, "rb") as f: + with open(rel_obj_path, 'rb') as f: rel_bin = bytearray(f.read()) return rel_bin -@register_func("tvm_callback_read_binary_section") +@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 @@ -270,26 +259,26 @@ def tvm_callback_read_binary_section(binary, section, toolchain_prefix): 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: + 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)) run_cmd([ - "{}objcopy".format(toolchain_prefix), - "--dump-section", - ".{}={}".format(section, tmp_section), + '{}objcopy'.format(toolchain_prefix), + '--dump-section', + '.{}={}'.format(section, tmp_section), tmp_bin]) if os.path.isfile(tmp_section): # Get section content if it exists. - with open(tmp_section, "rb") as f: + 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") + section_bin = bytearray('', 'utf-8') return section_bin -@register_func("tvm_callback_get_symbol_map") +@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 @@ -308,18 +297,18 @@ def tvm_callback_get_symbol_map(binary, toolchain_prefix): 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: + tmp_obj = tmp_dir.relpath('tmp_obj.bin') + with open(tmp_obj, 'wb') as out_file: out_file.write(bytes(binary)) nm_output = run_cmd([ - "{}nm".format(toolchain_prefix), - "-C", - "--defined-only", + '{}nm'.format(toolchain_prefix), + '-C', + '--defined-only', tmp_obj]) nm_output = nm_output.splitlines() - map_str = "" + map_str = '' for line in nm_output: line = line.split() - map_str += line[2] + "\n" - map_str += line[0] + "\n" + map_str += line[2] + '\n' + map_str += line[0] + '\n' return map_str diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 789971bff447..92e4879f13c6 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -41,27 +41,18 @@ class Session: Parameters ---------- - device_type : str - type of low-level device - - toolchain_prefix : str - toolchain prefix to be used. For example, a prefix of - "riscv64-unknown-elf-" means "riscv64-unknown-elf-gcc" is used as - the compiler and "riscv64-unknown-elf-ld" is used as the linker, - etc. + config : dict + configuration for this session (as generated by + `tvm.micro.device.host.default_config()`, for example) Example -------- .. code-block:: python c_mod = ... # some module generated with "c" as the target - dev_config = micro.device.stm32f746xx.default_config('127.0.0.1', 6666) - with tvm.micro.Session(dev_config): - c_mod.export_library( - lib_obj_path, - fcompile=tvm.micro.cross_compiler(dev_config['binutil'], - tvm.micro.LibType.OPERATOR)) - micro_mod = tvm.module.load(lib_obj_path, 'micro_dev') + dev_config = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) + with tvm.micro.Session(dev_config) as sess: + micro_mod = sess.create_micro_mod(c_mod) """ def __init__(self, config): @@ -154,9 +145,9 @@ def _check_system(self): def _check_config(self, config): """Check if the given configuration is valid.""" - #if device_type == "host": + #if device_type == 'host': # pass - #elif device_type == "openocd": + #elif device_type == 'openocd': # assert "base_addr" in args # assert "server_addr" in args # assert "port" in args diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index cceb3a90ae5a..37648841d307 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -9,6 +9,16 @@ from tvm.micro import LibType class MicroBinutil: + """Base class for GCC-specific library compilation for MicroTVM + + Parameters + ---------- + toolchain_prefix : str + toolchain prefix to be used. For example, a prefix of + "riscv64-unknown-elf-" means "riscv64-unknown-elf-gcc" is used as + the compiler and "riscv64-unknown-elf-ld" is used as the linker, + etc. + """ def __init__(self, toolchain_prefix): self._toolchain_prefix = toolchain_prefix @@ -23,12 +33,11 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): src_path : str path to source file - toolchain_prefix : str - toolchain prefix to be used + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library - include_dev_lib_header : bool - whether to include the device library header containing definitions of - library functions. + options : List[str] + additional options to pass to GCC """ print('[MicroBinutil.create_lib]') print(' EXTENDED OPTIONS') @@ -122,7 +131,15 @@ def toolchain_prefix(self): from . import arm from . import riscv_spike +# TODO use registry pattern? def get_binutil(name): + """Get matching MicroBinutil subclass from `name` + + Return + ------ + binutil : MicroBinutil + MicroBinutil subclass + """ if name == 'host': return host.HostBinutil() elif name == 'stm32f746xx': diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 3c941f6223bb..8079b2385d55 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -1,9 +1,10 @@ from .. import MicroBinutil # -# Memory layout +# [Device Memory Layout] # RAM (rwx) : START = 0x20000000, LENGTH = 320K # FLASH (rx) : START = 0x8000000, LENGTH = 1024K +# class Stm32F746XXBinutil(MicroBinutil): def __init__(self): diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index bd8a1aafe325..6dfe0d9634be 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -20,7 +20,7 @@ def main(): help="RPC key used to identify the connection type.") parser.add_argument('--tracker', type=str, default="", help="Report to RPC tracker") - parser.add_argument('--dev-config', type=str, + parser.add_argument('--dev-config', type=str, required=True, help="JSON config file for the target device") args = parser.parse_args() logging.basicConfig(level=logging.INFO) @@ -39,14 +39,11 @@ def main(): dev_config = json.load(dev_conf_file) #dev_config = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) #dev_config = micro.device.host.default_config() - # TODO remove line above - #assert False @tvm.register_func("tvm.rpc.server.start", override=True) def server_start(): session = micro.Session(dev_config) session._enter() - #_load_module = tvm.get_global_func("tvm.rpc.server.load_module") @tvm.register_func("tvm.rpc.server.shutdown", override=True) def server_shutdown(): diff --git a/python/tvm/module.py b/python/tvm/module.py index 87a402e9cda8..e8f5a4ef64a0 100644 --- a/python/tvm/module.py +++ b/python/tvm/module.py @@ -202,20 +202,10 @@ def evaluator(*args): print('[Module.time_evaluator.evaluator]') # Wrap feval so we can add more stats in future. blob = feval(*args) - if ctx.device_type == 128 + 13: # RPC micro device - fmt = "@" + ("L" * repeat) - results = struct.unpack(fmt, blob) - print(f' results: {results}') - mean = sum(results) / float(repeat) - print(f' mean: {mean}') - results = list(map(float, results)) - print(f' floated results: {results}') - return ProfileResult(mean=mean, results=results) - else: - fmt = "@" + ("d" * repeat) - results = struct.unpack(fmt, blob) - mean = sum(results) / float(repeat) - return ProfileResult(mean=mean, results=results) + fmt = "@" + ("d" * repeat) + results = struct.unpack(fmt, blob) + mean = sum(results) / float(repeat) + return ProfileResult(mean=mean, results=results) return evaluator except NameError: @@ -276,7 +266,7 @@ def load(path, fmt=""): files = [tar_temp.relpath(x) for x in tar_temp.listdir()] _cc.create_shared(path + ".so", files) path += ".so" - # TODO(weberlo): unhackify + # TODO(weberlo): we should probably use a more distinctive suffix for uTVM object files elif path.endswith(".obj"): fmt = "micro_dev" # Redirect to the load API diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 54936085ee9b..31cd62b23061 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -35,30 +35,6 @@ namespace tvm { namespace runtime { -size_t GetDefaultSectionSize(SectionKind kind) { - switch (kind) { - case SectionKind::kText: - return 0x5000; - case SectionKind::kRodata: - return 0x5000; - case SectionKind::kData: - return 0x300; - case SectionKind::kBss: - return 0x300; - case SectionKind::kArgs: - return 0x500; - case SectionKind::kHeap: - return 0x40000; - case SectionKind::kWorkspace: - return 0x5000; - case SectionKind::kStack: - return 0x50; - default: - LOG(FATAL) << "invalid section " << static_cast(kind); - return 0; - } -} - const char* SectionToString(SectionKind section) { switch (section) { case SectionKind::kText: return "text"; @@ -73,16 +49,6 @@ const char* SectionToString(SectionKind section) { } } -static std::string AddrToString(void* addr) { - std::stringstream stream; - if (addr != nullptr) - stream << addr; - else - stream << "0x0"; - std::string string_addr = stream.str(); - return string_addr; -} - std::string RelocateBinarySections( const std::string& binary_path, size_t word_size, diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 3f1394bfd568..44c520b8aa4d 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -262,11 +262,6 @@ struct BinaryContents { std::string bss_contents; }; -/*! - * \brief return default size of given section kind in bytes - */ -size_t GetDefaultSectionSize(SectionKind kind); - /*! * \brief upper-aligns value according to specified alignment * \param value value to be aligned diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 558986085dcf..c1746ce6785e 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -98,7 +98,7 @@ class MicroWrappedFunc { void operator()(TVMArgs args, TVMRetValue* rv) const { std::cout << "[MicroWrappedFunc::operator()]" << std::endl; - *rv = (int) session_->PushToExecQueue(func_ptr_, args); + *rv = session_->PushToExecQueue(func_ptr_, args); } private: diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index afc652741b85..fd475cad916f 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -212,7 +212,7 @@ MicroSession::~MicroSession() { low_level_device_ = nullptr; } -uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { +double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << "[MicroSession::PushToExecQueue]" << std::endl; if (thumb_mode_) { func_ptr += 1; @@ -282,8 +282,8 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { low_level_device()->Execute(utvm_init_addr, utvm_done_addr); - //// Check if there was an error during execution. If so, log it. - //CheckDeviceError(); + // Check if there was an error during execution. If so, log it. + CheckDeviceError(); uint64_t workspace_start = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_start"); std::cout << " workspace start: " << workspace_start << std::endl; @@ -305,7 +305,7 @@ uint32_t MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { std::cout << " --------------------------------------------------------------------------------" << std::endl; GetAllocator(SectionKind::kArgs)->Free(stream_dev_addr); - return task_time; + return static_cast(task_time); } BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_dylib_pointers) { diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index ba66ed06db39..421fb6263331 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -147,8 +147,9 @@ class MicroSession : public ModuleNode { * \brief sets up runtime metadata for `func` and copies arguments for on-device execution * \param func address of the function to be executed * \param args args to the packed function + * \return elapsed time during function execution on the device */ - uint32_t PushToExecQueue(DevPtr func, const TVMArgs& args); + double PushToExecQueue(DevPtr func, const TVMArgs& args); /*! * \brief read value of symbol from device memory @@ -187,14 +188,16 @@ class MicroSession : public ModuleNode { section_allocators_[static_cast(SectionKind::kNumKinds)]; /*! \brief total number of bytes of usable device memory for this session */ size_t memory_size_; - /*! \brief TODO */ + /*! \brief number of bytes in a word on the target device */ size_t word_size_; - /*! \brief TODO */ - // ARM and other manufacturers use the lowest bit of a function address to determine - // whether it's a "thumb mode" function. The Thumb ISA is more restricted, but - // results in more compact binaries. + /*! \brief whether the device requires a thumb-mode bit on function addresses + * + * ARM and other manufacturers use the lowest bit of a function address to determine + * whether it's a "thumb mode" function. The Thumb ISA is more restricted, but + * results in more compact binaries. + */ bool thumb_mode_; - /*! \brief TODO */ + /*! \brief symbol map for the device runtime */ SymbolMap runtime_symbol_map_; /*! @@ -203,12 +206,6 @@ class MicroSession : public ModuleNode { */ void PatchImplHole(const SymbolMap& symbol_map, const std::string& func_name); - /*! - * \brief sets the runtime binary path - * \param path to runtime binary - */ - void SetRuntimeBinaryPath(std::string path); - /*! * \brief appends arguments to the host-side buffer of `encoder` * \param encoder encoder being used to append `args` diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index b8b3939ce358..c4e7f94ef7be 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -1282,13 +1282,12 @@ PackedFunc MicroTimeEvaluator( DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); for (int i = 0; i < repeat; ++i) { - unsigned long speed = 0; + double speed = 0.0; for (int j = 0; j < number; ++j) { pf.CallPacked(args, &temp); DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); - speed += (uint32_t) (temp.operator int()); + speed += (temp.operator double()) / number; } - speed /= number; std::cout << " [[TRIAL " << i << " AVERAGE IS " << speed << "]]" << std::endl; os.write(reinterpret_cast(&speed), sizeof(speed)); } @@ -1310,7 +1309,6 @@ PackedFunc WrapTimeEvaluator(PackedFunc pf, if (ctx.device_type == kDLMicroDev) { return MicroTimeEvaluator(pf, ctx, number, repeat, min_repeat_ms); } - CHECK(false) << "not using micro time eval"; auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { TVMRetValue temp; diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 312d7fdbfc4d..2abf207dc675 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -25,8 +25,8 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -DEV_CONFIG = micro.device.host.default_config() -#DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +#DEV_CONFIG = micro.device.host.default_config() +DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) #def create_micro_mod(c_mod, dev_config): # """Produces a micro module from a given module. @@ -388,6 +388,6 @@ def test_inactive_session_use(): test_graph_runtime() test_conv2d() test_multiple_modules() - test_interleave_sessions() - test_nested_sessions() - test_inactive_session_use() + #test_interleave_sessions() + #test_nested_sessions() + #test_inactive_session_use() From 6843fb81852c19371f17fad23115543ab89c1ca1 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 14:56:17 -0800 Subject: [PATCH 37/70] garbage collect --- arm-auto-utvm-demo/tune_relay_utvm.py | 6 +- .../micro/device/stm32f746xx/utvm_init.c | 36 -- .../micro/device/stm32f746xx/utvm_init.s.bak | 589 ------------------ .../micro/device/stm32f746xx/utvm_link.ld | 87 --- .../micro/device/stm32f746xx/utvm_unit.c.bak | 278 --------- 5 files changed, 3 insertions(+), 993 deletions(-) delete mode 100644 src/runtime/micro/device/stm32f746xx/utvm_init.c delete mode 100644 src/runtime/micro/device/stm32f746xx/utvm_init.s.bak delete mode 100644 src/runtime/micro/device/stm32f746xx/utvm_link.ld delete mode 100644 src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index ed4b38da04b2..b61114850dad 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -32,10 +32,10 @@ from vta.top import graph_pack # first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal -# then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro` in another +# then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro --dev-config=` in another -#DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) -DEV_CONFIG = micro.device.host.default_config() +DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +#DEV_CONFIG = micro.device.host.default_config() DEVICE = 'arm-cortex-m' TARGET = tvm.target.create('c -device=micro_dev') diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.c b/src/runtime/micro/device/stm32f746xx/utvm_init.c deleted file mode 100644 index 306bc34b0c0f..000000000000 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.c +++ /dev/null @@ -1,36 +0,0 @@ -//#include "stm32f7xx.h" - -//extern char _stext; -void _UTVMInit(void) -{ -// /* FPU settings ------------------------------------------------------------*/ -// #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) -// SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ -// #endif -// /* Reset the RCC clock configuration to the default reset state ------------*/ -// /* Set HSION bit */ -// RCC->CR |= (uint32_t)0x00000001; -// -// /* Reset CFGR register */ -// RCC->CFGR = 0x00000000; -// -// /* Reset HSEON, CSSON and PLLON bits */ -// RCC->CR &= (uint32_t)0xFEF6FFFF; -// -// /* Reset PLLCFGR register */ -// RCC->PLLCFGR = 0x24003010; -// -// /* Reset HSEBYP bit */ -// RCC->CR &= (uint32_t)0xFFFBFFFF; -// -// /* Disable all interrupts */ -// RCC->CIR = 0x00000000; -// -// /* Configure the Vector Table location add offset address ------------------*/ -//#ifdef VECT_TAB_SRAM -// SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -//#else -// SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -//#endif - //SCB->VTOR = &_stext; /* Vector Table Relocation in Internal SRAM */ -} diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.s.bak b/src/runtime/micro/device/stm32f746xx/utvm_init.s.bak deleted file mode 100644 index 5eda6ab09b4f..000000000000 --- a/src/runtime/micro/device/stm32f746xx/utvm_init.s.bak +++ /dev/null @@ -1,589 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32f746xx.s - * @author MCD Application Team - * @brief STM32F746xx Devices vector table for GCC based toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M7 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m7 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M7. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* Reserved */ - .word RNG_IRQHandler /* Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word SPI6_IRQHandler /* SPI6 */ - .word SAI1_IRQHandler /* SAI1 */ - .word LTDC_IRQHandler /* LTDC */ - .word LTDC_ER_IRQHandler /* LTDC error */ - .word DMA2D_IRQHandler /* DMA2D */ - .word SAI2_IRQHandler /* SAI2 */ - .word QUADSPI_IRQHandler /* QUADSPI */ - .word LPTIM1_IRQHandler /* LPTIM1 */ - .word CEC_IRQHandler /* HDMI_CEC */ - .word I2C4_EV_IRQHandler /* I2C4 Event */ - .word I2C4_ER_IRQHandler /* I2C4 Error */ - .word SPDIF_RX_IRQHandler /* SPDIF_RX */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak LTDC_IRQHandler - .thumb_set LTDC_IRQHandler,Default_Handler - - .weak LTDC_ER_IRQHandler - .thumb_set LTDC_ER_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak CEC_IRQHandler - .thumb_set CEC_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler - .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak SPDIF_RX_IRQHandler - .thumb_set SPDIF_RX_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - diff --git a/src/runtime/micro/device/stm32f746xx/utvm_link.ld b/src/runtime/micro/device/stm32f746xx/utvm_link.ld deleted file mode 100644 index c90c140dd19d..000000000000 --- a/src/runtime/micro/device/stm32f746xx/utvm_link.ld +++ /dev/null @@ -1,87 +0,0 @@ -/* -***************************************************************************** -** - -** File : LinkerScript.ld -** -** Abstract : Linker script for STM32F746ZGTx Device with -** 1024KByte FLASH, 320KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** -** Distribution: The file is distributed as is, without any warranty -** of any kind. -** -** (c)Copyright Ac6. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Ac6 permit registered System Workbench for MCU users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the System Workbench for MCU toolchain. -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(UTVMInit) - -/* Highest address of the user mode stack */ -_estack = 0x20050000; /* end of RAM */ - -/* Specify the memory areas */ -MEMORY -{ -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K -FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K -} - -/* Define output sections */ -SECTIONS -{ - /* . = %s; */ - . = ALIGN(4); - .text : - { - . = ALIGN(4); - *(.text) - *(.text*) - . = ALIGN(4); - } >RAM - - /* . = %s; */ - . = ALIGN(4); - .rodata : - { - . = ALIGN(4); - *(.rodata) - *(.rodata*) - . = ALIGN(4); - } >RAM - - /* . = %s; */ - . = ALIGN(4); - .data : - { - . = ALIGN(4); - *(.data) - *(.data*) - . = ALIGN(4); - } >RAM - - /* . = %s; */ - . = ALIGN(4); - .bss : - { - . = ALIGN(4); - *(.bss) - *(.bss*) - . = ALIGN(4); - } >RAM -} diff --git a/src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak b/src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak deleted file mode 100644 index 1a362bdf618f..000000000000 --- a/src/runtime/micro/device/stm32f746xx/utvm_unit.c.bak +++ /dev/null @@ -1,278 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32f7xx.c - * @author MCD Application Team - * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. - * - * This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f7xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f7xx_system - * @{ - */ - -/** @addtogroup STM32F7xx_System_Private_Includes - * @{ - */ - -#include "stm32f7xx.h" - -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Defines - * @{ - */ - -/************************* Miscellaneous Configuration ************************/ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Variables - * @{ - */ - - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ - uint32_t SystemCoreClock = 16000000; - const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F7xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemFrequency variable. - * @param None - * @retval None - */ -void SystemInit(void) -{ - /* FPU settings ------------------------------------------------------------*/ - #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif - /* Reset the RCC clock configuration to the default reset state ------------*/ - /* Set HSION bit */ - RCC->CR |= (uint32_t)0x00000001; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000; - - /* Reset HSEON, CSSON and PLLON bits */ - RCC->CR &= (uint32_t)0xFEF6FFFF; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = 0x24003010; - - /* Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /* Disable all interrupts */ - RCC->CIR = 0x00000000; - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value - * 25 MHz), user has to ensure that HSE_VALUE is same as the real - * frequency of the crystal used. Otherwise, this function may - * have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From feeb3b8e57876d62ddaf674e617ef96428d14fb6 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 16:54:56 -0800 Subject: [PATCH 38/70] cleanup --- python/tvm/micro/__init__.py | 2 +- python/tvm/micro/base.py | 21 ++---- python/tvm/micro/device/__init__.py | 78 +++++++++------------- python/tvm/micro/device/arm/stm32f746xx.py | 6 +- python/tvm/micro/device/host.py | 6 +- 5 files changed, 47 insertions(+), 66 deletions(-) diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 0d86867f5404..ebf8b470df4a 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -23,5 +23,5 @@ """ from ..contrib import binutil -from .base import LibType, Session, cross_compiler +from .base import Session, cross_compiler, LibType, get_micro_host_driven_dir, get_micro_device_dir from . import device diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 92e4879f13c6..051920ab24f6 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -57,8 +57,9 @@ class Session: def __init__(self, config): self._check_system() - self._check_config(config) + # TODO(weberlo): add config validation + # grab a binutil instance from the ID in the config self.binutil = tvm.micro.device.get_binutil(config['binutil']) self.mem_layout = config['mem_layout'] self.word_size = config['word_size'] @@ -66,7 +67,7 @@ def __init__(self, config): self.comms_method = config['comms_method'] # First, find and compile runtime library. - runtime_src_path = os.path.join(_get_micro_host_driven_dir(), 'utvm_runtime.c') + runtime_src_path = os.path.join(get_micro_host_driven_dir(), 'utvm_runtime.c') tmp_dir = _util.tempdir() runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) @@ -143,15 +144,6 @@ def _check_system(self): if sys.maxsize <= 2**32: raise RuntimeError('MicroTVM is currently only supported on 64-bit platforms') - def _check_config(self, config): - """Check if the given configuration is valid.""" - #if device_type == 'host': - # pass - #elif device_type == 'openocd': - # assert "base_addr" in args - # assert "server_addr" in args - # assert "port" in args - def __enter__(self): self._enter() return self @@ -167,7 +159,8 @@ def cross_compiler(dev_binutil, lib_type): Parameters ---------- - lib_type: DFSDF + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library Return ------ @@ -195,7 +188,7 @@ def compile_func(obj_path, src_path, **kwargs): return _cc.cross_compiler(compile_func, output_format='obj') -def _get_micro_host_driven_dir(): +def get_micro_host_driven_dir(): """Get directory path for uTVM host-driven runtime source files. Return @@ -209,7 +202,7 @@ def _get_micro_host_driven_dir(): return micro_host_driven_dir -def _get_micro_device_dir(): +def get_micro_device_dir(): """Get directory path for TODO Return diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index 37648841d307..23b965f82a8a 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -6,7 +6,35 @@ from tvm.contrib import util as _util from tvm.contrib.binutil import run_cmd from tvm._ffi.libinfo import find_include_path -from tvm.micro import LibType +from tvm.micro import LibType, get_micro_host_driven_dir, get_micro_device_dir + +BINUTIL_REGISTRY = {} + +def register_binutil(binutil): + name = binutil.device_id() + if name in BINUTIL_REGISTRY: + raise RuntimeError(f'"{name}" already exists in the binutil registry') + BINUTIL_REGISTRY[name] = binutil + + +def get_binutil(device_id): + """Get matching MicroBinutil subclass from `device_id` + + Parameters + ---------- + device_id : str + unique identifier for the target device + + Return + ------ + binutil : MicroBinutil + MicroBinutil subclass + """ + if device_id not in BINUTIL_REGISTRY: + raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') + binutil = BINUTIL_REGISTRY[device_id] + return binutil() + class MicroBinutil: """Base class for GCC-specific library compilation for MicroTVM @@ -64,12 +92,12 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): base_compile_cmd += options src_paths = [] - include_paths = find_include_path() + [_get_micro_host_driven_dir()] + include_paths = find_include_path() + [get_micro_host_driven_dir()] ld_script_path = None tmp_dir = _util.tempdir() if lib_type == LibType.RUNTIME: import glob - dev_dir = _get_micro_device_dir() + '/' + self.device_id() + dev_dir = get_micro_device_dir() + '/' + self.__class__.device_id() print(dev_dir) dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') @@ -131,47 +159,3 @@ def toolchain_prefix(self): from . import arm from . import riscv_spike -# TODO use registry pattern? -def get_binutil(name): - """Get matching MicroBinutil subclass from `name` - - Return - ------ - binutil : MicroBinutil - MicroBinutil subclass - """ - if name == 'host': - return host.HostBinutil() - elif name == 'stm32f746xx': - return arm.stm32f746xx.Stm32F746XXBinutil() - else: - assert False - - -def _get_micro_host_driven_dir(): - """Get directory path for uTVM host-driven runtime source files. - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, '..', '..', '..', '..', - 'src', 'runtime', 'micro', 'host_driven') - return micro_host_driven_dir - - -def _get_micro_device_dir(): - """Get directory path for TODO - - Return - ------ - micro_device_dir : str - directory path - """ - micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, "..", "..", "..", "..", - "src", "runtime", "micro", "device") - return micro_device_dir - diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 8079b2385d55..f1b60401a918 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -1,4 +1,4 @@ -from .. import MicroBinutil +from .. import MicroBinutil, register_binutil # # [Device Memory Layout] @@ -23,10 +23,12 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): ] super(Stm32F746XXBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) - def device_id(self): + def device_id(): return 'stm32f746xx' +register_binutil(Stm32F746XXBinutil) + def default_config(server_addr, server_port): return { 'binutil': 'stm32f746xx', diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 6bcc1760b6f8..2cb146015efd 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -1,6 +1,6 @@ import sys -from . import MicroBinutil +from . import MicroBinutil, register_binutil class HostBinutil(MicroBinutil): def __init__(self): @@ -13,10 +13,12 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): options += ['-mcmodel=large'] super(HostBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) - def device_id(self): + def device_id(): return 'host' +register_binutil(HostBinutil) + def default_config(): return { 'binutil': 'host', From 097528b6cb92c6c4a5d4ec35372a9ba16bc95bac Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 17:30:15 -0800 Subject: [PATCH 39/70] clean --- python/tvm/micro/base.py | 9 ++-- python/tvm/micro/device/__init__.py | 9 ++-- python/tvm/micro/device/arm/stm32f746xx.py | 4 +- src/codegen/codegen_c_host.cc | 30 +++++++----- src/codegen/codegen_c_host.h | 4 +- src/relay/backend/graph_runtime_codegen.cc | 3 -- .../device/{ => arm}/stm32f746xx/utvm_init.s | 0 .../stm32f746xx/utvm_timer.c} | 0 .../device/host/{utvm_api.c => utvm_timer.c} | 2 +- src/runtime/micro/host_driven/utvm_runtime.c | 8 ++-- src/runtime/micro/micro_common.cc | 4 +- src/runtime/micro/micro_common.h | 47 +++---------------- tests/python/unittest/test_runtime_micro.py | 30 ------------ 13 files changed, 48 insertions(+), 102 deletions(-) rename src/runtime/micro/device/{ => arm}/stm32f746xx/utvm_init.s (100%) rename src/runtime/micro/device/{stm32f746xx/utvm_api.c => arm/stm32f746xx/utvm_timer.c} (100%) rename src/runtime/micro/device/host/{utvm_api.c => utvm_timer.c} (95%) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 051920ab24f6..9e865b7720f5 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -153,12 +153,15 @@ def __exit__(self, exc_type, exc_value, exc_traceback): def cross_compiler(dev_binutil, lib_type): - """Creates a cross compile function that wraps `create_micro_lib`. + """Create a cross compile function that wraps `create_lib` for a `Binutil` instance. For use in `tvm.module.Module.export_library`. Parameters ---------- + dev_binutil : Union[MicroBinutil, str] + a `MicroBinutil` subclass or a string ID for a registered binutil class + lib_type : micro.LibType whether to compile a MicroTVM runtime or operator library @@ -173,7 +176,7 @@ def cross_compiler(dev_binutil, lib_type): .. code-block:: python c_mod = ... # some module generated with "c" as the target - fcompile = tvm.micro.cross_compiler(lib_type=LibType.OPERATOR) + fcompile = tvm.micro.cross_compiler('arm.stm32f746xx', LibType.OPERATOR) c_mod.export_library('dev_lib.obj', fcompile=fcompile) """ if isinstance(dev_binutil, str): @@ -203,7 +206,7 @@ def get_micro_host_driven_dir(): def get_micro_device_dir(): - """Get directory path for TODO + """Get directory path for parent directory of device-specific source files Return ------ diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index 23b965f82a8a..f0b9c5ead16e 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -1,3 +1,4 @@ +import glob import os import sys from enum import Enum @@ -96,8 +97,7 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): ld_script_path = None tmp_dir = _util.tempdir() if lib_type == LibType.RUNTIME: - import glob - dev_dir = get_micro_device_dir() + '/' + self.__class__.device_id() + dev_dir = self._get_device_source_dir() print(dev_dir) dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') @@ -139,6 +139,10 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): ld_cmd += ['-o', obj_path] run_cmd(ld_cmd) + def _get_device_source_dir(self): + dev_subdir = '/'.join(self.__class__.device_id().split('.')) + return get_micro_device_dir() + '/' + dev_subdir + def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) i = 2 @@ -158,4 +162,3 @@ def toolchain_prefix(self): from . import host from . import arm from . import riscv_spike - diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index f1b60401a918..6c2cc0580012 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -24,14 +24,14 @@ def create_lib(self, obj_path, src_path, lib_type, options=None): super(Stm32F746XXBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) def device_id(): - return 'stm32f746xx' + return 'arm.stm32f746xx' register_binutil(Stm32F746XXBinutil) def default_config(server_addr, server_port): return { - 'binutil': 'stm32f746xx', + 'binutil': 'arm.stm32f746xx', 'mem_layout': { 'text': { 'start': 0x20000180, diff --git a/src/codegen/codegen_c_host.cc b/src/codegen/codegen_c_host.cc index 063962a91ffe..9c099a425fd6 100644 --- a/src/codegen/codegen_c_host.cc +++ b/src/codegen/codegen_c_host.cc @@ -33,7 +33,8 @@ CodeGenCHost::CodeGenCHost() { module_name_ = GetUniqueName("__tvm_module_ctx"); } -void CodeGenCHost::Init(bool output_ssa) { +void CodeGenCHost::Init(bool output_ssa, bool emit_asserts) { + emit_asserts_ = emit_asserts; decl_stream << "#include \"tvm/runtime/c_runtime_api.h\"\n"; decl_stream << "#include \"tvm/runtime/c_backend_api.h\"\n"; decl_stream << "extern void* " << module_name_ << " = NULL;\n"; @@ -237,17 +238,19 @@ void CodeGenCHost::VisitExpr_(const Call *op, std::ostream& os) { // NOLINT(*) } void CodeGenCHost::VisitStmt_(const AssertStmt *op) { // NOLINT(*) - //std::string cond = PrintExpr(op->condition); - //PrintIndent(); - //stream << "if (!(" << cond << ")) {\n"; - //int assert_if_scope = this->BeginScope(); - //PrintIndent(); - //stream << "TVMAPISetLastError(\"" << op->message.as()->value << "\");\n"; - //PrintIndent(); - //stream << "return -1;\n"; - //this->EndScope(assert_if_scope); - //PrintIndent(); - //stream << "}\n"; + if (emit_asserts_) { + std::string cond = PrintExpr(op->condition); + PrintIndent(); + stream << "if (!(" << cond << ")) {\n"; + int assert_if_scope = this->BeginScope(); + PrintIndent(); + stream << "TVMAPISetLastError(\"" << op->message.as()->value << "\");\n"; + PrintIndent(); + stream << "return -1;\n"; + this->EndScope(assert_if_scope); + PrintIndent(); + stream << "}\n"; + } this->PrintStmt(op->body); } @@ -277,8 +280,9 @@ inline void CodeGenCHost::PrintTernaryCondExpr(const T* op, runtime::Module BuildCHost(Array funcs) { using tvm::runtime::Registry; bool output_ssa = false; + bool emit_asserts = false; CodeGenCHost cg; - cg.Init(output_ssa); + cg.Init(output_ssa, emit_asserts); for (LoweredFunc f : funcs) { cg.AddFunction(f); } diff --git a/src/codegen/codegen_c_host.h b/src/codegen/codegen_c_host.h index 1b3271fd2c6b..80e359c33ce0 100644 --- a/src/codegen/codegen_c_host.h +++ b/src/codegen/codegen_c_host.h @@ -35,7 +35,7 @@ namespace codegen { class CodeGenCHost final : public CodeGenC { public: CodeGenCHost(); - void Init(bool output_ssa); + void Init(bool output_ssa, bool emit_asserts); void AddFunction(LoweredFunc f); std::string Finish(); @@ -53,6 +53,8 @@ class CodeGenCHost final : public CodeGenC { private: std::string module_name_; + /*! \brief whether to emit asserts in the resulting C code */ + bool emit_asserts_; void PrintGetFuncFromBackend(const std::string& func_name, const std::string& packed_func_name); void PrintFuncCall(const std::string& packed_func_name, int num_args); diff --git a/src/relay/backend/graph_runtime_codegen.cc b/src/relay/backend/graph_runtime_codegen.cc index b8a3c75d0264..e2881785766c 100644 --- a/src/relay/backend/graph_runtime_codegen.cc +++ b/src/relay/backend/graph_runtime_codegen.cc @@ -201,7 +201,6 @@ class GraphRuntimeCodegen auto pf = GetPackedFunc("relay.backend.GraphPlanMemory"); storage_device_map_ = (*pf)(func); // First we convert all the parameters into input nodes. - std::cout << "we have " << func->params.size() << " params" << std::endl; for (auto param : func->params) { auto node_ptr = GraphInputNode::make_node_ptr(param->name_hint(), GraphAttrs()); var_map_[param.get()] = AddNode(node_ptr, param); @@ -213,7 +212,6 @@ class GraphRuntimeCodegen LoweredOutput ret; ret.graph_json = os.str(); ret.params = params_; - std::cout << "we have " << lowered_funcs_.size() << " lowered funcs" << std::endl; for (auto& kv : lowered_funcs_) { if (ret.lowered_funcs.count(kv.first) == 0) { ret.lowered_funcs.Set(kv.first, Array()); @@ -228,7 +226,6 @@ class GraphRuntimeCodegen } ret.lowered_funcs.Set(kv.first, tmp); } - std::cout << "finished codegen" << std::endl; return ret; } diff --git a/src/runtime/micro/device/stm32f746xx/utvm_init.s b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s similarity index 100% rename from src/runtime/micro/device/stm32f746xx/utvm_init.s rename to src/runtime/micro/device/arm/stm32f746xx/utvm_init.s diff --git a/src/runtime/micro/device/stm32f746xx/utvm_api.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c similarity index 100% rename from src/runtime/micro/device/stm32f746xx/utvm_api.c rename to src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c diff --git a/src/runtime/micro/device/host/utvm_api.c b/src/runtime/micro/device/host/utvm_timer.c similarity index 95% rename from src/runtime/micro/device/host/utvm_api.c rename to src/runtime/micro/device/host/utvm_timer.c index c88c98a80561..9e8664e604e4 100644 --- a/src/runtime/micro/device/host/utvm_api.c +++ b/src/runtime/micro/device/host/utvm_timer.c @@ -18,7 +18,7 @@ void UTVMTimerStop() { } void UTVMTimerReset() { } uint32_t UTVMTimerRead() { - return 420; + return 1; } #ifdef __cplusplus diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 2bbd6015f9c7..7e52a8b3f62e 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -46,13 +46,13 @@ size_t utvm_word_size = 0; // NOLINT(*) // These pointers are patched at load time to point to the workspace section. char* utvm_workspace_start = NULL; // NOLINT(*) -char* utvm_workspace_end = NULL; // NOLINT(*) -char* utvm_workspace_curr = NULL; // NOLINT(*) +char* utvm_workspace_end = NULL; // NOLINT(*) +char* utvm_workspace_curr = NULL; // NOLINT(*) // Keep track of how many active allocations there are on the workspace. size_t utvm_num_active_allocs = 0; const char* utvm_last_error = NULL; // NOLINT(*) -int32_t utvm_return_code = 0; // NOLINT(*) +int32_t utvm_return_code = 0; // NOLINT(*) uint32_t utvm_task_time = 0; @@ -66,7 +66,7 @@ void UTVMMain() { UTVMTimerReset(); UTVMTimerStart(); utvm_return_code = utvm_task.func( - (void*) utvm_task.arg_values, // NOLINT(*) + (void*) utvm_task.arg_values, // NOLINT(*) (void*) utvm_task.arg_type_codes, // NOLINT(*) utvm_task.num_args); UTVMTimerStop(); diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 31cd62b23061..632b6048b182 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -56,7 +56,7 @@ std::string RelocateBinarySections( DevPtr rodata_start, DevPtr data_start, DevPtr bss_start, - DevPtr stack_end_start, + DevPtr stack_end, const std::string& toolchain_prefix) { const auto* f = Registry::Get("tvm_callback_relocate_binary"); CHECK(f != nullptr) @@ -67,7 +67,7 @@ std::string RelocateBinarySections( rodata_start.cast_to(), data_start.cast_to(), bss_start.cast_to(), - stack_end_start.cast_to(), + stack_end.cast_to(), toolchain_prefix); return relocated_bin; } diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 44c520b8aa4d..f3c4d1e5c815 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -128,41 +128,6 @@ class DevPtr : public DeviceLocation { } }; -///*! \brief offset from device base address */ -//class DevBaseOffset : public DeviceLocation { -// public: -// /*! \brief construct a base offset with value `value` */ -// explicit DevBaseOffset(std::uintptr_t value) : DeviceLocation(value) {} -// -// /*! \brief default constructor */ -// DevBaseOffset() : DeviceLocation() {} -// -// /*! \brief construct a null base offset */ -// explicit DevBaseOffset(std::nullptr_t value) : DeviceLocation(value) {} -// -// /*! \brief add an integer to this base offset to get a larger base offset */ -// DevBaseOffset operator+(size_t n) const { -// return DevBaseOffset(value_ + n); -// } -// -// /*! \brief mutably add an integer to this base offset */ -// DevBaseOffset& operator+=(size_t n) { -// value_ += n; -// return *this; -// } -// -// /*! \brief subtract an integer from this base offset to get a smaller base offset */ -// DevBaseOffset operator-(size_t n) const { -// return DevBaseOffset(value_ - n); -// } -// -// /*! \brief mutably subtract an integer from this base offset */ -// DevBaseOffset& operator-=(size_t n) { -// value_ -= n; -// return *this; -// } -//}; - /*! * \brief map from symbols to their on-device offsets */ @@ -283,10 +248,12 @@ const char* SectionToString(SectionKind section); /*! * \brief links binary by repositioning section addresses * \param binary_name input binary filename - * \param text new text section address - * \param rodata new rodata section address - * \param data new data section address - * \param bss new bss section address + * \param word_size word size on the target machine + * \param text_start text section address + * \param rodata_start rodata section address + * \param data_start data section address + * \param bss_start bss section address + * \param stack_end stack section end address * \param toolchain_prefix prefix of compiler toolchain to use * \return relocated binary file contents */ @@ -297,7 +264,7 @@ std::string RelocateBinarySections( DevPtr rodata_start, DevPtr data_start, DevPtr bss_start, - DevPtr stack_end_start, + DevPtr stack_end, const std::string& toolchain_prefix); /*! diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 2abf207dc675..2f89e3cdc8bf 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -28,32 +28,6 @@ #DEV_CONFIG = micro.device.host.default_config() DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) -#def create_micro_mod(c_mod, dev_config): -# """Produces a micro module from a given module. -# -# Parameters -# ---------- -# c_mod : tvm.module.Module -# module with "c" as its target backend -# -# toolchain_prefix : str -# toolchain prefix to be used (see `tvm.micro.Session` docs) -# -# Return -# ------ -# micro_mod : tvm.module.Module -# micro module for the target device -# """ -# print('[create_micro_mod]') -# temp_dir = util.tempdir() -# lib_obj_path = temp_dir.relpath("dev_lib.obj") -# c_mod.export_library( -# lib_obj_path, -# fcompile=tvm.micro.cross_compiler(dev_config['binutil'], micro.LibType.OPERATOR)) -# micro_mod = tvm.module.load(lib_obj_path) -# return micro_mod - - def relay_micro_build(func, sess, params=None): """Create a graph runtime module with a micro device context from a Relay function. @@ -99,10 +73,6 @@ def reset_gdbinit(): f.write(gdbinit_contents) -# TODO(weberlo): Add example program to test scalar double/int TVMValue serialization. -# TODO(weberlo): How can we test the OpenOCD device? The CI would need to have OpenOCD -# and Spike installed. - def test_alloc(): """Test tensor allocation on the device.""" if not tvm.module.enabled("micro_dev"): From b609e7667b61729d46f7b39f6b684d38d833d859 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 6 Nov 2019 18:06:16 -0800 Subject: [PATCH 40/70] refactor and docs --- python/tvm/micro/__init__.py | 8 +- python/tvm/micro/base.py | 3 +- python/tvm/micro/device/__init__.py | 180 +++------------------ python/tvm/micro/device/arm/__init__.py | 18 +++ python/tvm/micro/device/arm/stm32f746xx.py | 18 +++ python/tvm/micro/device/base.py | 171 ++++++++++++++++++++ python/tvm/micro/device/host.py | 18 +++ 7 files changed, 246 insertions(+), 170 deletions(-) create mode 100644 python/tvm/micro/device/base.py diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index ebf8b470df4a..73612b3c4b43 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -14,13 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - -"""uTVM module for bare-metal backends. - -uTVM (or the micro backend) enables provides support for bare-metal devices. -Its targets currently include a host-emulated device which is used for testing, -and JTAG-based openocd device which allows actual interfacing with microdevices. -""" +"""MicroTVM module for bare-metal backends""" from ..contrib import binutil from .base import Session, cross_compiler, LibType, get_micro_host_driven_dir, get_micro_device_dir diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 9e865b7720f5..c3267ac54cdf 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -14,8 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - -"""Base definitions for micro.""" +"""Base definitions for MicroTVM""" from __future__ import absolute_import diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index f0b9c5ead16e..bf9d85cb3b1b 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -1,164 +1,22 @@ -import glob -import os -import sys -from enum import Enum -from pathlib import Path - -from tvm.contrib import util as _util -from tvm.contrib.binutil import run_cmd -from tvm._ffi.libinfo import find_include_path -from tvm.micro import LibType, get_micro_host_driven_dir, get_micro_device_dir - -BINUTIL_REGISTRY = {} - -def register_binutil(binutil): - name = binutil.device_id() - if name in BINUTIL_REGISTRY: - raise RuntimeError(f'"{name}" already exists in the binutil registry') - BINUTIL_REGISTRY[name] = binutil - - -def get_binutil(device_id): - """Get matching MicroBinutil subclass from `device_id` - - Parameters - ---------- - device_id : str - unique identifier for the target device - - Return - ------ - binutil : MicroBinutil - MicroBinutil subclass - """ - if device_id not in BINUTIL_REGISTRY: - raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') - binutil = BINUTIL_REGISTRY[device_id] - return binutil() - - -class MicroBinutil: - """Base class for GCC-specific library compilation for MicroTVM - - Parameters - ---------- - toolchain_prefix : str - toolchain prefix to be used. For example, a prefix of - "riscv64-unknown-elf-" means "riscv64-unknown-elf-gcc" is used as - the compiler and "riscv64-unknown-elf-ld" is used as the linker, - etc. - """ - def __init__(self, toolchain_prefix): - self._toolchain_prefix = toolchain_prefix - - def create_lib(self, obj_path, src_path, lib_type, options=None): - """Compiles code into a binary for the target micro device. - - Parameters - ---------- - obj_path : Optional[str] - path to generated object file (defaults to same directory as `src_path`) - - src_path : str - path to source file - - lib_type : micro.LibType - whether to compile a MicroTVM runtime or operator library - - options : List[str] - additional options to pass to GCC - """ - print('[MicroBinutil.create_lib]') - print(' EXTENDED OPTIONS') - print(f' {obj_path}') - print(f' {src_path}') - print(f' {lib_type}') - print(f' {options}') - base_compile_cmd = [ - f'{self.toolchain_prefix()}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - ] - if options is not None: - base_compile_cmd += options - - src_paths = [] - include_paths = find_include_path() + [get_micro_host_driven_dir()] - ld_script_path = None - tmp_dir = _util.tempdir() - if lib_type == LibType.RUNTIME: - dev_dir = self._get_device_source_dir() - - print(dev_dir) - dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') - print(dev_src_paths) - # there needs to at least be a utvm_timer.c file - assert dev_src_paths - - src_paths += dev_src_paths - elif lib_type == LibType.OPERATOR: - # Create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - temp_src_path = tmp_dir.relpath('temp.c') - with open(src_path, 'r') as f: - src_lines = f.read().splitlines() - src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') - with open(temp_src_path, 'w') as f: - f.write('\n'.join(src_lines)) - src_path = temp_src_path - - base_compile_cmd += ['-c'] - else: - raise RuntimeError('unknown lib type') - - src_paths += [src_path] - - print(f'include paths: {include_paths}') - for path in include_paths: - base_compile_cmd += ['-I', path] - - prereq_obj_paths = [] - for src_path in src_paths: - curr_obj_path = self._get_unique_obj_name(src_path, prereq_obj_paths, tmp_dir) - prereq_obj_paths.append(curr_obj_path) - curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] - run_cmd(curr_compile_cmd) - - ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] - ld_cmd += prereq_obj_paths - ld_cmd += ['-o', obj_path] - run_cmd(ld_cmd) - - def _get_device_source_dir(self): - dev_subdir = '/'.join(self.__class__.device_id().split('.')) - return get_micro_device_dir() + '/' + dev_subdir - - def _get_unique_obj_name(self, src_path, obj_paths, tmp_dir): - res = tmp_dir.relpath(Path(src_path).with_suffix('.o').name) - i = 2 - # if the name collides, try increasing numeric suffixes until the name doesn't collide - while res in obj_paths: - res = tmp_dir.relpath(Path(os.path.basename(src_path).split('.')[0] + str(i)).with_suffix('.o').name) - i += 1 - return res - - def device_id(self): - raise RuntimeError('no device ID for abstract MicroBinutil') - - def toolchain_prefix(self): - return self._toolchain_prefix - - +# 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. +"""Device-specific configuration for MicroTVM""" + +from .base import register_binutil, get_binutil, MicroBinutil from . import host from . import arm from . import riscv_spike diff --git a/python/tvm/micro/device/arm/__init__.py b/python/tvm/micro/device/arm/__init__.py index c0f979b4c02a..be323b9e0a2b 100644 --- a/python/tvm/micro/device/arm/__init__.py +++ b/python/tvm/micro/device/arm/__init__.py @@ -1 +1,19 @@ +# 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. +"""Base module for ARM device configurations""" + from . import stm32f746xx diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 6c2cc0580012..2829c463ca0d 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -1,3 +1,21 @@ +# 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. +"""Config definitions for ARM STM32F746XX devices""" + from .. import MicroBinutil, register_binutil # diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py new file mode 100644 index 000000000000..28151f22b66e --- /dev/null +++ b/python/tvm/micro/device/base.py @@ -0,0 +1,171 @@ +# 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. +"""Base definitions for MicroTVM config""" + +import glob +import os +import sys +from enum import Enum +from pathlib import Path + +from tvm.contrib import util as _util +from tvm.contrib.binutil import run_cmd +from tvm._ffi.libinfo import find_include_path +from tvm.micro import LibType, get_micro_host_driven_dir, get_micro_device_dir + +BINUTIL_REGISTRY = {} + +def register_binutil(binutil): + name = binutil.device_id() + if name in BINUTIL_REGISTRY: + raise RuntimeError(f'"{name}" already exists in the binutil registry') + BINUTIL_REGISTRY[name] = binutil + + +def get_binutil(device_id): + """Get matching MicroBinutil subclass from `device_id` + + Parameters + ---------- + device_id : str + unique identifier for the target device + + Return + ------ + binutil : MicroBinutil + MicroBinutil subclass + """ + if device_id not in BINUTIL_REGISTRY: + raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') + binutil = BINUTIL_REGISTRY[device_id] + return binutil() + + +class MicroBinutil: + """Base class for GCC-specific library compilation for MicroTVM + + Parameters + ---------- + toolchain_prefix : str + toolchain prefix to be used. For example, a prefix of + "riscv64-unknown-elf-" means "riscv64-unknown-elf-gcc" is used as + the compiler and "riscv64-unknown-elf-ld" is used as the linker, + etc. + """ + def __init__(self, toolchain_prefix): + self._toolchain_prefix = toolchain_prefix + + def create_lib(self, obj_path, src_path, lib_type, options=None): + """Compiles code into a binary for the target micro device. + + Parameters + ---------- + obj_path : Optional[str] + path to generated object file (defaults to same directory as `src_path`) + + src_path : str + path to source file + + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library + + options : List[str] + additional options to pass to GCC + """ + print('[MicroBinutil.create_lib]') + print(' EXTENDED OPTIONS') + print(f' {obj_path}') + print(f' {src_path}') + print(f' {lib_type}') + print(f' {options}') + base_compile_cmd = [ + f'{self.toolchain_prefix()}gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-c', + '-O0', + '-g', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + ] + if options is not None: + base_compile_cmd += options + + src_paths = [] + include_paths = find_include_path() + [get_micro_host_driven_dir()] + ld_script_path = None + tmp_dir = _util.tempdir() + if lib_type == LibType.RUNTIME: + dev_dir = self._get_device_source_dir() + + print(dev_dir) + dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + print(dev_src_paths) + # there needs to at least be a utvm_timer.c file + assert dev_src_paths + assert 'utvm_timer.c' in map(os.path.basename, dev_src_paths) + + src_paths += dev_src_paths + elif lib_type == LibType.OPERATOR: + # create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath('temp.c') + with open(src_path, 'r') as f: + src_lines = f.read().splitlines() + src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') + with open(temp_src_path, 'w') as f: + f.write('\n'.join(src_lines)) + src_path = temp_src_path + + base_compile_cmd += ['-c'] + else: + raise RuntimeError('unknown lib type') + + src_paths += [src_path] + + print(f'include paths: {include_paths}') + for path in include_paths: + base_compile_cmd += ['-I', path] + + prereq_obj_paths = [] + for src_path in src_paths: + curr_obj_path = Path(src_path).with_suffix('.o').name + assert curr_obj_path not in prereq_obj_paths + prereq_obj_paths.append(curr_obj_path) + curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + run_cmd(curr_compile_cmd) + + ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] + ld_cmd += prereq_obj_paths + ld_cmd += ['-o', obj_path] + run_cmd(ld_cmd) + + def _get_device_source_dir(self): + """Grabs the source directory for device-specific uTVM files""" + dev_subdir = '/'.join(self.__class__.device_id().split('.')) + return get_micro_device_dir() + '/' + dev_subdir + + def device_id(self): + raise RuntimeError('no device ID for abstract MicroBinutil') + + def toolchain_prefix(self): + return self._toolchain_prefix diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 2cb146015efd..447f1d7c7304 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -1,3 +1,21 @@ +# 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. +"""Config for the host emulated device""" + import sys from . import MicroBinutil, register_binutil From bcede675b5c721cb447c191b54a539990e1106e1 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 09:58:26 -0800 Subject: [PATCH 41/70] More cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 5 +- python/tvm/micro/base.py | 21 +- python/tvm/micro/device/__init__.py | 2 +- python/tvm/micro/device/arm/stm32f746xx.py | 57 +- python/tvm/micro/device/base.py | 226 ++++---- python/tvm/micro/device/host.py | 34 +- python/tvm/micro/rpc_server.py | 51 +- .../micro/device/arm/stm32f746xx/utvm_init.s | 517 ------------------ .../micro/device/arm/stm32f746xx/utvm_timer.c | 16 +- src/runtime/micro/device/host/utvm_timer.c | 6 +- src/runtime/micro/host_driven/utvm_runtime.c | 6 +- src/runtime/micro/host_driven/utvm_runtime.h | 2 +- src/runtime/micro/micro_module.cc | 30 - src/runtime/micro/micro_session.cc | 49 +- src/runtime/micro/micro_session.h | 8 +- tests/python/unittest/test_runtime_micro.py | 1 - 16 files changed, 232 insertions(+), 799 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index b61114850dad..34d8ae1f0c7b 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -31,8 +31,9 @@ from vta.testing import simulator from vta.top import graph_pack -# first, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal -# then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro --dev-config=` in another +# First, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal. +# Then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro +# --dev-config=` in another. DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) #DEV_CONFIG = micro.device.host.default_config() diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index c3267ac54cdf..4c9dfcf2242b 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -59,7 +59,8 @@ def __init__(self, config): # TODO(weberlo): add config validation # grab a binutil instance from the ID in the config - self.binutil = tvm.micro.device.get_binutil(config['binutil']) + self.create_micro_lib = tvm.micro.device.get_device_funcs(config['device_id'])['create_micro_lib'] + self.toolchain_prefix = config['toolchain_prefix'] self.mem_layout = config['mem_layout'] self.word_size = config['word_size'] self.thumb_mode = config['thumb_mode'] @@ -69,7 +70,7 @@ def __init__(self, config): runtime_src_path = os.path.join(get_micro_host_driven_dir(), 'utvm_runtime.c') tmp_dir = _util.tempdir() runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') - self.binutil.create_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) + self.create_micro_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) #input(f'check {runtime_obj_path}: ') comms_method = config['comms_method'] @@ -85,7 +86,7 @@ def __init__(self, config): self.module = _CreateSession( comms_method, runtime_obj_path, - self.binutil.toolchain_prefix(), + self.toolchain_prefix, self.mem_layout['text'].get('start', 0), self.mem_layout['text']['size'], self.mem_layout['rodata'].get('start', 0), @@ -127,7 +128,7 @@ def create_micro_mod(self, c_mod): lib_obj_path = temp_dir.relpath('dev_lib.obj') c_mod.export_library( lib_obj_path, - fcompile=cross_compiler(self.binutil, LibType.OPERATOR)) + fcompile=cross_compiler(self.create_micro_lib, LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path) return micro_mod @@ -151,15 +152,16 @@ def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() -def cross_compiler(dev_binutil, lib_type): +def cross_compiler(create_micro_lib, lib_type): """Create a cross compile function that wraps `create_lib` for a `Binutil` instance. For use in `tvm.module.Module.export_library`. Parameters ---------- - dev_binutil : Union[MicroBinutil, str] - a `MicroBinutil` subclass or a string ID for a registered binutil class + create_micro_lib : func + function for creating MicroTVM libraries for a specific device (e.g., + `tvm.micro.device.get_device_funcs('arm.stm32f746xx')['create_micro_lib']`) lib_type : micro.LibType whether to compile a MicroTVM runtime or operator library @@ -178,15 +180,12 @@ def cross_compiler(dev_binutil, lib_type): fcompile = tvm.micro.cross_compiler('arm.stm32f746xx', LibType.OPERATOR) c_mod.export_library('dev_lib.obj', fcompile=fcompile) """ - if isinstance(dev_binutil, str): - dev_binutil = tvm.micro.device.get_binutil(dev_binutil) - def compile_func(obj_path, src_path, **kwargs): if isinstance(obj_path, list): obj_path = obj_path[0] if isinstance(src_path, list): src_path = src_path[0] - dev_binutil.create_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) + create_micro_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) return _cc.cross_compiler(compile_func, output_format='obj') diff --git a/python/tvm/micro/device/__init__.py b/python/tvm/micro/device/__init__.py index bf9d85cb3b1b..1ccd6847edd8 100644 --- a/python/tvm/micro/device/__init__.py +++ b/python/tvm/micro/device/__init__.py @@ -16,7 +16,7 @@ # under the License. """Device-specific configuration for MicroTVM""" -from .base import register_binutil, get_binutil, MicroBinutil +from .base import register_device, get_device_funcs, create_micro_lib_base from . import host from . import arm from . import riscv_spike diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 2829c463ca0d..d4e72b3513d9 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -15,41 +15,34 @@ # specific language governing permissions and limitations # under the License. """Config definitions for ARM STM32F746XX devices""" +from .. import create_micro_lib_base, register_device -from .. import MicroBinutil, register_binutil +DEVICE_ID = 'arm.stm32f746xx' +TOOLCHAIN_PREFIX = 'arm-none-eabi-' -# -# [Device Memory Layout] -# RAM (rwx) : START = 0x20000000, LENGTH = 320K -# FLASH (rx) : START = 0x8000000, LENGTH = 1024K -# - -class Stm32F746XXBinutil(MicroBinutil): - def __init__(self): - super(Stm32F746XXBinutil, self).__init__('arm-none-eabi-') - - def create_lib(self, obj_path, src_path, lib_type, options=None): - if options is None: - options = [] - options += [ - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-mthumb', - '-gdwarf-5', - ] - super(Stm32F746XXBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) +def create_micro_lib(obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + options += [ + '-mcpu=cortex-m7', + '-mlittle-endian', + '-mfloat-abi=hard', + '-mfpu=fpv5-sp-d16', + '-mthumb', + '-gdwarf-5', + ] + create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) - def device_id(): - return 'arm.stm32f746xx' - - -register_binutil(Stm32F746XXBinutil) def default_config(server_addr, server_port): return { - 'binutil': 'arm.stm32f746xx', + 'device_id': DEVICE_ID, + 'toolchain_prefix': TOOLCHAIN_PREFIX, + # + # [Device Memory Layout] + # RAM (rwx) : START = 0x20000000, LENGTH = 320K + # FLASH (rx) : START = 0x8000000, LENGTH = 1024K + # 'mem_layout': { 'text': { 'start': 0x20000180, @@ -90,3 +83,9 @@ def default_config(server_addr, server_port): 'server_addr': server_addr, 'server_port': server_port, } + + +register_device(DEVICE_ID, { + 'create_micro_lib': create_micro_lib, + 'default_config': default_config, +}) diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index 28151f22b66e..2dacfab26cf4 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. """Base definitions for MicroTVM config""" - import glob import os import sys @@ -27,17 +26,16 @@ from tvm._ffi.libinfo import find_include_path from tvm.micro import LibType, get_micro_host_driven_dir, get_micro_device_dir -BINUTIL_REGISTRY = {} +DEVICE_REGISTRY = {} -def register_binutil(binutil): - name = binutil.device_id() - if name in BINUTIL_REGISTRY: - raise RuntimeError(f'"{name}" already exists in the binutil registry') - BINUTIL_REGISTRY[name] = binutil +def register_device(device_id, device_funcs): + if device_id in DEVICE_REGISTRY: + raise RuntimeError(f'"{device_id}" already exists in the device registry') + DEVICE_REGISTRY[device_id] = device_funcs -def get_binutil(device_id): - """Get matching MicroBinutil subclass from `device_id` +def get_device_funcs(device_id): + """Get compilation and config generation functions for device Parameters ---------- @@ -46,126 +44,116 @@ def get_binutil(device_id): Return ------ - binutil : MicroBinutil - MicroBinutil subclass + device_funcs : Dict[str, func] + dictionary with compilation and config generation functions as values """ - if device_id not in BINUTIL_REGISTRY: + if device_id not in DEVICE_REGISTRY: raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') - binutil = BINUTIL_REGISTRY[device_id] - return binutil() + device_funcs = DEVICE_REGISTRY[device_id] + return device_funcs -class MicroBinutil: - """Base class for GCC-specific library compilation for MicroTVM +def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_type, options=None): + """Compiles code into a binary for the target micro device. Parameters ---------- + obj_path : Optional[str] + path to generated object file (defaults to same directory as `src_path`) + + src_path : str + path to source file + toolchain_prefix : str toolchain prefix to be used. For example, a prefix of "riscv64-unknown-elf-" means "riscv64-unknown-elf-gcc" is used as the compiler and "riscv64-unknown-elf-ld" is used as the linker, etc. + + device_id : str + unique identifier for the target device + + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library + + options : List[str] + additional options to pass to GCC """ - def __init__(self, toolchain_prefix): - self._toolchain_prefix = toolchain_prefix - - def create_lib(self, obj_path, src_path, lib_type, options=None): - """Compiles code into a binary for the target micro device. - - Parameters - ---------- - obj_path : Optional[str] - path to generated object file (defaults to same directory as `src_path`) - - src_path : str - path to source file - - lib_type : micro.LibType - whether to compile a MicroTVM runtime or operator library - - options : List[str] - additional options to pass to GCC - """ - print('[MicroBinutil.create_lib]') - print(' EXTENDED OPTIONS') - print(f' {obj_path}') - print(f' {src_path}') - print(f' {lib_type}') - print(f' {options}') - base_compile_cmd = [ - f'{self.toolchain_prefix()}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - ] - if options is not None: - base_compile_cmd += options - - src_paths = [] - include_paths = find_include_path() + [get_micro_host_driven_dir()] - ld_script_path = None - tmp_dir = _util.tempdir() - if lib_type == LibType.RUNTIME: - dev_dir = self._get_device_source_dir() - - print(dev_dir) - dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') - print(dev_src_paths) - # there needs to at least be a utvm_timer.c file - assert dev_src_paths - assert 'utvm_timer.c' in map(os.path.basename, dev_src_paths) - - src_paths += dev_src_paths - elif lib_type == LibType.OPERATOR: - # create a temporary copy of the source, so we can inject the dev lib - # header without modifying the original. - temp_src_path = tmp_dir.relpath('temp.c') - with open(src_path, 'r') as f: - src_lines = f.read().splitlines() - src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') - with open(temp_src_path, 'w') as f: - f.write('\n'.join(src_lines)) - src_path = temp_src_path - - base_compile_cmd += ['-c'] - else: - raise RuntimeError('unknown lib type') - - src_paths += [src_path] - - print(f'include paths: {include_paths}') - for path in include_paths: - base_compile_cmd += ['-I', path] - - prereq_obj_paths = [] - for src_path in src_paths: - curr_obj_path = Path(src_path).with_suffix('.o').name - assert curr_obj_path not in prereq_obj_paths - prereq_obj_paths.append(curr_obj_path) - curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] - run_cmd(curr_compile_cmd) - - ld_cmd = [f'{self.toolchain_prefix()}ld', '-relocatable'] - ld_cmd += prereq_obj_paths - ld_cmd += ['-o', obj_path] - run_cmd(ld_cmd) - - def _get_device_source_dir(self): - """Grabs the source directory for device-specific uTVM files""" - dev_subdir = '/'.join(self.__class__.device_id().split('.')) - return get_micro_device_dir() + '/' + dev_subdir - - def device_id(self): - raise RuntimeError('no device ID for abstract MicroBinutil') - - def toolchain_prefix(self): - return self._toolchain_prefix + print('[MicroBinutil.create_lib]') + print(' EXTENDED OPTIONS') + print(f' {obj_path}') + print(f' {src_path}') + print(f' {lib_type}') + print(f' {options}') + base_compile_cmd = [ + f'{toolchain_prefix}gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-c', + '-O0', + '-g', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + ] + if options is not None: + base_compile_cmd += options + + src_paths = [] + include_paths = find_include_path() + [get_micro_host_driven_dir()] + ld_script_path = None + tmp_dir = _util.tempdir() + if lib_type == LibType.RUNTIME: + dev_dir = _get_device_source_dir(device_id) + + print(dev_dir) + dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + print(dev_src_paths) + # there needs to at least be a utvm_timer.c file + assert dev_src_paths + assert 'utvm_timer.c' in map(os.path.basename, dev_src_paths) + + src_paths += dev_src_paths + elif lib_type == LibType.OPERATOR: + # create a temporary copy of the source, so we can inject the dev lib + # header without modifying the original. + temp_src_path = tmp_dir.relpath('temp.c') + with open(src_path, 'r') as f: + src_lines = f.read().splitlines() + src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') + with open(temp_src_path, 'w') as f: + f.write('\n'.join(src_lines)) + src_path = temp_src_path + + base_compile_cmd += ['-c'] + else: + raise RuntimeError('unknown lib type') + + src_paths += [src_path] + + print(f'include paths: {include_paths}') + for path in include_paths: + base_compile_cmd += ['-I', path] + + prereq_obj_paths = [] + for src_path in src_paths: + curr_obj_path = Path(src_path).with_suffix('.o').name + assert curr_obj_path not in prereq_obj_paths + prereq_obj_paths.append(curr_obj_path) + curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + run_cmd(curr_compile_cmd) + + ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] + ld_cmd += prereq_obj_paths + ld_cmd += ['-o', obj_path] + run_cmd(ld_cmd) + + +def _get_device_source_dir(device_id): + """Grabs the source directory for device-specific uTVM files""" + dev_subdir = '/'.join(device_id.split('.')) + return get_micro_device_dir() + '/' + dev_subdir diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 447f1d7c7304..687a66e2ac2f 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -15,31 +15,25 @@ # specific language governing permissions and limitations # under the License. """Config for the host emulated device""" - import sys -from . import MicroBinutil, register_binutil - -class HostBinutil(MicroBinutil): - def __init__(self): - super(HostBinutil, self).__init__('') - - def create_lib(self, obj_path, src_path, lib_type, options=None): - if options is None: - options = [] - if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - options += ['-mcmodel=large'] - super(HostBinutil, self).create_lib(obj_path, src_path, lib_type, options=options) +from . import create_micro_lib_base, register_device - def device_id(): - return 'host' +DEVICE_ID = 'host' +TOOLCHAIN_PREFIX = '' +def create_micro_lib(obj_path, src_path, lib_type, options=None): + if options is None: + options = [] + if sys.maxsize > 2**32 and sys.platform.startswith('linux'): + options += ['-mcmodel=large'] + create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) -register_binutil(HostBinutil) def default_config(): return { - 'binutil': 'host', + 'device_id': DEVICE_ID, + 'toolchain_prefix': TOOLCHAIN_PREFIX, 'mem_layout': { 'text': { 'size': 20480, @@ -70,3 +64,9 @@ def default_config(): 'thumb_mode': False, 'comms_method': 'host', } + + +register_device(DEVICE_ID, { + 'create_micro_lib': create_micro_lib, + 'default_config': default_config, +}) diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 6dfe0d9634be..6835d8075563 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -1,3 +1,21 @@ +# 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. +"""RPC server for interacting with devices via MicroTVM""" + import logging import argparse import os @@ -8,7 +26,6 @@ from tvm import micro def main(): - """Main function""" parser = argparse.ArgumentParser() parser.add_argument('--host', type=str, default="0.0.0.0", help='the hostname of the server') @@ -17,35 +34,43 @@ def main(): parser.add_argument('--port-end', type=int, default=9199, help='The end search port of the RPC') parser.add_argument('--key', type=str, default="", - help="RPC key used to identify the connection type.") + help='RPC key used to identify the connection type.') parser.add_argument('--tracker', type=str, default="", - help="Report to RPC tracker") - parser.add_argument('--dev-config', type=str, required=True, - help="JSON config file for the target device") + help='Report to RPC tracker') + parser.add_argument('--dev-config', type=str, + help='JSON config file for the target device') + parser.add_argument('--dev-id', type=str, + help='Unique ID for the target device') args = parser.parse_args() logging.basicConfig(level=logging.INFO) if args.tracker: - url, port = args.tracker.split(":") + url, port = args.tracker.split(':') port = int(port) tracker_addr = (url, port) if not args.key: raise RuntimeError( - "Need key to present type of resource when tracker is available") + 'Need key to present type of resource when tracker is available') else: tracker_addr = None - with open(args.dev_config, 'r') as dev_conf_file: - dev_config = json.load(dev_conf_file) - #dev_config = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) - #dev_config = micro.device.host.default_config() + if not (args.dev_config or args.dev_id): + raise RuntimeError('must provide either --dev-config or --dev-id') + if args.dev_config and args.dev_id: + raise RuntimeError('only one of --dev-config and --dev-id allowed') + + if args.dev_config: + with open(args.dev_config, 'r') as dev_conf_file: + dev_config = json.load(dev_conf_file) + else: + dev_config = micro.device.get_config(args.dev_id) - @tvm.register_func("tvm.rpc.server.start", override=True) + @tvm.register_func('tvm.rpc.server.start', override=True) def server_start(): session = micro.Session(dev_config) session._enter() - @tvm.register_func("tvm.rpc.server.shutdown", override=True) + @tvm.register_func('tvm.rpc.server.shutdown', override=True) def server_shutdown(): session._exit() diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s index 947918e0d183..448fb773a2f8 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s @@ -1,46 +1,3 @@ -/** - ****************************************************************************** - * @file startup_stm32f767xx.s - * @author MCD Application Team - * @brief STM32F767xx Devices vector table for GCC based toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == UTVMInit, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M7 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - .syntax unified .cpu cortex-m7 .fpu softvfp @@ -61,477 +18,3 @@ UTVMInit: ldr sp, =_utvm_stack_pointer_init bl UTVMMain .size UTVMInit, .-UTVMInit - - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ -.section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler - - -/****************************************************************************** -* -* The minimal vector table for a Cortex M7. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ -.section .isr_vector,"a",%progbits -.type g_pfnVectors, %object -.size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _utvm_stack_pointer_init - .word UTVMInit - - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* Reserved */ - .word RNG_IRQHandler /* Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word SPI6_IRQHandler /* SPI6 */ - .word SAI1_IRQHandler /* SAI1 */ - .word LTDC_IRQHandler /* LTDC */ - .word LTDC_ER_IRQHandler /* LTDC error */ - .word DMA2D_IRQHandler /* DMA2D */ - .word SAI2_IRQHandler /* SAI2 */ - .word QUADSPI_IRQHandler /* QUADSPI */ - .word LPTIM1_IRQHandler /* LPTIM1 */ - .word CEC_IRQHandler /* HDMI_CEC */ - .word I2C4_EV_IRQHandler /* I2C4 Event */ - .word I2C4_ER_IRQHandler /* I2C4 Error */ - .word SPDIF_RX_IRQHandler /* SPDIF_RX */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak LTDC_IRQHandler - .thumb_set LTDC_IRQHandler,Default_Handler - - .weak LTDC_ER_IRQHandler - .thumb_set LTDC_ER_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak CEC_IRQHandler - .thumb_set CEC_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler - .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak SPDIF_RX_IRQHandler - .thumb_set SPDIF_RX_IRQHandler,Default_Handler diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index 0ae1016e2a31..d16515e6039e 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -2,8 +2,6 @@ extern "C" { #endif -// TODO rename file to `utvm_timer.c` - #include "utvm_runtime.h" // There are two implementations of cycle counters on the STM32F7X: SysTick and @@ -30,11 +28,12 @@ extern "C" { unsigned long start_time = 0; unsigned long stop_time = 0; -void UTVMTimerStart() { +int32_t UTVMTimerStart() { SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); // wait until timer starts while (SYST_CVR == 0); start_time = SYST_CVR; + return 0; } void UTVMTimerStop() { @@ -73,12 +72,11 @@ void UTVMTimerReset() { DWT_CYCCNT = 0; } -void UTVMTimerStart() { - // TODO: change API so we can return errors from here - //if (DWT_CTRL & DWT_CTRL_NOCYCCNT) { - // TVMAPISetLastError("cycle counter not implemented on device"); - // return -1; - //} +int32_t UTVMTimerStart() { + if (DWT_CTRL & DWT_CTRL_NOCYCCNT) { + TVMAPISetLastError("cycle counter not implemented on device"); + return -1; + } start_time = DWT_CYCCNT; DWT_CTRL |= (1 << DWT_CTRL_CYCCNTENA); } diff --git a/src/runtime/micro/device/host/utvm_timer.c b/src/runtime/micro/device/host/utvm_timer.c index 9e8664e604e4..51e78924d567 100644 --- a/src/runtime/micro/device/host/utvm_timer.c +++ b/src/runtime/micro/device/host/utvm_timer.c @@ -11,14 +11,16 @@ void UTVMInit() { UTVMMain(); } -void UTVMTimerStart() { } +int32_t UTVMTimerStart() { + return 0; +} void UTVMTimerStop() { } void UTVMTimerReset() { } uint32_t UTVMTimerRead() { - return 1; + return 1; } #ifdef __cplusplus diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 7e52a8b3f62e..4666cc6c09dd 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -64,7 +64,11 @@ void UTVMMain() { utvm_return_code = 0; utvm_task_time = 0; UTVMTimerReset(); - UTVMTimerStart(); + int32_t err = UTVMTimerStart(); + if (err < 0) { + utvm_return_code = err; + UTVMDone(); + } utvm_return_code = utvm_task.func( (void*) utvm_task.arg_values, // NOLINT(*) (void*) utvm_task.arg_type_codes, // NOLINT(*) diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index b5e44dfde38b..7b203e9adbef 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -50,7 +50,7 @@ extern void UTVMInit(); extern void UTVMTimerReset(); -extern void UTVMTimerStart(); +extern int32_t UTVMTimerStart(); extern void UTVMTimerStop(); diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index c1746ce6785e..f480b9658484 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -38,17 +38,6 @@ namespace runtime { */ class MicroModuleNode final : public ModuleNode { public: - // TODO(weberlo): enqueue each loaded module into a vector of bin contents. - // then concatenate the contents, build it, and flush it once a function call - // is attempted. - // - // We might not be able to flush *all* sections. Depends how st-flash works. - // it only asks to specify the start of the flash section, so does it also - // flash the RAM sections? It's also weird that it asks for the start of the - // flash section, because that should already be encoded in the binary. check - // the .bin files to see if symbol addrs are assigned. also, check the - // st-flash docs, because the arg could just be for the address of `main`. - MicroModuleNode() {} ~MicroModuleNode() {} @@ -72,16 +61,6 @@ class MicroModuleNode final : public ModuleNode { std::cout << " end" << std::endl; } - ///*! - // * \brief runs selected function on the micro device - // * \param func_name name of the function to be run - // * \param func_ptr offset of the function to be run - // * \param args type-erased arguments passed to the function - // */ - //void RunFunction(DevPtr func_ptr, const TVMArgs& args) { - // session_->PushToExecQueue(func_ptr, args); - //} - private: SymbolMap symbol_map_; /*! \brief global session pointer */ @@ -114,20 +93,11 @@ PackedFunc MicroModuleNode::GetFunction( std::cout << "[MicroModuleNode::GetFunction(name=" << name << ")]" << std::endl; DevPtr func_ptr; if (name == tvm::runtime::symbol::tvm_module_main) { - std::cout << " here" << std::endl; if (symbol_map_.HasSymbol(tvm::runtime::symbol::tvm_module_main)) { - std::cout << " ayy" << std::endl; func_ptr = symbol_map_[tvm::runtime::symbol::tvm_module_main]; } else { - std::cout << " lmao" << std::endl; func_ptr = symbol_map_["default_function"]; } - //std::cout << " symbols:" << std::endl; - //for (const auto& sym_name : symbol_map_.GetSymbols()) { - // std::cout << " " << sym_name << std::endl; - //} - //CHECK(symbol_map_.size() == 1) << "entry point requested with multiple functions in module"; - //func_ptr = symbol_map_[symbol_map_.GetSymbols()[0]]; } else { func_ptr = symbol_map_[name]; } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index fd475cad916f..5448a14fdc8a 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -82,9 +82,10 @@ MicroSession::MicroSession( size_t word_size, bool thumb_mode, const std::string& server_addr, - int port) : word_size_(word_size), thumb_mode_(thumb_mode) { - toolchain_prefix_ = toolchain_prefix; + int port) : toolchain_prefix_(toolchain_prefix), word_size_(word_size), thumb_mode_(thumb_mode) { + CHECK(word_size_ == 4 || word_size_ == 8) << "unsupported word size " << word_size_; if (comms_method == "host") { + // TODO(weberlo): move checks to python CHECK( text_start == 0 && rodata_start == 0 && @@ -97,8 +98,8 @@ MicroSession::MicroSession( size_t memory_size = text_size + rodata_size + data_size + bss_size + args_size + heap_size + workspace_size + stack_size; void* base_addr; low_level_device_ = HostLowLevelDeviceCreate(memory_size, &base_addr); - CHECK(reinterpret_cast(base_addr) % word_size_ == 0) << "base address not aligned to " << word_size_ << " bytes"; - std::cout << "base addr is " << base_addr << std::endl; + CHECK_EQ(reinterpret_cast(base_addr) % word_size_, 0) + << "base address not aligned to " << word_size_ << " bytes"; DevPtr curr_addr = DevPtr(reinterpret_cast(base_addr)); section_allocators_[0] = std::make_shared(DevMemRegion { @@ -142,7 +143,6 @@ MicroSession::MicroSession( }, word_size_); curr_addr += stack_size; } else if (comms_method == "openocd") { - // TODO(weberlo): We need a better way of configuring devices. low_level_device_ = OpenOCDLowLevelDeviceCreate(server_addr, port); section_allocators_[0] = std::make_shared(DevMemRegion { .start = DevPtr(text_start), @@ -194,15 +194,12 @@ MicroSession::MicroSession( std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; - DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); - // Patch workspace pointers to the start of the workspace section. + // Patch pointers to define the bounds of the workspace section and the word size (for allocation alignment). void* workspace_start_addr = GetAllocator(SectionKind::kWorkspace)->start_addr().cast_to(); void* workspace_end_addr = GetAllocator(SectionKind::kWorkspace)->max_addr().cast_to(); - // TODO(weberlo): A lot of these symbol writes can be converted into symbols - // in the C source, where the symbols are created by the linker script we - // generate in python. DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); } MicroSession::~MicroSession() { @@ -225,19 +222,14 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { DevPtr args_addr = GetAllocator(SectionKind::kArgs)->curr_end_addr(); TargetDataLayoutEncoder encoder(args_addr, word_size_); - std::cout << " after encoder alloc" << std::endl; - std::tuple arg_field_addrs = EncoderAppend(&encoder, args); - std::cout << " after encoder append" << std::endl; // Flush `stream` to device memory. DevPtr stream_dev_addr = GetAllocator(SectionKind::kArgs)->Allocate(encoder.buf_size()); - std::cout << " low-level device: " << low_level_device() << std::endl; low_level_device()->Write(stream_dev_addr, reinterpret_cast(encoder.data()), encoder.buf_size()); - std::cout << " after encoder write" << std::endl; if (word_size_ == 4) { TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); @@ -261,9 +253,6 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { }; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); - } else { - // TODO hoist word size check to initialization - CHECK(false) << "unsupported word size " << word_size_; } std::cout << " after task write" << std::endl; @@ -338,7 +327,6 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::string relocated_bin = RelocateBinarySections( binary_path, word_size_, - // TODO fill in new args text_section.start, rodata_section.start, data_section.start, @@ -420,21 +408,6 @@ std::tuple MicroSession::EncoderAppend( } DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { - // TODO make this code mux on the word size - /* - typedef struct StructARMTVMArray { - uint32_t data; - DLContext ctx; - int ndim; - DLDataType dtype; - uint32_t shape; - uint32_t strides; - uint32_t pad1; - uint32_t byte_offset; - uint32_t pad2; - } ARMTVMArray; - */ - if (word_size_ == 4) { auto tvm_arr_slot = encoder->Alloc(); //CHECK(false) << "should we be allocing int32_t?"; @@ -497,10 +470,6 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr // checks that it is a host array. CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - //// Add the base address of the device to the array's data's device offset to - //// get a device address. - //DevPtr arr_offset(reinterpret_cast(arr.data)); - //dev_arr.data = low_level_device()->ToDevPtr(arr_offset).cast_to(); dev_arr.shape = shape_addr.cast_to(); dev_arr.strides = strides_addr.cast_to(); tvm_arr_slot.WriteValue(dev_arr); @@ -543,8 +512,6 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint32_t) runtime_impl_addr.value()); } else if (word_size_ == 8) { DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint64_t) runtime_impl_addr.value()); - } else { - CHECK(false) << "ayy"; } } @@ -657,8 +624,6 @@ TVM_REGISTER_GLOBAL("micro._CreateSession") thumb_mode, server_addr, port); - //session->CreateSession( - // "openocd", binary_path, "arm-none-eabi-", 0, "127.0.0.1", 6666); *rv = Module(session); }); diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 421fb6263331..46b0bf3eba5f 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -47,7 +47,6 @@ #include #include "low_level_device.h" -//#include "host_driven/utvm_runtime.h" #include "target_data_layout_encoder.h" namespace tvm { @@ -241,6 +240,7 @@ class MicroSession : public ModuleNode { * The session on top of the stack is used as the current global session. */ static void EnterWithScope(ObjectPtr session); + /*! * \brief Pop a session off the thread-local context stack, * restoring the previous session as the current context. @@ -261,7 +261,7 @@ struct MicroDevSpace { ObjectPtr session; }; -// tvm array for serialization to 32-bit devices +/*! \brief TVM array for serialization to 32-bit devices */ typedef struct StructTVMArray32 { uint32_t data; DLContext ctx; @@ -275,7 +275,7 @@ typedef struct StructTVMArray32 { uint32_t pad2; } TVMArray32; -// utvm task for serialization to 32-bit devices +/*! \brief MicroTVM task for serialization to 32-bit devices */ typedef struct StructUTVMTask32 { /*! \brief Pointer to function to call for this task */ uint32_t func; @@ -287,7 +287,7 @@ typedef struct StructUTVMTask32 { int32_t num_args; } UTVMTask32; -// utvm task for serialization to 64-bit devices +/*! \brief MicroTVM task for serialization to 64-bit devices */ typedef struct StructUTVMTask64 { /*! \brief Pointer to function to call for this task */ uint64_t func; diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 2f89e3cdc8bf..8a42facc274c 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -14,7 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - import os import numpy as np From 9a76461502e6fdece155f4f464e327bc32c953a9 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 11:27:39 -0800 Subject: [PATCH 42/70] Cleanup --- arm-auto-utvm-demo/tune_relay_utvm.py | 4 +- python/tvm/micro/device/riscv_spike.py | 77 +++++++++++++++++++++ python/tvm/micro/rpc_server.py | 14 ++-- src/runtime/micro/micro_common.h | 1 - src/runtime/micro/micro_section_allocator.h | 5 +- src/runtime/micro/micro_session.cc | 42 +++++++---- src/runtime/micro/micro_session.h | 44 ++++++++++-- 7 files changed, 157 insertions(+), 30 deletions(-) diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py index 34d8ae1f0c7b..147ea09f0151 100644 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ b/arm-auto-utvm-demo/tune_relay_utvm.py @@ -36,6 +36,7 @@ # --dev-config=` in another. DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +DEV_CREATE_MICRO_LIB = micro.device.get_device_funcs(DEV_CONFIG['device_id'])['create_micro_lib'] #DEV_CONFIG = micro.device.host.default_config() DEVICE = 'arm-cortex-m' @@ -88,7 +89,7 @@ def tune(): early_stopping = None measure_option = autotvm.measure_option( builder=autotvm.LocalBuilder( - build_func=tvm.micro.cross_compiler(DEV_CONFIG['binutil'], micro.LibType.OPERATOR)), + build_func=tvm.micro.cross_compiler(DEV_CREATE_MICRO_LIB, micro.LibType.OPERATOR)), runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=N_PARALLEL, number=N_PER_TRIAL) ) @@ -115,7 +116,6 @@ def tune(): def evaluate(): print('[EVALUATE]') # compile kernels with history best records - #with autotvm.tophub.context(TARGET, extra_files=[LOG_FILE_NAME]): with autotvm.apply_history_best(LOG_FILE_NAME): with TARGET: sched, arg_bufs = matmul(N, L, M, DTYPE) diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py index e69de29bb2d1..c70367c9f957 100644 --- a/python/tvm/micro/device/riscv_spike.py +++ b/python/tvm/micro/device/riscv_spike.py @@ -0,0 +1,77 @@ +# 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. +"""Config definitions for Spike, a RISC-V functional ISA simulator""" +from collections import OrderedDict + +from . import create_micro_lib_base, register_device + +DEVICE_ID = 'riscv_spike' +TOOLCHAIN_PREFIX = 'riscv64-unknown-elf-' + +def create_micro_lib(obj_path, src_path, lib_type, options=None): + create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) + + +def default_config(base_addr, server_addr, server_port): + res = { + 'device_id': DEVICE_ID, + 'toolchain_prefix': TOOLCHAIN_PREFIX, + 'mem_layout': OrderedDict([ + ('text', { + 'size': 20480, + }), + ('rodata', { + 'size': 20480, + }), + ('data', { + 'size': 768, + }), + ('bss', { + 'size': 768, + }), + ('args', { + 'size': 1280, + }), + ('heap', { + 'size': 262144, + }), + ('workspace', { + 'size': 20480, + }), + ('stack', { + 'size': 80, + }), + ]), + 'word_size': 4, + 'thumb_mode': True, + 'comms_method': 'openocd', + 'server_addr': server_addr, + 'server_port': server_port, + } + # generate section start addresses from the given `base_addr` + curr_offset = 0 + mem_layout = res['mem_layout'] + for section_name, region_dict in mem_layout: + mem_layout[section_name]['start'] = base_addr + curr_offset + curr_offset += mem_layout[section_name]['size'] + return res + + +register_device(DEVICE_ID, { + 'create_micro_lib': create_micro_lib, + 'default_config': default_config, +}) diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 6835d8075563..bf779f46bb3e 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -16,11 +16,12 @@ # under the License. """RPC server for interacting with devices via MicroTVM""" -import logging import argparse -import os +import ast import ctypes import json +import logging +import os import tvm from tvm import rpc from tvm import micro @@ -41,6 +42,8 @@ def main(): help='JSON config file for the target device') parser.add_argument('--dev-id', type=str, help='Unique ID for the target device') + parser.add_argument('--dev-config-args', type=str, + help='Python list of literals required to generate a default config (if --dev-id is specified)') args = parser.parse_args() logging.basicConfig(level=logging.INFO) @@ -54,8 +57,8 @@ def main(): else: tracker_addr = None - if not (args.dev_config or args.dev_id): - raise RuntimeError('must provide either --dev-config or --dev-id') + if not (args.dev_config or (args.dev_id and args.dev_config_args)): + raise RuntimeError('must provide either --dev-config or --dev-id and --dev-config-args') if args.dev_config and args.dev_id: raise RuntimeError('only one of --dev-config and --dev-id allowed') @@ -63,7 +66,8 @@ def main(): with open(args.dev_config, 'r') as dev_conf_file: dev_config = json.load(dev_conf_file) else: - dev_config = micro.device.get_config(args.dev_id) + dev_config_args = ast.literal_eval(args.dev_config_args) + dev_config = micro.device.get_device_funcs(args.dev_id)['default_config'](*dev_config_args) @tvm.register_func('tvm.rpc.server.start', override=True) def server_start(): diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index f3c4d1e5c815..441e17721ad9 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -244,7 +244,6 @@ inline size_t UpperAlignValue(size_t value, size_t align) { */ const char* SectionToString(SectionKind section); -// todo new docs /*! * \brief links binary by repositioning section addresses * \param binary_name input binary filename diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index e5e83930dd9f..0551959627bd 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -43,7 +43,8 @@ class MicroSectionAllocator { size_(0), capacity_(region.size), word_size_(word_size) { - CHECK_EQ(start_addr_.value() % word_size, 0) << "micro section not aligned to " << word_size << " bytes"; + CHECK_EQ(start_addr_.value() % word_size, 0) << "micro section start not aligned to " << word_size << " bytes"; + CHECK_EQ(capacity_ % word_size, 0) << "micro section end not aligned to " << word_size << " bytes"; } /*! @@ -112,7 +113,7 @@ class MicroSectionAllocator { size_t size_; /*! \brief total storage capacity of the section */ size_t capacity_; - /*! \brief TODO */ + /*! \brief number of bytes in a word on the target device */ size_t word_size_; /*! \brief allocation map for allocation sizes */ std::unordered_map alloc_map_; diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 5448a14fdc8a..4acc869ffb6e 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -195,11 +195,21 @@ MicroSession::MicroSession( std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; // Patch pointers to define the bounds of the workspace section and the word size (for allocation alignment). - void* workspace_start_addr = GetAllocator(SectionKind::kWorkspace)->start_addr().cast_to(); - void* workspace_end_addr = GetAllocator(SectionKind::kWorkspace)->max_addr().cast_to(); - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); + if (word_size_ == 4) { + uint32_t workspace_start_addr = (uint32_t) GetAllocator(SectionKind::kWorkspace)->start_addr().value(); + uint32_t workspace_end_addr = (uint32_t) GetAllocator(SectionKind::kWorkspace)->max_addr().value(); + uint32_t word_size = (uint32_t) word_size_; + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size); + } else if (word_size_ == 8) { + uint64_t workspace_start_addr = (uint64_t) GetAllocator(SectionKind::kWorkspace)->start_addr().value(); + uint64_t workspace_end_addr = (uint64_t) GetAllocator(SectionKind::kWorkspace)->max_addr().value(); + uint64_t word_size = (uint64_t) word_size_; + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); + } } MicroSession::~MicroSession() { @@ -268,7 +278,6 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { //std::cout << " do execution things: "; //char tmp; //std::cin >> tmp; - low_level_device()->Execute(utvm_init_addr, utvm_done_addr); // Check if there was an error during execution. If so, log it. @@ -410,7 +419,6 @@ std::tuple MicroSession::EncoderAppend( DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { if (word_size_ == 4) { auto tvm_arr_slot = encoder->Alloc(); - //CHECK(false) << "should we be allocing int32_t?"; auto shape_slot = encoder->Alloc(arr.ndim); // `shape` and `strides` are stored on the host, so we need to write them to @@ -431,6 +439,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr .data = *((uint32_t*) &arr.data), .ctx = arr.ctx, .ndim = arr.ndim, + .pad0 = 0, .dtype = arr.dtype, .shape = *((uint32_t*) &dev_shape), .strides = *((uint32_t*) &dev_strides), @@ -445,7 +454,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr tvm_arr_slot.WriteValue(dev_arr); return tvm_arr_slot.start_addr(); } else if (word_size_ == 8) { - auto tvm_arr_slot = encoder->Alloc(); + auto tvm_arr_slot = encoder->Alloc(); auto shape_slot = encoder->Alloc(arr.ndim); // `shape` and `strides` are stored on the host, so we need to write them to @@ -462,16 +471,21 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); + TVMArray64 dev_arr = { + .data = *((uint64_t*) &arr.data), + .ctx = arr.ctx, + .ndim = arr.ndim, + .pad0 = 0, + .dtype = arr.dtype, + .shape = *((uint64_t*) &dev_shape), + .strides = *((uint64_t*) &dev_strides), + .byte_offset = *((uint64_t*) &arr.byte_offset), + }; - // Copy `arr`, update the copy's pointers to be device pointers, then - // write the copy to `tvm_arr_slot`. - TVMArray dev_arr = arr; // Update the device type to look like a host, because codegen generates // checks that it is a host array. CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - dev_arr.shape = shape_addr.cast_to(); - dev_arr.strides = strides_addr.cast_to(); tvm_arr_slot.WriteValue(dev_arr); return tvm_arr_slot.start_addr(); } else { @@ -505,7 +519,7 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& if (thumb_mode_) { runtime_impl_addr += 1; } - std::cout << "patching " << func_name << " with addr " << runtime_impl_addr.cast_to() << std::endl; + std::cout << "patching " << func_name << " at " << symbol_map[func_name].cast_to() << " with addr " << runtime_impl_addr.cast_to() << std::endl; std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; if (word_size_ == 4) { diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 46b0bf3eba5f..910c5f7f78f0 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -73,11 +73,31 @@ class MicroSession : public ModuleNode { return "MicroSession"; } - // TODO make a micro session config object /*! * \brief creates session by setting up a low-level device and initting allocators for it - * \param args TVMArgs passed into the micro.init packedfunc - * TODO rewrite docs + * \param comms_method method of communication with the device (e.g., "openocd") + * \param binary_path file system path to the runtime binary + * \param toolchain_prefix GCC toolchain prefix + * \param text_start text section start address + * \param text_size text section size + * \param rodata_start text section start address + * \param rodata_size rodata section size + * \param data_start data section start address + * \param data_size data section size + * \param bss_start bss section start address + * \param bss_size bss section size + * \param args_start args section start address + * \param args_size args section size + * \param heap_start heap section start address + * \param heap_size heap section size + * \param workspace_start workspace section start address + * \param workspace_size workspace section size + * \param stack_start stack section start address + * \param stack_size stack section size + * \param word_size number of bytes in a word on the target device + * \param thumb_mode whether the target device requires a thumb-mode bit on function addresses + * \param server_addr address of the OpenOCD server to connect to (if `comms_method == "openocd"`) + * \param port port of the OpenOCD server to connect to (if `comms_method == "openocd"`) */ MicroSession( const std::string& comms_method, @@ -189,7 +209,7 @@ class MicroSession : public ModuleNode { size_t memory_size_; /*! \brief number of bytes in a word on the target device */ size_t word_size_; - /*! \brief whether the device requires a thumb-mode bit on function addresses + /*! \brief whether the target device requires a thumb-mode bit on function addresses * * ARM and other manufacturers use the lowest bit of a function address to determine * whether it's a "thumb mode" function. The Thumb ISA is more restricted, but @@ -265,8 +285,8 @@ struct MicroDevSpace { typedef struct StructTVMArray32 { uint32_t data; DLContext ctx; - // todo make int32? - int ndim; + int32_t ndim; + uint32_t pad0; DLDataType dtype; uint32_t shape; uint32_t strides; @@ -275,6 +295,18 @@ typedef struct StructTVMArray32 { uint32_t pad2; } TVMArray32; +/*! \brief TVM array for serialization to 64-bit devices */ +typedef struct StructTVMArray64 { + uint64_t data; + DLContext ctx; + int32_t ndim; + uint32_t pad0; + DLDataType dtype; + uint64_t shape; + uint64_t strides; + uint64_t byte_offset; +} TVMArray64; + /*! \brief MicroTVM task for serialization to 32-bit devices */ typedef struct StructUTVMTask32 { /*! \brief Pointer to function to call for this task */ From b09a1760861080a32fd8dec8df4bebed95aae630 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 11:49:24 -0800 Subject: [PATCH 43/70] Last round of cleanup before we remove debug code --- python/tvm/contrib/binutil.py | 1 - python/tvm/rpc/client.py | 6 +- src/runtime/micro/low_level_device.h | 1 + src/runtime/micro/micro_common.h | 12 ---- src/runtime/micro/micro_session.cc | 2 - src/runtime/micro/micro_session.h | 57 ++++++++++++++----- src/runtime/micro/openocd_low_level_device.cc | 13 ----- .../micro/target_data_layout_encoder.h | 3 +- 8 files changed, 47 insertions(+), 48 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index dd00378a3e74..1b32f13f83df 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -29,7 +29,6 @@ def run_cmd(cmd): stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (output, _) = proc.communicate() - # todo need to use py_str? output = output.decode('utf-8') if proc.returncode != 0: cmd_str = ' '.join(cmd) diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index c30d5396ee60..39c7b564fad5 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -180,10 +180,6 @@ def ext_dev(self, dev_id=0): """Construct extension device.""" return self.context(12, dev_id) - def micro_dev(self, dev_id=0): - """Construct OpenGL device.""" - return self.context(13, dev_id) - class LocalSession(RPCSession): """RPCSession interface backed by local environment. @@ -413,7 +409,7 @@ def connect(url, port, key="", session_timeout=0): """ try: print('[client.connect]') - session_timeout = 0 + #session_timeout = 0 print(' hardcoding timeout to 0 (always keep alive)!') if session_timeout: key += " -timeout=%s" % str(session_timeout) diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index fd78790f3672..3158e2fe20de 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -76,6 +76,7 @@ class LowLevelDevice { /*! * \brief create a host low-level device * \param num_bytes size of the memory region + * \param base_addr pointer to write the host device's resulting base address into */ const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes, void** base_addr); diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index 441e17721ad9..dfb921f71b6a 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -180,18 +180,6 @@ class SymbolMap { return map_.find(name) != map_.end(); } - std::vector GetSymbols() const { - std::vector res; - for (const auto& it : map_) { - res.push_back(it.first); - } - return res; - } - - size_t size() const { - return map_.size(); - } - private: /*! \brief backing map */ std::unordered_map map_; diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 4acc869ffb6e..4f373db483a7 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -23,8 +23,6 @@ #include #include -#include -#include #include #include #include diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 910c5f7f78f0..657ceac6585d 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -131,14 +131,21 @@ class MicroSession : public ModuleNode { static ObjectPtr& Current(); - void CreateSession(); - - BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers); + /*! + * \brief sets up runtime metadata for `func` and copies arguments for on-device execution + * \param func address of the function to be executed + * \param args args to the packed function + * \return elapsed time during function execution on the device + */ + double PushToExecQueue(DevPtr func, const TVMArgs& args); /*! - * \brief ends the session by destructing the low-level device and its allocators + * \brief loads binary onto device + * \param binary_path path to binary object file + * \param patch_dylib_pointers whether to patch runtime API function pointers + * \return info about loaded binary */ - void EndSession(); + BinaryInfo LoadBinary(const std::string& binary_path, bool patch_dylib_pointers); /*! * \brief allocate memory in section @@ -162,14 +169,6 @@ class MicroSession : public ModuleNode { */ std::string ReadString(DevPtr str_addr); - /*! - * \brief sets up runtime metadata for `func` and copies arguments for on-device execution - * \param func address of the function to be executed - * \param args args to the packed function - * \return elapsed time during function execution on the device - */ - double PushToExecQueue(DevPtr func, const TVMArgs& args); - /*! * \brief read value of symbol from device memory * \param symbol_map symbol map to read location of symbol from @@ -283,27 +282,59 @@ struct MicroDevSpace { /*! \brief TVM array for serialization to 32-bit devices */ typedef struct StructTVMArray32 { + /*! + * \brief The opaque data pointer points to the allocated data. + * This will be CUDA device pointer or cl_mem handle in OpenCL. + * This pointer is always aligns to 256 bytes as in CUDA. + */ uint32_t data; + /*! \brief The device context of the tensor */ DLContext ctx; + /*! \brief Number of dimensions */ int32_t ndim; + /*! \brief Padding to enforce struct alignment */ uint32_t pad0; + /*! \brief The data type of the pointer */ DLDataType dtype; + /*! \brief The shape of the tensor */ uint32_t shape; + /*! + * \brief strides of the tensor, + * can be NULL, indicating tensor is compact. + */ uint32_t strides; + /*! \brief Padding to enforce struct alignment */ uint32_t pad1; + /*! \brief The offset in bytes to the beginning pointer to data */ uint32_t byte_offset; + /*! \brief Padding to enforce struct alignment */ uint32_t pad2; } TVMArray32; /*! \brief TVM array for serialization to 64-bit devices */ typedef struct StructTVMArray64 { + /*! + * \brief The opaque data pointer points to the allocated data. + * This will be CUDA device pointer or cl_mem handle in OpenCL. + * This pointer is always aligns to 256 bytes as in CUDA. + */ uint64_t data; + /*! \brief The device context of the tensor */ DLContext ctx; + /*! \brief Number of dimensions */ int32_t ndim; + /*! \brief Padding to enforce struct alignment */ uint32_t pad0; + /*! \brief The data type of the pointer */ DLDataType dtype; + /*! \brief The shape of the tensor */ uint64_t shape; + /*! + * \brief strides of the tensor, + * can be NULL, indicating tensor is compact. + */ uint64_t strides; + /*! \brief The offset in bytes to the beginning pointer to data */ uint64_t byte_offset; } TVMArray64; diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index c973dc3c0bb6..4c5c7e14c2b3 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -195,24 +195,11 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { socket_.SendCommand(); } - //std::uintptr_t base_addr() const final { - // return base_addr_; - //} - - //DevPtr stack_top() const { - // CHECK(stack_top_ != nullptr) << "stack top was never initialized"; - // return stack_top_; - //} - const char* device_type() const final { return "openocd"; } private: - ///*! \brief base address of the micro device memory region */ - //std::uintptr_t base_addr_; - /*! \brief top of the stack section */ - DevPtr stack_top_; /*! \brief socket used to communicate with the device through Tcl */ TclSocket socket_; diff --git a/src/runtime/micro/target_data_layout_encoder.h b/src/runtime/micro/target_data_layout_encoder.h index e443e6a6bbeb..56d3aabcdf4c 100644 --- a/src/runtime/micro/target_data_layout_encoder.h +++ b/src/runtime/micro/target_data_layout_encoder.h @@ -32,7 +32,6 @@ namespace runtime { // TODO(weberlo): Handle endianness. -// TODO: make this parameterizable /*! * \brief data encoder for uTVM that builds a host-side buffer */ @@ -142,7 +141,7 @@ class TargetDataLayoutEncoder { size_t curr_offset_; /*! \brief start address of the encoder in device memory */ DevPtr start_addr_; - /*! \brief TODO */ + /*! \brief number of bytes in a word on the target device */ size_t word_size_; }; From 05c53ee80911fa6ef1c924626206ae4a47fed19a Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 12:08:12 -0800 Subject: [PATCH 44/70] Remove debug code --- python/tvm/autotvm/measure/measure_methods.py | 3 - python/tvm/autotvm/task/task.py | 4 - python/tvm/contrib/binutil.py | 25 ------ python/tvm/micro/base.py | 3 +- python/tvm/micro/device/base.py | 12 --- python/tvm/module.py | 1 - python/tvm/rpc/client.py | 8 -- python/tvm/rpc/server.py | 2 - python/tvm/rpc/tracker.py | 3 - src/codegen/build_module.cc | 3 - src/runtime/micro/micro_module.cc | 4 - src/runtime/micro/micro_session.cc | 58 ------------ src/runtime/micro/micro_session.h | 2 + src/runtime/micro/tcl_socket.cc | 3 - src/runtime/rpc/rpc_session.cc | 52 ----------- src/runtime/rpc/rpc_session.h | 48 +++++----- tests/python/unittest/test_runtime_micro.py | 90 +------------------ 17 files changed, 31 insertions(+), 290 deletions(-) diff --git a/python/tvm/autotvm/measure/measure_methods.py b/python/tvm/autotvm/measure/measure_methods.py index 436134c1d8d6..861719fffe53 100644 --- a/python/tvm/autotvm/measure/measure_methods.py +++ b/python/tvm/autotvm/measure/measure_methods.py @@ -246,7 +246,6 @@ def get_build_kwargs(self): return kwargs def run(self, measure_inputs, build_results): - print('[RPCRunner.run]') results = [] remote_args = (self.key, self.host, self.port, self.priority, self.timeout) @@ -271,9 +270,7 @@ def run(self, measure_inputs, build_results): if isinstance(res, Exception): # executor error or timeout results.append(MeasureResult((str(res),), MeasureErrorNo.RUN_TIMEOUT, self.timeout, time.time())) - raise Exception(f'encountered exception during measurement: {results}') else: - print(f' got a result: {res}') results.append(res) return results diff --git a/python/tvm/autotvm/task/task.py b/python/tvm/autotvm/task/task.py index 8abf20f37a3b..7f36914eb0a6 100644 --- a/python/tvm/autotvm/task/task.py +++ b/python/tvm/autotvm/task/task.py @@ -178,11 +178,8 @@ def create(func_name, args, target, target_host=None, template_key=None): func = TASK_TABLE[func_name] ret = Task(func_name, args) - print('[autotvm.task.create]') - print(f' target before: {target}') if isinstance(target, str): target = _target.create(target) - print(f' target after: {target}') # init config space ret.config_space = ConfigSpace() @@ -193,7 +190,6 @@ def create(func_name, args, target, target_host=None, template_key=None): with target: sch, _ = func(*args) ret.config_space.code_hash = getattr(sch, 'code_hash', None) - print(f' ctx: {ctx}') ret.workload = ctx.workload ret.flop = ret.config_space.flop or compute_flop(sch) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 1b32f13f83df..d48c0bb1ac2d 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -22,7 +22,6 @@ from .._ffi.base import py_str from ..api import register_func - def run_cmd(cmd): proc = subprocess.Popen( cmd, @@ -147,21 +146,6 @@ def tvm_callback_relocate_binary( rel_bin : bytearray the relocated binary """ - global TEMPDIR_REFS - tmp_dir = util.tempdir() - TEMPDIR_REFS.append(tmp_dir) - rel_obj_path = tmp_dir.relpath('relocated.obj') - #rel_obj_path = '/home/pratyush/Code/nucleo-interaction-from-scratch/src/main_relocated.o' - with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'r') as f: - gdbinit_contents = f.read().split('\n') - new_contents = [] - for line in gdbinit_contents: - new_contents.append(line) - if line.startswith('target'): - new_contents.append(f'add-symbol-file {rel_obj_path}') - with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: - f.write('\n'.join(new_contents)) - stack_pointer_init = stack_end - word_size ld_script_contents = '' @@ -215,14 +199,6 @@ def tvm_callback_relocate_binary( }} }} """ - print(ld_script_contents) - #input('check script: ') - print(f'relocing lib {binary_path}') - print(f' text_start: {text_start}') - print(f' rodata_start: {rodata_start}') - print(f' data_start: {data_start}') - print(f' bss_start: {bss_start}') - rel_ld_script_path = tmp_dir.relpath('relocated.lds') with open(rel_ld_script_path, 'w') as f: f.write(ld_script_contents) @@ -231,7 +207,6 @@ def tvm_callback_relocate_binary( binary_path, '-T', rel_ld_script_path, '-o', rel_obj_path]) - #input(f'relocated obj path is {rel_obj_path}') with open(rel_obj_path, 'rb') as f: rel_bin = bytearray(f.read()) return rel_bin diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 4c9dfcf2242b..a68f204fa73f 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -123,7 +123,6 @@ def create_micro_mod(self, c_mod): micro_mod : tvm.module.Module micro module for the target device """ - print('[create_micro_mod]') temp_dir = _util.tempdir() lib_obj_path = temp_dir.relpath('dev_lib.obj') c_mod.export_library( @@ -153,7 +152,7 @@ def __exit__(self, exc_type, exc_value, exc_traceback): def cross_compiler(create_micro_lib, lib_type): - """Create a cross compile function that wraps `create_lib` for a `Binutil` instance. + """Create a cross-compile function that wraps `create_lib` for a `Binutil` instance. For use in `tvm.module.Module.export_library`. diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index 2dacfab26cf4..a0e50dad9877 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -79,12 +79,6 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t options : List[str] additional options to pass to GCC """ - print('[MicroBinutil.create_lib]') - print(' EXTENDED OPTIONS') - print(f' {obj_path}') - print(f' {src_path}') - print(f' {lib_type}') - print(f' {options}') base_compile_cmd = [ f'{toolchain_prefix}gcc', '-std=c11', @@ -109,14 +103,10 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t tmp_dir = _util.tempdir() if lib_type == LibType.RUNTIME: dev_dir = _get_device_source_dir(device_id) - - print(dev_dir) dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') - print(dev_src_paths) # there needs to at least be a utvm_timer.c file assert dev_src_paths assert 'utvm_timer.c' in map(os.path.basename, dev_src_paths) - src_paths += dev_src_paths elif lib_type == LibType.OPERATOR: # create a temporary copy of the source, so we can inject the dev lib @@ -128,14 +118,12 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t with open(temp_src_path, 'w') as f: f.write('\n'.join(src_lines)) src_path = temp_src_path - base_compile_cmd += ['-c'] else: raise RuntimeError('unknown lib type') src_paths += [src_path] - print(f'include paths: {include_paths}') for path in include_paths: base_compile_cmd += ['-I', path] diff --git a/python/tvm/module.py b/python/tvm/module.py index e8f5a4ef64a0..0cd522ed1edd 100644 --- a/python/tvm/module.py +++ b/python/tvm/module.py @@ -199,7 +199,6 @@ def time_evaluator(self, func_name, ctx, number=10, repeat=1, min_repeat_ms=0): def evaluator(*args): """Internal wrapped evaluator.""" - print('[Module.time_evaluator.evaluator]') # Wrap feval so we can add more stats in future. blob = feval(*args) fmt = "@" + ("d" * repeat) diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index 39c7b564fad5..13868f05cacb 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -70,9 +70,6 @@ def context(self, dev_type, dev_id=0): ctx: TVMContext The corresponding encoded remote context. """ - print('[RPCSession.context]') - print(f' dev_type: {dev_type}') - print(f' dev_id: {dev_id}') if '-device=micro_dev' in dev_type: dev_type = 'micro_dev' ctx = nd.context(dev_type, dev_id) @@ -408,14 +405,9 @@ def connect(url, port, key="", session_timeout=0): The connected session. """ try: - print('[client.connect]') - #session_timeout = 0 - print(' hardcoding timeout to 0 (always keep alive)!') if session_timeout: key += " -timeout=%s" % str(session_timeout) - print(f' connecting to RPC server with {url}, {port}, {key}') sess = base._Connect(url, port, key) - print(f' finished connecting!') except NameError: raise RuntimeError("Please compile with USE_RPC=1") return RPCSession(sess) diff --git a/python/tvm/rpc/server.py b/python/tvm/rpc/server.py index 1ac03485e37d..9e03097e89a7 100644 --- a/python/tvm/rpc/server.py +++ b/python/tvm/rpc/server.py @@ -66,9 +66,7 @@ def get_workpath(path): def load_module(file_name): """Load module from remote side.""" path = temp.relpath(file_name) - print('[rpc.server] ABOUT TO LOAD MOD') m = _load_module(path) - print('[rpc.server] DONE LOADING MOD') logger.info("load_module %s", path) return m diff --git a/python/tvm/rpc/tracker.py b/python/tvm/rpc/tracker.py index bed131962750..b9b29a7fe4a1 100644 --- a/python/tvm/rpc/tracker.py +++ b/python/tvm/rpc/tracker.py @@ -297,11 +297,8 @@ def _event_handler(_, events): def _on_event(self, _): while True: try: - print('waiting for connection!') conn, addr = self._sock.accept() - print(f'got new conn: {conn}, {addr}') TCPEventHandler(self, conn, addr) - print(f'made event handler') except socket.error as err: if err.args[0] in (errno.EAGAIN, errno.EWOULDBLOCK): break diff --git a/src/codegen/build_module.cc b/src/codegen/build_module.cc index e40a30d7de90..ed438e9fb7f8 100644 --- a/src/codegen/build_module.cc +++ b/src/codegen/build_module.cc @@ -216,7 +216,6 @@ std::string GetDeviceName(const std::string& target_str) { } Target Target::Create(const std::string& target_str) { - std::cout << "[Target::Create]" << std::endl; if (target_str.length() == 0) { LOG(ERROR) << "target_str must not be empty"; } @@ -226,13 +225,11 @@ Target Target::Create(const std::string& target_str) { ss >> target_name; auto device_name = GetDeviceName(target_str); - std::cout << " device_name: " << device_name << std::endl; std::vector options; std::string item; while (ss >> item) { options.push_back(item); - std::cout << " option: " << item << std::endl; } return CreateTarget(target_name, options); diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index f480b9658484..09834f166c21 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -54,11 +54,8 @@ class MicroModuleNode final : public ModuleNode { * \param binary_path path of the binary to be loaded */ void InitMicroModule(const std::string& binary_path) { - std::cout << "[MicroModuleNode::InitMicroModule]" << std::endl; - std::cout << " start" << std::endl; session_ = MicroSession::Current(); symbol_map_ = session_->LoadBinary(binary_path, true).symbol_map; - std::cout << " end" << std::endl; } private: @@ -76,7 +73,6 @@ class MicroWrappedFunc { } void operator()(TVMArgs args, TVMRetValue* rv) const { - std::cout << "[MicroWrappedFunc::operator()]" << std::endl; *rv = session_->PushToExecQueue(func_ptr_, args); } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 4f373db483a7..50813ff9b67b 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -178,19 +178,7 @@ MicroSession::MicroSession( LOG(FATAL) << "unsupported micro low-level device"; } - std::cout << "[Memory Layout]" << std::endl; - std::cout << " text (size = " << (section_allocators_[0]->capacity() / 1000.0) << " KB): " << section_allocators_[0]->start_addr().cast_to() << std::endl; - std::cout << " rodata (size = " << (section_allocators_[1]->capacity() / 1000.0) << " KB): " << section_allocators_[1]->start_addr().cast_to() << std::endl; - std::cout << " data (size = " << (section_allocators_[2]->capacity() / 1000.0) << " KB): " << section_allocators_[2]->start_addr().cast_to() << std::endl; - std::cout << " bss (size = " << (section_allocators_[3]->capacity() / 1000.0) << " KB): " << section_allocators_[3]->start_addr().cast_to() << std::endl; - std::cout << " args (size = " << (section_allocators_[4]->capacity() / 1000.0) << " KB): " << section_allocators_[4]->start_addr().cast_to() << std::endl; - std::cout << " heap (size = " << (section_allocators_[5]->capacity() / 1000.0) << " KB): " << section_allocators_[5]->start_addr().cast_to() << std::endl; - std::cout << " workspace (size = " << (section_allocators_[6]->capacity() / 1000.0) << " KB): " << section_allocators_[6]->start_addr().cast_to() << std::endl; - std::cout << " stack (size = " << (section_allocators_[7]->capacity() / 1000.0) << " KB): " << section_allocators_[7]->start_addr().cast_to() << std::endl; - runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; - std::cout << runtime_symbol_map_["UTVMMain"].cast_to() << std::endl; - std::cout << runtime_symbol_map_["utvm_task"].cast_to() << std::endl; // Patch pointers to define the bounds of the workspace section and the word size (for allocation alignment). if (word_size_ == 4) { @@ -218,7 +206,6 @@ MicroSession::~MicroSession() { } double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { - std::cout << "[MicroSession::PushToExecQueue]" << std::endl; if (thumb_mode_) { func_ptr += 1; } @@ -263,43 +250,16 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } - std::cout << " after task write" << std::endl; - DevPtr utvm_init_addr = runtime_symbol_map_["UTVMInit"]; DevPtr utvm_done_addr = runtime_symbol_map_["UTVMDone"]; if (thumb_mode_) { utvm_init_addr += 1; } - std::cout << " UTVMInit loc: " << utvm_init_addr.cast_to() << std::endl; - std::cout << " UTVMDone loc: " << utvm_done_addr.cast_to() << std::endl; - //std::cout << " do execution things: "; - //char tmp; - //std::cin >> tmp; low_level_device()->Execute(utvm_init_addr, utvm_done_addr); - // Check if there was an error during execution. If so, log it. CheckDeviceError(); - - uint64_t workspace_start = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_start"); - std::cout << " workspace start: " << workspace_start << std::endl; - uint64_t workspace_end = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_end"); - std::cout << " workspace end: " << workspace_end << std::endl; - uint64_t word_size = DevSymbolRead(runtime_symbol_map_, "utvm_word_size"); - std::cout << " word size: " << word_size << std::endl; - - //std::uintptr_t workspace_curr = DevSymbolRead(runtime_symbol_map_, "utvm_workspace_curr"); - //std::cout << " workspace curr: " << workspace_curr << std::endl; - //size_t num_active_allocs = DevSymbolRead(runtime_symbol_map_, "utvm_num_active_allocs"); - //std::cout << " num active allocs: " << num_active_allocs << std::endl; - //std::uintptr_t last_error = DevSymbolRead(runtime_symbol_map_, "utvm_last_error"); - //std::cout << " last error: " << last_error << std::endl; - //int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); - //std::cout << " return code: " << return_code << std::endl; uint32_t task_time = DevSymbolRead(runtime_symbol_map_, "utvm_task_time"); - std::cout << " task time was " << task_time << std::endl; - std::cout << " --------------------------------------------------------------------------------" << std::endl; - GetAllocator(SectionKind::kArgs)->Free(stream_dev_addr); return static_cast(task_time); } @@ -314,10 +274,6 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, word_size_); data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, word_size_); bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, word_size_); - std::cout << "text size: " << std::hex << text_section.size << std::endl; - std::cout << "rodata size: " << std::hex << rodata_section.size << std::endl; - std::cout << "data size: " << std::hex << data_section.size << std::endl; - std::cout << "bss size: " << std::hex << bss_section.size << std::endl; text_section.start = AllocateInSection(SectionKind::kText, text_section.size); rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); @@ -327,10 +283,6 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d data_section.start != nullptr && bss_section.start != nullptr) << "not enough space to load module on device"; - std::cout << "text start: " << std::hex << text_section.start.value() << std::endl; - std::cout << "rodata start: " << std::hex << rodata_section.start.value() << std::endl; - std::cout << "data start: " << std::hex << data_section.start.value() << std::endl; - std::cout << "bss start: " << std::hex << bss_section.start.value() << std::endl; std::string relocated_bin = RelocateBinarySections( binary_path, word_size_, @@ -345,13 +297,9 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::string data_contents = ReadSection(relocated_bin, SectionKind::kData, toolchain_prefix_); std::string bss_contents = ReadSection(relocated_bin, SectionKind::kBss, toolchain_prefix_); - std::cout << "writing text (size = " << std::dec << text_contents.size() << ")" << std::endl; low_level_device_->Write(text_section.start, &text_contents[0], text_section.size); - std::cout << "writing rodata (size = " << std::dec << rodata_contents.size() << ")" << std::endl; low_level_device_->Write(rodata_section.start, &rodata_contents[0], rodata_section.size); - std::cout << "writing data (size = " << std::dec << data_contents.size() << ")" << std::endl; low_level_device_->Write(data_section.start, &data_contents[0], data_section.size); - std::cout << "writing bss (size = " << std::dec << bss_contents.size() << ")" << std::endl; low_level_device_->Write(bss_section.start, &bss_contents[0], bss_section.size); SymbolMap symbol_map {relocated_bin, toolchain_prefix_}; @@ -373,7 +321,6 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d std::tuple MicroSession::EncoderAppend( TargetDataLayoutEncoder* encoder, const TVMArgs& args) { - std::cout << "[MicroSession::EncoderAppend]" << std::endl; const int* type_codes = args.type_codes; int num_args = args.num_args; @@ -492,10 +439,7 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr } void MicroSession::CheckDeviceError() { - std::cout << "[MicroSession::CheckDeviceError]" << std::endl; int32_t return_code = DevSymbolRead(runtime_symbol_map_, "utvm_return_code"); - std::cout << " return_code: " << return_code << std::endl; - std::cout << " return_code loc: " << runtime_symbol_map_["utvm_return_code"].cast_to() << std::endl; if (return_code) { std::uintptr_t last_error = @@ -517,7 +461,6 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& if (thumb_mode_) { runtime_impl_addr += 1; } - std::cout << "patching " << func_name << " at " << symbol_map[func_name].cast_to() << " with addr " << runtime_impl_addr.cast_to() << std::endl; std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; if (word_size_ == 4) { @@ -556,7 +499,6 @@ void MicroSession::FreeInSection(SectionKind type, DevPtr addr) { template T MicroSession::DevSymbolRead(const SymbolMap& symbol_map, const std::string& symbol) { DevPtr sym_addr = symbol_map[symbol]; - std::cout << "sym offset for " << symbol << " is " << sym_addr.cast_to() << std::endl; T result; low_level_device()->Read(sym_addr, &result, sizeof(T)); return result; diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 657ceac6585d..704c5b238dbd 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -280,6 +280,8 @@ struct MicroDevSpace { ObjectPtr session; }; +// TODO(weberlo): maybe templatize serialization to reduce redundancy + /*! \brief TVM array for serialization to 32-bit devices */ typedef struct StructTVMArray32 { /*! diff --git a/src/runtime/micro/tcl_socket.cc b/src/runtime/micro/tcl_socket.cc index 1f3f4922d2f4..107fb1529498 100644 --- a/src/runtime/micro/tcl_socket.cc +++ b/src/runtime/micro/tcl_socket.cc @@ -42,11 +42,8 @@ void TclSocket::Connect(tvm::common::SockAddr addr) { } void TclSocket::SendCommand() { - //std::cout << "[TclSocket::SendCommand]" << std::endl; - //std::cout << " cmd: " << cmd_builder_.str() << std::endl; cmd_builder_ << kCommandTerminateToken; std::string full_cmd = cmd_builder_.str(); - CHECK(tcp_socket_.Send(full_cmd.data(), full_cmd.length()) != -1) << "failed to send command"; cmd_builder_.str(std::string()); diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index c4e7f94ef7be..0c913464c3f9 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -42,36 +42,6 @@ namespace tvm { namespace runtime { -std::string RPCCodeToString(RPCCode code) { - switch (code) { - case RPCCode::kNone: return "None"; - case RPCCode::kCallFunc: return "CallFunc"; - case RPCCode::kReturn: return "Return"; - case RPCCode::kException: return "Exception"; - case RPCCode::kShutdown: return "Shutdown"; - case RPCCode::kCopyFromRemote: return "CopyFromRemote"; - case RPCCode::kCopyToRemote: return "CopyToRemote"; - case RPCCode::kCopyAck: return "CopyAck"; - case RPCCode::kSystemFuncStart: return "SystemFuncStart"; - case RPCCode::kGetGlobalFunc: return "GetGlobalFunc"; - case RPCCode::kGetTimeEvaluator: return "GetTimeEvaluator"; - case RPCCode::kFreeFunc: return "FreeFunc"; - case RPCCode::kDevSetDevice: return "DevSetDevice"; - case RPCCode::kDevGetAttr: return "DevGetAttr"; - case RPCCode::kDevAllocData: return "DevAllocData"; - case RPCCode::kDevFreeData: return "DevFreeData"; - case RPCCode::kDevStreamSync: return "DevStreamSync"; - case RPCCode::kCopyAmongRemote: return "CopyAmongRemote"; - case RPCCode::kModuleLoad: return "ModuleLoad"; - case RPCCode::kModuleImport: return "ModuleImport"; - case RPCCode::kModuleFree: return "ModuleFree"; - case RPCCode::kModuleGetFunc: return "ModuleGetFunc"; - case RPCCode::kModuleGetSource: return "ModuleGetSource"; - case RPCCode::kNDArrayFree: return "NDArrayFree"; - default: CHECK(false) << "invalid RPC code"; - } -} - // Temp buffer for data array struct RPCByteArrayBuffer { TVMByteArray arr; @@ -903,12 +873,6 @@ void RPCSession::Init() { &reader_, &writer_, table_index_, name_, &remote_key_); // Quick function to call remote. call_remote_ = PackedFunc([this](TVMArgs args, TVMRetValue* rv) { - std::cout << "[RPCSession::call_remote_]" << std::endl; - if (args.type_codes[0] == kTVMContext) { - const TVMContext ctx = args[0]; - std::cout << " ctx.device_type: " << ctx.device_type << std::endl; - std::cout << " ctx.device_id: " << ctx.device_id << std::endl; - } handler_->SendPackedSeq(args.values, args.type_codes, args.num_args); RPCCode code = HandleUntilReturnEvent(rv, true, nullptr); CHECK(code == RPCCode::kReturn) << "code=" << static_cast(code); @@ -1088,10 +1052,7 @@ void RPCDevSetDevice(TVMArgs args, TVMRetValue *rv) { } void RPCDevGetAttr(TVMArgs args, TVMRetValue *rv) { - std::cout << "[RPCDevGetAttr]" << std::endl; TVMContext ctx = args[0]; - std::cout << " ctx.device_type: " << ctx.device_type << std::endl; - std::cout << " ctx.device_id: " << ctx.device_id << std::endl; DeviceAttrKind kind = static_cast(args[1].operator int()); if (kind == kExist) { DeviceAPI* api = DeviceAPI::Get(ctx, true); @@ -1107,10 +1068,7 @@ void RPCDevGetAttr(TVMArgs args, TVMRetValue *rv) { } void RPCDevAllocData(TVMArgs args, TVMRetValue *rv) { - std::cout << "[RPCDevAllocData]" << std::endl; TVMContext ctx = args[0]; - std::cout << " ctx.device_type: " << ctx.device_type << std::endl; - std::cout << " ctx.device_id: " << ctx.device_id << std::endl; uint64_t nbytes = args[1]; uint64_t alignment = args[2]; TVMType type_hint = args[3]; @@ -1132,18 +1090,13 @@ void RPCDevStreamSync(TVMArgs args, TVMRetValue *rv) { } void RPCCopyAmongRemote(TVMArgs args, TVMRetValue *rv) { - std::cout << "[RPCCopyAmongRemote]" << std::endl; void* from = args[0]; uint64_t from_offset = args[1]; void* to = args[2]; uint64_t to_offset = args[3]; uint64_t size = args[4]; TVMContext ctx_from = args[5]; - std::cout << " ctx_from.device_type: " << ctx_from.device_type << std::endl; - std::cout << " ctx_from.device_id: " << ctx_from.device_type << std::endl; TVMContext ctx_to = args[6]; - std::cout << " ctx_to.device_type: " << ctx_to.device_type << std::endl; - std::cout << " ctx_to.device_id: " << ctx_to.device_type << std::endl; TVMType type_hint = args[7]; TVMStreamHandle stream = args[8]; TVMContext ctx = ctx_from; @@ -1218,7 +1171,6 @@ void RPCGetTimeEvaluator(TVMArgs args, TVMRetValue *rv) { } void RPCSession::EventHandler::HandlePackedCall() { - std::cout << "[RPCSession::EventHandler::HandlePackedCall]" << std::endl; CHECK_EQ(pending_request_bytes_, 0U); if (code_ == RPCCode::kReturn) { state_ = kReturnReceived; return; @@ -1227,7 +1179,6 @@ void RPCSession::EventHandler::HandlePackedCall() { state_ = kRecvCode; this->RequestBytes(sizeof(RPCCode)); // Event handler sit at clean state at this point. - std::cout << " RPC code is " << RPCCodeToString(code_) << std::endl; switch (code_) { case RPCCode::kCallFunc: { PackedFunc* pf = reinterpret_cast(call_handle_); @@ -1242,7 +1193,6 @@ void RPCSession::EventHandler::HandlePackedCall() { std::ostringstream os; os << "Except caught from RPC call: " << arg_buf_->value[0].v_str; arg_buf_.reset(); - std::cout << os.str() << std::endl; throw dmlc::Error(os.str()); break; } @@ -1274,7 +1224,6 @@ PackedFunc MicroTimeEvaluator( int repeat, int min_repeat_ms) { auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { - std::cout << "[WrapTimeEvaluator::MicroTimeEvaluator]" << std::endl; TVMRetValue temp; std::ostringstream os; // skip first time call, to activate lazy compilation components. @@ -1288,7 +1237,6 @@ PackedFunc MicroTimeEvaluator( DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); speed += (temp.operator double()) / number; } - std::cout << " [[TRIAL " << i << " AVERAGE IS " << speed << "]]" << std::endl; os.write(reinterpret_cast(&speed), sizeof(speed)); } std::string blob = os.str(); diff --git a/src/runtime/rpc/rpc_session.h b/src/runtime/rpc/rpc_session.h index 743dc8d1e6e0..ab5f16dadc46 100644 --- a/src/runtime/rpc/rpc_session.h +++ b/src/runtime/rpc/rpc_session.h @@ -63,31 +63,31 @@ struct RPCArgBuffer; /*! \brief The RPC code */ enum class RPCCode : int { - kNone = 0, - kCallFunc = 1, - kReturn = 2, - kException = 3, - kShutdown = 4, - kCopyFromRemote = 5, - kCopyToRemote = 6, - kCopyAck = 7, + kNone, + kCallFunc, + kReturn, + kException, + kShutdown, + kCopyFromRemote, + kCopyToRemote, + kCopyAck, // The following are code that can send over CallRemote - kSystemFuncStart = 8, - kGetGlobalFunc = 9, - kGetTimeEvaluator = 10, - kFreeFunc = 11, - kDevSetDevice = 12, - kDevGetAttr = 13, - kDevAllocData = 14, - kDevFreeData = 15, - kDevStreamSync = 16, - kCopyAmongRemote = 17, - kModuleLoad = 18, - kModuleImport = 19, - kModuleFree = 20, - kModuleGetFunc = 21, - kModuleGetSource = 22, - kNDArrayFree = 23 + kSystemFuncStart, + kGetGlobalFunc, + kGetTimeEvaluator, + kFreeFunc, + kDevSetDevice, + kDevGetAttr, + kDevAllocData, + kDevFreeData, + kDevStreamSync, + kCopyAmongRemote, + kModuleLoad, + kModuleImport, + kModuleFree, + kModuleGetFunc, + kModuleGetSource, + kNDArrayFree }; /*! diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 8a42facc274c..e227b2b2d4d3 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -24,8 +24,7 @@ from tvm.relay.testing import resnet # Use the host emulated micro device. -#DEV_CONFIG = micro.device.host.default_config() -DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) +DEV_CONFIG = micro.device.host.default_config() def relay_micro_build(func, sess, params=None): """Create a graph runtime module with a micro device context from a Relay function. @@ -52,26 +51,6 @@ def relay_micro_build(func, sess, params=None): return mod -def reset_gdbinit(): - with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: - gdbinit_contents = ( -"""layout asm -target remote localhost:3333 - -#print "(*((TVMValue*) utvm_task.arg_values)).v_handle" -#print (*((TVMValue*) utvm_task.arg_values)).v_handle -#print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" -#print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) -#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" -#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] -#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" -#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] -#break UTVMMain -#break UTVMDone -#jump UTVMMain""") - f.write(gdbinit_contents) - - def test_alloc(): """Test tensor allocation on the device.""" if not tvm.module.enabled("micro_dev"): @@ -92,8 +71,6 @@ def test_add(): shape = (1024,) dtype = "float32" - reset_gdbinit() - # Construct TVM expression. tvm_shape = tvm.convert(shape) A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) @@ -111,11 +88,7 @@ def test_add(): a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print(a) - print(b) - print(c) micro_func(a, b, c) - print(c) tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + b.asnumpy()) @@ -145,11 +118,8 @@ def test_workspace_add(): micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - print(a) c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print(c) micro_func(a, c) - print(c) tvm.testing.assert_allclose( c.asnumpy(), a.asnumpy() + 2.0) @@ -172,64 +142,13 @@ def test_graph_runtime(): mod = relay_micro_build(func, sess) x_in = np.random.uniform(size=shape[0]).astype(dtype) - print(x_in) mod.run(x=x_in) result = mod.get_output(0).asnumpy() - print(result) tvm.testing.assert_allclose( result, x_in * x_in + 1.0) -def test_conv2d(): - if not tvm.module.enabled("micro_dev"): - return - - from tvm.relay import create_executor - from tvm.relay import transform - - dshape = (1, 4, 16, 16) - dtype = 'float32' - func_name = 'fused_nn_conv2d' - - reset_gdbinit() - - # Construct Relay program. - x = relay.var("x", shape=dshape, dtype=dtype) - conv_expr = relay.nn.conv2d( - x, relay.var("w"), - kernel_size=(3, 3), - padding=(1, 1), - channels=4) - func = relay.Function(relay.analysis.free_vars(conv_expr), conv_expr) - mod = relay.Module.from_expr(func) - mod = transform.InferType()(mod) - - x_shape = list(map(lambda x: x.value, mod['main'].params[0].checked_type.shape)) - w_shape = list(map(lambda x: x.value, mod['main'].params[1].checked_type.shape)) - out_shape = list(map(lambda x: x.value, mod['main'].ret_type.shape)) - - with tvm.build_config(disable_vectorize=True): - graph, c_mod, params = relay.build(mod, target="c") - - with micro.Session(DEV_CONFIG) as sess: - micro_mod = sess.create_micro_mod(c_mod) - micro_func = micro_mod[func_name] - ctx = tvm.micro_dev(0) - - x_data = tvm.nd.array(np.random.uniform(size=x_shape).astype(dtype), ctx) - w_data = tvm.nd.array(np.random.uniform(size=w_shape).astype(dtype), ctx) - result = tvm.nd.array(np.zeros(shape=out_shape, dtype=dtype), ctx) - micro_func(x_data, w_data, result) - - out_data = np.zeros(out_shape, dtype=dtype) - params = { 'x': x_data.asnumpy(), 'w': w_data.asnumpy() } - intrp = create_executor('debug') - expected_result = intrp.evaluate(mod['main'])(x_data, w_data).data - - tvm.testing.assert_allclose(result.asnumpy(), expected_result.asnumpy()) - - def test_multiple_modules(): """Test loading multiple modules on the device simultaneously.""" if not tvm.module.enabled("micro_dev"): @@ -355,8 +274,7 @@ def test_inactive_session_use(): test_add() test_workspace_add() test_graph_runtime() - test_conv2d() test_multiple_modules() - #test_interleave_sessions() - #test_nested_sessions() - #test_inactive_session_use() + test_interleave_sessions() + test_nested_sessions() + test_inactive_session_use() From 625c16a0b5a89b04adad68dd1096463eb3dbf9e3 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 12:27:16 -0800 Subject: [PATCH 45/70] remove demo files (temporarily) --- arm-auto-utvm-demo/test_micro_rpc.py | 136 ------------------------ arm-auto-utvm-demo/tune_relay_utvm.py | 144 -------------------------- 2 files changed, 280 deletions(-) delete mode 100644 arm-auto-utvm-demo/test_micro_rpc.py delete mode 100644 arm-auto-utvm-demo/tune_relay_utvm.py diff --git a/arm-auto-utvm-demo/test_micro_rpc.py b/arm-auto-utvm-demo/test_micro_rpc.py deleted file mode 100644 index fd980dc7b140..000000000000 --- a/arm-auto-utvm-demo/test_micro_rpc.py +++ /dev/null @@ -1,136 +0,0 @@ -import logging -import os - -import numpy as np - -import tvm -from tvm import rpc -from tvm import micro -from tvm.contrib import graph_runtime, util - -assert tvm.module.enabled("rpc") -assert tvm.module.enabled("micro_dev") - -def create_and_load_micro_mod(remote, c_mod, name, toolchain_prefix): - """Produces a micro module from a given module. - - Parameters - ---------- - c_mod : tvm.module.Module - module with "c" as its target backend - - toolchain_prefix : str - toolchain prefix to be used (see `tvm.micro.Session` docs) - - Return - ------ - micro_mod : tvm.module.Module - micro module for the target device - """ - temp_dir = util.tempdir() - lib_obj_path = temp_dir.relpath(f'{name}.obj') - c_mod.export_library( - lib_obj_path, - fcompile=tvm.micro.cross_compiler(toolchain_prefix, micro.LibType.OPERATOR)) - remote.upload(lib_obj_path) - micro_mod = remote.load_module(os.path.basename(lib_obj_path)) - #micro_mod = tvm.module.load(lib_obj_path) - return micro_mod - - -def reset_gdbinit(): - with open('/home/pratyush/Code/nucleo-interaction-from-scratch/.gdbinit', 'w') as f: - gdbinit_contents = ( -"""layout asm -target remote localhost:3333 - -#print "(*((TVMValue*) utvm_task.arg_values)).v_handle" -#print (*((TVMValue*) utvm_task.arg_values)).v_handle -#print "*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))" -#print *((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle)) -#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0]" -#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[0] -#print "((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1]" -#print ((float*) (*((TVMArray*) ((*((TVMValue*) utvm_task.arg_values)).v_handle))).data)[1] -#break UTVMMain -#break UTVMDone -#jump UTVMMain""") - f.write(gdbinit_contents) - - -#DEVICE_TYPE = 'host' -#TOOLCHAIN_PREFIX = '' -DEVICE_TYPE = 'openocd' -TOOLCHAIN_PREFIX = 'arm-none-eabi-' - -def test_utvm_session(): - server = rpc.Server("localhost", key="micro") - remote = rpc.connect(server.host, server.port, key="micro") - utvm_sess_create = remote.get_function("micro.create_session") - sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) - sess['enter']() - sess['exit']() - - -def test_rpc_alloc(): - shape = (1024,) - dtype = "float32" - - server = rpc.Server("localhost", key="micro") - remote = rpc.connect(server.host, server.port, key="micro") - utvm_sess_create = remote.get_function("micro.create_session") - sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) - sess['enter']() - - ctx = remote.micro_dev(0) - np_tensor = np.random.uniform(size=shape).astype(dtype) - micro_tensor = tvm.nd.array(np_tensor, ctx) - tvm.testing.assert_allclose(np_tensor, micro_tensor.asnumpy()) - - sess['exit']() - - -def test_rpc_add(): - shape = (1024,) - dtype = "float32" - - reset_gdbinit() - - server = rpc.Server("localhost", key="micro") - remote = rpc.connect(server.host, server.port, key="micro") - utvm_sess_create = remote.get_function("micro.create_session") - sess = utvm_sess_create(DEVICE_TYPE, TOOLCHAIN_PREFIX) - - # Construct TVM expression. - tvm_shape = tvm.convert(shape) - A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) - B = tvm.placeholder(tvm_shape, name="B", dtype=dtype) - C = tvm.compute(A.shape, lambda *i: A(*i) + B(*i), name="C") - s = tvm.create_schedule(C.op) - - func_name = 'fadd' - c_mod = tvm.build(s, [A, B, C], target='c', name=func_name) - - sess['enter']() - - micro_mod = create_and_load_micro_mod(remote, c_mod, 'fadd', TOOLCHAIN_PREFIX) - micro_func = micro_mod[func_name] - - ctx = remote.micro_dev(0) - a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - print(a) - b = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) - print(b) - c = tvm.nd.array(np.zeros(shape, dtype=dtype), ctx) - print(c) - micro_func(a, b, c) - print(c) - - sess['exit']() - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - #test_utvm_session() - #test_rpc_alloc() - test_rpc_add() diff --git a/arm-auto-utvm-demo/tune_relay_utvm.py b/arm-auto-utvm-demo/tune_relay_utvm.py deleted file mode 100644 index 147ea09f0151..000000000000 --- a/arm-auto-utvm-demo/tune_relay_utvm.py +++ /dev/null @@ -1,144 +0,0 @@ -# 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 os -from mxnet.gluon.model_zoo import vision -import numpy as np -from PIL import Image - -import topi -import tvm -from tvm import rpc, autotvm, relay -from tvm.contrib import graph_runtime, util, download -from tvm.autotvm.measure.measure_methods import request_remote -from tvm.autotvm.tuner import XGBTuner, GATuner, RandomTuner, GridSearchTuner -import tvm.micro as micro - -import vta -from vta.testing import simulator -from vta.top import graph_pack - -# First, run `python -m tvm.exec.rpc_tracker --host 0.0.0.0 --port=9190` in one terminal. -# Then, run `python -m tvm.micro.rpc_server --tracker=0.0.0.0:9190 --key=micro -# --dev-config=` in another. - -DEV_CONFIG = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) -DEV_CREATE_MICRO_LIB = micro.device.get_device_funcs(DEV_CONFIG['device_id'])['create_micro_lib'] -#DEV_CONFIG = micro.device.host.default_config() - -DEVICE = 'arm-cortex-m' -TARGET = tvm.target.create('c -device=micro_dev') - -N, L, M = 32, 32, 32 -DTYPE = 'float32' -N_TRIAL = 2 -N_PER_TRIAL = 1 -N_PARALLEL = 1 - -SERVER_ADDR = '0.0.0.0' -SERVER_PORT = 9190 - -LOG_FILE_NAME = f'{DEVICE}.log' -if os.path.exists(LOG_FILE_NAME): - os.remove(LOG_FILE_NAME) - -@autotvm.template -def matmul(N, L, M, dtype): - A = tvm.placeholder((N, L), name='A', dtype=dtype) - B = tvm.placeholder((L, M), name='B', dtype=dtype) - - k = tvm.reduce_axis((0, L), name='k') - C = tvm.compute((N, M), lambda i, j: tvm.sum(A[i, k] * B[k, j], axis=k), name='C') - s = tvm.create_schedule(C.op) - - # schedule - y, x = s[C].op.axis - k = s[C].op.reduce_axis[0] - - # define schedule space - cfg = autotvm.get_config() - cfg.define_split('tile_y', y, num_outputs=2) - cfg.define_split('tile_x', x, num_outputs=2) - - # schedule according to config - yo, yi = cfg['tile_y'].apply(s, C, y) - xo, xi = cfg['tile_x'].apply(s, C, x) - - s[C].reorder(yo, xo, k, yi, xi) - - return s, [A, B, C] - - -def tune(): - print('[TUNE]') - task = autotvm.task.create(matmul, args=(N, L, M, DTYPE), target=TARGET) - - early_stopping = None - measure_option = autotvm.measure_option( - builder=autotvm.LocalBuilder( - build_func=tvm.micro.cross_compiler(DEV_CREATE_MICRO_LIB, micro.LibType.OPERATOR)), - runner=autotvm.RPCRunner('micro', SERVER_ADDR, SERVER_PORT, n_parallel=N_PARALLEL, number=N_PER_TRIAL) - ) - - # create tmp log file - tmp_log_file = LOG_FILE_NAME + '.tmp' - if os.path.exists(tmp_log_file): - os.remove(tmp_log_file) - - tuner = RandomTuner(task) - - # do tuning - tuner.tune(n_trial=min(N_TRIAL, len(task.config_space)), - early_stopping=early_stopping, - measure_option=measure_option, - callbacks=[ - autotvm.callback.progress_bar(N_TRIAL, prefix='[Matmul Task]'), - autotvm.callback.log_to_file(tmp_log_file)]) - - # pick best records to a cache file - autotvm.record.pick_best(tmp_log_file, LOG_FILE_NAME) - os.remove(tmp_log_file) - - -def evaluate(): - print('[EVALUATE]') - # compile kernels with history best records - with autotvm.apply_history_best(LOG_FILE_NAME): - with TARGET: - sched, arg_bufs = matmul(N, L, M, DTYPE) - c_mod = tvm.build(sched, arg_bufs, name='matmul') - - with micro.Session(DEV_CONFIG) as sess: - micro_mod = sess.create_micro_mod(c_mod) - micro_func = micro_mod['matmul'] - ctx = tvm.micro_dev(0) - - # check correctness - a_np = np.random.uniform(size=(N, L)).astype(np.float32) - b_np = np.random.uniform(size=(L, M)).astype(np.float32) - c_np = a_np.dot(b_np) - - c_tvm = tvm.nd.empty(c_np.shape, ctx=ctx) - res = micro_func(tvm.nd.array(a_np, ctx), tvm.nd.array(b_np, ctx), c_tvm) - print(f'cycle count: {res}') - - tvm.testing.assert_allclose(c_np, c_tvm.asnumpy(), rtol=1e-2) - - -if __name__ == '__main__': - tune() - input('finished tuning...') - evaluate() From 4cb9a2ae28a233aa8730f119f75bc6da787507b0 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 13:01:07 -0800 Subject: [PATCH 46/70] Remove old debug code --- tests/python/unittest/test_runtime_micro.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index e227b2b2d4d3..895f1e6b5c53 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -100,8 +100,6 @@ def test_workspace_add(): shape = (1024,) dtype = "float32" - reset_gdbinit() - # Construct TVM expression. tvm_shape = tvm.convert(shape) A = tvm.placeholder(tvm_shape, name="A", dtype=dtype) From 7f91d79704877fb66de06d813982a629a15699bb Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 7 Nov 2019 16:28:36 -0800 Subject: [PATCH 47/70] Partially address comments --- python/tvm/contrib/binutil.py | 118 +++++++++++------- python/tvm/micro/base.py | 3 + python/tvm/micro/device/arm/stm32f746xx.py | 33 ++++- python/tvm/micro/device/base.py | 26 ++-- python/tvm/micro/device/host.py | 25 +++- python/tvm/micro/device/riscv_spike.py | 36 +++++- .../micro/device/arm/stm32f746xx/utvm_timer.c | 34 ++--- src/runtime/micro/openocd_low_level_device.cc | 5 +- 8 files changed, 201 insertions(+), 79 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index d48c0bb1ac2d..cd6556658212 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -22,7 +22,67 @@ from .._ffi.base import py_str from ..api import register_func +RELOCATION_LD_SCRIPT_TEMPLATE = """ +/* linker symbol for use in UTVMInit */ +_utvm_stack_pointer_init = 0x{stack_pointer_init:x}; + +SECTIONS +{{ + . = 0x{text_start:x}; + . = ALIGN({word_size}); + .text : + {{ + . = ALIGN({word_size}); + KEEP(*(.text)) + KEEP(*(.text*)) + . = ALIGN({word_size}); + }} + + . = 0x{rodata_start:x}; + . = ALIGN({word_size}); + .rodata : + {{ + . = ALIGN({word_size}); + KEEP(*(.rodata)) + KEEP(*(.rodata*)) + . = ALIGN({word_size}); + }} + + . = 0x{data_start:x}; + . = ALIGN({word_size}); + .data : + {{ + . = ALIGN({word_size}); + KEEP(*(.data)) + KEEP(*(.data*)) + . = ALIGN({word_size}); + }} + + . = 0x{bss_start:x}; + . = ALIGN({word_size}); + .bss : + {{ + . = ALIGN({word_size}); + KEEP(*(.bss)) + KEEP(*(.bss*)) + . = ALIGN({word_size}); + }} +}} +""" + def run_cmd(cmd): + """Runs `cmd` in a subprocess and awaits its completion. + + Parameters + ---------- + cmd : List[str] + list of command-line arguments + + Returns + ------- + output : str + resulting stdout capture from the subprocess + """ proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, @@ -147,58 +207,20 @@ def tvm_callback_relocate_binary( the relocated binary """ stack_pointer_init = stack_end - word_size - 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' - ld_script_contents += f""" -/* linker symbol for use in UTVMInit */ -_utvm_stack_pointer_init = 0x{stack_pointer_init:x}; - -SECTIONS -{{ - . = 0x{text_start:x}; - . = ALIGN({word_size}); - .text : - {{ - . = ALIGN({word_size}); - KEEP(*(.text)) - KEEP(*(.text*)) - . = ALIGN({word_size}); - }} - - . = 0x{rodata_start:x}; - . = ALIGN({word_size}); - .rodata : - {{ - . = ALIGN({word_size}); - KEEP(*(.rodata)) - KEEP(*(.rodata*)) - . = ALIGN({word_size}); - }} - - . = 0x{data_start:x}; - . = ALIGN({word_size}); - .data : - {{ - . = ALIGN({word_size}); - KEEP(*(.data)) - KEEP(*(.data*)) - . = ALIGN({word_size}); - }} + ld_script_contents += 'OUTPUT_ARCH( "riscv" )\n\n' + ld_script_contents += RELOCATION_LD_SCRIPT_TEMPLATE.format( + word_size=word_size, + text_start=text_start, + rodata_start=rodata_start, + data_start=data_start, + bss_start=bss_start, + stack_pointer_init=stack_pointer_init) - . = 0x{bss_start:x}; - . = ALIGN({word_size}); - .bss : - {{ - . = ALIGN({word_size}); - KEEP(*(.bss)) - KEEP(*(.bss*)) - . = ALIGN({word_size}); - }} -}} - """ + tmp_dir = util.tempdir() + rel_obj_path = tmp_dir.relpath('relocated.obj') rel_ld_script_path = tmp_dir.relpath('relocated.lds') with open(rel_ld_script_path, 'w') as f: f.write(ld_script_contents) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index a68f204fa73f..5c3366096b0e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -31,7 +31,10 @@ from .._ffi.libinfo import find_include_path class LibType(Enum): + """Enumeration of library types that can be compiled and loaded onto a device""" + # library to be used as a MicroTVM runtime RUNTIME = 0 + # library to be used as an operator OPERATOR = 1 diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index d4e72b3513d9..049832abc296 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -14,13 +14,29 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -"""Config definitions for ARM STM32F746XX devices""" +"""Compilation and config definitions for ARM STM32F746XX devices""" from .. import create_micro_lib_base, register_device DEVICE_ID = 'arm.stm32f746xx' TOOLCHAIN_PREFIX = 'arm-none-eabi-' def create_micro_lib(obj_path, src_path, lib_type, options=None): + """Wrapper over `create_micro_lib_base` to add device-specific options + + Parameters + ---------- + obj_path : str + path to generated object file + + src_path : str + path to source file + + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library + + options : Optional[List[str]] + additional options to pass to GCC + """ if options is None: options = [] options += [ @@ -35,6 +51,21 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): def default_config(server_addr, server_port): + """Generates a default configuration for ARM STM32F746XX devices + + Parameters + ---------- + server_addr : str + address of OpenOCD server to connect to + + server_port : int + port of OpenOCD server to connect to + + Return + ------ + config : Dict[str, Any] + MicroTVM config dict for this device + """ return { 'device_id': DEVICE_ID, 'toolchain_prefix': TOOLCHAIN_PREFIX, diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index a0e50dad9877..46e61f1e8799 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -26,12 +26,22 @@ from tvm._ffi.libinfo import find_include_path from tvm.micro import LibType, get_micro_host_driven_dir, get_micro_device_dir -DEVICE_REGISTRY = {} +_DEVICE_REGISTRY = {} def register_device(device_id, device_funcs): - if device_id in DEVICE_REGISTRY: + """Register a device and associated compilation/config functions + + Parameters + ---------- + device_id : str + unique identifier for the device + + device_funcs : Dict[str, func] + dictionary with compilation and config generation functions as values + """ + if device_id in _DEVICE_REGISTRY: raise RuntimeError(f'"{device_id}" already exists in the device registry') - DEVICE_REGISTRY[device_id] = device_funcs + _DEVICE_REGISTRY[device_id] = device_funcs def get_device_funcs(device_id): @@ -40,16 +50,16 @@ def get_device_funcs(device_id): Parameters ---------- device_id : str - unique identifier for the target device + unique identifier for the device Return ------ device_funcs : Dict[str, func] dictionary with compilation and config generation functions as values """ - if device_id not in DEVICE_REGISTRY: + if device_id not in _DEVICE_REGISTRY: raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') - device_funcs = DEVICE_REGISTRY[device_id] + device_funcs = _DEVICE_REGISTRY[device_id] return device_funcs @@ -58,8 +68,8 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t Parameters ---------- - obj_path : Optional[str] - path to generated object file (defaults to same directory as `src_path`) + obj_path : str + path to generated object file src_path : str path to source file diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 687a66e2ac2f..33fffadea3c4 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -14,7 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -"""Config for the host emulated device""" +"""Compilation and config definitions for the host emulated device""" import sys from . import create_micro_lib_base, register_device @@ -23,6 +23,22 @@ TOOLCHAIN_PREFIX = '' def create_micro_lib(obj_path, src_path, lib_type, options=None): + """Wrapper over `create_micro_lib_base` to add device-specific options + + Parameters + ---------- + obj_path : str + path to generated object file + + src_path : str + path to source file + + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library + + options : Optional[List[str]] + additional options to pass to GCC + """ if options is None: options = [] if sys.maxsize > 2**32 and sys.platform.startswith('linux'): @@ -31,6 +47,13 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): def default_config(): + """Generates a default configuration for the host emulated device + + Return + ------ + config : Dict[str, Any] + MicroTVM config dict for this device + """ return { 'device_id': DEVICE_ID, 'toolchain_prefix': TOOLCHAIN_PREFIX, diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py index c70367c9f957..0df564ac1b80 100644 --- a/python/tvm/micro/device/riscv_spike.py +++ b/python/tvm/micro/device/riscv_spike.py @@ -14,7 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -"""Config definitions for Spike, a RISC-V functional ISA simulator""" +"""Compilation and config definitions for Spike, a RISC-V functional ISA simulator""" from collections import OrderedDict from . import create_micro_lib_base, register_device @@ -23,10 +23,44 @@ TOOLCHAIN_PREFIX = 'riscv64-unknown-elf-' def create_micro_lib(obj_path, src_path, lib_type, options=None): + """Wrapper over `create_micro_lib_base` to add device-specific options + + Parameters + ---------- + obj_path : str + path to generated object file + + src_path : str + path to source file + + lib_type : micro.LibType + whether to compile a MicroTVM runtime or operator library + + options : Optional[List[str]] + additional options to pass to GCC + """ create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) def default_config(base_addr, server_addr, server_port): + """Generates a default configuration for Spike + + Parameters + ---------- + base_addr : int + base address of the simulator (for calculating the memory layout) + + server_addr : str + address of OpenOCD server to connect to + + server_port : int + port of OpenOCD server to connect to + + Return + ------ + config : Dict[str, Any] + MicroTVM config dict for this device + """ res = { 'device_id': DEVICE_ID, 'toolchain_prefix': TOOLCHAIN_PREFIX, diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index d16515e6039e..16ffa003b60c 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -29,32 +29,32 @@ unsigned long start_time = 0; unsigned long stop_time = 0; int32_t UTVMTimerStart() { - SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); - // wait until timer starts - while (SYST_CVR == 0); - start_time = SYST_CVR; - return 0; + SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); + // wait until timer starts + while (SYST_CVR == 0); + start_time = SYST_CVR; + return 0; } void UTVMTimerStop() { - SYST_CSR = 0; - stop_time = SYST_CVR; + SYST_CSR = 0; + stop_time = SYST_CVR; } void UTVMTimerReset() { - SYST_CSR = 0; - // maximum reload value (24-bit) - SYST_RVR = (~((unsigned long) 0)) >> 8; - SYST_CVR = 0; + SYST_CSR = 0; + // maximum reload value (24-bit) + SYST_RVR = (~((unsigned long) 0)) >> 8; + SYST_CVR = 0; } uint32_t UTVMTimerRead() { - if (SYST_CSR & SYST_COUNTFLAG) { - TVMAPISetLastError("timer overflowed"); - return -1; - } else { - return start_time - stop_time; - } + if (SYST_CSR & SYST_COUNTFLAG) { + TVMAPISetLastError("timer overflowed"); + return -1; + } else { + return start_time - stop_time; + } } #else // !USE_SYSTICK diff --git a/src/runtime/micro/openocd_low_level_device.cc b/src/runtime/micro/openocd_low_level_device.cc index 4c5c7e14c2b3..5e6685a3a09b 100644 --- a/src/runtime/micro/openocd_low_level_device.cc +++ b/src/runtime/micro/openocd_low_level_device.cc @@ -42,14 +42,12 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { */ explicit OpenOCDLowLevelDevice(const std::string& server_addr, int port) : socket_() { - std::cout << "[OpenOCDLowLevelDevice]" << std::endl; server_addr_ = server_addr; port_ = port; socket_.Connect(tvm::common::SockAddr(server_addr_.c_str(), port_)); socket_.cmd_builder() << "halt 0"; socket_.SendCommand(); - std::cout << " finished init" << std::endl; } void Read(DevPtr addr, void* buf, size_t num_bytes) { @@ -202,8 +200,9 @@ class OpenOCDLowLevelDevice final : public LowLevelDevice { private: /*! \brief socket used to communicate with the device through Tcl */ TclSocket socket_; - + /*! \brief address of OpenOCD server */ std::string server_addr_; + /*! \brief port of OpenOCD server */ int port_; /*! \brief number of bytes in a word on the target device (64-bit) */ From 8b72d2bcc5eea4cfffddf03f344ad2dbf8b29fe3 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 8 Nov 2019 10:02:13 -0800 Subject: [PATCH 48/70] Enable ".s" files and add Apache header --- .../micro/device/arm/stm32f746xx/utvm_init.s | 18 ++++++++++++++++++ tests/lint/check_file_type.py | 1 + 2 files changed, 19 insertions(+) diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s index 448fb773a2f8..b852dd97db2b 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s @@ -1,3 +1,21 @@ +/* + * 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. + */ .syntax unified .cpu cortex-m7 .fpu softvfp diff --git a/tests/lint/check_file_type.py b/tests/lint/check_file_type.py index 0998c789332c..5b83641eb8e1 100644 --- a/tests/lint/check_file_type.py +++ b/tests/lint/check_file_type.py @@ -25,6 +25,7 @@ "cc", "c", "h", + "s", "rs", "m", "mm", From ba8a88db8f6920753443359324ec7b8d164a95f8 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 9 Nov 2019 22:25:53 -0800 Subject: [PATCH 49/70] Add ASF headers and split host uTVM API defs --- .../micro/device/arm/stm32f746xx/utvm_init.s | 7 ++++ .../micro/device/arm/stm32f746xx/utvm_timer.c | 25 ++++++++++++ src/runtime/micro/device/host/utvm_init.c | 39 +++++++++++++++++++ src/runtime/micro/device/host/utvm_timer.c | 28 +++++++++++-- src/runtime/micro/host_driven/utvm_runtime.c | 6 +-- 5 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/runtime/micro/device/host/utvm_init.c diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s index b852dd97db2b..5861c0326dbf 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s @@ -16,6 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + +/*! + * Copyright (c) 2019 by Contributors + * \file utvm_init.s + * \brief uTVM init definition for STM32F746XX-series boards + */ + .syntax unified .cpu cortex-m7 .fpu softvfp diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index 16ffa003b60c..df603b828b02 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -1,3 +1,28 @@ +/* + * 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. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file utvm_timer.c + * \brief uTVM timer API definitions for STM32F746XX-series boards + */ + #ifdef __cplusplus extern "C" { #endif diff --git a/src/runtime/micro/device/host/utvm_init.c b/src/runtime/micro/device/host/utvm_init.c new file mode 100644 index 000000000000..02888f04c48e --- /dev/null +++ b/src/runtime/micro/device/host/utvm_init.c @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file utvm_init.c + * \brief uTVM init definition for the host emulated device + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "utvm_runtime.h" + +void UTVMInit() { + // no init required for the host + UTVMMain(); +} + +#ifdef __cplusplus +} // TVM_EXTERN_C +#endif diff --git a/src/runtime/micro/device/host/utvm_timer.c b/src/runtime/micro/device/host/utvm_timer.c index 51e78924d567..fffbf7dc8eb1 100644 --- a/src/runtime/micro/device/host/utvm_timer.c +++ b/src/runtime/micro/device/host/utvm_timer.c @@ -1,3 +1,27 @@ +/* + * 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. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file utvm_timer.c + * \brief uTVM timer API stubs for the host emulated device + */ #ifdef __cplusplus extern "C" { @@ -7,10 +31,6 @@ extern "C" { // TODO(weberlo): use this? https://stackoverflow.com/questions/5141960/get-the-current-time-in-c -void UTVMInit() { - UTVMMain(); -} - int32_t UTVMTimerStart() { return 0; } diff --git a/src/runtime/micro/host_driven/utvm_runtime.c b/src/runtime/micro/host_driven/utvm_runtime.c index 4666cc6c09dd..a4de495a185c 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.c +++ b/src/runtime/micro/host_driven/utvm_runtime.c @@ -21,9 +21,9 @@ * \file utvm_runtime.cc * \brief uTVM runtime * - * All function calls go through `UTVMMain`, which reads from the current - * `UTVMTask` and calls the appropriate function with the arguments from the - * task. + * All function calls go through the externally defined `UTVMInit`, which + * performs device-specific setup, then calls `UTVMMain`. `UTVMMain` then + * calls the function in `utvm_task` with the arguments from the task. * * Additionally included in this file are definitions for some of the most * common functions used in the C runtime API. From 0d8f4f9a7bc9ce910c9ff731e500a85d7180c5b0 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 9 Nov 2019 23:58:27 -0800 Subject: [PATCH 50/70] Lint --- src/codegen/build_module.cc | 2 +- .../micro/device/arm/stm32f746xx/utvm_timer.c | 26 +++---- src/runtime/micro/host_driven/utvm_runtime.h | 6 +- src/runtime/micro/micro_section_allocator.h | 6 +- src/runtime/micro/micro_session.cc | 67 +++++++++++-------- 5 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/codegen/build_module.cc b/src/codegen/build_module.cc index ed438e9fb7f8..80fd57af66f9 100644 --- a/src/codegen/build_module.cc +++ b/src/codegen/build_module.cc @@ -85,7 +85,7 @@ Target CreateTarget(const std::string& target_name, } t->device_type = kDLCPU; t->thread_warp_size = 1; - if (target_name == "c" and t->device_name == "micro_dev") { + if (target_name == "c" && t->device_name == "micro_dev") { t->device_type = kDLMicroDev; } else if (target_name == "c" || target_name == "llvm") { t->keys_array.push_back(ir::StringImm::make("cpu")); diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index df603b828b02..8766d9a793ae 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -27,6 +27,8 @@ extern "C" { #endif +#include + #include "utvm_runtime.h" // There are two implementations of cycle counters on the STM32F7X: SysTick and @@ -37,10 +39,10 @@ extern "C" { #ifdef USE_SYSTICK -#define SYST_CSR (*((volatile unsigned long *) 0xE000E010)) -#define SYST_RVR (*((volatile unsigned long *) 0xE000E014)) -#define SYST_CVR (*((volatile unsigned long *) 0xE000E018)) -#define SYST_CALIB (*((volatile unsigned long *) 0xE000E01C)) +#define SYST_CSR (*((volatile uint32_t *) 0xE000E010)) +#define SYST_RVR (*((volatile uint32_t *) 0xE000E014)) +#define SYST_CVR (*((volatile uint32_t *) 0xE000E018)) +#define SYST_CALIB (*((volatile uint32_t *) 0xE000E01C)) #define SYST_CSR_ENABLE 0 #define SYST_CSR_TICKINT 1 @@ -50,8 +52,8 @@ extern "C" { #define SYST_CALIB_NOREF 31 #define SYST_CALIB_SKEW 30 -unsigned long start_time = 0; -unsigned long stop_time = 0; +uint32_t start_time = 0; +uint32_t stop_time = 0; int32_t UTVMTimerStart() { SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); @@ -69,7 +71,7 @@ void UTVMTimerStop() { void UTVMTimerReset() { SYST_CSR = 0; // maximum reload value (24-bit) - SYST_RVR = (~((unsigned long) 0)) >> 8; + SYST_RVR = (~((uint32_t) 0)) >> 8; SYST_CVR = 0; } @@ -84,14 +86,14 @@ uint32_t UTVMTimerRead() { #else // !USE_SYSTICK -#define DWT_CTRL (*((volatile unsigned long *) 0xE0001000)) -#define DWT_CYCCNT (*((volatile unsigned long *) 0xE0001004)) +#define DWT_CTRL (*((volatile uint32_t *) 0xE0001000)) +#define DWT_CYCCNT (*((volatile uint32_t *) 0xE0001004)) #define DWT_CTRL_NOCYCCNT 25 #define DWT_CTRL_CYCCNTENA 0 -unsigned long start_time = 0; -unsigned long stop_time = 0; +uint32_t start_time = 0; +uint32_t stop_time = 0; void UTVMTimerReset() { DWT_CYCCNT = 0; @@ -115,7 +117,7 @@ int32_t UTVMTimerRead() { if (stop_time > stop_time) { return stop_time - start_time; } else { - unsigned long largest = ~0; + uint32_t largest = ~0; return (largest - start_time) + stop_time; } } diff --git a/src/runtime/micro/host_driven/utvm_runtime.h b/src/runtime/micro/host_driven/utvm_runtime.h index 7b203e9adbef..c364ecf40792 100644 --- a/src/runtime/micro/host_driven/utvm_runtime.h +++ b/src/runtime/micro/host_driven/utvm_runtime.h @@ -21,8 +21,8 @@ * \file utvm_runtime.h * \brief uTVM runtime headers */ -#ifndef TVM_RUNTIME_MICRO_DEVICE_UTVM_RUNTIME_H_ -#define TVM_RUNTIME_MICRO_DEVICE_UTVM_RUNTIME_H_ +#ifndef TVM_RUNTIME_MICRO_HOST_DRIVEN_UTVM_RUNTIME_H_ +#define TVM_RUNTIME_MICRO_HOST_DRIVEN_UTVM_RUNTIME_H_ #ifdef __cplusplus extern "C" { @@ -64,4 +64,4 @@ void UTVMDone(); } // TVM_EXTERN_C #endif -#endif // TVM_RUNTIME_MICRO_DEVICE_UTVM_RUNTIME_H_ +#endif // TVM_RUNTIME_MICRO_HOST_DRIVEN_UTVM_RUNTIME_H_ diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index 0551959627bd..0f4215d94d0e 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -43,8 +43,10 @@ class MicroSectionAllocator { size_(0), capacity_(region.size), word_size_(word_size) { - CHECK_EQ(start_addr_.value() % word_size, 0) << "micro section start not aligned to " << word_size << " bytes"; - CHECK_EQ(capacity_ % word_size, 0) << "micro section end not aligned to " << word_size << " bytes"; + CHECK_EQ(start_addr_.value() % word_size, 0) + << "micro section start not aligned to " << word_size << " bytes"; + CHECK_EQ(capacity_ % word_size, 0) + << "micro section end not aligned to " << word_size << " bytes"; } /*! diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 50813ff9b67b..c3db84a74ec5 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -80,7 +80,10 @@ MicroSession::MicroSession( size_t word_size, bool thumb_mode, const std::string& server_addr, - int port) : toolchain_prefix_(toolchain_prefix), word_size_(word_size), thumb_mode_(thumb_mode) { + int port) + : toolchain_prefix_(toolchain_prefix) + , word_size_(word_size) + , thumb_mode_(thumb_mode) { CHECK(word_size_ == 4 || word_size_ == 8) << "unsupported word size " << word_size_; if (comms_method == "host") { // TODO(weberlo): move checks to python @@ -93,7 +96,9 @@ MicroSession::MicroSession( heap_start == 0 && workspace_start == 0 && stack_start == 0) << "unable to specify section addresses for host device"; - size_t memory_size = text_size + rodata_size + data_size + bss_size + args_size + heap_size + workspace_size + stack_size; + size_t memory_size = + text_size + rodata_size + data_size + bss_size + + args_size + heap_size + workspace_size + stack_size; void* base_addr; low_level_device_ = HostLowLevelDeviceCreate(memory_size, &base_addr); CHECK_EQ(reinterpret_cast(base_addr) % word_size_, 0) @@ -181,16 +186,19 @@ MicroSession::MicroSession( runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; // Patch pointers to define the bounds of the workspace section and the word size (for allocation alignment). + std::shared_ptr workspace_allocator = GetAllocator(SectionKind::kWorkspace); + uint64_t ws_start = workspace_allocator->start_addr().value(); + uint64_t ws_end = workspace_allocator->max_addr().value(); if (word_size_ == 4) { - uint32_t workspace_start_addr = (uint32_t) GetAllocator(SectionKind::kWorkspace)->start_addr().value(); - uint32_t workspace_end_addr = (uint32_t) GetAllocator(SectionKind::kWorkspace)->max_addr().value(); + uint32_t workspace_start_addr = (uint32_t) ws_start; + uint32_t workspace_end_addr = (uint32_t) ws_end; uint32_t word_size = (uint32_t) word_size_; DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size); } else if (word_size_ == 8) { - uint64_t workspace_start_addr = (uint64_t) GetAllocator(SectionKind::kWorkspace)->start_addr().value(); - uint64_t workspace_end_addr = (uint64_t) GetAllocator(SectionKind::kWorkspace)->max_addr().value(); + uint64_t workspace_start_addr = (uint64_t) ws_start; + uint64_t workspace_end_addr = (uint64_t) ws_end; uint64_t word_size = (uint64_t) word_size_; DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); @@ -230,9 +238,9 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); UTVMTask32 task = { - .func = *((uint32_t*) &func_dev_addr), - .arg_values = *((uint32_t*) &arg_values_dev_addr), - .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), + .func = *((uint32_t*) &func_dev_addr), // NOLINT(*) + .arg_values = *((uint32_t*) &arg_values_dev_addr), // NOLINT(*) + .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), // NOLINT(*) .num_args = args.num_args, }; // Write the task. @@ -241,9 +249,9 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); UTVMTask64 task = { - .func = *((uint64_t*) &func_dev_addr), - .arg_values = *((uint64_t*) &arg_values_dev_addr), - .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), + .func = *((uint64_t*) &func_dev_addr), // NOLINT(*) + .arg_values = *((uint64_t*) &arg_values_dev_addr), // NOLINT(*) + .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), // NOLINT(*) .num_args = args.num_args, }; // Write the task. @@ -270,10 +278,14 @@ BinaryInfo MicroSession::LoadBinary(const std::string& binary_path, bool patch_d DevMemRegion data_section; DevMemRegion bss_section; - text_section.size = GetSectionSize(binary_path, SectionKind::kText, toolchain_prefix_, word_size_); - rodata_section.size = GetSectionSize(binary_path, SectionKind::kRodata, toolchain_prefix_, word_size_); - data_section.size = GetSectionSize(binary_path, SectionKind::kData, toolchain_prefix_, word_size_); - bss_section.size = GetSectionSize(binary_path, SectionKind::kBss, toolchain_prefix_, word_size_); + text_section.size = GetSectionSize( + binary_path, SectionKind::kText, toolchain_prefix_, word_size_); + rodata_section.size = GetSectionSize( + binary_path, SectionKind::kRodata, toolchain_prefix_, word_size_); + data_section.size = GetSectionSize( + binary_path, SectionKind::kData, toolchain_prefix_, word_size_); + bss_section.size = GetSectionSize( + binary_path, SectionKind::kBss, toolchain_prefix_, word_size_); text_section.start = AllocateInSection(SectionKind::kText, text_section.size); rodata_section.start = AllocateInSection(SectionKind::kRodata, rodata_section.size); @@ -381,15 +393,15 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); TVMArray32 dev_arr = { - .data = *((uint32_t*) &arr.data), + .data = *((uint32_t*) &arr.data), // NOLINT(*) .ctx = arr.ctx, .ndim = arr.ndim, .pad0 = 0, .dtype = arr.dtype, - .shape = *((uint32_t*) &dev_shape), - .strides = *((uint32_t*) &dev_strides), + .shape = *((uint32_t*) &dev_shape), // NOLINT(*) + .strides = *((uint32_t*) &dev_strides), // NOLINT(*) .pad1 = 0, - .byte_offset = *((uint32_t*) &arr.byte_offset), + .byte_offset = *((uint32_t*) &arr.byte_offset), // NOLINT(*) .pad2 = 0, }; // Update the device type to look like a host, because codegen generates @@ -417,19 +429,20 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr int64_t* dev_shape = shape_addr.cast_to(); int64_t* dev_strides = strides_addr.cast_to(); TVMArray64 dev_arr = { - .data = *((uint64_t*) &arr.data), + .data = *((uint64_t*) &arr.data), // NOLINT(*) .ctx = arr.ctx, .ndim = arr.ndim, .pad0 = 0, .dtype = arr.dtype, - .shape = *((uint64_t*) &dev_shape), - .strides = *((uint64_t*) &dev_strides), - .byte_offset = *((uint64_t*) &arr.byte_offset), + .shape = *((uint64_t*) &dev_shape), // NOLINT(*) + .strides = *((uint64_t*) &dev_strides), // NOLINT(*) + .byte_offset = *((uint64_t*) &arr.byte_offset), // NOLINT(*) }; - // Update the device type to look like a host, because codegen generates - // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; + // Update the device type to look like a host, because from the device's + // perspective, it is the host. + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) + << "attempt to write TVMArray with non-micro device type"; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; tvm_arr_slot.WriteValue(dev_arr); return tvm_arr_slot.start_addr(); From 8ad3744083e046ee86fe6cb71e837bf207ce4a30 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sun, 10 Nov 2019 14:29:26 -0800 Subject: [PATCH 51/70] Lint --- .../micro/device/arm/stm32f746xx/utvm_timer.c | 2 +- src/runtime/micro/micro_session.cc | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index 8766d9a793ae..0651b4f4fe64 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -58,7 +58,7 @@ uint32_t stop_time = 0; int32_t UTVMTimerStart() { SYST_CSR = (1 << SYST_CSR_ENABLE) | (1 << SYST_CSR_CLKSOURCE); // wait until timer starts - while (SYST_CVR == 0); + while (SYST_CVR == 0) {} start_time = SYST_CVR; return 0; } diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index c3db84a74ec5..cbed771c51b5 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -185,10 +185,11 @@ MicroSession::MicroSession( runtime_symbol_map_ = LoadBinary(binary_path, false).symbol_map; - // Patch pointers to define the bounds of the workspace section and the word size (for allocation alignment). - std::shared_ptr workspace_allocator = GetAllocator(SectionKind::kWorkspace); - uint64_t ws_start = workspace_allocator->start_addr().value(); - uint64_t ws_end = workspace_allocator->max_addr().value(); + // Patch pointers to define the bounds of the workspace section and the word + // size (for allocation alignment). + std::shared_ptr ws_allocator = GetAllocator(SectionKind::kWorkspace); + uint64_t ws_start = ws_allocator->start_addr().value(); + uint64_t ws_end = ws_allocator->max_addr().value(); if (word_size_ == 4) { uint32_t workspace_start_addr = (uint32_t) ws_start; uint32_t workspace_end_addr = (uint32_t) ws_end; @@ -406,7 +407,8 @@ DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMAr }; // Update the device type to look like a host, because codegen generates // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) << "attempt to write TVMArray with non-micro device type"; + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) + << "attempt to write TVMArray with non-micro device type"; dev_arr.ctx.device_type = DLDeviceType::kDLCPU; tvm_arr_slot.WriteValue(dev_arr); return tvm_arr_slot.start_addr(); From b8855e6efe52824d24b2282b1d9c1f4c507cd1cf Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sun, 10 Nov 2019 22:11:50 -0800 Subject: [PATCH 52/70] Lint --- python/tvm/contrib/binutil.py | 23 +++++------ python/tvm/micro/base.py | 10 ++--- python/tvm/micro/device/arm/stm32f746xx.py | 3 +- python/tvm/micro/device/base.py | 47 +++++++++++----------- python/tvm/micro/device/host.py | 3 +- python/tvm/micro/device/riscv_spike.py | 12 ++++-- python/tvm/micro/rpc_server.py | 3 +- 7 files changed, 52 insertions(+), 49 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index cd6556658212..545314df237c 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -19,7 +19,6 @@ import os import subprocess from . import util -from .._ffi.base import py_str from ..api import register_func RELOCATION_LD_SCRIPT_TEMPLATE = """ @@ -84,9 +83,9 @@ def run_cmd(cmd): resulting stdout capture from the subprocess """ proc = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) (output, _) = proc.communicate() output = output.decode('utf-8') if proc.returncode != 0: @@ -140,8 +139,8 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): continue entry_name = tokens[0] entry_size = int(tokens[1]) - for section_name in sections_to_sum: - if entry_name.startswith(section_name): + for section in sections_to_sum: + if entry_name.startswith(section): section_size += entry_size break @@ -212,12 +211,12 @@ def tvm_callback_relocate_binary( if 'riscv' in toolchain_prefix: ld_script_contents += 'OUTPUT_ARCH( "riscv" )\n\n' ld_script_contents += RELOCATION_LD_SCRIPT_TEMPLATE.format( - word_size=word_size, - text_start=text_start, - rodata_start=rodata_start, - data_start=data_start, - bss_start=bss_start, - stack_pointer_init=stack_pointer_init) + word_size=word_size, + text_start=text_start, + rodata_start=rodata_start, + data_start=data_start, + bss_start=bss_start, + stack_pointer_init=stack_pointer_init) tmp_dir = util.tempdir() rel_obj_path = tmp_dir.relpath('relocated.obj') diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 5c3366096b0e..0e8cd09bdbc1 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -18,17 +18,14 @@ from __future__ import absolute_import -import logging import os import sys from enum import Enum -from pathlib import Path import tvm from tvm.contrib import util as _util from tvm.contrib import cc as _cc from .._ffi.function import _init_api -from .._ffi.libinfo import find_include_path class LibType(Enum): """Enumeration of library types that can be compiled and loaded onto a device""" @@ -62,7 +59,8 @@ def __init__(self, config): # TODO(weberlo): add config validation # grab a binutil instance from the ID in the config - self.create_micro_lib = tvm.micro.device.get_device_funcs(config['device_id'])['create_micro_lib'] + dev_funcs = tvm.micro.device.get_device_funcs(config['device_id']) + self.create_micro_lib = dev_funcs['create_micro_lib'] self.toolchain_prefix = config['toolchain_prefix'] self.mem_layout = config['mem_layout'] self.word_size = config['word_size'] @@ -129,8 +127,8 @@ def create_micro_mod(self, c_mod): temp_dir = _util.tempdir() lib_obj_path = temp_dir.relpath('dev_lib.obj') c_mod.export_library( - lib_obj_path, - fcompile=cross_compiler(self.create_micro_lib, LibType.OPERATOR)) + lib_obj_path, + fcompile=cross_compiler(self.create_micro_lib, LibType.OPERATOR)) micro_mod = tvm.module.load(lib_obj_path) return micro_mod diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 049832abc296..950d5da42355 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -47,7 +47,8 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): '-mthumb', '-gdwarf-5', ] - create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) + create_micro_lib_base( + obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) def default_config(server_addr, server_port): diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index 46e61f1e8799..aa02064497e9 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -17,8 +17,6 @@ """Base definitions for MicroTVM config""" import glob import os -import sys -from enum import Enum from pathlib import Path from tvm.contrib import util as _util @@ -63,15 +61,15 @@ def get_device_funcs(device_id): return device_funcs -def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_type, options=None): +def create_micro_lib_base(out_obj_path, in_src_path, toolchain_prefix, device_id, lib_type, options=None): """Compiles code into a binary for the target micro device. Parameters ---------- - obj_path : str + out_obj_path : str path to generated object file - src_path : str + in_src_path : str path to source file toolchain_prefix : str @@ -90,27 +88,28 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t additional options to pass to GCC """ base_compile_cmd = [ - f'{toolchain_prefix}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', - ] + f'{toolchain_prefix}gcc', + '-std=c11', + '-Wall', + '-Wextra', + '--pedantic', + '-c', + '-O0', + '-g', + '-nostartfiles', + '-nodefaultlibs', + '-nostdlib', + '-fdata-sections', + '-ffunction-sections', + ] if options is not None: base_compile_cmd += options src_paths = [] include_paths = find_include_path() + [get_micro_host_driven_dir()] - ld_script_path = None tmp_dir = _util.tempdir() + # we might transform the src path in one of the branches below + new_in_src_path = in_src_path if lib_type == LibType.RUNTIME: dev_dir = _get_device_source_dir(device_id) dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') @@ -122,17 +121,17 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t # create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. temp_src_path = tmp_dir.relpath('temp.c') - with open(src_path, 'r') as f: + with open(in_src_path, 'r') as f: src_lines = f.read().splitlines() src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') with open(temp_src_path, 'w') as f: f.write('\n'.join(src_lines)) - src_path = temp_src_path + new_in_src_path = temp_src_path base_compile_cmd += ['-c'] else: raise RuntimeError('unknown lib type') - src_paths += [src_path] + src_paths += [new_in_src_path] for path in include_paths: base_compile_cmd += ['-I', path] @@ -147,7 +146,7 @@ def create_micro_lib_base(obj_path, src_path, toolchain_prefix, device_id, lib_t ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] ld_cmd += prereq_obj_paths - ld_cmd += ['-o', obj_path] + ld_cmd += ['-o', out_obj_path] run_cmd(ld_cmd) diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 33fffadea3c4..0131ea78e578 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -43,7 +43,8 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): options = [] if sys.maxsize > 2**32 and sys.platform.startswith('linux'): options += ['-mcmodel=large'] - create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) + create_micro_lib_base( + obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) def default_config(): diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py index 0df564ac1b80..0ebd624ddfa6 100644 --- a/python/tvm/micro/device/riscv_spike.py +++ b/python/tvm/micro/device/riscv_spike.py @@ -39,7 +39,13 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): options : Optional[List[str]] additional options to pass to GCC """ - create_micro_lib_base(obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) + create_micro_lib_base( + obj_path, + src_path, + TOOLCHAIN_PREFIX, + DEVICE_ID, + lib_type, + options=options) def default_config(base_addr, server_addr, server_port): @@ -100,8 +106,8 @@ def default_config(base_addr, server_addr, server_port): curr_offset = 0 mem_layout = res['mem_layout'] for section_name, region_dict in mem_layout: - mem_layout[section_name]['start'] = base_addr + curr_offset - curr_offset += mem_layout[section_name]['size'] + region_dict['start'] = base_addr + curr_offset + curr_offset += region_dict['size'] return res diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index bf779f46bb3e..6d3c7fadc98e 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -18,10 +18,8 @@ import argparse import ast -import ctypes import json import logging -import os import tvm from tvm import rpc from tvm import micro @@ -71,6 +69,7 @@ def main(): @tvm.register_func('tvm.rpc.server.start', override=True) def server_start(): + # pylint: disable=unused-variable session = micro.Session(dev_config) session._enter() From 2129037381a343da6acfef39de6735ecf3ac7380 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 12 Nov 2019 09:28:40 -0800 Subject: [PATCH 53/70] Lint --- python/tvm/micro/device/base.py | 8 +++++++- python/tvm/micro/device/riscv_spike.py | 2 +- python/tvm/micro/rpc_server.py | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index aa02064497e9..138c939d1d00 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -61,7 +61,13 @@ def get_device_funcs(device_id): return device_funcs -def create_micro_lib_base(out_obj_path, in_src_path, toolchain_prefix, device_id, lib_type, options=None): +def create_micro_lib_base( + out_obj_path, + in_src_path, + toolchain_prefix, + device_id, + lib_type, + options=None): """Compiles code into a binary for the target micro device. Parameters diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py index 0ebd624ddfa6..46cd131bea60 100644 --- a/python/tvm/micro/device/riscv_spike.py +++ b/python/tvm/micro/device/riscv_spike.py @@ -105,7 +105,7 @@ def default_config(base_addr, server_addr, server_port): # generate section start addresses from the given `base_addr` curr_offset = 0 mem_layout = res['mem_layout'] - for section_name, region_dict in mem_layout: + for region_dict in mem_layout.values(): region_dict['start'] = base_addr + curr_offset curr_offset += region_dict['size'] return res diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py index 6d3c7fadc98e..8da2a3a1f452 100644 --- a/python/tvm/micro/rpc_server.py +++ b/python/tvm/micro/rpc_server.py @@ -25,6 +25,7 @@ from tvm import micro def main(): + """Entry point to MicroTVM RPC server""" parser = argparse.ArgumentParser() parser.add_argument('--host', type=str, default="0.0.0.0", help='the hostname of the server') @@ -41,7 +42,8 @@ def main(): parser.add_argument('--dev-id', type=str, help='Unique ID for the target device') parser.add_argument('--dev-config-args', type=str, - help='Python list of literals required to generate a default config (if --dev-id is specified)') + help=('Python list of literals required to generate a default config' + ' (if --dev-id is specified)')) args = parser.parse_args() logging.basicConfig(level=logging.INFO) From 7b559b6c43837507567944417b11a04d9782e342 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 12 Nov 2019 09:45:28 -0800 Subject: [PATCH 54/70] Fix rebase artifact --- src/runtime/micro/micro_module.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 09834f166c21..4a41d4bca28f 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -78,7 +78,7 @@ class MicroWrappedFunc { private: /*! \brief reference to the session for this function (to keep the session alive) */ - std::shared_ptr session_; + ObjectPtr session_; /*! \brief offset of the function to be called */ DevPtr func_ptr_; }; @@ -86,7 +86,6 @@ class MicroWrappedFunc { PackedFunc MicroModuleNode::GetFunction( const std::string& name, const ObjectPtr& sptr_to_self) { - std::cout << "[MicroModuleNode::GetFunction(name=" << name << ")]" << std::endl; DevPtr func_ptr; if (name == tvm::runtime::symbol::tvm_module_main) { if (symbol_map_.HasSymbol(tvm::runtime::symbol::tvm_module_main)) { From 3fde1021c33c7e20456a8182e9d83ea3fa86b32b Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 12 Nov 2019 10:12:26 -0800 Subject: [PATCH 55/70] Merge MicroTVM RPC server --- python/tvm/exec/rpc_server.py | 37 ++++++++++++++ python/tvm/micro/rpc_server.py | 91 ---------------------------------- 2 files changed, 37 insertions(+), 91 deletions(-) delete mode 100644 python/tvm/micro/rpc_server.py diff --git a/python/tvm/exec/rpc_server.py b/python/tvm/exec/rpc_server.py index 397238e0eef1..00e972d7b95e 100644 --- a/python/tvm/exec/rpc_server.py +++ b/python/tvm/exec/rpc_server.py @@ -19,10 +19,13 @@ from __future__ import absolute_import import argparse +import ast import multiprocessing import sys import logging +import tvm from .. import rpc +from tvm import micro def main(args): """Main function""" @@ -37,6 +40,9 @@ def main(args): else: tracker_addr = None + if args.utvm_dev_config or args.utvm_dev_id: + init_utvm(args) + server = rpc.Server(args.host, args.port, args.port_end, @@ -48,6 +54,30 @@ def main(args): server.proc.join() +def init_utvm(args): + if args.utvm_dev_config and args.utvm_dev_id: + raise RuntimeError('only one of --utvm-dev-config and --utvm-dev-id allowed') + + if args.utvm_dev_config: + with open(args.utvm_dev_config, 'r') as dev_conf_file: + dev_config = json.load(dev_conf_file) + else: + dev_config_args = ast.literal_eval(args.utvm_dev_config_args) + dev_config = micro.device.get_device_funcs(args.utvm_dev_id)['default_config'](*dev_config_args) + + if args.utvm_dev_config or args.utvm_dev_id: + # add MicroTVM overrides + @tvm.register_func('tvm.rpc.server.start', override=True) + def server_start(): + # pylint: disable=unused-variable + session = micro.Session(dev_config) + session._enter() + + @tvm.register_func('tvm.rpc.server.shutdown', override=True) + def server_shutdown(): + session._exit() + + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('--host', type=str, default="0.0.0.0", @@ -71,6 +101,13 @@ def main(args): and ROCM compilers.") parser.add_argument('--custom-addr', type=str, help="Custom IP Address to Report to RPC Tracker") + parser.add_argument('--utvm-dev-config', type=str, + help='JSON config file for the target device (if using MicroTVM)') + parser.add_argument('--utvm-dev-id', type=str, + help='Unique ID for the target device (if using MicroTVM)') + parser.add_argument('--utvm-dev-config-args', type=str, + help=('Python list of literals required to generate a default' + ' MicroTVM config (if --utvm-dev-id is specified)')) parser.set_defaults(fork=True) args = parser.parse_args() diff --git a/python/tvm/micro/rpc_server.py b/python/tvm/micro/rpc_server.py deleted file mode 100644 index 8da2a3a1f452..000000000000 --- a/python/tvm/micro/rpc_server.py +++ /dev/null @@ -1,91 +0,0 @@ -# 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. -"""RPC server for interacting with devices via MicroTVM""" - -import argparse -import ast -import json -import logging -import tvm -from tvm import rpc -from tvm import micro - -def main(): - """Entry point to MicroTVM RPC server""" - parser = argparse.ArgumentParser() - parser.add_argument('--host', type=str, default="0.0.0.0", - help='the hostname of the server') - parser.add_argument('--port', type=int, default=9091, - help='The port of the RPC') - parser.add_argument('--port-end', type=int, default=9199, - help='The end search port of the RPC') - parser.add_argument('--key', type=str, default="", - help='RPC key used to identify the connection type.') - parser.add_argument('--tracker', type=str, default="", - help='Report to RPC tracker') - parser.add_argument('--dev-config', type=str, - help='JSON config file for the target device') - parser.add_argument('--dev-id', type=str, - help='Unique ID for the target device') - parser.add_argument('--dev-config-args', type=str, - help=('Python list of literals required to generate a default config' - ' (if --dev-id is specified)')) - args = parser.parse_args() - logging.basicConfig(level=logging.INFO) - - if args.tracker: - url, port = args.tracker.split(':') - port = int(port) - tracker_addr = (url, port) - if not args.key: - raise RuntimeError( - 'Need key to present type of resource when tracker is available') - else: - tracker_addr = None - - if not (args.dev_config or (args.dev_id and args.dev_config_args)): - raise RuntimeError('must provide either --dev-config or --dev-id and --dev-config-args') - if args.dev_config and args.dev_id: - raise RuntimeError('only one of --dev-config and --dev-id allowed') - - if args.dev_config: - with open(args.dev_config, 'r') as dev_conf_file: - dev_config = json.load(dev_conf_file) - else: - dev_config_args = ast.literal_eval(args.dev_config_args) - dev_config = micro.device.get_device_funcs(args.dev_id)['default_config'](*dev_config_args) - - @tvm.register_func('tvm.rpc.server.start', override=True) - def server_start(): - # pylint: disable=unused-variable - session = micro.Session(dev_config) - session._enter() - - @tvm.register_func('tvm.rpc.server.shutdown', override=True) - def server_shutdown(): - session._exit() - - server = rpc.Server(args.host, - args.port, - args.port_end, - key=args.key, - tracker_addr=tracker_addr) - server.proc.join() - - -if __name__ == "__main__": - main() From c85b4750fc5ee63de0c5dd2a2232e3356f4589db Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Tue, 12 Nov 2019 14:13:52 -0800 Subject: [PATCH 56/70] Lint --- python/tvm/exec/rpc_server.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/python/tvm/exec/rpc_server.py b/python/tvm/exec/rpc_server.py index 00e972d7b95e..dbb690267e2a 100644 --- a/python/tvm/exec/rpc_server.py +++ b/python/tvm/exec/rpc_server.py @@ -24,12 +24,17 @@ import sys import logging import tvm -from .. import rpc from tvm import micro +from .. import rpc def main(args): - """Main function""" + """Main function + Parameters + ---------- + args : argparse.Namespace + parsed args from command-line invocation + """ if args.tracker: url, port = args.tracker.rsplit(":", 1) port = int(port) @@ -55,6 +60,13 @@ def main(args): def init_utvm(args): + """MicroTVM-specific RPC initialization + + Parameters + ---------- + args : argparse.Namespace + parsed args from command-line invocation + """ if args.utvm_dev_config and args.utvm_dev_id: raise RuntimeError('only one of --utvm-dev-config and --utvm-dev-id allowed') @@ -63,7 +75,8 @@ def init_utvm(args): dev_config = json.load(dev_conf_file) else: dev_config_args = ast.literal_eval(args.utvm_dev_config_args) - dev_config = micro.device.get_device_funcs(args.utvm_dev_id)['default_config'](*dev_config_args) + default_config_func = micro.device.get_device_funcs(args.utvm_dev_id)['default_config'] + dev_config = default_config_func(*dev_config_args) if args.utvm_dev_config or args.utvm_dev_id: # add MicroTVM overrides From 07a21298ed387b220503d5e17b83ad09cc17d937 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 14 Nov 2019 14:24:21 -0800 Subject: [PATCH 57/70] Lint --- src/runtime/rpc/rpc_session.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index 0c913464c3f9..52abef0c8d92 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -1254,7 +1254,7 @@ PackedFunc WrapTimeEvaluator(PackedFunc pf, int number, int repeat, int min_repeat_ms) { - if (ctx.device_type == kDLMicroDev) { + if (static_cast(ctx.device_type) == static_cast(kDLMicroDev)) { return MicroTimeEvaluator(pf, ctx, number, repeat, min_repeat_ms); } From 5e38d2b50a6226af27252aa909ab64c6b983d50d Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 15 Nov 2019 10:49:04 -0800 Subject: [PATCH 58/70] Address tqchen's comment Also, - templatize `EncoderAppend` - remove `DeviceLocation` class - add `TargetVal` union that `DevPtr` uses --- src/runtime/micro/host_low_level_device.cc | 2 +- src/runtime/micro/micro_common.h | 65 ++++--- src/runtime/micro/micro_section_allocator.h | 10 +- src/runtime/micro/micro_session.cc | 160 ++++++------------ src/runtime/micro/micro_session.h | 44 ++++- .../micro/target_data_layout_encoder.h | 2 +- 6 files changed, 132 insertions(+), 151 deletions(-) diff --git a/src/runtime/micro/host_low_level_device.cc b/src/runtime/micro/host_low_level_device.cc index 17590770e440..a24994a2a0e5 100644 --- a/src/runtime/micro/host_low_level_device.cc +++ b/src/runtime/micro/host_low_level_device.cc @@ -69,7 +69,7 @@ class HostLowLevelDevice final : public LowLevelDevice { } void Execute(DevPtr func_addr, DevPtr breakpoint_addr) { - reinterpret_cast(func_addr.value())(); + reinterpret_cast(func_addr.value().val64)(); } const char* device_type() const final { diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index dfb921f71b6a..4a0189b3e89e 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -52,80 +52,73 @@ enum class SectionKind : size_t { kNumKinds, }; -/*! \brief default size alignment */ +/*! \brief union for storing values on varying target word sizes */ +union TargetVal { + /*! \brief 32-bit pointer */ + uint32_t val32; + /*! \brief 64-bit pointer */ + uint64_t val64; +}; -/*! \brief Base class for interfacing with device locations (pointers/offsets) */ -class DeviceLocation { +/*! \brief absolute device address */ +class DevPtr { public: - /*! \brief construct a location with value `value` */ - explicit DeviceLocation(std::uintptr_t value) : value_(value) {} + /*! \brief construct a device address with value `value` */ + explicit DevPtr(std::uintptr_t value) : value_(TargetVal { .val64 = value }) {} /*! \brief default constructor */ - DeviceLocation() : value_(0) {} + DevPtr() : value_(TargetVal { .val64 = 0 }) {} - /*! \brief construct a null location */ - explicit DeviceLocation(std::nullptr_t value) : value_(0) {} + /*! \brief construct a null address */ + explicit DevPtr(std::nullptr_t value) : value_(TargetVal { .val64 = 0 }) {} /*! \brief destructor */ - virtual ~DeviceLocation() {} + ~DevPtr() {} /*! - * \brief get value of location - * \return value of location + * \brief get value of pointer + * \return value of pointer */ - std::uintptr_t value() const { return value_; } + TargetVal value() const { return value_; } /*! * \brief cast location to type `T` * \return casted result */ template - T cast_to() const { return reinterpret_cast(value_); } + T cast_to() const { return reinterpret_cast(value_.val64); } /*! \brief check if location is null */ - bool operator==(std::nullptr_t) const { return value_ == 0; } + bool operator==(std::nullptr_t) const { return value_.val64 == 0; } /*! \brief check if location is not null */ - bool operator!=(std::nullptr_t) const { return value_ != 0; } - - protected: - /*! \brief raw value storing the location */ - std::uintptr_t value_; -}; - -/*! \brief absolute device address */ -class DevPtr : public DeviceLocation { - public: - /*! \brief construct an absolute address with value `value` */ - explicit DevPtr(std::uintptr_t val) : DeviceLocation(val) {} - - /*! \brief default constructor */ - DevPtr() : DeviceLocation() {} - - /*! \brief construct a null absolute address */ - explicit DevPtr(std::nullptr_t val) : DeviceLocation(val) {} + bool operator!=(std::nullptr_t) const { return value_.val64 != 0; } /*! \brief add an integer to this absolute address to get a larger absolute address */ DevPtr operator+(size_t n) const { - return DevPtr(value_ + n); + return DevPtr(value_.val64 + n); } /*! \brief mutably add an integer to this absolute address */ DevPtr& operator+=(size_t n) { - value_ += n; + value_.val64 += n; return *this; } /*! \brief subtract an integer from this absolute address to get a smaller absolute address */ DevPtr operator-(size_t n) const { - return DevPtr(value_ - n); + return DevPtr(value_.val64 - n); } /*! \brief mutably subtract an integer from this absolute address */ DevPtr& operator-=(size_t n) { - value_ -= n; + value_.val64 -= n; return *this; } + + private: + /*! \brief raw value storing the pointer */ + TargetVal value_; }; /*! diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index 0f4215d94d0e..f6033d183710 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -43,7 +43,7 @@ class MicroSectionAllocator { size_(0), capacity_(region.size), word_size_(word_size) { - CHECK_EQ(start_addr_.value() % word_size, 0) + CHECK_EQ(start_addr_.value().val64 % word_size, 0) << "micro section start not aligned to " << word_size << " bytes"; CHECK_EQ(capacity_ % word_size, 0) << "micro section end not aligned to " << word_size << " bytes"; @@ -66,7 +66,7 @@ class MicroSectionAllocator { start_addr_.cast_to(); DevPtr alloc_addr = start_addr_ + size_; size_ += size; - alloc_map_[alloc_addr.value()] = size; + alloc_map_[alloc_addr.value().val64] = size; return alloc_addr; } @@ -76,8 +76,8 @@ class MicroSectionAllocator { * \note simple allocator scheme, more complex versions will be implemented later */ void Free(DevPtr addr) { - CHECK(alloc_map_.find(addr.value()) != alloc_map_.end()) << "freed pointer was never allocated"; - alloc_map_.erase(addr.value()); + CHECK(alloc_map_.find(addr.value().val64) != alloc_map_.end()) << "freed pointer was never allocated"; + alloc_map_.erase(addr.value().val64); if (alloc_map_.empty()) { size_ = 0; } @@ -118,7 +118,7 @@ class MicroSectionAllocator { /*! \brief number of bytes in a word on the target device */ size_t word_size_; /*! \brief allocation map for allocation sizes */ - std::unordered_map alloc_map_; + std::unordered_map alloc_map_; }; } // namespace runtime diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index cbed771c51b5..69e7ca082ab2 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -188,22 +188,17 @@ MicroSession::MicroSession( // Patch pointers to define the bounds of the workspace section and the word // size (for allocation alignment). std::shared_ptr ws_allocator = GetAllocator(SectionKind::kWorkspace); - uint64_t ws_start = ws_allocator->start_addr().value(); - uint64_t ws_end = ws_allocator->max_addr().value(); + TargetVal ws_start = ws_allocator->start_addr().value(); + TargetVal ws_end = ws_allocator->max_addr().value(); + TargetVal target_word_size { .val64 = word_size_ }; if (word_size_ == 4) { - uint32_t workspace_start_addr = (uint32_t) ws_start; - uint32_t workspace_end_addr = (uint32_t) ws_end; - uint32_t word_size = (uint32_t) word_size_; - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", ws_start.val32); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", ws_end.val32); + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", target_word_size.val32); } else if (word_size_ == 8) { - uint64_t workspace_start_addr = (uint64_t) ws_start; - uint64_t workspace_end_addr = (uint64_t) ws_end; - uint64_t word_size = (uint64_t) word_size_; - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", workspace_start_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", workspace_end_addr); - DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", word_size_); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_start", ws_start.val64); + DevSymbolWrite(runtime_symbol_map_, "utvm_workspace_end", ws_end.val64); + DevSymbolWrite(runtime_symbol_map_, "utvm_word_size", target_word_size.val64); } } @@ -218,8 +213,7 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { if (thumb_mode_) { func_ptr += 1; } - int32_t (*func_dev_addr)(void*, void*, int32_t) = - reinterpret_cast(func_ptr.value()); + TargetVal func_dev_addr = { .val64 = func_ptr.value() }; // Create an allocator stream for the memory region after the most recent // allocation in the args section. @@ -235,24 +229,22 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { reinterpret_cast(encoder.data()), encoder.buf_size()); + TargetVal arg_values_dev_addr = { .val64 = std::get<0>(arg_field_addrs).value() }; + TargetVal arg_type_codes_dev_addr = { .val64 = std::get<1>(arg_field_addrs).value() }; if (word_size_ == 4) { - TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); UTVMTask32 task = { - .func = *((uint32_t*) &func_dev_addr), // NOLINT(*) - .arg_values = *((uint32_t*) &arg_values_dev_addr), // NOLINT(*) - .arg_type_codes = *((uint32_t*) &arg_type_codes_dev_addr), // NOLINT(*) + .func = func_dev_addr.val32, + .arg_values = arg_values_dev_addr.val32, + .arg_type_codes = arg_type_codes_dev_addr.val32, .num_args = args.num_args, }; // Write the task. DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else if (word_size_ == 8) { - TVMValue* arg_values_dev_addr = std::get<0>(arg_field_addrs).cast_to(); - int* arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).cast_to(); UTVMTask64 task = { - .func = *((uint64_t*) &func_dev_addr), // NOLINT(*) - .arg_values = *((uint64_t*) &arg_values_dev_addr), // NOLINT(*) - .arg_type_codes = *((uint64_t*) &arg_type_codes_dev_addr), // NOLINT(*) + .func = func_dev_addr.val64, + .arg_values = arg_values_dev_addr.val64, + .arg_type_codes = arg_type_codes_dev_addr.val64, .num_args = args.num_args, }; // Write the task. @@ -352,7 +344,12 @@ std::tuple MicroSession::EncoderAppend( // Mutate the array to unwrap the `data` field. base_arr_handle->data = reinterpret_cast(old_data)->data; // Now, encode the unwrapped version. - void* arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + void* arr_ptr = nullptr; + if (word_size_ == 4) { + arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + } else if (word_size_ == 8) { + arr_ptr = EncoderAppend(encoder, *base_arr_handle).cast_to(); + } // And restore the original wrapped version. base_arr_handle->data = old_data; @@ -374,83 +371,38 @@ std::tuple MicroSession::EncoderAppend( return std::make_tuple(tvm_vals_slot.start_addr(), type_codes_slot.start_addr()); } +template DevPtr MicroSession::EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr) { - if (word_size_ == 4) { - auto tvm_arr_slot = encoder->Alloc(); - auto shape_slot = encoder->Alloc(arr.ndim); - - // `shape` and `strides` are stored on the host, so we need to write them to - // the device first. The `data` field is already allocated on the device and - // is a device pointer, so we don't need to write it. - shape_slot.WriteArray(arr.shape, arr.ndim); - DevPtr shape_addr = shape_slot.start_addr(); - DevPtr strides_addr = DevPtr(nullptr); - if (arr.strides != nullptr) { - auto stride_slot = encoder->Alloc(arr.ndim); - stride_slot.WriteArray(arr.strides, arr.ndim); - strides_addr = stride_slot.start_addr(); - } - - int64_t* dev_shape = shape_addr.cast_to(); - int64_t* dev_strides = strides_addr.cast_to(); - TVMArray32 dev_arr = { - .data = *((uint32_t*) &arr.data), // NOLINT(*) - .ctx = arr.ctx, - .ndim = arr.ndim, - .pad0 = 0, - .dtype = arr.dtype, - .shape = *((uint32_t*) &dev_shape), // NOLINT(*) - .strides = *((uint32_t*) &dev_strides), // NOLINT(*) - .pad1 = 0, - .byte_offset = *((uint32_t*) &arr.byte_offset), // NOLINT(*) - .pad2 = 0, - }; - // Update the device type to look like a host, because codegen generates - // checks that it is a host array. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) - << "attempt to write TVMArray with non-micro device type"; - dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - tvm_arr_slot.WriteValue(dev_arr); - return tvm_arr_slot.start_addr(); - } else if (word_size_ == 8) { - auto tvm_arr_slot = encoder->Alloc(); - auto shape_slot = encoder->Alloc(arr.ndim); - - // `shape` and `strides` are stored on the host, so we need to write them to - // the device first. The `data` field is already allocated on the device and - // is a device pointer, so we don't need to write it. - shape_slot.WriteArray(arr.shape, arr.ndim); - DevPtr shape_addr = shape_slot.start_addr(); - DevPtr strides_addr = DevPtr(nullptr); - if (arr.strides != nullptr) { - auto stride_slot = encoder->Alloc(arr.ndim); - stride_slot.WriteArray(arr.strides, arr.ndim); - strides_addr = stride_slot.start_addr(); - } - - int64_t* dev_shape = shape_addr.cast_to(); - int64_t* dev_strides = strides_addr.cast_to(); - TVMArray64 dev_arr = { - .data = *((uint64_t*) &arr.data), // NOLINT(*) - .ctx = arr.ctx, - .ndim = arr.ndim, - .pad0 = 0, - .dtype = arr.dtype, - .shape = *((uint64_t*) &dev_shape), // NOLINT(*) - .strides = *((uint64_t*) &dev_strides), // NOLINT(*) - .byte_offset = *((uint64_t*) &arr.byte_offset), // NOLINT(*) - }; - - // Update the device type to look like a host, because from the device's - // perspective, it is the host. - CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) - << "attempt to write TVMArray with non-micro device type"; - dev_arr.ctx.device_type = DLDeviceType::kDLCPU; - tvm_arr_slot.WriteValue(dev_arr); - return tvm_arr_slot.start_addr(); - } else { - CHECK(false) << "invalid word size"; + auto tvm_arr_slot = encoder->Alloc(); + auto shape_slot = encoder->Alloc(arr.ndim); + + // `shape` and `strides` are stored on the host, so we need to write them to + // the device first. The `data` field is already allocated on the device and + // is a device pointer, so we don't need to write it. + shape_slot.WriteArray(arr.shape, arr.ndim); + DevPtr shape_dev_addr = shape_slot.start_addr(); + DevPtr strides_dev_addr = DevPtr(nullptr); + if (arr.strides != nullptr) { + auto stride_slot = encoder->Alloc(arr.ndim); + stride_slot.WriteArray(arr.strides, arr.ndim); + strides_dev_addr = stride_slot.start_addr(); } + + T dev_arr( + TargetVal { .val64 = reinterpret_cast(arr.data) }, + arr.ctx, + arr.ndim, + arr.dtype, + shape_dev_addr.value(), + strides_dev_addr.value(), + TargetVal { .val64 = arr.byte_offset }); + CHECK(dev_arr.ctx.device_type == static_cast(kDLMicroDev)) + << "attempt to write TVMArray with non-micro device type"; + // Update the device type to CPU, because from the microcontroller's + // perspective, it is. + dev_arr.ctx.device_type = DLDeviceType::kDLCPU; + tvm_arr_slot.WriteValue(dev_arr); + return tvm_arr_slot.start_addr(); } void MicroSession::CheckDeviceError() { @@ -479,9 +431,9 @@ void MicroSession::PatchImplHole(const SymbolMap& symbol_map, const std::string& std::ostringstream func_name_underscore; func_name_underscore << func_name << "_"; if (word_size_ == 4) { - DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint32_t) runtime_impl_addr.value()); + DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr.value().val32); } else if (word_size_ == 8) { - DevSymbolWrite(symbol_map, func_name_underscore.str(), (uint64_t) runtime_impl_addr.value()); + DevSymbolWrite(symbol_map, func_name_underscore.str(), runtime_impl_addr.value().val64); } } diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 704c5b238dbd..6a0919f7369a 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -238,6 +238,7 @@ class MicroSession : public ModuleNode { * \param arr TVMArray to be appended * \return device address of the allocated `TVMArray` */ + template DevPtr EncoderAppend(TargetDataLayoutEncoder* encoder, const TVMArray& arr); /*! @@ -283,7 +284,26 @@ struct MicroDevSpace { // TODO(weberlo): maybe templatize serialization to reduce redundancy /*! \brief TVM array for serialization to 32-bit devices */ -typedef struct StructTVMArray32 { +struct TVMArray32 { + TVMArray32( + TargetVal data, + DLContext ctx, + int32_t ndim, + DLDataType dtype, + TargetVal shape, + TargetVal strides, + TargetVal byte_offset) + : data(data.val32), + ctx(ctx), + ndim(ndim), + pad0(0), + dtype(dtype), + shape(shape.val32), + strides(strides.val32), + pad1(0), + byte_offset(byte_offset.val32), + pad2(0) { } + /*! * \brief The opaque data pointer points to the allocated data. * This will be CUDA device pointer or cl_mem handle in OpenCL. @@ -311,10 +331,26 @@ typedef struct StructTVMArray32 { uint32_t byte_offset; /*! \brief Padding to enforce struct alignment */ uint32_t pad2; -} TVMArray32; +}; /*! \brief TVM array for serialization to 64-bit devices */ -typedef struct StructTVMArray64 { +struct TVMArray64 { + TVMArray64( + TargetVal data, + DLContext ctx, + int32_t ndim, + DLDataType dtype, + TargetVal shape, + TargetVal strides, + TargetVal byte_offset) + : data(data.val64), + ctx(ctx), + ndim(ndim), + pad0(0), + dtype(dtype), + shape(shape.val64), + strides(strides.val64), + byte_offset(byte_offset.val64) { } /*! * \brief The opaque data pointer points to the allocated data. * This will be CUDA device pointer or cl_mem handle in OpenCL. @@ -338,7 +374,7 @@ typedef struct StructTVMArray64 { uint64_t strides; /*! \brief The offset in bytes to the beginning pointer to data */ uint64_t byte_offset; -} TVMArray64; +}; /*! \brief MicroTVM task for serialization to 32-bit devices */ typedef struct StructUTVMTask32 { diff --git a/src/runtime/micro/target_data_layout_encoder.h b/src/runtime/micro/target_data_layout_encoder.h index 56d3aabcdf4c..e0275165e774 100644 --- a/src/runtime/micro/target_data_layout_encoder.h +++ b/src/runtime/micro/target_data_layout_encoder.h @@ -98,7 +98,7 @@ class TargetDataLayoutEncoder { */ explicit TargetDataLayoutEncoder(DevPtr start_addr, size_t word_size) : buf_(std::vector()), curr_offset_(0), word_size_(word_size) { - start_addr_ = DevPtr(UpperAlignValue(start_addr.value(), word_size_)); + start_addr_ = DevPtr(UpperAlignValue(start_addr.value().val64, word_size_)); } /*! From 17715ee9d7d482a608113c41568b28f431ab25cd Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 15 Nov 2019 10:53:18 -0800 Subject: [PATCH 59/70] Lint --- src/runtime/micro/micro_section_allocator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index f6033d183710..71b986d2ff71 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -76,7 +76,8 @@ class MicroSectionAllocator { * \note simple allocator scheme, more complex versions will be implemented later */ void Free(DevPtr addr) { - CHECK(alloc_map_.find(addr.value().val64) != alloc_map_.end()) << "freed pointer was never allocated"; + CHECK(alloc_map_.find(addr.value().val64) != alloc_map_.end()) + << "freed pointer was never allocated"; alloc_map_.erase(addr.value().val64); if (alloc_map_.empty()) { size_ = 0; From aeb840f33e335a8e426b5679df391b7f5ffea079 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 20 Nov 2019 10:54:23 -0800 Subject: [PATCH 60/70] Fix CI --- python/tvm/rpc/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index 13868f05cacb..9f069d45b5cf 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -70,7 +70,7 @@ def context(self, dev_type, dev_id=0): ctx: TVMContext The corresponding encoded remote context. """ - if '-device=micro_dev' in dev_type: + if isinstance(dev_type, str) and '-device=micro_dev' in dev_type: dev_type = 'micro_dev' ctx = nd.context(dev_type, dev_id) encode = (self._tbl_index + 1) * base.RPC_SESS_MASK From 70d607efdf79753293dd12cbdeb2a5f3cb622100 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 20 Nov 2019 11:47:39 -0800 Subject: [PATCH 61/70] Move '-device_type=micro_dev' check to ndarray.py --- python/tvm/_ffi/ndarray.py | 11 +++++++---- python/tvm/rpc/client.py | 2 -- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/python/tvm/_ffi/ndarray.py b/python/tvm/_ffi/ndarray.py index 3b6181a85c58..36fd4456e160 100644 --- a/python/tvm/_ffi/ndarray.py +++ b/python/tvm/_ffi/ndarray.py @@ -75,10 +75,13 @@ def context(dev_type, dev_id=0): assert tvm.context("cuda", 0) == tvm.gpu(0) """ if isinstance(dev_type, string_types): - dev_type = dev_type.split()[0] - if dev_type not in TVMContext.STR2MASK: - raise ValueError("Unknown device type %s" % dev_type) - dev_type = TVMContext.STR2MASK[dev_type] + if '-device_name=micro_dev' in dev_type: + dev_type = 'micro_dev' + else: + dev_type = dev_type.split()[0] + if dev_type not in TVMContext.STR2MASK: + raise ValueError("Unknown device type %s" % dev_type) + dev_type = TVMContext.STR2MASK[dev_type] return TVMContext(dev_type, dev_id) diff --git a/python/tvm/rpc/client.py b/python/tvm/rpc/client.py index 9f069d45b5cf..9c0dea5b0863 100644 --- a/python/tvm/rpc/client.py +++ b/python/tvm/rpc/client.py @@ -70,8 +70,6 @@ def context(self, dev_type, dev_id=0): ctx: TVMContext The corresponding encoded remote context. """ - if isinstance(dev_type, str) and '-device=micro_dev' in dev_type: - dev_type = 'micro_dev' ctx = nd.context(dev_type, dev_id) encode = (self._tbl_index + 1) * base.RPC_SESS_MASK ctx.device_type += encode From 3ecd4bf0a2d64476088b624184d64b0522105d50 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Wed, 20 Nov 2019 11:51:32 -0800 Subject: [PATCH 62/70] Fix --- python/tvm/_ffi/ndarray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/_ffi/ndarray.py b/python/tvm/_ffi/ndarray.py index 36fd4456e160..da0783e10410 100644 --- a/python/tvm/_ffi/ndarray.py +++ b/python/tvm/_ffi/ndarray.py @@ -75,7 +75,7 @@ def context(dev_type, dev_id=0): assert tvm.context("cuda", 0) == tvm.gpu(0) """ if isinstance(dev_type, string_types): - if '-device_name=micro_dev' in dev_type: + if '-device=micro_dev' in dev_type: dev_type = 'micro_dev' else: dev_type = dev_type.split()[0] From 98462b9ce4aeedc372cab47884597630fc318dd5 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 21 Nov 2019 08:55:50 -0800 Subject: [PATCH 63/70] Fix binutil tests --- tests/python/contrib/test_binutil.py | 42 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/python/contrib/test_binutil.py b/tests/python/contrib/test_binutil.py index e4ebd74a1a9c..44739bbda3cb 100644 --- a/tests/python/contrib/test_binutil.py +++ b/tests/python/contrib/test_binutil.py @@ -73,12 +73,21 @@ def test_tvm_callback_relocate_binary(): with open(tmp_bin, "wb") as f: f.write(binary) def verify(): - text_loc_str = "0x0" - rodata_loc_str = "0x10000" - data_loc_str = "0x20000" - bss_loc_str = "0x30000" + word_size = 8 + text_loc = 0x0 + rodata_loc = 0x10000 + data_loc = 0x20000 + bss_loc = 0x30000 + stack_end = 0x50000 rel_bin = tvm_callback_relocate_binary( - tmp_bin, text_loc_str, rodata_loc_str, data_loc_str, bss_loc_str, TOOLCHAIN_PREFIX) + tmp_bin, + word_size, + text_loc, + rodata_loc, + data_loc, + bss_loc, + stack_end, + TOOLCHAIN_PREFIX) print("Relocated binary section sizes") test_tvm_callback_get_section_size(binary=rel_bin) relf = tmp_dir.relpath("rel.bin") @@ -88,10 +97,6 @@ def verify(): stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (out, _) = nm_proc.communicate() - # Ensure the relocated symbols are within the ranges we specified. - text_loc = int(text_loc_str, 16) - data_loc = int(data_loc_str, 16) - bss_loc = int(bss_loc_str, 16) symbol_entries = out.decode("utf-8").split("\n") for entry in symbol_entries: if len(entry) == 0: @@ -127,12 +132,21 @@ def test_tvm_callback_get_symbol_map(): with open(tmp_bin, "wb") as f: f.write(binary) def verify(): - text_loc_str = "0x0" - rodata_loc_str = "0x10000" - data_loc_str = "0x20000" - bss_loc_str = "0x30000" + word_size = 8 + text_loc = 0x0 + rodata_loc = 0x10000 + data_loc = 0x20000 + bss_loc = 0x30000 + stack_end = 0x50000 rel_bin = tvm_callback_relocate_binary( - tmp_bin, text_loc_str, rodata_loc_str, data_loc_str, bss_loc_str, TOOLCHAIN_PREFIX) + tmp_bin, + word_size, + text_loc, + rodata_loc, + data_loc, + bss_loc, + stack_end, + TOOLCHAIN_PREFIX) symbol_map = tvm_callback_get_symbol_map(rel_bin, TOOLCHAIN_PREFIX) symbols = set() for i, line in enumerate(symbol_map.split('\n')): From 1224eedfe14c0d00cb6ff790fb8c1f2cbd6d0694 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 21 Nov 2019 09:30:07 -0800 Subject: [PATCH 64/70] Fix --- src/runtime/rpc/rpc_session.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/runtime/rpc/rpc_session.cc b/src/runtime/rpc/rpc_session.cc index 52abef0c8d92..c7e524d2f295 100644 --- a/src/runtime/rpc/rpc_session.cc +++ b/src/runtime/rpc/rpc_session.cc @@ -1221,15 +1221,13 @@ PackedFunc MicroTimeEvaluator( PackedFunc pf, TVMContext ctx, int number, - int repeat, - int min_repeat_ms) { - auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { + int repeat) { + auto ftimer = [pf, ctx, number, repeat](TVMArgs args, TVMRetValue *rv) mutable { TVMRetValue temp; std::ostringstream os; // skip first time call, to activate lazy compilation components. pf.CallPacked(args, &temp); DeviceAPI::Get(ctx)->StreamSync(ctx, nullptr); - for (int i = 0; i < repeat; ++i) { double speed = 0.0; for (int j = 0; j < number; ++j) { @@ -1255,7 +1253,7 @@ PackedFunc WrapTimeEvaluator(PackedFunc pf, int repeat, int min_repeat_ms) { if (static_cast(ctx.device_type) == static_cast(kDLMicroDev)) { - return MicroTimeEvaluator(pf, ctx, number, repeat, min_repeat_ms); + return MicroTimeEvaluator(pf, ctx, number, repeat); } auto ftimer = [pf, ctx, number, repeat, min_repeat_ms](TVMArgs args, TVMRetValue *rv) mutable { From 721ceb315fee7a3354f87819cbca2cfcf78eeb7c Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 21 Nov 2019 18:17:58 -0800 Subject: [PATCH 65/70] Fix --- src/runtime/micro/micro_section_allocator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/micro/micro_section_allocator.h b/src/runtime/micro/micro_section_allocator.h index 71b986d2ff71..5c75f92737ab 100644 --- a/src/runtime/micro/micro_section_allocator.h +++ b/src/runtime/micro/micro_section_allocator.h @@ -60,7 +60,7 @@ class MicroSectionAllocator { * \return pointer to allocated memory region in section, nullptr if out of space */ DevPtr Allocate(size_t size) { - size_ = UpperAlignValue(size_, 8); + size_ = UpperAlignValue(size_, word_size_); CHECK(size_ + size < capacity_) << "cannot alloc " << size << " bytes in section with start_addr " << start_addr_.cast_to(); From 27897d63773ad69ca2555a8b93aa86b70e3e2192 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Thu, 21 Nov 2019 21:37:37 -0800 Subject: [PATCH 66/70] Fix --- src/runtime/micro/micro_session.cc | 9 ++++----- src/runtime/micro/micro_session.h | 2 -- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index 69e7ca082ab2..06ffa73e79df 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -213,7 +213,6 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { if (thumb_mode_) { func_ptr += 1; } - TargetVal func_dev_addr = { .val64 = func_ptr.value() }; // Create an allocator stream for the memory region after the most recent // allocation in the args section. @@ -229,11 +228,11 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { reinterpret_cast(encoder.data()), encoder.buf_size()); - TargetVal arg_values_dev_addr = { .val64 = std::get<0>(arg_field_addrs).value() }; - TargetVal arg_type_codes_dev_addr = { .val64 = std::get<1>(arg_field_addrs).value() }; + TargetVal arg_values_dev_addr = std::get<0>(arg_field_addrs).value(); + TargetVal arg_type_codes_dev_addr = std::get<1>(arg_field_addrs).value(); if (word_size_ == 4) { UTVMTask32 task = { - .func = func_dev_addr.val32, + .func = func_ptr.value().val32, .arg_values = arg_values_dev_addr.val32, .arg_type_codes = arg_type_codes_dev_addr.val32, .num_args = args.num_args, @@ -242,7 +241,7 @@ double MicroSession::PushToExecQueue(DevPtr func_ptr, const TVMArgs& args) { DevSymbolWrite(runtime_symbol_map_, "utvm_task", task); } else if (word_size_ == 8) { UTVMTask64 task = { - .func = func_dev_addr.val64, + .func = func_ptr.value().val64, .arg_values = arg_values_dev_addr.val64, .arg_type_codes = arg_type_codes_dev_addr.val64, .num_args = args.num_args, diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 6a0919f7369a..dddacda7e126 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -204,8 +204,6 @@ class MicroSession : public ModuleNode { /*! \brief array of memory allocators for each on-device section */ std::shared_ptr section_allocators_[static_cast(SectionKind::kNumKinds)]; - /*! \brief total number of bytes of usable device memory for this session */ - size_t memory_size_; /*! \brief number of bytes in a word on the target device */ size_t word_size_; /*! \brief whether the target device requires a thumb-mode bit on function addresses From 013795e5f7a117c090aba9fb9d4855c3b2c5735a Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Fri, 22 Nov 2019 09:45:32 -0800 Subject: [PATCH 67/70] Make quotes thicker --- python/tvm/contrib/binutil.py | 78 ++++++++-------- python/tvm/micro/base.py | 102 ++++++++++----------- python/tvm/micro/device/arm/stm32f746xx.py | 84 ++++++++--------- python/tvm/micro/device/base.py | 62 ++++++------- python/tvm/micro/device/host.py | 56 +++++------ python/tvm/micro/device/riscv_spike.py | 62 ++++++------- 6 files changed, 222 insertions(+), 222 deletions(-) diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 545314df237c..1f322acdf8b9 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -87,10 +87,10 @@ def run_cmd(cmd): stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (output, _) = proc.communicate() - output = output.decode('utf-8') + output = output.decode("utf-8") if proc.returncode != 0: - cmd_str = ' '.join(cmd) - msg = f'error while running command \"{cmd_str}\":\n{output}' + cmd_str = " ".join(cmd) + msg = f"error while running command \"{cmd_str}\":\n{output}" raise RuntimeError(msg) return output @@ -117,18 +117,18 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): size of the section in bytes """ if not os.path.isfile(binary_path): - raise RuntimeError('no such file \"{}\"'.format(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_output = run_cmd(['{}size'.format(toolchain_prefix), '-A', binary_path]) + size_output = run_cmd(["{}size".format(toolchain_prefix), "-A", binary_path]) # 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'], + ".text": [".text"], + ".rodata": [".rodata"], + ".data": [".data", ".sdata"], + ".bss": [".bss", ".sbss"], } sections_to_sum = section_mapping["." + section_name] section_size = 0 @@ -147,7 +147,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): # NOTE: For some reason, the size of the BSS section on the RISC-V # GCC is sometimes reported to be smaller than it is, so we need to adjust # for this. - if 'riscv' in toolchain_prefix and section_name == 'bss': + if "riscv" in toolchain_prefix and section_name == "bss": # TODO(weberlo): Figure out why 32 is the minimum constant that works. # # The current hypothesis is that the last symbols in the ".bss" and @@ -162,7 +162,7 @@ def tvm_callback_get_section_size(binary_path, section_name, toolchain_prefix): return section_size -@register_func('tvm_callback_relocate_binary') +@register_func("tvm_callback_relocate_binary") def tvm_callback_relocate_binary( binary_path, word_size, @@ -206,10 +206,10 @@ def tvm_callback_relocate_binary( the relocated binary """ stack_pointer_init = stack_end - word_size - ld_script_contents = '' + 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' + if "riscv" in toolchain_prefix: + ld_script_contents += "OUTPUT_ARCH( \"riscv\" )\n\n" ld_script_contents += RELOCATION_LD_SCRIPT_TEMPLATE.format( word_size=word_size, text_start=text_start, @@ -219,21 +219,21 @@ def tvm_callback_relocate_binary( stack_pointer_init=stack_pointer_init) tmp_dir = util.tempdir() - rel_obj_path = tmp_dir.relpath('relocated.obj') - rel_ld_script_path = tmp_dir.relpath('relocated.lds') - with open(rel_ld_script_path, 'w') as f: + rel_obj_path = tmp_dir.relpath("relocated.obj") + rel_ld_script_path = tmp_dir.relpath("relocated.lds") + with open(rel_ld_script_path, "w") as f: f.write(ld_script_contents) run_cmd([ - '{}ld'.format(toolchain_prefix), + "{}ld".format(toolchain_prefix), binary_path, - '-T', rel_ld_script_path, - '-o', rel_obj_path]) - with open(rel_obj_path, 'rb') as f: + "-T", rel_ld_script_path, + "-o", rel_obj_path]) + with open(rel_obj_path, "rb") as f: rel_bin = bytearray(f.read()) return rel_bin -@register_func('tvm_callback_read_binary_section') +@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 @@ -254,26 +254,26 @@ def tvm_callback_read_binary_section(binary, section, toolchain_prefix): 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: + 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)) run_cmd([ - '{}objcopy'.format(toolchain_prefix), - '--dump-section', - '.{}={}'.format(section, tmp_section), + "{}objcopy".format(toolchain_prefix), + "--dump-section", + ".{}={}".format(section, tmp_section), tmp_bin]) if os.path.isfile(tmp_section): # Get section content if it exists. - with open(tmp_section, 'rb') as f: + 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') + section_bin = bytearray("", "utf-8") return section_bin -@register_func('tvm_callback_get_symbol_map') +@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 @@ -292,18 +292,18 @@ def tvm_callback_get_symbol_map(binary, toolchain_prefix): 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: + tmp_obj = tmp_dir.relpath("tmp_obj.bin") + with open(tmp_obj, "wb") as out_file: out_file.write(bytes(binary)) nm_output = run_cmd([ - '{}nm'.format(toolchain_prefix), - '-C', - '--defined-only', + "{}nm".format(toolchain_prefix), + "-C", + "--defined-only", tmp_obj]) nm_output = nm_output.splitlines() - map_str = '' + map_str = "" for line in nm_output: line = line.split() - map_str += line[2] + '\n' - map_str += line[0] + '\n' + map_str += line[2] + "\n" + map_str += line[0] + "\n" return map_str diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 0e8cd09bdbc1..710ce84f0710 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -49,7 +49,7 @@ class Session: .. code-block:: python c_mod = ... # some module generated with "c" as the target - dev_config = micro.device.arm.stm32f746xx.default_config('127.0.0.1', 6666) + dev_config = micro.device.arm.stm32f746xx.default_config("127.0.0.1", 6666) with tvm.micro.Session(dev_config) as sess: micro_mod = sess.create_micro_mod(c_mod) """ @@ -59,57 +59,57 @@ def __init__(self, config): # TODO(weberlo): add config validation # grab a binutil instance from the ID in the config - dev_funcs = tvm.micro.device.get_device_funcs(config['device_id']) - self.create_micro_lib = dev_funcs['create_micro_lib'] - self.toolchain_prefix = config['toolchain_prefix'] - self.mem_layout = config['mem_layout'] - self.word_size = config['word_size'] - self.thumb_mode = config['thumb_mode'] - self.comms_method = config['comms_method'] + dev_funcs = tvm.micro.device.get_device_funcs(config["device_id"]) + self.create_micro_lib = dev_funcs["create_micro_lib"] + self.toolchain_prefix = config["toolchain_prefix"] + self.mem_layout = config["mem_layout"] + self.word_size = config["word_size"] + self.thumb_mode = config["thumb_mode"] + self.comms_method = config["comms_method"] # First, find and compile runtime library. - runtime_src_path = os.path.join(get_micro_host_driven_dir(), 'utvm_runtime.c') + runtime_src_path = os.path.join(get_micro_host_driven_dir(), "utvm_runtime.c") tmp_dir = _util.tempdir() - runtime_obj_path = tmp_dir.relpath('utvm_runtime.obj') + runtime_obj_path = tmp_dir.relpath("utvm_runtime.obj") self.create_micro_lib(runtime_obj_path, runtime_src_path, LibType.RUNTIME) - #input(f'check {runtime_obj_path}: ') - - comms_method = config['comms_method'] - if comms_method == 'openocd': - server_addr = config['server_addr'] - server_port = config['server_port'] - elif comms_method == 'host': - server_addr = '' + #input(f"check {runtime_obj_path}: ") + + comms_method = config["comms_method"] + if comms_method == "openocd": + server_addr = config["server_addr"] + server_port = config["server_port"] + elif comms_method == "host": + server_addr = "" server_port = 0 else: - raise RuntimeError(f'unknown communication method: f{self.comms_method}') + raise RuntimeError(f"unknown communication method: f{self.comms_method}") self.module = _CreateSession( comms_method, runtime_obj_path, self.toolchain_prefix, - self.mem_layout['text'].get('start', 0), - self.mem_layout['text']['size'], - self.mem_layout['rodata'].get('start', 0), - self.mem_layout['rodata']['size'], - self.mem_layout['data'].get('start', 0), - self.mem_layout['data']['size'], - self.mem_layout['bss'].get('start', 0), - self.mem_layout['bss']['size'], - self.mem_layout['args'].get('start', 0), - self.mem_layout['args']['size'], - self.mem_layout['heap'].get('start', 0), - self.mem_layout['heap']['size'], - self.mem_layout['workspace'].get('start', 0), - self.mem_layout['workspace']['size'], - self.mem_layout['stack'].get('start', 0), - self.mem_layout['stack']['size'], + self.mem_layout["text"].get("start", 0), + self.mem_layout["text"]["size"], + self.mem_layout["rodata"].get("start", 0), + self.mem_layout["rodata"]["size"], + self.mem_layout["data"].get("start", 0), + self.mem_layout["data"]["size"], + self.mem_layout["bss"].get("start", 0), + self.mem_layout["bss"]["size"], + self.mem_layout["args"].get("start", 0), + self.mem_layout["args"]["size"], + self.mem_layout["heap"].get("start", 0), + self.mem_layout["heap"]["size"], + self.mem_layout["workspace"].get("start", 0), + self.mem_layout["workspace"]["size"], + self.mem_layout["stack"].get("start", 0), + self.mem_layout["stack"]["size"], self.word_size, self.thumb_mode, server_addr, server_port) - self._enter = self.module['enter'] - self._exit = self.module['exit'] + self._enter = self.module["enter"] + self._exit = self.module["exit"] def create_micro_mod(self, c_mod): """Produces a micro module from a given module. @@ -125,7 +125,7 @@ def create_micro_mod(self, c_mod): micro module for the target device """ temp_dir = _util.tempdir() - lib_obj_path = temp_dir.relpath('dev_lib.obj') + lib_obj_path = temp_dir.relpath("dev_lib.obj") c_mod.export_library( lib_obj_path, fcompile=cross_compiler(self.create_micro_lib, LibType.OPERATOR)) @@ -137,12 +137,12 @@ def _check_system(self): Raises error if not supported. """ - if not sys.platform.startswith('linux'): - raise RuntimeError('MicroTVM is currently only supported on Linux') + if not sys.platform.startswith("linux"): + raise RuntimeError("MicroTVM is currently only supported on Linux") # TODO(weberlo): Add 32-bit support. # It's primarily the compilation pipeline that isn't compatible. if sys.maxsize <= 2**32: - raise RuntimeError('MicroTVM is currently only supported on 64-bit platforms') + raise RuntimeError("MicroTVM is currently only supported on 64-bit platforms") def __enter__(self): self._enter() @@ -161,7 +161,7 @@ def cross_compiler(create_micro_lib, lib_type): ---------- create_micro_lib : func function for creating MicroTVM libraries for a specific device (e.g., - `tvm.micro.device.get_device_funcs('arm.stm32f746xx')['create_micro_lib']`) + `tvm.micro.device.get_device_funcs("arm.stm32f746xx")["create_micro_lib"]`) lib_type : micro.LibType whether to compile a MicroTVM runtime or operator library @@ -177,16 +177,16 @@ def cross_compiler(create_micro_lib, lib_type): .. code-block:: python c_mod = ... # some module generated with "c" as the target - fcompile = tvm.micro.cross_compiler('arm.stm32f746xx', LibType.OPERATOR) - c_mod.export_library('dev_lib.obj', fcompile=fcompile) + fcompile = tvm.micro.cross_compiler("arm.stm32f746xx", LibType.OPERATOR) + c_mod.export_library("dev_lib.obj", fcompile=fcompile) """ def compile_func(obj_path, src_path, **kwargs): if isinstance(obj_path, list): obj_path = obj_path[0] if isinstance(src_path, list): src_path = src_path[0] - create_micro_lib(obj_path, src_path, lib_type, kwargs.get('options', None)) - return _cc.cross_compiler(compile_func, output_format='obj') + create_micro_lib(obj_path, src_path, lib_type, kwargs.get("options", None)) + return _cc.cross_compiler(compile_func, output_format="obj") def get_micro_host_driven_dir(): @@ -198,8 +198,8 @@ def get_micro_host_driven_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_host_driven_dir = os.path.join(micro_dir, '..', '..', '..', - 'src', 'runtime', 'micro', 'host_driven') + micro_host_driven_dir = os.path.join(micro_dir, "..", "..", "..", + "src", "runtime", "micro", "host_driven") return micro_host_driven_dir @@ -212,9 +212,9 @@ def get_micro_device_dir(): directory path """ micro_dir = os.path.dirname(os.path.realpath(os.path.expanduser(__file__))) - micro_device_dir = os.path.join(micro_dir, '..', '..', '..', - 'src', 'runtime', 'micro', 'device') + micro_device_dir = os.path.join(micro_dir, "..", "..", "..", + "src", "runtime", "micro", "device") return micro_device_dir -_init_api('tvm.micro', 'tvm.micro.base') +_init_api("tvm.micro", "tvm.micro.base") diff --git a/python/tvm/micro/device/arm/stm32f746xx.py b/python/tvm/micro/device/arm/stm32f746xx.py index 950d5da42355..31b44cf9d36b 100644 --- a/python/tvm/micro/device/arm/stm32f746xx.py +++ b/python/tvm/micro/device/arm/stm32f746xx.py @@ -17,8 +17,8 @@ """Compilation and config definitions for ARM STM32F746XX devices""" from .. import create_micro_lib_base, register_device -DEVICE_ID = 'arm.stm32f746xx' -TOOLCHAIN_PREFIX = 'arm-none-eabi-' +DEVICE_ID = "arm.stm32f746xx" +TOOLCHAIN_PREFIX = "arm-none-eabi-" def create_micro_lib(obj_path, src_path, lib_type, options=None): """Wrapper over `create_micro_lib_base` to add device-specific options @@ -40,12 +40,12 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): if options is None: options = [] options += [ - '-mcpu=cortex-m7', - '-mlittle-endian', - '-mfloat-abi=hard', - '-mfpu=fpv5-sp-d16', - '-mthumb', - '-gdwarf-5', + "-mcpu=cortex-m7", + "-mlittle-endian", + "-mfloat-abi=hard", + "-mfpu=fpv5-sp-d16", + "-mthumb", + "-gdwarf-5", ] create_micro_lib_base( obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) @@ -68,56 +68,56 @@ def default_config(server_addr, server_port): MicroTVM config dict for this device """ return { - 'device_id': DEVICE_ID, - 'toolchain_prefix': TOOLCHAIN_PREFIX, + "device_id": DEVICE_ID, + "toolchain_prefix": TOOLCHAIN_PREFIX, # # [Device Memory Layout] # RAM (rwx) : START = 0x20000000, LENGTH = 320K # FLASH (rx) : START = 0x8000000, LENGTH = 1024K # - 'mem_layout': { - 'text': { - 'start': 0x20000180, - 'size': 20480, + "mem_layout": { + "text": { + "start": 0x20000180, + "size": 20480, }, - 'rodata': { - 'start': 0x20005180, - 'size': 20480, + "rodata": { + "start": 0x20005180, + "size": 20480, }, - 'data': { - 'start': 0x2000a180, - 'size': 768, + "data": { + "start": 0x2000a180, + "size": 768, }, - 'bss': { - 'start': 0x2000a480, - 'size': 768, + "bss": { + "start": 0x2000a480, + "size": 768, }, - 'args': { - 'start': 0x2000a780, - 'size': 1280, + "args": { + "start": 0x2000a780, + "size": 1280, }, - 'heap': { - 'start': 0x2000ac80, - 'size': 262144, + "heap": { + "start": 0x2000ac80, + "size": 262144, }, - 'workspace': { - 'start': 0x2004ac80, - 'size': 20480, + "workspace": { + "start": 0x2004ac80, + "size": 20480, }, - 'stack': { - 'start': 0x2004fc80, - 'size': 80, + "stack": { + "start": 0x2004fc80, + "size": 80, }, }, - 'word_size': 4, - 'thumb_mode': True, - 'comms_method': 'openocd', - 'server_addr': server_addr, - 'server_port': server_port, + "word_size": 4, + "thumb_mode": True, + "comms_method": "openocd", + "server_addr": server_addr, + "server_port": server_port, } register_device(DEVICE_ID, { - 'create_micro_lib': create_micro_lib, - 'default_config': default_config, + "create_micro_lib": create_micro_lib, + "default_config": default_config, }) diff --git a/python/tvm/micro/device/base.py b/python/tvm/micro/device/base.py index 138c939d1d00..ae53b9cc539f 100644 --- a/python/tvm/micro/device/base.py +++ b/python/tvm/micro/device/base.py @@ -38,7 +38,7 @@ def register_device(device_id, device_funcs): dictionary with compilation and config generation functions as values """ if device_id in _DEVICE_REGISTRY: - raise RuntimeError(f'"{device_id}" already exists in the device registry') + raise RuntimeError(f"\"{device_id}\" already exists in the device registry") _DEVICE_REGISTRY[device_id] = device_funcs @@ -56,7 +56,7 @@ def get_device_funcs(device_id): dictionary with compilation and config generation functions as values """ if device_id not in _DEVICE_REGISTRY: - raise RuntimeError(f'"{device_id}" does not exist in the binutil registry') + raise RuntimeError(f"\"{device_id}\" does not exist in the binutil registry") device_funcs = _DEVICE_REGISTRY[device_id] return device_funcs @@ -94,19 +94,19 @@ def create_micro_lib_base( additional options to pass to GCC """ base_compile_cmd = [ - f'{toolchain_prefix}gcc', - '-std=c11', - '-Wall', - '-Wextra', - '--pedantic', - '-c', - '-O0', - '-g', - '-nostartfiles', - '-nodefaultlibs', - '-nostdlib', - '-fdata-sections', - '-ffunction-sections', + f"{toolchain_prefix}gcc", + "-std=c11", + "-Wall", + "-Wextra", + "--pedantic", + "-c", + "-O0", + "-g", + "-nostartfiles", + "-nodefaultlibs", + "-nostdlib", + "-fdata-sections", + "-ffunction-sections", ] if options is not None: base_compile_cmd += options @@ -118,45 +118,45 @@ def create_micro_lib_base( new_in_src_path = in_src_path if lib_type == LibType.RUNTIME: dev_dir = _get_device_source_dir(device_id) - dev_src_paths = glob.glob(f'{dev_dir}/*.[csS]') + dev_src_paths = glob.glob(f"{dev_dir}/*.[csS]") # there needs to at least be a utvm_timer.c file assert dev_src_paths - assert 'utvm_timer.c' in map(os.path.basename, dev_src_paths) + assert "utvm_timer.c" in map(os.path.basename, dev_src_paths) src_paths += dev_src_paths elif lib_type == LibType.OPERATOR: # create a temporary copy of the source, so we can inject the dev lib # header without modifying the original. - temp_src_path = tmp_dir.relpath('temp.c') - with open(in_src_path, 'r') as f: + temp_src_path = tmp_dir.relpath("temp.c") + with open(in_src_path, "r") as f: src_lines = f.read().splitlines() - src_lines.insert(0, '#include "utvm_device_dylib_redirect.c"') - with open(temp_src_path, 'w') as f: - f.write('\n'.join(src_lines)) + src_lines.insert(0, "#include \"utvm_device_dylib_redirect.c\"") + with open(temp_src_path, "w") as f: + f.write("\n".join(src_lines)) new_in_src_path = temp_src_path - base_compile_cmd += ['-c'] + base_compile_cmd += ["-c"] else: - raise RuntimeError('unknown lib type') + raise RuntimeError("unknown lib type") src_paths += [new_in_src_path] for path in include_paths: - base_compile_cmd += ['-I', path] + base_compile_cmd += ["-I", path] prereq_obj_paths = [] for src_path in src_paths: - curr_obj_path = Path(src_path).with_suffix('.o').name + curr_obj_path = Path(src_path).with_suffix(".o").name assert curr_obj_path not in prereq_obj_paths prereq_obj_paths.append(curr_obj_path) - curr_compile_cmd = base_compile_cmd + [src_path, '-o', curr_obj_path] + curr_compile_cmd = base_compile_cmd + [src_path, "-o", curr_obj_path] run_cmd(curr_compile_cmd) - ld_cmd = [f'{toolchain_prefix}ld', '-relocatable'] + ld_cmd = [f"{toolchain_prefix}ld", "-relocatable"] ld_cmd += prereq_obj_paths - ld_cmd += ['-o', out_obj_path] + ld_cmd += ["-o", out_obj_path] run_cmd(ld_cmd) def _get_device_source_dir(device_id): """Grabs the source directory for device-specific uTVM files""" - dev_subdir = '/'.join(device_id.split('.')) - return get_micro_device_dir() + '/' + dev_subdir + dev_subdir = "/".join(device_id.split(".")) + return get_micro_device_dir() + "/" + dev_subdir diff --git a/python/tvm/micro/device/host.py b/python/tvm/micro/device/host.py index 0131ea78e578..a5495b60cf99 100644 --- a/python/tvm/micro/device/host.py +++ b/python/tvm/micro/device/host.py @@ -19,8 +19,8 @@ from . import create_micro_lib_base, register_device -DEVICE_ID = 'host' -TOOLCHAIN_PREFIX = '' +DEVICE_ID = "host" +TOOLCHAIN_PREFIX = "" def create_micro_lib(obj_path, src_path, lib_type, options=None): """Wrapper over `create_micro_lib_base` to add device-specific options @@ -41,8 +41,8 @@ def create_micro_lib(obj_path, src_path, lib_type, options=None): """ if options is None: options = [] - if sys.maxsize > 2**32 and sys.platform.startswith('linux'): - options += ['-mcmodel=large'] + if sys.maxsize > 2**32 and sys.platform.startswith("linux"): + options += ["-mcmodel=large"] create_micro_lib_base( obj_path, src_path, TOOLCHAIN_PREFIX, DEVICE_ID, lib_type, options=options) @@ -56,41 +56,41 @@ def default_config(): MicroTVM config dict for this device """ return { - 'device_id': DEVICE_ID, - 'toolchain_prefix': TOOLCHAIN_PREFIX, - 'mem_layout': { - 'text': { - 'size': 20480, + "device_id": DEVICE_ID, + "toolchain_prefix": TOOLCHAIN_PREFIX, + "mem_layout": { + "text": { + "size": 20480, }, - 'rodata': { - 'size': 20480, + "rodata": { + "size": 20480, }, - 'data': { - 'size': 768, + "data": { + "size": 768, }, - 'bss': { - 'size': 768, + "bss": { + "size": 768, }, - 'args': { - 'size': 1280, + "args": { + "size": 1280, }, - 'heap': { - 'size': 262144, + "heap": { + "size": 262144, }, - 'workspace': { - 'size': 20480, + "workspace": { + "size": 20480, }, - 'stack': { - 'size': 80, + "stack": { + "size": 80, }, }, - 'word_size': 8 if sys.maxsize > 2**32 else 4, - 'thumb_mode': False, - 'comms_method': 'host', + "word_size": 8 if sys.maxsize > 2**32 else 4, + "thumb_mode": False, + "comms_method": "host", } register_device(DEVICE_ID, { - 'create_micro_lib': create_micro_lib, - 'default_config': default_config, + "create_micro_lib": create_micro_lib, + "default_config": default_config, }) diff --git a/python/tvm/micro/device/riscv_spike.py b/python/tvm/micro/device/riscv_spike.py index 46cd131bea60..923e5dfb23a2 100644 --- a/python/tvm/micro/device/riscv_spike.py +++ b/python/tvm/micro/device/riscv_spike.py @@ -19,8 +19,8 @@ from . import create_micro_lib_base, register_device -DEVICE_ID = 'riscv_spike' -TOOLCHAIN_PREFIX = 'riscv64-unknown-elf-' +DEVICE_ID = "riscv_spike" +TOOLCHAIN_PREFIX = "riscv64-unknown-elf-" def create_micro_lib(obj_path, src_path, lib_type, options=None): """Wrapper over `create_micro_lib_base` to add device-specific options @@ -68,50 +68,50 @@ def default_config(base_addr, server_addr, server_port): MicroTVM config dict for this device """ res = { - 'device_id': DEVICE_ID, - 'toolchain_prefix': TOOLCHAIN_PREFIX, - 'mem_layout': OrderedDict([ - ('text', { - 'size': 20480, + "device_id": DEVICE_ID, + "toolchain_prefix": TOOLCHAIN_PREFIX, + "mem_layout": OrderedDict([ + ("text", { + "size": 20480, }), - ('rodata', { - 'size': 20480, + ("rodata", { + "size": 20480, }), - ('data', { - 'size': 768, + ("data", { + "size": 768, }), - ('bss', { - 'size': 768, + ("bss", { + "size": 768, }), - ('args', { - 'size': 1280, + ("args", { + "size": 1280, }), - ('heap', { - 'size': 262144, + ("heap", { + "size": 262144, }), - ('workspace', { - 'size': 20480, + ("workspace", { + "size": 20480, }), - ('stack', { - 'size': 80, + ("stack", { + "size": 80, }), ]), - 'word_size': 4, - 'thumb_mode': True, - 'comms_method': 'openocd', - 'server_addr': server_addr, - 'server_port': server_port, + "word_size": 4, + "thumb_mode": True, + "comms_method": "openocd", + "server_addr": server_addr, + "server_port": server_port, } # generate section start addresses from the given `base_addr` curr_offset = 0 - mem_layout = res['mem_layout'] + mem_layout = res["mem_layout"] for region_dict in mem_layout.values(): - region_dict['start'] = base_addr + curr_offset - curr_offset += region_dict['size'] + region_dict["start"] = base_addr + curr_offset + curr_offset += region_dict["size"] return res register_device(DEVICE_ID, { - 'create_micro_lib': create_micro_lib, - 'default_config': default_config, + "create_micro_lib": create_micro_lib, + "default_config": default_config, }) From 9d77f82d3887ff45e076e2cf1e10ed11f25649a6 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sat, 23 Nov 2019 19:00:01 -0800 Subject: [PATCH 68/70] Address comments --- python/tvm/micro/base.py | 4 ++-- src/runtime/micro/micro_session.h | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index 710ce84f0710..f84c6ac8025e 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -138,11 +138,11 @@ def _check_system(self): Raises error if not supported. """ if not sys.platform.startswith("linux"): - raise RuntimeError("MicroTVM is currently only supported on Linux") + raise RuntimeError("MicroTVM is currently only supported on Linux hosts") # TODO(weberlo): Add 32-bit support. # It's primarily the compilation pipeline that isn't compatible. if sys.maxsize <= 2**32: - raise RuntimeError("MicroTVM is currently only supported on 64-bit platforms") + raise RuntimeError("MicroTVM is currently only supported on 64-bit host platforms") def __enter__(self): self._enter() diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index dddacda7e126..495fc74aa177 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -302,11 +302,7 @@ struct TVMArray32 { byte_offset(byte_offset.val32), pad2(0) { } - /*! - * \brief The opaque data pointer points to the allocated data. - * This will be CUDA device pointer or cl_mem handle in OpenCL. - * This pointer is always aligns to 256 bytes as in CUDA. - */ + /*! \brief opaque pointer to the allocated data */ uint32_t data; /*! \brief The device context of the tensor */ DLContext ctx; @@ -349,11 +345,8 @@ struct TVMArray64 { shape(shape.val64), strides(strides.val64), byte_offset(byte_offset.val64) { } - /*! - * \brief The opaque data pointer points to the allocated data. - * This will be CUDA device pointer or cl_mem handle in OpenCL. - * This pointer is always aligns to 256 bytes as in CUDA. - */ + + /*! \brief opaque pointer to the allocated data */ uint64_t data; /*! \brief The device context of the tensor */ DLContext ctx; From 3d594b79e1a39811f781eb595645e1ad6611b38a Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Sun, 24 Nov 2019 15:56:39 -0800 Subject: [PATCH 69/70] Remove copyright lines --- src/runtime/micro/device/arm/stm32f746xx/utvm_init.s | 1 - src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c | 1 - src/runtime/micro/device/host/utvm_init.c | 1 - src/runtime/micro/device/host/utvm_timer.c | 1 - 4 files changed, 4 deletions(-) diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s index 5861c0326dbf..300deb8079a0 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_init.s @@ -18,7 +18,6 @@ */ /*! - * Copyright (c) 2019 by Contributors * \file utvm_init.s * \brief uTVM init definition for STM32F746XX-series boards */ diff --git a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c index 0651b4f4fe64..1b8376150fce 100644 --- a/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c +++ b/src/runtime/micro/device/arm/stm32f746xx/utvm_timer.c @@ -18,7 +18,6 @@ */ /*! - * Copyright (c) 2019 by Contributors * \file utvm_timer.c * \brief uTVM timer API definitions for STM32F746XX-series boards */ diff --git a/src/runtime/micro/device/host/utvm_init.c b/src/runtime/micro/device/host/utvm_init.c index 02888f04c48e..4fb43c11d20e 100644 --- a/src/runtime/micro/device/host/utvm_init.c +++ b/src/runtime/micro/device/host/utvm_init.c @@ -18,7 +18,6 @@ */ /*! - * Copyright (c) 2019 by Contributors * \file utvm_init.c * \brief uTVM init definition for the host emulated device */ diff --git a/src/runtime/micro/device/host/utvm_timer.c b/src/runtime/micro/device/host/utvm_timer.c index fffbf7dc8eb1..56a36ebae86d 100644 --- a/src/runtime/micro/device/host/utvm_timer.c +++ b/src/runtime/micro/device/host/utvm_timer.c @@ -18,7 +18,6 @@ */ /*! - * Copyright (c) 2019 by Contributors * \file utvm_timer.c * \brief uTVM timer API stubs for the host emulated device */ From afd614e7f5699e2f6cb30a2f771d976b9e1c3942 Mon Sep 17 00:00:00 2001 From: Logan Weber Date: Mon, 25 Nov 2019 09:01:00 -0800 Subject: [PATCH 70/70] Make create_micro_mod static --- python/tvm/micro/__init__.py | 3 +- python/tvm/micro/base.py | 59 +++++++++++---------- tests/python/unittest/test_runtime_micro.py | 34 ++++++------ 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/python/tvm/micro/__init__.py b/python/tvm/micro/__init__.py index 73612b3c4b43..9e984c08fe2c 100644 --- a/python/tvm/micro/__init__.py +++ b/python/tvm/micro/__init__.py @@ -17,5 +17,6 @@ """MicroTVM module for bare-metal backends""" from ..contrib import binutil -from .base import Session, cross_compiler, LibType, get_micro_host_driven_dir, get_micro_device_dir +from .base import Session, create_micro_mod, cross_compiler +from .base import LibType, get_micro_host_driven_dir, get_micro_device_dir from . import device diff --git a/python/tvm/micro/base.py b/python/tvm/micro/base.py index f84c6ac8025e..e2e1329cb36c 100644 --- a/python/tvm/micro/base.py +++ b/python/tvm/micro/base.py @@ -51,7 +51,7 @@ class Session: c_mod = ... # some module generated with "c" as the target dev_config = micro.device.arm.stm32f746xx.default_config("127.0.0.1", 6666) with tvm.micro.Session(dev_config) as sess: - micro_mod = sess.create_micro_mod(c_mod) + micro_mod = create_micro_mod(c_mod, dev_config) """ def __init__(self, config): @@ -111,27 +111,6 @@ def __init__(self, config): self._enter = self.module["enter"] self._exit = self.module["exit"] - def create_micro_mod(self, c_mod): - """Produces a micro module from a given module. - - Parameters - ---------- - c_mod : tvm.module.Module - module with "c" as its target backend - - Return - ------ - micro_mod : tvm.module.Module - micro module for the target device - """ - temp_dir = _util.tempdir() - lib_obj_path = temp_dir.relpath("dev_lib.obj") - c_mod.export_library( - lib_obj_path, - fcompile=cross_compiler(self.create_micro_lib, LibType.OPERATOR)) - micro_mod = tvm.module.load(lib_obj_path) - return micro_mod - def _check_system(self): """Check if the user's system is supported by MicroTVM. @@ -152,16 +131,40 @@ def __exit__(self, exc_type, exc_value, exc_traceback): self._exit() -def cross_compiler(create_micro_lib, lib_type): +def create_micro_mod(c_mod, dev_config): + """Produces a micro module from a given module. + + Parameters + ---------- + c_mod : tvm.module.Module + module with "c" as its target backend + + dev_config : Dict[str, Any] + MicroTVM config dict for the target device + + Return + ------ + micro_mod : tvm.module.Module + micro module for the target device + """ + temp_dir = _util.tempdir() + lib_obj_path = temp_dir.relpath("dev_lib.obj") + c_mod.export_library( + lib_obj_path, + fcompile=cross_compiler(dev_config, LibType.OPERATOR)) + micro_mod = tvm.module.load(lib_obj_path) + return micro_mod + + +def cross_compiler(dev_config, lib_type): """Create a cross-compile function that wraps `create_lib` for a `Binutil` instance. For use in `tvm.module.Module.export_library`. Parameters ---------- - create_micro_lib : func - function for creating MicroTVM libraries for a specific device (e.g., - `tvm.micro.device.get_device_funcs("arm.stm32f746xx")["create_micro_lib"]`) + dev_config : Dict[str, Any] + MicroTVM config dict for the target device lib_type : micro.LibType whether to compile a MicroTVM runtime or operator library @@ -177,9 +180,11 @@ def cross_compiler(create_micro_lib, lib_type): .. code-block:: python c_mod = ... # some module generated with "c" as the target - fcompile = tvm.micro.cross_compiler("arm.stm32f746xx", LibType.OPERATOR) + fcompile = tvm.micro.cross_compiler(dev_config, LibType.OPERATOR) c_mod.export_library("dev_lib.obj", fcompile=fcompile) """ + dev_funcs = tvm.micro.device.get_device_funcs(dev_config['device_id']) + create_micro_lib = dev_funcs['create_micro_lib'] def compile_func(obj_path, src_path, **kwargs): if isinstance(obj_path, list): obj_path = obj_path[0] diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 895f1e6b5c53..e94c09991b35 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -21,12 +21,13 @@ from tvm.contrib import graph_runtime, util from tvm import relay import tvm.micro as micro +from tvm.micro import create_micro_mod from tvm.relay.testing import resnet # Use the host emulated micro device. DEV_CONFIG = micro.device.host.default_config() -def relay_micro_build(func, sess, params=None): +def relay_micro_build(func, dev_config, params=None): """Create a graph runtime module with a micro device context from a Relay function. Parameters @@ -34,6 +35,9 @@ def relay_micro_build(func, sess, params=None): func : relay.Function function to compile + dev_config : Dict[str, Any] + MicroTVM config dict for the target device + params : dict input parameters that do not change during inference @@ -44,7 +48,7 @@ def relay_micro_build(func, sess, params=None): """ with tvm.build_config(disable_vectorize=True): graph, c_mod, params = relay.build(func, target="c", params=params) - micro_mod = sess.create_micro_mod(c_mod) + micro_mod = create_micro_mod(c_mod, dev_config) ctx = tvm.micro_dev(0) mod = graph_runtime.create(graph, micro_mod, ctx) mod.set_input(**params) @@ -81,8 +85,8 @@ def test_add(): func_name = "fadd" c_mod = tvm.build(s, [A, B, C], target="c", name=func_name) - with micro.Session(DEV_CONFIG) as sess: - micro_mod = sess.create_micro_mod(c_mod) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -111,8 +115,8 @@ def test_workspace_add(): func_name = "fadd_two_workspace" c_mod = tvm.build(s, [A, C], target="c", name=func_name) - with micro.Session(DEV_CONFIG) as sess: - micro_mod = sess.create_micro_mod(c_mod) + with micro.Session(DEV_CONFIG): + micro_mod = create_micro_mod(c_mod, DEV_CONFIG) micro_func = micro_mod[func_name] ctx = tvm.micro_dev(0) a = tvm.nd.array(np.random.uniform(size=shape).astype(dtype), ctx) @@ -136,8 +140,8 @@ def test_graph_runtime(): z = relay.add(xx, relay.const(1.0)) func = relay.Function([x], z) - with micro.Session(DEV_CONFIG) as sess: - mod = relay_micro_build(func, sess) + with micro.Session(DEV_CONFIG): + mod = relay_micro_build(func, DEV_CONFIG) x_in = np.random.uniform(size=shape[0]).astype(dtype) mod.run(x=x_in) @@ -163,9 +167,9 @@ def test_multiple_modules(): ret = relay.subtract(x, relay.const(1.0)) sub_const_func = relay.Function([x], ret) - with micro.Session(DEV_CONFIG) as sess: - add_const_mod = relay_micro_build(add_const_func, sess) - sub_const_mod = relay_micro_build(sub_const_func, sess) + with micro.Session(DEV_CONFIG): + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) + sub_const_mod = relay_micro_build(sub_const_func, DEV_CONFIG) x_in = np.random.uniform(size=shape[0]).astype(dtype) add_const_mod.run(x=x_in) @@ -200,13 +204,13 @@ def test_interleave_sessions(): np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) with sess_a: - add_const_mod = relay_micro_build(add_const_func, sess_a) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( add_result, np_tensor_a + 1.0) with sess_b: - add_const_mod = relay_micro_build(add_const_func, sess_b) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_b) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -233,7 +237,7 @@ def test_nested_sessions(): with sess_b: np_tensor_b = np.random.uniform(size=shape).astype(dtype) micro_tensor_b = tvm.nd.array(np_tensor_b, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, sess_a) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) add_const_mod.run(x=micro_tensor_a) add_result = add_const_mod.get_output(0).asnumpy() tvm.testing.assert_allclose( @@ -257,7 +261,7 @@ def test_inactive_session_use(): with sess_a: np_tensor_a = np.random.uniform(size=shape).astype(dtype) micro_tensor_a = tvm.nd.array(np_tensor_a, tvm.micro_dev(0)) - add_const_mod = relay_micro_build(add_const_func, sess_a) + add_const_mod = relay_micro_build(add_const_func, DEV_CONFIG) with sess_b: # These objects belong to `sess_a`.