You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by me...@apache.org on 2022/09/21 17:48:24 UTC

[tvm] 01/01: address comments

This is an automated email from the ASF dual-hosted git repository.

mehrdadh pushed a commit to branch micro/update_project_options
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit 4c921e3ff5bf4e157e35eb33384c54cc604dc9ad
Author: Mehrdad Hessar <mh...@octoml.ai>
AuthorDate: Wed Sep 21 10:43:47 2022 -0700

    address comments
---
 .../arduino/template_project/Makefile.template     |  21 ++--
 .../template_project/microtvm_api_server.py        | 109 ++++++++++++---------
 python/tvm/micro/project_api/server.py             |  21 +---
 3 files changed, 80 insertions(+), 71 deletions(-)

diff --git a/apps/microtvm/arduino/template_project/Makefile.template b/apps/microtvm/arduino/template_project/Makefile.template
index 7a51f6adae..a22bd25300 100644
--- a/apps/microtvm/arduino/template_project/Makefile.template
+++ b/apps/microtvm/arduino/template_project/Makefile.template
@@ -15,7 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-MAKE_DIR		    := $(PWD)
 FQBN			    ?= <FQBN>
 VERBOSE_FLAG	    ?= <VERBOSE_FLAG>
 BUILD_DIR		    := $(subst :,.,build)
@@ -28,12 +27,13 @@ SRC        	:= $(wildcard *.ino)
 BIN        	:= $(BUILD_DIR)/$(SRC).bin
 ELF        	:= $(BUILD_DIR)/$(SRC).elf
 
-$(info FQBN			is [${FQBN}])
-$(info MAKE_DIR		is [${MAKE_DIR}])
-$(info BUILD_DIR	is [${BUILD_DIR}])
-$(info SRC			is [${SRC}])
-$(info BIN			is [${BIN}])
-$(info PORT			is [${PORT}])
+$(info FQBN                 `fully qualified board name` => [${FQBN}])
+$(info BUILD_DIR            `build directory for this project` => [${BUILD_DIR}])
+$(info SRC                  `Arduino .ino file for this project` => [${SRC}])
+$(info BIN                  `generated binary file path` => [${BIN}])
+$(info PORT                 `board's port` => [${PORT}])
+$(info BOARD                `board name` => [${BOARD}])
+$(info BUILD_EXTRA_FLAGS    `build extra flags including header include directories and other compiler flags` => [${BUILD_EXTRA_FLAGS}])
 
 all: $(ELF) flash
 .PHONY: all
@@ -53,5 +53,12 @@ flash:
 	else $(ARUINO_CLI_CMD) upload --fqbn $(FQBN) --input-dir $(BUILD_DIR) --port $(PORT) $(VERBOSE_FLAG); \
 	fi
 
+info:
+	$(info --------------------------------------INFO--------------------------------------)
+	$(info This makefile is for building and flashing an Arduino project with TVM.)
+	$(info To build run: `make build`)
+	$(info To upload the sketch run: `make flash PORT=<Arduino board port path>`)
+	$(info --------------------------------------INFO--------------------------------------)
+
 clean:
 	rm -rf build
diff --git a/apps/microtvm/arduino/template_project/microtvm_api_server.py b/apps/microtvm/arduino/template_project/microtvm_api_server.py
index f75983bcc2..8de0bef47c 100644
--- a/apps/microtvm/arduino/template_project/microtvm_api_server.py
+++ b/apps/microtvm/arduino/template_project/microtvm_api_server.py
@@ -161,12 +161,6 @@ class Handler(server.ProjectAPIHandler):
         "src/runtime/crt/tab",
     ]
 
-    FQBN_TOKEN = "<FQBN>"
-    VERBOSE_FLAG_TOKEN = "<VERBOSE_FLAG>"
-    ARUINO_CLI_CMD_TOKEN = "<ARUINO_CLI_CMD>"
-    BOARD_TOKEN = "<BOARD>"
-    BUILD_EXTRA_FLAGS_TOKEN = "<BUILD_EXTRA_FLAGS>"
-
     def _remove_unused_components(self, source_dir, project_type):
         unused_components = []
         if project_type == "example_project":
@@ -304,43 +298,80 @@ class Handler(server.ProjectAPIHandler):
         # It's probably a standard C/C++ header
         return include_path
 
-    def _cmsis_required(self, project_path: Union[str, pathlib.Path]) -> bool:
+    CMSIS_INCLUDE_HEADERS = [
+        "arm_nn_math_types.h",
+        "arm_nn_tables.h",
+        "arm_nn_types.h",
+        "arm_nnfunctions.h",
+        "arm_nnsupportfunctions.h",
+    ]
+
+    def _cmsis_required(self, project_path: pathlib.Path) -> bool:
         """Check if CMSIS dependency is required."""
         project_path = pathlib.Path(project_path)
         for path in (project_path / "src" / "model").iterdir():
             if path.is_file():
+                # Encoding is for reading C generated code which also includes hex numbers
                 with open(path, "r", encoding="ISO-8859-1") as lib_f:
                     lib_content = lib_f.read()
-                if any(
-                    header in lib_content
-                    for header in [
-                        "<arm_nnsupportfunctions.h>",
-                        "arm_nn_types.h",
-                        "arm_nnfunctions.h",
-                    ]
-                ):
+                if any(header in lib_content for header in self.CMSIS_INCLUDE_HEADERS):
                     return True
         return False
 
-    def _copy_cmsis(self, project_path: Union[str, pathlib.Path], cmsis_path: str):
+    def _copy_cmsis(self, project_path: pathlib.Path, cmsis_path: str):
         """Copy CMSIS header files to project.
         Note: We use this CMSIS package:https://www.arduino.cc/reference/en/libraries/arduino_cmsis-dsp/
         However, the latest release does not include header files that are copied in this function.
         """
         (project_path / "include" / "cmsis").mkdir()
         cmsis_path = get_cmsis_path(cmsis_path)
-        for item in [
-            "arm_nn_types.h",
-            "arm_nn_tables.h",
-            "arm_nnsupportfunctions.h",
-            "arm_nn_math_types.h",
-            "arm_nnfunctions.h",
-        ]:
+        for item in self.CMSIS_INCLUDE_HEADERS:
             shutil.copy2(
                 cmsis_path / "CMSIS" / "NN" / "Include" / item,
                 project_path / "include" / "cmsis" / item,
             )
 
+    # These tokens are used in the Makefile.template file.
+    # They are replaced with proper value in generate_project step.
+    FQBN_TOKEN = "<FQBN>"
+    VERBOSE_FLAG_TOKEN = "<VERBOSE_FLAG>"
+    ARUINO_CLI_CMD_TOKEN = "<ARUINO_CLI_CMD>"
+    BOARD_TOKEN = "<BOARD>"
+    BUILD_EXTRA_FLAGS_TOKEN = "<BUILD_EXTRA_FLAGS>"
+
+    def _populate_makefile(
+        self,
+        makefile_template_path: pathlib.Path,
+        makefile_path: pathlib.Path,
+        board: str,
+        verbose: bool,
+        arduino_cli_cmd: str,
+        build_extra_flags: str,
+    ):
+        """Generate Makefile from template."""
+        with open(makefile_path, "w") as makefile_f:
+            with open(makefile_template_path, "r") as makefile_template_f:
+                for line in makefile_template_f:
+                    if self.FQBN_TOKEN in line:
+                        line = line.replace(self.FQBN_TOKEN, self._get_fqbn(board))
+
+                    if self.VERBOSE_FLAG_TOKEN in line:
+                        if verbose:
+                            flag = "--verbose"
+                        else:
+                            flag = ""
+                        line = line.replace(self.VERBOSE_FLAG_TOKEN, flag)
+                    if self.ARUINO_CLI_CMD_TOKEN in line:
+                        line = line.replace(
+                            self.ARUINO_CLI_CMD_TOKEN, self._get_arduino_cli_cmd(arduino_cli_cmd)
+                        )
+                    if self.BOARD_TOKEN in line:
+                        line = line.replace(self.BOARD_TOKEN, board)
+                    if self.BUILD_EXTRA_FLAGS_TOKEN in line:
+                        line = line.replace(self.BUILD_EXTRA_FLAGS_TOKEN, build_extra_flags)
+
+                    makefile_f.write(line)
+
     def generate_project(self, model_library_format_path, standalone_crt_dir, project_dir, options):
         # List all used project options
         board = options["board"]
