Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[microTVM] Use default Project Options in template projects and add Makefile for Arduino template project #12818

Merged
merged 24 commits into from
Oct 4, 2022

Conversation

mehrdadh
Copy link
Member

@mehrdadh mehrdadh commented Sep 16, 2022

This PR:

  • Refactors common project options to a single place for template projects
  • Adds a feature to update project options for customization
  • Adds a Makefile for Arduino project to make the build/flash process more standalone
  • Adds CMSIS support to Arduino template project
  • Refactors zephyr_board and arduino_board to board

cc @alanmacd @areusch @gromero @guberti

@github-actions github-actions bot requested review from areusch and gromero September 16, 2022 17:15
@mehrdadh mehrdadh force-pushed the micro/update_project_options branch 3 times, most recently from f8848c0 to 3c476d1 Compare September 19, 2022 23:45
Copy link
Member

@guberti guberti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of adding a Makefile to the Arduino project, but I would really love more documentation about how to use it (full disclosure - I've never been great with make 😅). I'd love some usage examples both in the Makefile.template and in a README.md file.

I've left some other comments as well - thanks for the change!

Comment on lines 18 to 24
MAKE_DIR := $(PWD)
FQBN ?= <FQBN>
VERBOSE_FLAG ?= <VERBOSE_FLAG>
BUILD_DIR := $(subst :,.,build)
PORT ?=
ARUINO_CLI_CMD ?= <ARUINO_CLI_CMD>
BOARD := <BOARD>
BUILD_EXTRA_FLAGS := <BUILD_EXTRA_FLAGS>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really love some documentation on what these flags do. I can piece together some of them, but what is BUILD_EXTRA_FLAGS? What is MAKE_DIR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed MAKE_DIR, we don't need that
Also added more info on each variable

python/tvm/micro/project_api/server.py Outdated Show resolved Hide resolved
python/tvm/micro/project_api/server.py Show resolved Hide resolved
python/tvm/micro/project_api/server.py Show resolved Hide resolved
Comment on lines 831 to 841
for name, config in kw.items():
option_found = False
for ind, option in enumerate(options):
if option.name == name:
options[ind] = option.replace(**config)
option_found = True
break
if not option_found:
raise ValueError("Option {} was not found in default ProjectOptions.".format(name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment explaining what these lines are doing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are updating the default options and I think the function string explains it

Copy link
Member Author

@mehrdadh mehrdadh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guberti thanks for the review! PTAL

python/tvm/micro/project_api/server.py Outdated Show resolved Hide resolved
python/tvm/micro/project_api/server.py Show resolved Hide resolved
python/tvm/micro/project_api/server.py Show resolved Hide resolved
Comment on lines 831 to 841
for name, config in kw.items():
option_found = False
for ind, option in enumerate(options):
if option.name == name:
options[ind] = option.replace(**config)
option_found = True
break
if not option_found:
raise ValueError("Option {} was not found in default ProjectOptions.".format(name))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are updating the default options and I think the function string explains it

Copy link
Member

@guberti guberti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small nits, but looks good. Thanks for the change!

Comment on lines +816 to +841
for name, config in kw.items():
option_found = False
for ind, option in enumerate(options):
if option.name == name:
options[ind] = option.replace(config)
option_found = True
break
if not option_found:
raise ValueError("Option {} was not found in default ProjectOptions.".format(name))
Copy link
Member

@guberti guberti Sep 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possible nit:

Suggested change
for name, config in kw.items():
option_found = False
for ind, option in enumerate(options):
if option.name == name:
options[ind] = option.replace(config)
option_found = True
break
if not option_found:
raise ValueError("Option {} was not found in default ProjectOptions.".format(name))
assert kw.keys() <= {o.name for o in options}, "Unknown option!"
for index, option in enumerate(options):
if option.name in kw:
options[index] = option.replace(config)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that doesn't work because the kw is a list of suggested changes but option has ProjectOption type

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this should be if option.name in kw. Fixed!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix this in a follow up PR if there was no other comments

@@ -368,43 +436,33 @@ def _get_platform_version(self, arduino_cli_path: str) -> float:
return version.parse(str_version)

# This will only be run for build and upload
def _check_platform_version(self, options):
def _check_platform_version(self, arduino_cli_cmd: str, warning_as_error: bool):
Copy link
Member

@guberti guberti Sep 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are your thoughts on the typing stuff here?

@mehrdadh mehrdadh force-pushed the micro/update_project_options branch from 2022a91 to 014fa3b Compare September 21, 2022 22:38
Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @mehrdadh ! cc @gromero


# These tokens are used in the Makefile.template file.
# They are replaced with proper value in generate_project step.
FQBN_TOKEN = "<FQBN>"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this a regexp and use re.findall to substitute? e.g.

VARS = {"VERBOSE_FLAG": "--verbose" if verbose else "", ...}
SUBST_TOKEN_RE = re.compile(r"<(?P<var>[A-Z]_+)>")
outs = []
for i, m in enumerate(re.split(SUBST_TOKEN_RE, line)):
  if i % 2 == 1:
    # m is a var
    m = VARS[m]
   outs.append(m)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

self,
makefile_template_path: pathlib.Path,
makefile_path: pathlib.Path,
board: str,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not accept options dict here? it might make it a little easier to move code around in this file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all the high level API functions to explicitly capture the required/optional ProjectOption and pass it to the internal function. I think this way is more clear to set the requirement for each project option. Previously options were passed multiple levels and made it hard to track. thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i agree there is a bit of a problem that everything depends on all options. typically this problem manifests itself in more complex codebases where refactoring becomes difficult because the member functions organically grow to the point they need interfaces, but interfaces are hard to define because the dependency net is too wide.

the drawback to factoring stuff out here is that it's possible to modify it, and then the meaning of a var could change depending on if it used the modified value or the original one present in options. for example, you access some vars as mandatory here and use .get() which means their value could be the var or None.

overall it's a tradeoff between these two. do you feel the code is sufficiently complex to need interfaces?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed this offline, I think either of the solutions has tradeoff. To make sure we use the correct optional/required for each option, I added few tests here:
aa13413#diff-f461d1a4c216e770f22b27fc7926b7fd31cde6273b1e15f9d5d08ec2892ec251R1

@mehrdadh
Copy link
Member Author

@tvm-bot rerun

@mehrdadh
Copy link
Member Author

@guberti @areusch PTAL, thanks!

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last couple things here--apologies for the delay

assert option.name in option_names


def test_default_options_requirements(platform):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, i appreciate the intent behind this test, but i don't know we should submit it. this one is essentially a "change-detector test"--a test that fails when the codebase changes at all. i think we can have test coverage of these options via test_zephyr.py (essentially, just see if you can build/run with excluding all the optional options). i'm ok without exhaustively testing those in this PR, though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! I updated the test.

assert option.optional == [API_GENERATE_PROJECT]


def test_extra_options_requirements(platform):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with this one

@mehrdadh mehrdadh force-pushed the micro/update_project_options branch from aa13413 to 3ffd38b Compare September 29, 2022 22:06
@mehrdadh
Copy link
Member Author

mehrdadh commented Oct 3, 2022

@areusch I think this is ready, PTAL. thanks!

@areusch areusch merged commit 61a7632 into apache:main Oct 4, 2022
xinetzone pushed a commit to daobook/tvm that referenced this pull request Nov 25, 2022
…akefile for Arduino template project (apache#12818)

* add default options

* add updat

* add more options

* add makefile for arduino

* fixed flash command

* add arduino-cli flag option

* cleanup

* lint

* lint and test added

* lint

* fix test

* fix flash command

* fix test, add board to makefile

* fix test

* fix flash and build command

* add cmsis support

* address comments

* lint

* address comments, refactor two more options

* change build.extra_flags to be empty when no flag added

* fix test

* address comments

* add test for project options

* update test
@mehrdadh mehrdadh deleted the micro/update_project_options branch January 20, 2023 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants