areusch commented on a change in pull request #9229:
URL: https://github.com/apache/tvm/pull/9229#discussion_r727495939



##########
File path: apps/microtvm/zephyr/template_project/microtvm_api_server.py
##########
@@ -229,40 +229,69 @@ def _get_nrf_device_args(options):
 PROJECT_OPTIONS = [
     server.ProjectOption(
         "extra_files_tar",
+        optional=["generate_project"],
+        type="str",
         help="If given, during generate_project, uncompress the tarball at 
this path into the project dir.",
     ),
     server.ProjectOption(
-        "gdbserver_port", help=("If given, port number to use when running the 
local gdbserver.")
+        "gdbserver_port",
+        help=("If given, port number to use when running the local 
gdbserver."),
+        optional=["open_transport"],
+        type="int",
     ),
     server.ProjectOption(
         "nrfjprog_snr",
+        optional=["open_transport"],
+        type="int",
         help=("When used with nRF targets, serial # of the attached board to 
use, from nrfjprog."),
     ),
     server.ProjectOption(
         "openocd_serial",
+        optional=["open_transport"],
+        type="int",
         help=("When used with OpenOCD targets, serial # of the attached board 
to use."),
     ),
     server.ProjectOption(
         "project_type",
-        help="Type of project to generate.",
         choices=tuple(PROJECT_TYPES),
+        required=["generate_project"],
+        type="str",
+        help="Type of project to generate.",
+    ),
+    server.ProjectOption(
+        "verbose",
+        optional=["build"],
+        help="Run build with verbose output.",
+        type="bool",
     ),
-    server.ProjectOption("verbose", help="Run build with verbose output.", 
choices=(True, False)),
     server.ProjectOption(
         "west_cmd",
+        optional=["generate_project"],
+        default="python3 -m west",

Review comment:
       is this needed? prefer `sys.executable` if possible

##########
File path: python/tvm/driver/tvmc/common.py
##########
@@ -520,3 +522,84 @@ def parse_configs(input_configs):
         pass_context_configs[name] = parsed_value
 
     return pass_context_configs
+
+
+def get_project_options(project_info):

Review comment:
       can you add docstring and type annotation if possible?

##########
File path: python/tvm/driver/tvmc/micro.py
##########
@@ -0,0 +1,278 @@
+# 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
+import shutil
+from pathlib import Path
+from collections import defaultdict
+import argparse
+
+import tvm.micro.project as project
+from tvm.micro.project_api.server import ServerError
+from .main import register_parser
+from .common import (
+    TVMCException,
+    get_project_options,
+    get_options,
+    check_options,
+    check_options_choices,
+)
+from .fmtopt import format_option
+
+
+TVM_HOME = os.getenv("TVM_HOME")
+
+
+ZEPHYR_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/zephyr/template_project"
+ARDUINO_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/arduino/template_project"
+
+
+TEMPLATES = {
+    "zephyr": ZEPHYR_TEMPLATE_DIR,
+    "arduino": ARDUINO_TEMPLATE_DIR,
+}
+
+
+@register_parser
+def add_micro_parser(subparsers, main_parser):
+    micro = subparsers.add_parser("micro", help="select micro context.")
+    micro.set_defaults(func=drive_micro)
+
+    micro_parser = micro.add_subparsers(title="subcommands")
+    # Selecting a subcommand under 'micro' is mandatory
+    micro_parser.required = True
+    micro_parser.dest = "subcommand"  # options available to select
+
+    # 'create_project' subcommand
+    create_project_parser = micro_parser.add_parser(
+        "create-project", help="create a project template of a given type or 
given a template dir."
+    )
+    
create_project_parser.set_defaults(subcommand_handler=create_project_handler)
+    create_project_parser.add_argument(
+        "PROJECT_DIR",
+        help="Project dir where the new project based on the template dir will 
be created.",
+    )
+    create_project_parser.add_argument("MLF", help="MLF .tar archive.")
+    create_project_parser.add_argument(
+        "-f",
+        "--force",
+        action="store_true",
+        help="force project creating even if the specified PROJECT_DIR already 
exists.",
+    )
+
+    # 'build' subcommand
+    build_parser = micro_parser.add_parser(
+        "build",
+        help="build a project dir, generally creating an image to be flashed, 
e.g. zephyr.elf.",
+    )
+    build_parser.set_defaults(subcommand_handler=build_handler)
+    build_parser.add_argument("PROJECT_DIR", help="Project dir to build.")
+    build_parser.add_argument("-f", "--force", action="store_true", 
help="Force rebuild.")
+
+    # 'flash' subcommand
+    flash_parser = micro_parser.add_parser(
+        "flash", help="flash the built image on a given micro target."
+    )
+    flash_parser.set_defaults(subcommand_handler=flash_handler)
+    flash_parser.add_argument("PROJECT_DIR", help="Project dir with a image 
built.")
+
+    # TODO(gromero): list and select serial when multiple devices exist
+    # It's not clear yet if the device list should be determined by TVMC or 
returned by the Project API
+
+    # For each platform add arguments detected automatically using Project API 
info query.
+
+    # Create subparsers for the platforms under 'create-project', 'build', and 
'flash' subcommands first.
+    help_msg = "you must selected a platform from the list. You can pass '-h' 
for a selected platform to list its options."
+    create_project_platforms_parser = create_project_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+    build_platforms_parser = build_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+    flash_platforms_parser = flash_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+
+    # Map used to map a API method to proper CLI parsers and handlers.
+    #           API method          parser                           handler   
              smbcmd domain
+    subcmds = {
+        "generate_project": [create_project_platforms_parser, 
create_project_handler],
+        "build": [build_platforms_parser, build_handler],
+        "flash": [flash_platforms_parser, flash_handler],
+    }
+
+    # Helper to add a platform to a subcmd parser.
+    def _add_parser(parser, platform):
+        platform_name = platform[0].upper() + platform[1:] + " platform"
+        o = parser.add_parser(platform, add_help=False, help=f"select 
{platform_name}.")
+        o.set_defaults(platform=platform)
+        return o
+
+    parser_by_subcmd = {}
+    for subcmd, o in subcmds.items():
+        parser_by_platform = {}
+        o[0].required = True  # Selecting a platform/template is mandatory
+        for platform in TEMPLATES:
+            new_parser = _add_parser(o[0], platform)
+            parser_by_platform[platform] = new_parser
+
+        new_parser = o[0].add_parser("template", add_help=False, help="select 
an adhoc template.")
+        new_parser.add_argument(
+            "-d", metavar="TEMPLATE_DIR", required=True, help="project API 
template directory."
+        )
+        new_parser.set_defaults(platform="template")
+        parser_by_platform["template"] = new_parser
+
+        parser_by_subcmd[subcmd] = parser_by_platform
+
+    known_args, unkown_args = main_parser.parse_known_args()
+
+    try:
+        subcmd = known_args.subcommand
+        platform = known_args.platform
+    except AttributeError:
+        # No subcommand or platform, so not need to augment the parser.
+        return
+
+    # Augment parser with project options
+
+    if platform == "template":
+        # adhoc template
+        template_dir = known_args.d
+    else:
+        # default template
+        template_dir = TEMPLATES[platform]
+
+    template = project.TemplateProject.from_directory(template_dir)
+    template_info = template.info()
+
+    options_by_method = get_project_options(template_info)
+
+    # TODO(gromero): refactor to remove this map.
+    subcmd_to_method = {
+        "create-project": "generate_project",
+        "build": "build",
+        "flash": "flash",
+    }
+
+    method = subcmd_to_method[subcmd]
+    parser_by_subcmd_n_platform = parser_by_subcmd[method][platform]
+    _, handler = subcmds[method]
+
+    parser_by_subcmd_n_platform.formatter_class = (
+        argparse.RawTextHelpFormatter
+    )  # Set raw help text so help_text format works
+    parser_by_subcmd_n_platform.set_defaults(
+        subcommand_handler=handler,
+        valid_options=options_by_method[method],
+        template_dir=template_dir,
+    )
+
+    parser_by_subcmd_n_platform.add_argument(
+        "--list-options",
+        action="help",
+        help="show all options/values for selected platforms/template.",
+    )
+
+    required = any([opt["required"] for opt in options_by_method[method]])
+    nargs = "+" if required else "*"
+
+    help_text_by_option = [opt["help_text"] for opt in 
options_by_method[method]]
+    help_text = "\n\n".join(help_text_by_option) + "\n\n"
+
+    # TODO(gromero): Experiment with required=required below
+    parser_by_subcmd_n_platform.add_argument(
+        "-o", required=True, metavar="OPTION=VALUE", nargs=nargs, 
help=help_text

Review comment:
       i might suggest adding --project-option as an arg name to keep the code 
more readable

##########
File path: python/tvm/driver/tvmc/common.py
##########
@@ -520,3 +522,84 @@ def parse_configs(input_configs):
         pass_context_configs[name] = parsed_value
 
     return pass_context_configs
+
+
+def get_project_options(project_info):
+    options = project_info["project_options"]
+
+    options_by_method = defaultdict(list)
+    for opt in options:
+        # Get list of methods associated with an option based on the
+        # existance of a 'required' or 'optional' lists. API specification
+        # guarantees at least one of these lists will exist. If a list does
+        # not exist it's returned as None by the API.
+        metadata = ["required", "optional"]
+        om = [(opt[md], True if md == "required" else False) for md in 
metadata if opt[md]]
+        for methods, is_opt_required in om:
+            for method in methods:
+                name = opt["name"]
+
+                if opt["type"] == "bool":
+                    # TODO(gromero): Use only choices= and merge with non-bool 
options below
+                    option_choices_text = f"{name}={{true, false}}"

Review comment:
       it might be a bit cleaner to just set `choices = ["true", "false"]` and 
reuse the logic below.

##########
File path: apps/microtvm/zephyr/template_project/microtvm_api_server.py
##########
@@ -229,40 +229,69 @@ def _get_nrf_device_args(options):
 PROJECT_OPTIONS = [
     server.ProjectOption(
         "extra_files_tar",
+        optional=["generate_project"],
+        type="str",

Review comment:
       i think use just `str` not `"str"` here and elsewhere

##########
File path: python/tvm/driver/tvmc/fmtopt.py
##########
@@ -0,0 +1,70 @@
+# 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.
+
+from textwrap import TextWrapper
+
+
+def format_option(option_text, help_text, required=True):
+    # Maximum column length starting at the option name.
+    COL_LEN = 80
+
+    # Extract option name (option name + '=' char, i.e. '=' is part of what
+    # is considered here 'optname') plus its length for choices and help
+    # text justification.
+    optname_break = option_text.find("=")

Review comment:
       cleaner: `optname, chioces_text = option_text.split("=", 1)`

##########
File path: python/tvm/driver/tvmc/fmtopt.py
##########
@@ -0,0 +1,70 @@
+# 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.
+
+from textwrap import TextWrapper
+
+
+def format_option(option_text, help_text, required=True):
+    # Maximum column length starting at the option name.
+    COL_LEN = 80

Review comment:
       move this to module scope

##########
File path: python/tvm/driver/tvmc/micro.py
##########
@@ -0,0 +1,278 @@
+# 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
+import shutil
+from pathlib import Path
+from collections import defaultdict
+import argparse
+
+import tvm.micro.project as project
+from tvm.micro.project_api.server import ServerError
+from .main import register_parser
+from .common import (
+    TVMCException,
+    get_project_options,
+    get_options,
+    check_options,
+    check_options_choices,
+)
+from .fmtopt import format_option
+
+
+TVM_HOME = os.getenv("TVM_HOME")
+
+
+ZEPHYR_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/zephyr/template_project"
+ARDUINO_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/arduino/template_project"
+
+
+TEMPLATES = {
+    "zephyr": ZEPHYR_TEMPLATE_DIR,
+    "arduino": ARDUINO_TEMPLATE_DIR,
+}
+
+
+@register_parser
+def add_micro_parser(subparsers, main_parser):
+    micro = subparsers.add_parser("micro", help="select micro context.")
+    micro.set_defaults(func=drive_micro)
+
+    micro_parser = micro.add_subparsers(title="subcommands")
+    # Selecting a subcommand under 'micro' is mandatory
+    micro_parser.required = True
+    micro_parser.dest = "subcommand"  # options available to select
+
+    # 'create_project' subcommand
+    create_project_parser = micro_parser.add_parser(
+        "create-project", help="create a project template of a given type or 
given a template dir."
+    )
+    
create_project_parser.set_defaults(subcommand_handler=create_project_handler)
+    create_project_parser.add_argument(
+        "PROJECT_DIR",

Review comment:
       slight preference for lowercase param names but curious on your take?

##########
File path: python/tvm/driver/tvmc/micro.py
##########
@@ -0,0 +1,278 @@
+# 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
+import shutil
+from pathlib import Path
+from collections import defaultdict
+import argparse
+
+import tvm.micro.project as project
+from tvm.micro.project_api.server import ServerError
+from .main import register_parser
+from .common import (
+    TVMCException,
+    get_project_options,
+    get_options,
+    check_options,
+    check_options_choices,
+)
+from .fmtopt import format_option
+
+
+TVM_HOME = os.getenv("TVM_HOME")
+
+
+ZEPHYR_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/zephyr/template_project"
+ARDUINO_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/arduino/template_project"
+
+
+TEMPLATES = {
+    "zephyr": ZEPHYR_TEMPLATE_DIR,
+    "arduino": ARDUINO_TEMPLATE_DIR,
+}
+
+
+@register_parser
+def add_micro_parser(subparsers, main_parser):
+    micro = subparsers.add_parser("micro", help="select micro context.")
+    micro.set_defaults(func=drive_micro)
+
+    micro_parser = micro.add_subparsers(title="subcommands")
+    # Selecting a subcommand under 'micro' is mandatory
+    micro_parser.required = True
+    micro_parser.dest = "subcommand"  # options available to select
+
+    # 'create_project' subcommand
+    create_project_parser = micro_parser.add_parser(
+        "create-project", help="create a project template of a given type or 
given a template dir."
+    )
+    
create_project_parser.set_defaults(subcommand_handler=create_project_handler)
+    create_project_parser.add_argument(
+        "PROJECT_DIR",
+        help="Project dir where the new project based on the template dir will 
be created.",
+    )
+    create_project_parser.add_argument("MLF", help="MLF .tar archive.")

Review comment:
       spell out the acronym in the help

##########
File path: apps/microtvm/zephyr/template_project/microtvm_api_server.py
##########
@@ -229,40 +229,69 @@ def _get_nrf_device_args(options):
 PROJECT_OPTIONS = [
     server.ProjectOption(
         "extra_files_tar",
+        optional=["generate_project"],
+        type="str",
         help="If given, during generate_project, uncompress the tarball at 
this path into the project dir.",
     ),
     server.ProjectOption(
-        "gdbserver_port", help=("If given, port number to use when running the 
local gdbserver.")
+        "gdbserver_port",
+        help=("If given, port number to use when running the local 
gdbserver."),
+        optional=["open_transport"],
+        type="int",
     ),
     server.ProjectOption(
         "nrfjprog_snr",
+        optional=["open_transport"],
+        type="int",
         help=("When used with nRF targets, serial # of the attached board to 
use, from nrfjprog."),
     ),
     server.ProjectOption(
         "openocd_serial",
+        optional=["open_transport"],
+        type="int",
         help=("When used with OpenOCD targets, serial # of the attached board 
to use."),
     ),
     server.ProjectOption(
         "project_type",
-        help="Type of project to generate.",
         choices=tuple(PROJECT_TYPES),
+        required=["generate_project"],
+        type="str",
+        help="Type of project to generate.",
+    ),
+    server.ProjectOption(
+        "verbose",
+        optional=["build"],
+        help="Run build with verbose output.",
+        type="bool",
     ),
-    server.ProjectOption("verbose", help="Run build with verbose output.", 
choices=(True, False)),
     server.ProjectOption(
         "west_cmd",
+        optional=["generate_project"],
+        default="python3 -m west",
+        type="str",
         help=(
             "Path to the west tool. If given, supersedes both the zephyr_base "
             "option and ZEPHYR_BASE environment variable."
         ),
     ),
-    server.ProjectOption("zephyr_base", help="Path to the zephyr base 
directory."),
+    server.ProjectOption(
+        "zephyr_base",
+        optional=["build", "open_transport"],
+        default="ZEPHYR_BASE",

Review comment:
       why this default?

##########
File path: python/tvm/driver/tvmc/runner.py
##########
@@ -404,16 +513,24 @@ def run_module(
         dev = session.vulkan()
     elif device == "rocm":
         dev = session.rocm()
+    elif device == "micro":
+        dev = session.device
+        lib = session.get_system_lib()
     else:
         assert device == "cpu"
         dev = session.cpu()
 
+    # TODO(gromero): Adjust for micro targets.

Review comment:
       can you explain more?

##########
File path: src/runtime/rpc/rpc_module.cc
##########
@@ -164,7 +164,7 @@ class RPCModuleNode final : public ModuleNode {
   ~RPCModuleNode() {
     if (module_handle_ != nullptr) {
       try {
-        sess_->FreeHandle(module_handle_, kTVMModuleHandle);
+        // sess_->FreeHandle(module_handle_, kTVMModuleHandle);

Review comment:
       nit: uncomment

##########
File path: python/tvm/driver/tvmc/micro.py
##########
@@ -0,0 +1,278 @@
+# 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
+import shutil
+from pathlib import Path
+from collections import defaultdict
+import argparse
+
+import tvm.micro.project as project
+from tvm.micro.project_api.server import ServerError
+from .main import register_parser
+from .common import (
+    TVMCException,
+    get_project_options,
+    get_options,
+    check_options,
+    check_options_choices,
+)
+from .fmtopt import format_option
+
+
+TVM_HOME = os.getenv("TVM_HOME")
+
+
+ZEPHYR_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/zephyr/template_project"
+ARDUINO_TEMPLATE_DIR = TVM_HOME + "/apps/microtvm/arduino/template_project"
+
+
+TEMPLATES = {
+    "zephyr": ZEPHYR_TEMPLATE_DIR,
+    "arduino": ARDUINO_TEMPLATE_DIR,
+}
+
+
+@register_parser
+def add_micro_parser(subparsers, main_parser):
+    micro = subparsers.add_parser("micro", help="select micro context.")
+    micro.set_defaults(func=drive_micro)
+
+    micro_parser = micro.add_subparsers(title="subcommands")
+    # Selecting a subcommand under 'micro' is mandatory
+    micro_parser.required = True
+    micro_parser.dest = "subcommand"  # options available to select
+
+    # 'create_project' subcommand
+    create_project_parser = micro_parser.add_parser(
+        "create-project", help="create a project template of a given type or 
given a template dir."
+    )
+    
create_project_parser.set_defaults(subcommand_handler=create_project_handler)
+    create_project_parser.add_argument(
+        "PROJECT_DIR",
+        help="Project dir where the new project based on the template dir will 
be created.",
+    )
+    create_project_parser.add_argument("MLF", help="MLF .tar archive.")
+    create_project_parser.add_argument(
+        "-f",
+        "--force",
+        action="store_true",
+        help="force project creating even if the specified PROJECT_DIR already 
exists.",
+    )
+
+    # 'build' subcommand
+    build_parser = micro_parser.add_parser(
+        "build",
+        help="build a project dir, generally creating an image to be flashed, 
e.g. zephyr.elf.",
+    )
+    build_parser.set_defaults(subcommand_handler=build_handler)
+    build_parser.add_argument("PROJECT_DIR", help="Project dir to build.")
+    build_parser.add_argument("-f", "--force", action="store_true", 
help="Force rebuild.")
+
+    # 'flash' subcommand
+    flash_parser = micro_parser.add_parser(
+        "flash", help="flash the built image on a given micro target."
+    )
+    flash_parser.set_defaults(subcommand_handler=flash_handler)
+    flash_parser.add_argument("PROJECT_DIR", help="Project dir with a image 
built.")
+
+    # TODO(gromero): list and select serial when multiple devices exist
+    # It's not clear yet if the device list should be determined by TVMC or 
returned by the Project API
+
+    # For each platform add arguments detected automatically using Project API 
info query.
+
+    # Create subparsers for the platforms under 'create-project', 'build', and 
'flash' subcommands first.
+    help_msg = "you must selected a platform from the list. You can pass '-h' 
for a selected platform to list its options."
+    create_project_platforms_parser = create_project_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+    build_platforms_parser = build_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+    flash_platforms_parser = flash_parser.add_subparsers(
+        title="platforms", help=help_msg, dest="platform"
+    )
+
+    # Map used to map a API method to proper CLI parsers and handlers.
+    #           API method          parser                           handler   
              smbcmd domain
+    subcmds = {
+        "generate_project": [create_project_platforms_parser, 
create_project_handler],
+        "build": [build_platforms_parser, build_handler],
+        "flash": [flash_platforms_parser, flash_handler],
+    }
+
+    # Helper to add a platform to a subcmd parser.
+    def _add_parser(parser, platform):
+        platform_name = platform[0].upper() + platform[1:] + " platform"
+        o = parser.add_parser(platform, add_help=False, help=f"select 
{platform_name}.")
+        o.set_defaults(platform=platform)
+        return o
+
+    parser_by_subcmd = {}
+    for subcmd, o in subcmds.items():
+        parser_by_platform = {}
+        o[0].required = True  # Selecting a platform/template is mandatory
+        for platform in TEMPLATES:
+            new_parser = _add_parser(o[0], platform)
+            parser_by_platform[platform] = new_parser
+
+        new_parser = o[0].add_parser("template", add_help=False, help="select 
an adhoc template.")
+        new_parser.add_argument(
+            "-d", metavar="TEMPLATE_DIR", required=True, help="project API 
template directory."

Review comment:
       can you add `--template-dir` as an option here and then you shouldn't 
need the metavar?

##########
File path: python/tvm/driver/tvmc/fmtopt.py
##########
@@ -0,0 +1,70 @@
+# 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.
+
+from textwrap import TextWrapper
+
+
+def format_option(option_text, help_text, required=True):
+    # Maximum column length starting at the option name.
+    COL_LEN = 80
+
+    # Extract option name (option name + '=' char, i.e. '=' is part of what
+    # is considered here 'optname') plus its length for choices and help
+    # text justification.
+    optname_break = option_text.find("=")
+    optname = option_text[: optname_break + 1]  # '=' is part of the option 
name in this context
+    optname_len = len(optname)
+
+    # Prepare optname + choices text chunck.
+    choices_text = option_text[optname_break + 1 :]  # '=' is not part of the 
choices
+    wrapper = TextWrapper(width=COL_LEN - optname_len)
+    choices_lines = wrapper.wrap(choices_text)
+
+    # Set first choices line which merely appends to optname string.
+    # No justification is necessary for the first line since first
+    # line was wrapped based on COL_LEN - optname_len, i.e. considering
+    # optname_len.
+    choices_just_lines = [optname + choices_lines[0]]
+
+    # Justify the remaining lines based on first optname + '='.
+    for line in choices_lines[1:]:
+        line_len = len(line)
+        line_just = line.rjust(
+            optname_len + 1 + line_len
+        )  # add 1 to align after '{' in the line above
+        choices_just_lines.append(line_just)
+
+    choices_text_just_chunk = "\n".join(choices_just_lines)
+
+    # Prepare help text chunck.
+    wrapper = TextWrapper(width=120)

Review comment:
       why 120 here?

##########
File path: python/tvm/micro/session.py
##########
@@ -107,7 +107,7 @@ def _wrap_transport_write(self, data, timeout_microsec):
 
         return len(data)  # TODO(areusch): delete
 
-    def __enter__(self):
+    def open(self):

Review comment:
       seems like open should return nothing and __enter__ should return self

##########
File path: python/tvm/driver/tvmc/runner.py
##########
@@ -366,13 +460,17 @@ def run_module(
             "Try calling tvmc.compile on the model before running it."
         )
 
-    # Currently only two package formats are supported: "classic" and
-    # "mlf". The later can only be used for micro targets, i.e. with microTVM.
-    if tvmc_package.type == "mlf":
-        raise TVMCException(
-            "You're trying to run a model saved using the Model Library Format 
(MLF)."
-            "MLF can only be used to run micro targets (microTVM)."
-        )
+    micro = False
+    if device == "micro":
+        if tvmc_package.type != "mlf":
+            TVMCException("--device 'micro' specified but no MLF archive found 
in PATH.")

Review comment:
       i'd phrase it more in terms of which command-line arg is missing

##########
File path: python/tvm/driver/tvmc/runner.py
##########
@@ -97,7 +111,55 @@ def add_run_parser(subparsers):
         help="hostname (required) and port (optional, defaults to 9090) of the 
RPC tracker, "
         "e.g. '192.168.0.100:9999'",
     )
-    parser.add_argument("FILE", help="path to the compiled module file")
+    parser.add_argument(
+        "PATH",
+        help="path to the compiled module file or to the project directory 
(micro devices only).",
+    )
+
+    #
+    # Hack to lookahead if 'run' was selected and make
+    # two dynamic parsers (in micro.py and in runner.py) work.
+    #
+    # print(sys.argv)
+    if "run" in sys.argv:

Review comment:
       suggest to invert the condition and return early. also, what if `run` is 
e.g. the value of --template-dir?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@tvm.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to