From 51f58a9fbb549d00b09dec8240f5a1562c4d3838 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Tue, 8 Jun 2021 08:39:03 +0200 Subject: [PATCH 01/10] Allow export of C++ kernels using correct file extension --- include/tvm/runtime/module.h | 5 +++++ python/tvm/micro/model_library_format.py | 4 +++- python/tvm/runtime/module.py | 12 ++++++++++-- src/runtime/module.cc | 9 +++++++++ src/target/source/source_module.cc | 9 +++++++-- 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/include/tvm/runtime/module.h b/include/tvm/runtime/module.h index 71be8d218d2d..c7753f23bfa6 100644 --- a/include/tvm/runtime/module.h +++ b/include/tvm/runtime/module.h @@ -156,6 +156,11 @@ class TVM_DLL ModuleNode : public Object { * \return Possible source code when available. */ virtual std::string GetSource(const std::string& format = ""); + /*! + * \brief Get the format of module, when available. + * \return Possible format when available. + */ + virtual std::string GetFormat(); /*! * \brief Get packed function from current module by name. * diff --git a/python/tvm/micro/model_library_format.py b/python/tvm/micro/model_library_format.py index f031acec0d76..e498a631cc3d 100644 --- a/python/tvm/micro/model_library_format.py +++ b/python/tvm/micro/model_library_format.py @@ -84,10 +84,12 @@ def _populate_codegen_dir(mod, codegen_dir: str, module_name: str = None): for dso_mod in dso_modules: if dso_mod.type_key == "c": + assert dso_mod.format in ["c", "cc", "cpp"] + ext = dso_mod.format index = mod_indices["src"] mod_indices["src"] += 1 parent_dir = os.path.join(host_codegen_dir, "src") - file_name = os.path.join(parent_dir, f"{lib_name}{index}.c") + file_name = os.path.join(parent_dir, f"{lib_name}{index}.{ext}") elif dso_mod.type_key == "llvm": index = mod_indices["lib"] mod_indices["lib"] += 1 diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 25a57bbb1c36..53be07112e6e 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -185,6 +185,11 @@ def type_key(self): """Get type key of the module.""" return _ffi_api.ModuleGetTypeKey(self) + @property + def format(self): + """Get format of the module.""" + return _ffi_api.ModuleGetFormat(self) + def get_source(self, fmt=""): """Get source code from module, if available. @@ -402,7 +407,8 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No for index, module in enumerate(modules): if fcompile is not None and hasattr(fcompile, "object_format"): if module.type_key == "c": - object_format = "c" + assert module.format in ["c", "cc", "cpp"] + object_format = module.format has_c_module = True else: object_format = fcompile.object_format @@ -412,7 +418,9 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No else: assert module.type_key == "c" object_format = "c" - if "cc" in kwargs: + if module.format in ["cc", "cpp"]: + object_format = module.format + elif "cc" in kwargs: if kwargs["cc"] == "nvcc": object_format = "cu" has_c_module = True diff --git a/src/runtime/module.cc b/src/runtime/module.cc index f9c281ab9d02..f16fbc37a5ff 100644 --- a/src/runtime/module.cc +++ b/src/runtime/module.cc @@ -127,6 +127,11 @@ const PackedFunc* ModuleNode::GetFuncFromEnv(const std::string& name) { } } +std::string ModuleNode::GetFormat() { + LOG(FATAL) << "Module[" << type_key() << "] does not support GetFormat"; + return ""; +} + bool RuntimeEnabled(const std::string& target) { std::string f_name; if (target == "cpu") { @@ -179,6 +184,10 @@ TVM_REGISTER_GLOBAL("runtime.ModuleGetTypeKey").set_body_typed([](Module mod) { return std::string(mod->type_key()); }); +TVM_REGISTER_GLOBAL("runtime.ModuleGetFormat").set_body_typed([](Module mod) { + return mod->GetFormat(); +}); + TVM_REGISTER_GLOBAL("runtime.ModuleLoadFromFile").set_body_typed(Module::LoadFromFile); TVM_REGISTER_GLOBAL("runtime.ModuleSaveToFile") diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 9b93b0726f3a..676e2a551247 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -62,6 +62,8 @@ class SourceModuleNode : public runtime::ModuleNode { std::string GetSource(const std::string& format) final { return code_; } + std::string GetFormat() { return fmt_; } + protected: std::string code_; std::string fmt_; @@ -101,10 +103,12 @@ class CSourceModuleNode : public runtime::ModuleNode { std::string GetSource(const std::string& format) final { return code_; } + std::string GetFormat() { return fmt_; } + void SaveToFile(const std::string& file_name, const std::string& format) final { std::string fmt = GetFileFormat(file_name, format); std::string meta_file = GetMetaFilePath(file_name); - if (fmt == "c" || fmt == "cu") { + if (fmt == "c" || fmt == "cc" || fmt == "cpp" || fmt == "cu") { ICHECK_NE(code_.length(), 0); SaveBinaryToFile(file_name, code_); } else { @@ -138,6 +142,7 @@ class CSourceCrtMetadataModuleNode : public runtime::ModuleNode { std::string GetSource(const std::string& format) final { return code_.str(); } + std::string GetFormat() { return fmt_; } PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { return PackedFunc(nullptr); } @@ -145,7 +150,7 @@ class CSourceCrtMetadataModuleNode : public runtime::ModuleNode { void SaveToFile(const std::string& file_name, const std::string& format) final { std::string fmt = GetFileFormat(file_name, format); std::string meta_file = GetMetaFilePath(file_name); - if (fmt == "c") { + if (fmt == "c" || fmt == "cc" || fmt == "cpp") { auto code_str = code_.str(); ICHECK_NE(code_str.length(), 0); SaveBinaryToFile(file_name, code_str); From d5666ee8315bcbe4a8b1ae74d7a90db4ca40720f Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Mon, 11 Oct 2021 10:13:33 +0200 Subject: [PATCH 02/10] [WIP] Set module_key=c for CSourceCrtMetadataModuleNode to temporarily fix failing tests I realized that the module format `cc` is currently already used by the `CSourceCrtMetadataModuleNode` declared in `src/target/source/source_module.cc`. This needs to be discussed first to decide if either the module_key should be changed or the test cases expecting the systemlib kernel (e.g. `default_lib0.c`) to have a `.c` extension. --- src/target/source/source_module.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 676e2a551247..5eb4a57a7aa8 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -333,7 +333,7 @@ runtime::Module CreateCSourceCrtMetadataModule(const Array& mod } } } - auto n = make_object(func_names, "cc", target, metadata); + auto n = make_object(func_names, "c", target, metadata); auto csrc_metadata_module = runtime::Module(n); for (const auto& mod : modules) { csrc_metadata_module.Import(mod); From 2024bc6b36a53490cd1244cac62a129dc9533aab Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Mon, 11 Oct 2021 10:15:28 +0200 Subject: [PATCH 03/10] Update Makefiles used by tests/python/relay/aot/ to support C++ file extensions AOT: Add c++ support to aot_test.mk AOT: Add c++ support to corstone300.mk --- tests/python/relay/aot/corstone300.mk | 12 +++++++----- tests/python/relay/aot/default.mk | 13 ++++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/python/relay/aot/corstone300.mk b/tests/python/relay/aot/corstone300.mk index 8d03ccc5b5f4..5488ca4d0363 100644 --- a/tests/python/relay/aot/corstone300.mk +++ b/tests/python/relay/aot/corstone300.mk @@ -61,8 +61,10 @@ QUIET ?= @ $(endif) CRT_SRCS = $(shell find $(CRT_ROOT)) -CODEGEN_SRCS = $(shell find $(abspath $(CODEGEN_ROOT)/host/src/*.c)) -CODEGEN_OBJS = $(subst .c,.o,$(CODEGEN_SRCS)) +C_CODEGEN_SRCS = $(shell find $(abspath $(CODEGEN_ROOT)/host/src/*.c)) +CC_CODEGEN_SRCS = $(shell find $(abspath $(CODEGEN_ROOT)/host/src/*.cc)) +C_CODEGEN_OBJS = $(subst .c,.o,$(C_CODEGEN_SRCS)) +CC_CODEGEN_OBJS = $(subst .cc,.o,$(CC_CODEGEN_SRCS)) CMSIS_STARTUP_SRCS = $(shell find ${CMSIS_PATH}/Device/ARM/${ARM_CPU}/Source/*.c) CMSIS_NN_SRCS = $(shell find ${CMSIS_PATH}/CMSIS/NN/Source/*/*.c) UART_SRCS = $(shell find ${PLATFORM_PATH}/*.c) @@ -82,9 +84,9 @@ $(build_dir)/crt_backend_api.o: $(TVM_ROOT)/src/runtime/crt/common/crt_backend_a $(QUIET)mkdir -p $(@D) $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^ -$(build_dir)/libcodegen.a: $(CODEGEN_SRCS) - $(QUIET)cd $(abspath $(CODEGEN_ROOT)/host/src) && $(CC) -c $(PKG_CFLAGS) $(CODEGEN_SRCS) - $(QUIET)$(AR) -cr $(abspath $(build_dir)/libcodegen.a) $(CODEGEN_OBJS) +$(build_dir)/libcodegen.a: $(C_CODEGEN_SRCS) $(CC_CODEGEN_SRCS) + $(QUIET)cd $(abspath $(CODEGEN_ROOT)/host/src) && $(CC) -c $(PKG_CFLAGS) $(C_CODEGEN_SRCS) $(CC_CODEGEN_SRCS) + $(QUIET)$(AR) -cr $(abspath $(build_dir)/libcodegen.a) $(C_CODEGEN_OBJS) $(CC_CODEGEN_OBJS) $(QUIET)$(RANLIB) $(abspath $(build_dir)/libcodegen.a) ${build_dir}/libcmsis_startup.a: $(CMSIS_STARTUP_SRCS) diff --git a/tests/python/relay/aot/default.mk b/tests/python/relay/aot/default.mk index f5edcb3d6422..b7258a3c6df8 100644 --- a/tests/python/relay/aot/default.mk +++ b/tests/python/relay/aot/default.mk @@ -22,6 +22,7 @@ ENABLE_TVM_PLATFORM_ABORT_BACKTRACE = 0 DMLC_CORE=$(TVM_ROOT)/3rdparty/dmlc-core PKG_COMPILE_OPTS = -g CC = gcc +#CC = g++ AR = ar RANLIB = ranlib CC_OPTS = CC=$(CC) AR=$(AR) RANLIB=$(RANLIB) @@ -39,10 +40,12 @@ $(endif) aot_test_runner: $(build_dir)/aot_test_runner -source_libs= $(wildcard $(build_dir)/../codegen/host/src/*.c) -lib_objs =$(source_libs:.c=.o) +c_source_libs= $(wildcard $(build_dir)/../codegen/host/src/*.c) +cc_source_libs= $(wildcard $(build_dir)/../codegen/host/src/*.cc) +c_lib_objs =$(c_source_libs:.c=.o) +cc_lib_objs =$(cc_source_libs:.cc=.o) -$(build_dir)/aot_test_runner: $(build_dir)/test.c $(source_libs) $(build_dir)/stack_allocator.o $(build_dir)/crt_backend_api.o +$(build_dir)/aot_test_runner: $(build_dir)/test.c $(c_source_libs) $(cc_source_libs) $(build_dir)/stack_allocator.o $(build_dir)/crt_backend_api.o $(QUIET)mkdir -p $(@D) $(QUIET)$(CC) $(CFLAGS) $(PKG_CFLAGS) -o $@ $^ $(PKG_LDFLAGS) $(BACKTRACE_LDFLAGS) $(BACKTRACE_CFLAGS) -lm @@ -50,6 +53,10 @@ $(build_dir)/%.o: $(build_dir)/../codegen/host/src/%.c $(QUIET)mkdir -p $(@D) $(QUIET)$(CC) $(CFLAGS) -c $(PKG_CFLAGS) -o $@ $^ $(BACKTRACE_CFLAGS) +$(build_dir)/%.o: $(build_dir)/../codegen/host/src/%.cc + $(QUIET)mkdir -p $(@D) + $(QUIET)$(CC) $(CFLAGS) -c $(PKG_CFLAGS) -o $@ $^ $(BACKTRACE_CFLAGS) + $(build_dir)/stack_allocator.o: $(STANDALONE_CRT_DIR)/src/runtime/crt/memory/stack_allocator.c $(QUIET)mkdir -p $(@D) $(QUIET)$(CC) $(CFLAGS) -c $(PKG_CFLAGS) -o $@ $^ $(BACKTRACE_CFLAGS) From fdfc59e7be7a98236d6999ac9170c33fbdd03bb5 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Thu, 14 Oct 2021 13:00:38 +0200 Subject: [PATCH 04/10] Add missing definition of GetFormat to cmsisnn and ethosn codegens (WIP) --- src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc | 2 ++ src/relay/backend/contrib/ethosu/source_module.cc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc b/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc index fb612e70311b..0fd778349baa 100644 --- a/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc +++ b/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc @@ -81,6 +81,8 @@ class CMSISNNModuleNode : public runtime::ModuleNode { const char* type_key() const { return "c"; } + std::string GetFormat() { return fmt_; } + PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { if (name == "get_symbol") { return PackedFunc( diff --git a/src/relay/backend/contrib/ethosu/source_module.cc b/src/relay/backend/contrib/ethosu/source_module.cc index e3f48bc27617..f7fe4c185567 100644 --- a/src/relay/backend/contrib/ethosu/source_module.cc +++ b/src/relay/backend/contrib/ethosu/source_module.cc @@ -89,6 +89,8 @@ class EthosUModuleNode : public ModuleNode { std::string GetSource(const std::string& format) final { return c_source; } + std::string GetFormat() { return fmt_; } + std::string GetCS() { return cmms_hex; } /*! From 0e7338d9aa1abb4a4c32234532200be6e0cf7343 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Thu, 21 Oct 2021 07:30:41 +0200 Subject: [PATCH 05/10] Resolve PR comments --- include/tvm/runtime/module.h | 2 +- python/tvm/runtime/module.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/tvm/runtime/module.h b/include/tvm/runtime/module.h index c7753f23bfa6..7b5326a44921 100644 --- a/include/tvm/runtime/module.h +++ b/include/tvm/runtime/module.h @@ -157,7 +157,7 @@ class TVM_DLL ModuleNode : public Object { */ virtual std::string GetSource(const std::string& format = ""); /*! - * \brief Get the format of module, when available. + * \brief Get the format of the module, when available. * \return Possible format when available. */ virtual std::string GetFormat(); diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 53be07112e6e..953d6cf626b7 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -187,7 +187,7 @@ def type_key(self): @property def format(self): - """Get format of the module.""" + """Get the format of the module.""" return _ffi_api.ModuleGetFormat(self) def get_source(self, fmt=""): @@ -418,9 +418,9 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No else: assert module.type_key == "c" object_format = "c" - if module.format in ["cc", "cpp"]: - object_format = module.format - elif "cc" in kwargs: + assert module.format in ["c", "cc", "cpp"], "The module.format needs to be either c, cc or cpp" + object_format = module.format + if "cc" in kwargs: if kwargs["cc"] == "nvcc": object_format = "cu" has_c_module = True From 5ffbde077391a68eed429a76ac500f5ba4f4460c Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Thu, 21 Oct 2021 07:44:55 +0200 Subject: [PATCH 06/10] lint python/tvm/runtime/module.py --- python/tvm/runtime/module.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 953d6cf626b7..0af50fbb8114 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -418,7 +418,11 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No else: assert module.type_key == "c" object_format = "c" - assert module.format in ["c", "cc", "cpp"], "The module.format needs to be either c, cc or cpp" + assert module.format in [ + "c", + "cc", + "cpp", + ], "The module.format needs to be either c, cc or cpp" object_format = module.format if "cc" in kwargs: if kwargs["cc"] == "nvcc": From b6100c362bb906c7d02eab8b97acd9f666dfc2b6 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Thu, 21 Oct 2021 08:35:52 +0200 Subject: [PATCH 07/10] fix EthosUModuleNode for CI --- src/relay/backend/contrib/ethosu/source_module.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/relay/backend/contrib/ethosu/source_module.cc b/src/relay/backend/contrib/ethosu/source_module.cc index f7fe4c185567..23354fcaaac8 100644 --- a/src/relay/backend/contrib/ethosu/source_module.cc +++ b/src/relay/backend/contrib/ethosu/source_module.cc @@ -89,7 +89,7 @@ class EthosUModuleNode : public ModuleNode { std::string GetSource(const std::string& format) final { return c_source; } - std::string GetFormat() { return fmt_; } + std::string GetFormat() { return "c"; } std::string GetCS() { return cmms_hex; } From 4158079db19161a994b5300962775506f9f97b1e Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Thu, 21 Oct 2021 12:27:49 +0200 Subject: [PATCH 08/10] Fix: detect empty module.format --- python/tvm/runtime/module.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 0af50fbb8114..77982af9a811 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -417,13 +417,15 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No object_format = "o" else: assert module.type_key == "c" - object_format = "c" - assert module.format in [ - "c", - "cc", - "cpp", - ], "The module.format needs to be either c, cc or cpp" - object_format = module.format + if len(module.format) > 0: + assert module.format in [ + "c", + "cc", + "cpp", + ], "The module.format needs to be either c, cc or cpp" + object_format = module.format + else: + object_format = "c" if "cc" in kwargs: if kwargs["cc"] == "nvcc": object_format = "cu" From 2daf5bb78768afca8f49697d2c09ca8c267d6f51 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Mon, 10 Jan 2022 11:25:22 +0100 Subject: [PATCH 09/10] Add error message to assertion --- python/tvm/runtime/module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 77982af9a811..60002eaaa0c0 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -407,7 +407,7 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No for index, module in enumerate(modules): if fcompile is not None and hasattr(fcompile, "object_format"): if module.type_key == "c": - assert module.format in ["c", "cc", "cpp"] + assert module.format in ["c", "cc", "cpp"], "The module.format needs to be either c, cc or cpp" object_format = module.format has_c_module = True else: From b1d9a5e03c8490802116884f1f380f4db071a053 Mon Sep 17 00:00:00 2001 From: Philipp van Kempen Date: Mon, 10 Jan 2022 12:31:52 +0100 Subject: [PATCH 10/10] Lint python/tvm/runtime/module.py --- python/tvm/runtime/module.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/tvm/runtime/module.py b/python/tvm/runtime/module.py index 60002eaaa0c0..37bab4a9b714 100644 --- a/python/tvm/runtime/module.py +++ b/python/tvm/runtime/module.py @@ -407,7 +407,11 @@ def export_library(self, file_name, fcompile=None, addons=None, workspace_dir=No for index, module in enumerate(modules): if fcompile is not None and hasattr(fcompile, "object_format"): if module.type_key == "c": - assert module.format in ["c", "cc", "cpp"], "The module.format needs to be either c, cc or cpp" + assert module.format in [ + "c", + "cc", + "cpp", + ], "The module.format needs to be either c, cc or cpp" object_format = module.format has_c_module = True else: