diff --git a/python/tvm/contrib/binutil.py b/python/tvm/contrib/binutil.py index 2d86f3d8bddad..105f42c29a0ae 100644 --- a/python/tvm/contrib/binutil.py +++ b/python/tvm/contrib/binutil.py @@ -81,13 +81,13 @@ def tvm_relocate_binary(binary_name, text, data, bss): @register_func("tvm_read_binary_section") -def tvm_read_binary_section(binary_name, section): +def tvm_read_binary_section(binary, section): """Returns the contents of the specified section in the binary file Parameters ---------- - binary_name : string - name of the binary file + binary : bytearray + contents of the binary section : string type of section @@ -98,10 +98,13 @@ def tvm_read_binary_section(binary_name, section): contents of the read section """ tmp_dir = util.tempdir() + tmp_bin = tmp_dir.relpath("temp.bin") tmp_section = tmp_dir.relpath("tmp_section.bin") + with open(tmp_bin, "wb") as out_file: + out_file.write(bytes(binary)) p1 = subprocess.Popen(["objcopy", "--dump-section", "." + section + "=" + tmp_section, - binary_name], + tmp_bin], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (out, _) = p1.communicate() diff --git a/src/runtime/micro/device/utvm_runtime.cc b/src/runtime/micro/device/utvm_runtime.cc index 3116390a30330..5eb589a4b9b9a 100644 --- a/src/runtime/micro/device/utvm_runtime.cc +++ b/src/runtime/micro/device/utvm_runtime.cc @@ -12,8 +12,7 @@ UTVMTask task; void UTVMDone() {} // init stub -int UTVMMain() -{ +int UTVMMain() { task.func(task.args, task.arg_type_ids, *task.num_args); UTVMDone(); return 0; diff --git a/src/runtime/micro/low_level_device.h b/src/runtime/micro/low_level_device.h index 9cc80b9717b13..233fa1f105dc9 100644 --- a/src/runtime/micro/low_level_device.h +++ b/src/runtime/micro/low_level_device.h @@ -3,8 +3,8 @@ * \file low_level_device.h * \brief Abstract low-level micro device management */ -#ifndef TVM_RUNTIME_LOW_LEVEL_DEVICE_H_ -#define TVM_RUNTIME_LOW_LEVEL_DEVICE_H_ +#ifndef TVM_RUNTIME_MICRO_LOW_LEVEL_DEVICE_H_ +#define TVM_RUNTIME_MICRO_LOW_LEVEL_DEVICE_H_ #include #include @@ -64,6 +64,6 @@ const std::shared_ptr HostLowLevelDeviceCreate(size_t num_bytes) * \param port port of the OpenOCD server to connect to */ const std::shared_ptr OpenOCDLowLevelDeviceCreate(int port); -} // namespace runtime -} // namespace tvm -#endif // TVM_RUNTIME_LOW_LEVEL_DEVICE_H_ +} // namespace runtime +} // namespace tvm +#endif // TVM_RUNTIME_MICRO_LOW_LEVEL_DEVICE_H_ diff --git a/src/runtime/micro/micro_common.cc b/src/runtime/micro/micro_common.cc index 94f6bf99ad2bf..007c2e66da78a 100644 --- a/src/runtime/micro/micro_common.cc +++ b/src/runtime/micro/micro_common.cc @@ -31,7 +31,7 @@ const char* SectionToString(SectionKind section) { void* GetSymbol(std::unordered_map symbol_map, std::string name, - void* base_addr) { + const void* base_addr) { void* symbol_addr = symbol_map[name]; return (void*)((uint8_t*) symbol_addr - (uint8_t*) base_addr); } @@ -59,12 +59,12 @@ std::string RelocateBinarySections(std::string binary_name, return relocated_bin; } -std::string ReadSection(std::string binary_name, SectionKind section) { +std::string ReadSection(std::string binary, SectionKind section) { CHECK(section == kText || section == kData || section == kBss) << "ReadSection requires section to be one of text, data or bss."; const auto* f = Registry::Get("tvm_read_binary_section"); CHECK(f != nullptr) << "Require tvm_read_binary_section to exist in registry"; - std::string section_contents = (*f)(binary_name, SectionToString(section)); + std::string section_contents = (*f)(binary, SectionToString(section)); return section_contents; } diff --git a/src/runtime/micro/micro_common.h b/src/runtime/micro/micro_common.h index c98a21341aa2f..853ae7b711961 100644 --- a/src/runtime/micro/micro_common.h +++ b/src/runtime/micro/micro_common.h @@ -88,7 +88,7 @@ const char* SectionToString(SectionKind section); */ void* GetSymbol(std::unordered_map symbol_map, std::string name, - void* base_addr); + const void* base_addr); /*! * \brief links binary by repositioning section addresses @@ -104,12 +104,12 @@ std::string RelocateBinarySections(std::string binary_name, void* bss); /*! - * \brief reads section from binary file - * \param binary_name input binary filename + * \brief reads section from binary + * \param binary input binary contents * \param section section type to be read * \return contents of the section */ -std::string ReadSection(std::string binary_name, SectionKind section); +std::string ReadSection(std::string binary, SectionKind section); /*! * \brief finds size of the section in the binary diff --git a/src/runtime/micro/micro_device_api.cc b/src/runtime/micro/micro_device_api.cc index 2771a14473561..ec246ac12c564 100644 --- a/src/runtime/micro/micro_device_api.cc +++ b/src/runtime/micro/micro_device_api.cc @@ -29,13 +29,13 @@ class MicroDeviceAPI final : public DeviceAPI { size_t alignment, TVMType type_hint) final { // TODO: can make this a private member, but where to best init it? - MicroSession* session = MicroSession::Global(); + std::shared_ptr session = MicroSession::Global(); void* alloc_ptr = session->AllocateInSection(kHeap, nbytes); return alloc_ptr; } void FreeDataSpace(TVMContext ctx, void* ptr) final { - MicroSession* session = MicroSession::Global(); + std::shared_ptr session = MicroSession::Global(); session->FreeInSection(kHeap, ptr); } @@ -48,7 +48,7 @@ class MicroDeviceAPI final : public DeviceAPI { TVMContext ctx_to, TVMType type_hint, TVMStreamHandle stream) final { - MicroSession* session = MicroSession::Global(); + std::shared_ptr session = MicroSession::Global(); uint8_t buffer[size]; constexpr int micro_devtype = kDLMicroDev; std::tuple type_from_to(ctx_from.device_type, ctx_to.device_type); @@ -75,20 +75,20 @@ class MicroDeviceAPI final : public DeviceAPI { } } - // TODO: ignore this? + // TODO(): ignore this? void StreamSync(TVMContext ctx, TVMStreamHandle stream) final { } // TODO: what about ctx? void* AllocWorkspace(TVMContext ctx, size_t size, TVMType type_hint) final { - MicroSession* session = MicroSession::Global(); + std::shared_ptr session = MicroSession::Global(); void* alloc_ptr = session->AllocateInSection(kWorkspace, size); return alloc_ptr; } // TODO: what about ctx? void FreeWorkspace(TVMContext ctx, void* data) final { - MicroSession* session = MicroSession::Global(); + std::shared_ptr session = MicroSession::Global(); session->FreeInSection(kWorkspace, data); } @@ -109,5 +109,5 @@ TVM_REGISTER_GLOBAL("device_api.micro_dev") DeviceAPI* ptr = MicroDeviceAPI::Global().get(); *rv = static_cast(ptr); }); -} // namespace runtime -} // namespace tvm +} // namespace runtime +} // namespace tvm diff --git a/src/runtime/micro/micro_module.cc b/src/runtime/micro/micro_module.cc index 411251f40cbf1..75b9c6c5b5b5c 100644 --- a/src/runtime/micro/micro_module.cc +++ b/src/runtime/micro/micro_module.cc @@ -11,6 +11,7 @@ #include "micro_session.h" #include "low_level_device.h" #include "micro_common.h" +#include "../pack_args.h" namespace tvm { namespace runtime { @@ -32,14 +33,24 @@ class MicroModuleNode final : public ModuleNode { * \brief initializes module by establishing device connection and loads binary * \param binary name of the binary to be loaded */ - void InitMicroModule(const std::string binary); + void InitMicroModule(const std::string binary) { + // TODO: if first MicroModule, then load init section in MicroSession + session_ = MicroSession::Global(); + // TODO: ensure low_level_device_ is initialized in MicroSession + lldevice_ = session_->low_level_device(); + binary_ = binary; + LoadBinary(); + } /*! * \brief runs selected function on the micro device * \param func name of the function to be run + * \param func_addr address of the function to be run * \param args type-erased arguments passed to the function */ - void RunFunction(std::string func, TVMArgs args); + void RunFunction(std::string func, void* func_addr, TVMArgs args) { + session_->PushToExecQueue(func_addr, args); + } private: /*! \brief loaded module text start address */ @@ -49,7 +60,7 @@ class MicroModuleNode final : public ModuleNode { /*! \brief loaded module bss start address */ void* bss_start_; /*! \brief size of module text section */ - size_t code_size_; + size_t text_size_; /*! \brief size of module data section */ size_t data_size_; /*! \brief size of module bss section */ @@ -61,7 +72,27 @@ class MicroModuleNode final : public ModuleNode { /*! \brief low-level device pointer */ std::shared_ptr lldevice_; /*! \brief symbol map to addresses */ - std::unordered_map symbol_map; + std::unordered_map symbol_map_; + + void LoadBinary() { + text_size_ = GetSectionSize(binary_, kText); + data_size_ = GetSectionSize(binary_, kData); + bss_size_ = GetSectionSize(binary_, kBss); + text_start_ = session_->AllocateInSection(kText, text_size_); + data_start_ = session_->AllocateInSection(kData, data_size_); + bss_start_ = session_->AllocateInSection(kBss, bss_size_); + CHECK(text_start_ != nullptr && data_start_ != nullptr && bss_start_ != nullptr) + << "Not enough space to load module on device"; + std::string relocated_bin = RelocateBinarySections(binary_, text_start_, + data_start_, bss_start_); + std::string text_contents = ReadSection(relocated_bin, kText); + std::string data_contents = ReadSection(relocated_bin, kData); + std::string bss_contents = ReadSection(relocated_bin, kBss); + lldevice_->Write(text_start_, &text_contents[0], text_size_); + lldevice_->Write(data_start_, &data_contents[0], data_size_); + lldevice_->Write(bss_start_, &bss_contents[0], bss_size_); + symbol_map_ = GetSymbolMap(relocated_bin); + } }; class MicroWrappedFunc { @@ -74,7 +105,9 @@ class MicroWrappedFunc { func_addr_ = func_addr; } - void operator()(TVMArgs args, TVMRetValue* rv) const { + void operator()(TVMArgs args, TVMRetValue* rv, void** void_args) const { + // no return value yet, but may implement in the future + m_->RunFunction(func_name_, func_addr_, args); } private: @@ -86,10 +119,20 @@ class MicroWrappedFunc { void* func_addr_; }; -// TODO: register module load function +PackedFunc MicroModuleNode::GetFunction( + const std::string& name, + const std::shared_ptr& sptr_to_self) { + void* func_addr = GetSymbol(symbol_map_, name, lldevice_->base_addr()); + MicroWrappedFunc f(this, name, func_addr); + return PackFuncVoidAddr(f, std::vector()); +} + // register loadfile function to load module from Python frontend TVM_REGISTER_GLOBAL("module.loadfile_micro_dev") .set_body([](TVMArgs args, TVMRetValue* rv) { + std::shared_ptr n = std::make_shared(); + n->InitMicroModule(args[0]); + *rv = runtime::Module(n); }); } // namespace runtime } // namespace tvm diff --git a/src/runtime/micro/micro_session.cc b/src/runtime/micro/micro_session.cc index b8654ad0c573b..9ef5601f99027 100644 --- a/src/runtime/micro/micro_session.cc +++ b/src/runtime/micro/micro_session.cc @@ -8,16 +8,267 @@ #include #include "micro_session.h" #include "low_level_device.h" +#include "allocator_stream.h" +#include namespace tvm { namespace runtime { -// TODO: create Python frontend for this + +MicroSession::MicroSession() { + text_allocator_ = new MicroSectionAllocator((void*) kTextStart, + (void*) kDataStart); + data_allocator_ = new MicroSectionAllocator((void*) kDataStart, + (void*) kBssStart); + bss_allocator_ = new MicroSectionAllocator((void*) kBssStart, + (void*) kArgsStart); + args_allocator_ = new MicroSectionAllocator((void*) kArgsStart, + (void*) kStackStart); + stack_allocator_ = new MicroSectionAllocator((void*) kStackStart, + (void*) kHeapStart); + heap_allocator_ = new MicroSectionAllocator((void*) kHeapStart, + (void*) kWorkspaceStart); + workspace_allocator_ = new MicroSectionAllocator((void*) kWorkspaceStart, + (void*) kMemorySize); +} + +void MicroSession::InitSession(TVMArgs args) { + if (args[0] == "host") { + low_level_device_ = HostLowLevelDeviceCreate(kMemorySize); + } else if (args[0] == "openocd") { + low_level_device_ = OpenOCDLowLevelDeviceCreate(args[1]); + } else { + LOG(FATAL) << "Unsupported micro low-level device"; + } + LoadInitStub(); +} + +void* MicroSession::AllocateInSection(SectionKind type, size_t size) { + void* alloc_ptr = nullptr; + switch (type) { + case kText: + alloc_ptr = text_allocator_->Allocate(size); + break; + case kData: + alloc_ptr = data_allocator_->Allocate(size); + break; + case kBss: + alloc_ptr = bss_allocator_->Allocate(size); + break; + case kArgs: + alloc_ptr = args_allocator_->Allocate(size); + break; + case kStack: + alloc_ptr = stack_allocator_->Allocate(size); + break; + case kHeap: + alloc_ptr = heap_allocator_->Allocate(size); + break; + case kWorkspace: + alloc_ptr = workspace_allocator_->Allocate(size); + break; + default: + LOG(FATAL) << "Unsupported section type during allocation"; + } + return alloc_ptr; +} + +void MicroSession::FreeInSection(SectionKind type, void* ptr) { + switch (type) { + case kText: + text_allocator_->Free(ptr); + break; + case kData: + data_allocator_->Free(ptr); + break; + case kBss: + bss_allocator_->Free(ptr); + break; + case kArgs: + args_allocator_->Free(ptr); + break; + case kStack: + stack_allocator_->Free(ptr); + break; + case kHeap: + heap_allocator_->Free(ptr); + break; + case kWorkspace: + workspace_allocator_->Free(ptr); + break; + default: + LOG(FATAL) << "Unsupported section type during free"; + } +} + +void MicroSession::PushToExecQueue(void* func, TVMArgs args) { + AllocateTVMArgs(args); + int num_args = args.num_args; + // TODO: setup init stub args to execute + void* func_addr = GetAddr(func, low_level_device()->base_addr()); + //low_level_device()->Write(GetSymbol("UTVM_task", low_level_device()->base_addr()), + // UTVMMain() + // UTVMTask task + void* func_end = GetSymbol(init_symbol_map_, "UTVMDone", + low_level_device()->base_addr()); + low_level_device()->Execute(func, func_end); +} + +void MicroSession::LoadInitStub() { + // TODO: this is the utvm device binary, probably alright to hard code (need path) + std::string binary = "utvm_runtime.o"; + init_text_size_ = GetSectionSize(binary, kText); + init_data_size_ = GetSectionSize(binary, kData); + init_bss_size_ = GetSectionSize(binary, kBss); + init_text_start_ = AllocateInSection(kText, init_text_size_); + init_data_start_ = AllocateInSection(kData, init_data_size_); + init_bss_start_ = AllocateInSection(kBss, init_bss_size_); + CHECK(init_text_start_ != nullptr && + init_data_start_ != nullptr && + init_bss_start_ != nullptr) + << "Not enough space to load init binary on device"; + std::string relocated_bin = RelocateBinarySections(binary, + init_text_start_, + init_data_start_, + init_bss_start_); + std::string text_contents = ReadSection(relocated_bin, kText); + std::string data_contents = ReadSection(relocated_bin, kData); + std::string bss_contents = ReadSection(relocated_bin, kBss); + low_level_device()->Write(init_text_start_, &text_contents[0], init_text_size_); + low_level_device()->Write(init_data_start_, &data_contents[0], init_data_size_); + low_level_device()->Write(init_bss_start_, &bss_contents[0], init_bss_size_); + init_symbol_map_ = GetSymbolMap(relocated_bin); +} + +// TODO: make target aware write functions for everything +// TODO: these need to be device-based sizeof +// TODO: what about kBytes, kHandle, kNull, kNodeHandle, kArrayHandle, kTVMType, kFuncHandle, kModuleHandle? +void MicroSession::TargetAwareWrite(int64_t val, AllocatorStream* stream) { +} + +void MicroSession::TargetAwareWrite(uint64_t val, AllocatorStream* stream) { +} + +void MicroSession::TargetAwareWrite(double val, AllocatorStream* stream) { +} + +void MicroSession::TargetAwareWrite(const char* val, AllocatorStream* stream) { +} + +void MicroSession::TargetAwareWrite(TVMType val, AllocatorStream* stream) { +} + +void MicroSession::TargetAwareWrite(TVMContext* val, AllocatorStream* stream) { +} + +// TODO: rename based on func arg +void MicroSession::TargetAwareWrite(TVMArray* val, AllocatorStream* stream) { + TVMArray* tarr = (TVMArray*)(values[i].v_handle); + size_t tarr_offset = stream->Allocate(sizeof(TVMArray)); + size_t shape_size = 1; + for (int dim = 0; dim < tarr->ndim; dim++) + shape_size *= tarr->shape[dim]; + size_t shape_offset = stream->Allocate(sizeof(int64_t) * tarr->ndim); + stream->Seek(shape_offset); + stream->Write(tarr->shape, sizeof(int64_t) * tarr->ndim); + size_t strides_offset = 0; + if (tarr->strides != NULL) { + strides_offset = stream->Allocate(sizeof(int64_t) * tarr->ndim); + stream->Seek(strides_offset); + stream->Write(tarr->strides, sizeof(int64_t) * tarr->ndim); + } + stream->Seek(tarr_offset); + stream->Write(tarr, sizeof(TVMArray)); + void* data_addr = (uint8_t*) base_addr + + reinterpret_cast(tarr->data) - + kArgsStart; + void* shape_addr = (uint8_t*) base_addr + shape_offset; + void* strides_addr = NULL; + if (tarr->strides != NULL) + strides_addr = (uint8_t*) base_addr + strides_offset; + stream->Seek(tarr_offset); + stream->Write(&data_addr, sizeof(void*)); + stream->Seek(tarr_offset + sizeof(void*) + sizeof(DLContext) + + sizeof(int) + sizeof(DLDataType)); + stream->Write(&shape_addr, sizeof(void*)); + stream->Write(&strides_addr, sizeof(void*)); + void* tarr_addr = (uint8_t*) base_addr + tarr_offset; + stream->Seek(args_offset + sizeof(TVMValue*) * i); + stream->Write(&tarr_addr, sizeof(void*)); +} + +void MicroSession::AllocateTVMArgs(TVMArgs args) { + std::string args_buf; + AllocatorStream* stream = new AllocatorStream(&args_buf); + // TODO: this needs to be args section base addr, not lldevice base_addr + // but make it generic by allocating a sufficiently large enough region first? + const void* base_addr = low_level_device()->base_addr(); + const TVMValue* values = args.values; + const int* type_codes = args.type_codes; + int num_args = args.num_args; + size_t args_offset = stream->Allocate(sizeof(TVMValue*) * num_args + + sizeof(const int*) * num_args + + sizeof(int)); + stream->Seek(args_offset + sizeof(TVMValue*) * num_args); + stream->Write(type_codes, sizeof(const int*) * num_args); + stream->Write(&num_args, sizeof(int)); + // TODO: implement all cases + for (int i = 0; i < num_args; i++) { + switch(type_codes[i]) { + case kDLInt: + TargetAwareWrite(values[i].v_int64, stream); + break; + case kDLUInt: + // TODO: is this fine? (how is uint passed?) + TargetAwareWrite(values[i].v_int64, stream); + break; + case kDLFloat: + TargetAwareWrite(values[i].v_float64, stream); + break; + case kStr: + TargetAwareWrite(values[i].v_str, stream); + break; + case kBytes: + printf("was bytes\n"); + break; + case kHandle: + printf("was handle\n"); + break; + case kNull: + printf("was null\n"); + break; + case kNodeHandle: + printf("was nodehandle\n"); + break; + case kArrayHandle: + printf("was arrayhandle\n"); + break; + case kTVMType: + TargetAwareWrite(values[i].v_type, stream); + break; + case kTVMContext: + TargetAwareWrite(values[i].v_ctx, stream); + break; + case kFuncHandle: + printf("was funchandle\n"); + break; + case kModuleHandle: + printf("was modulehandle\n"); + break; + case kNDArrayContainer: + TargetAwareWrite((TVMArray*) values[i].v_handle, stream); + break; + default: + LOG(FATAL) << "Could not process type code: " << type_codes[i]; + break; + } + } +} + // initializes micro session and low-level device from Python frontend TVM_REGISTER_GLOBAL("micro.init") .set_body([](TVMArgs args, TVMRetValue* rv) { - // create global micro session - // setup either host or OpenOCD low-level device - // setup init stub + std::shared_ptr session = MicroSession::Global(); + session->InitSession(args); }); } // namespace runtime } // namespace tvm diff --git a/src/runtime/micro/micro_session.h b/src/runtime/micro/micro_session.h index 57c2f01e40e5c..4b5f0fd900eef 100644 --- a/src/runtime/micro/micro_session.h +++ b/src/runtime/micro/micro_session.h @@ -28,21 +28,46 @@ class MicroSectionAllocator { * \param section_start start address of the section * \param section_end end address of the section (non inclusive) */ - MicroSectionAllocator(void* section_start, void* section_end); + MicroSectionAllocator(void* section_start, void* section_end) + : section_start_(section_start), section_end_(section_end), + section_max_(section_start) { + } + + MicroSectionAllocator() {} + + /*! + * \brief destructor + */ + ~MicroSectionAllocator() { + } /*! * \brief memory allocator * \param size size of allocated memory in bytes * \return pointer to allocated memory region in section, nullptr if out of space */ - void* Allocate(size_t size); + void* Allocate(size_t size) { + void* alloc_ptr = nullptr; + if ((uint8_t*) section_max_ + size < (uint8_t *) section_end_) { + alloc_ptr = section_max_; + section_max_ = (uint8_t*) section_max_ + size; + alloc_map_[alloc_ptr] = size; + } + return alloc_ptr; + } /*! * \brief free prior allocation from section * \param type type of section to allocate in * \param ptr pointer to allocated memory + * \note simple allocator scheme, more complex versions will be implemented later */ - void Free(void* ptr); + void Free(void* ptr) { + alloc_map_.erase(ptr); + if (alloc_map_.empty()) { + section_max_ = section_start_; + } + } private: /*! \brief start address of the section */ @@ -57,6 +82,11 @@ class MicroSectionAllocator { class MicroSession { public: + /*! + * \brief constructor + */ + MicroSession(); + /*! * \brief destructor */ @@ -66,7 +96,17 @@ class MicroSession { * \brief get MicroSession global singleton * \return pointer to the micro session global singleton */ - static const MicroSession* Global(); + static std::shared_ptr& Global() { + static std::shared_ptr inst = std::make_shared(); + return inst; + } + + /*! + * \brief initializes session by setting up low_level_device_ + * \param args TVMArgs passed into the micro.init packedfunc + * \note must be called upon first call to Global() + */ + void InitSession(TVMArgs args); /*! * \brief allocate memory in section @@ -102,31 +142,57 @@ class MicroSession { /*! \brief low-level device pointer */ std::shared_ptr low_level_device_; /*! \brief text section allocator */ - MicroSectionAllocator text_allocator_; + MicroSectionAllocator* text_allocator_; /*! \brief data section allocator */ - MicroSectionAllocator data_allocator_; + MicroSectionAllocator* data_allocator_; /*! \brief bss section allocator */ - MicroSectionAllocator bss_allocator_; + MicroSectionAllocator* bss_allocator_; /*! \brief args section allocator */ - MicroSectionAllocator args_allocator_; + MicroSectionAllocator* args_allocator_; /*! \brief stack section allocator */ - MicroSectionAllocator stack_allocator_; + MicroSectionAllocator* stack_allocator_; /*! \brief heap section allocator */ - MicroSectionAllocator heap_allocator_; + MicroSectionAllocator* heap_allocator_; /*! \brief workspace section allocator */ - MicroSectionAllocator workspace_allocator_; + MicroSectionAllocator* workspace_allocator_; + /*! \brief init text start address */ + void* init_text_start_; + /*! \brief init data start address */ + void* init_data_start_; + /*! \brief init bss start address */ + void* init_bss_start_; + /*! \brief size of init text section */ + size_t init_text_size_; + /*! \brief size of init data section */ + size_t init_data_size_; + /*! \brief size of init bss section */ + size_t init_bss_size_; /*! \brief symbol map for init stub */ std::unordered_map init_symbol_map_; /*! * \brief sets up and loads init stub into the low-level device memory */ - void SetupInitStub(); + void LoadInitStub(); /*! * \brief writes arguments to args section using allocator_stream */ void AllocateTVMArgs(TVMArgs args); + + void TargetAwareWrite(int64_t val, AllocatorStream* stream); + + void TargetAwareWrite(uint64_t val, AllocatorStream* stream); + + void TargetAwareWrite(double val, AllocatorStream* stream); + + void TargetAwareWrite(const char* val, AllocatorStream* stream); + + void TargetAwareWrite(TVMType val, AllocatorStream* stream); + + void TargetAwareWrite(TVMContext* val, AllocatorStream* stream); + + void TargetAwareWrite(TVMArray* val, AllocatorStream* stream); }; } // namespace runtime } // namespace tvm diff --git a/tests/python/contrib/test_binutil.py b/tests/python/contrib/test_binutil.py index 38d680932e4a8..2288eb3b3817d 100644 --- a/tests/python/contrib/test_binutil.py +++ b/tests/python/contrib/test_binutil.py @@ -60,14 +60,10 @@ def verify(): def test_tvm_read_binary_section(binary): - tmp_dir = util.tempdir() - tmp_bin = tmp_dir.relpath("obj.bin") - with open(tmp_bin, "wb") as f: - f.write(binary) def verify(): - text_bin = tvm_read_binary_section(tmp_bin, "text") - data_bin = tvm_read_binary_section(tmp_bin, "data") - bss_bin = tvm_read_binary_section(tmp_bin, "bss") + text_bin = tvm_read_binary_section(binary, "text") + data_bin = tvm_read_binary_section(binary, "data") + bss_bin = tvm_read_binary_section(binary, "bss") print("Read text section part of binary? %r" % (text_bin in binary)) print("Read data section part of binary? %r" % (data_bin in binary)) print("Read bss section part of binary? %r" % (bss_bin in binary)) diff --git a/tests/python/unittest/test_runtime_micro.py b/tests/python/unittest/test_runtime_micro.py index 8affc295dcbcf..2a3f2f7f104f7 100644 --- a/tests/python/unittest/test_runtime_micro.py +++ b/tests/python/unittest/test_runtime_micro.py @@ -5,9 +5,12 @@ import numpy as np from tvm.contrib import util +import tvm.micro # adds two arrays and stores result into third array def test_micro_add(): + tvm.module.load("lol", "micro_dev") + ctx = tvm.micro_dev(0) pass if __name__ == "__main__":