@@ -393,28 +424,14 @@ class Handler(server.ProjectAPIHandler):
             self._copy_cmsis(project_dir, cmsis_path)
 
         # Populate Makefile
-        with open(project_dir / MAKEFILE_FILENAME, "w") as makefile_f:
-            with open(API_SERVER_DIR / f"{MAKEFILE_FILENAME}.template", "r") as makefile_template_f:
-                for line in makefile_template_f:
-                    if self.FQBN_TOKEN in line:
-                        line = line.replace(self.FQBN_TOKEN, self._get_fqbn(board))
-
-                    if self.VERBOSE_FLAG_TOKEN in line:
-                        if verbose:
-                            flag = "--verbose"
-                        else:
-                            flag = ""
-                        line = line.replace(self.VERBOSE_FLAG_TOKEN, flag)
-                    if self.ARUINO_CLI_CMD_TOKEN in line:
-                        line = line.replace(
-                            self.ARUINO_CLI_CMD_TOKEN, self._get_arduino_cli_cmd(arduino_cli_cmd)
-                        )
-                    if self.BOARD_TOKEN in line:
-                        line = line.replace(self.BOARD_TOKEN, board)
-                    if self.BUILD_EXTRA_FLAGS_TOKEN in line:
-                        line = line.replace(self.BUILD_EXTRA_FLAGS_TOKEN, build_extra_flags)
-
-                    makefile_f.write(line)
+        self._populate_makefile(
+            API_SERVER_DIR / f"{MAKEFILE_FILENAME}.template",
+            project_dir / MAKEFILE_FILENAME,
+            board,
+            verbose,
+            arduino_cli_cmd,
+            build_extra_flags,
+        )
 
     def _get_arduino_cli_cmd(self, arduino_cli_cmd: str):
         if not arduino_cli_cmd:
@@ -526,7 +543,7 @@ class Handler(server.ProjectAPIHandler):
         with open(makefile_path) as makefile_f:
             line = makefile_f.readline()
             if "BOARD" in line:
-                board = line.replace(" ", "").replace("\n", "").replace("\r", "").split(":=")[1]
+                board = re.sub(r"\s", "", line).split(":=")[1]
                 return board
         raise RuntimeError("Board was not found in Makefile: {}".format(makefile_path))
 
diff --git a/python/tvm/micro/project_api/server.py b/python/tvm/micro/project_api/server.py
index e36cd0c699..a354abf5e9 100644
--- a/python/tvm/micro/project_api/server.py
+++ b/python/tvm/micro/project_api/server.py
@@ -64,25 +64,10 @@ class ProjectOption(_ProjectOption):
 
         return super().__new__(cls, **kw)
 
-    def replace(self, **kw):
+    def replace(self, kw):
         """Update attributes associated to the project option."""
         updated_option = self
-        for key, val in kw.items():
-            if key == "choices":
-                updated_option = updated_option._replace(choices=val)
-            elif key == "default":
-                updated_option = updated_option._replace(default=val)
-            elif key == "type":
-                updated_option = updated_option._replace(type=val)
-            elif key == "required":
-                updated_option = updated_option._replace(required=val)
-            elif key == "optional":
-                updated_option = updated_option._replace(optional=val)
-            elif key == "help":
-                updated_option = updated_option._replace(help=val)
-            else:
-                raise ValueError("Attribute {} is not supported.".format(key))
-        return updated_option
+        return updated_option._replace(**kw)
 
 
 ServerInfo = collections.namedtuple(
@@ -832,7 +817,7 @@ def default_project_options(**kw) -> typing.List[ProjectOption]:
         option_found = False
         for ind, option in enumerate(options):
             if option.name == name:
-                options[ind] = option.replace(**config)
+                options[ind] = option.replace(config)
                 option_found = True
                 break
         if not option_found: