1<!-- mdformat off(b/169948621#comment2) --> 2 3<!-- Define reference-style links used throughout the document --> 4[small PRs]: https://google.github.io/eng-practices/review/developer/small-cls.html 5[Micro Contributing Guidelines]: https://github.com/tensorflow/tflite-micro/blob/main/tensorflow/lite/micro/CONTRIBUTING.md 6[Providing Context]: https://testing.googleblog.com/2017/09/code-health-providing-context-with.html 7[`ParseOpDataTfLite()`]: https://github.com/tensorflow/tensorflow/blob/d8394a6d774f5e3c02d97f1fc18ff445199db598/tensorflow/lite/core/api/flatbuffer_conversions.cc#L135 8[PR #45307]: https://github.com/tensorflow/tensorflow/pull/45307 9[PR #46021]: https://github.com/tensorflow/tensorflow/pull/46021 10[PR #45311]: https://github.com/tensorflow/tensorflow/pull/45311 11[PR #45457]: https://github.com/tensorflow/tensorflow/pull/45457 12[PR #45646]: https://github.com/tensorflow/tensorflow/pull/45646 13[PR #45647]: https://github.com/tensorflow/tensorflow/pull/45647 14[pre-submit checklist]: https://github.com/tensorflow/tflite-micro/blob/main/tensorflow/lite/micro/CONTRIBUTING.md#before-submitting-your-pr 15[reference_ops.h]: https://github.com/tensorflow/tensorflow/blob/92f459e6b917fa5099ef5317d14c5100d33a86f0/tensorflow/lite/kernels/internal/reference/reference_ops.h 16[general porting guidelines]: #general-porting-guidelines 17 18# Porting Reference Ops from Lite to Micro 19 20This is a guide to porting reference ops from Lite to Micro. It explains, 21step-by-step, the recommended code changes and the process for submitting them 22for review and acceptance. The process results in multiple pull requests, or 23PRs. Multiple, [small PRs][] are easier for the project to review and merge. 24 25The [Micro Contributing Guidelines][] are prerequisite reading. They cover 26general code health, maintainability, style, and submission, as well as how to 27setup a development environment. This guide contains step-by-step instructions 28for the specific task of porting reference ops from Lite to Micro. 29 30<!-- 31Semi-automated TOC generation with instructions from 32https://github.com/ekalinin/github-markdown-toc#auto-insert-and-update-toc 33--> 34<!--ts--> 35* [Porting Reference Ops from Lite to Micro](#porting-reference-ops-from-lite-to-micro) 36 * [1. Look for a port already in progress](#1-look-for-a-port-already-in-progress) 37 * [2. Open a GitHub issue to track the port](#2-open-a-github-issue-to-track-the-port) 38 * [3. Extract Lite's code for parsing op parameters to a function (PR1)](#3-extract-lites-code-for-parsing-op-parameters-to-a-function-pr1) 39 * [4. Extract the reference for the op to a standalone header (PR2)](#4-extract-the-reference-for-the-op-to-a-standalone-header-pr2) 40 * [5. Port the op from Lite to Micro (PR3)](#5-port-the-op-from-lite-to-micro-pr3) 41* [General Guidelines](#general-guidelines) 42 * [Check each commit for formatting, lint, and unit-test passage](#check-each-commit-for-formatting-lint-and-unit-test-passage) 43 * [Add yourself as an asignee to PRs](#add-yourself-as-an-asignee-to-prs) 44 * [Maintain a 1:1 correspondence between Micro and Lite versions of unit tests](#maintain-a-11-correspondence-between-micro-and-lite-versions-of-unit-tests) 45 * [Sometimes CI checks on PRs are flakey and fail](#sometimes-ci-checks-on-prs-are-flakey-and-fail) 46* [Notes](#notes) 47 48<!-- Added by: rkuester, at: Wed 05 May 2021 07:44:11 PM CDT --> 49 50<!--te--> 51 52## 1. Look for a port already in progress 53 54Begin by searching the TensorFlow GitHub repository for issues containing the 55name of the op under consideration to ensure someone isn't already working on a 56port. 57 58## 2. Open a GitHub issue to track the port 59 60Open a GitHub issue to announce your intent to port the op, and to begin a 61record of your work. Document the entire process of porting the op in this 62issue. Link constituent PRs to this issue. See the article [Providing 63Context][] for background on documenting your work via bug reports. 64 65A good example is [issue #45306: micro: port op FILL from lite](https://github.com/tensorflow/tensorflow/issues/45306). 66 67## 3. Extract Lite's code for parsing op parameters to a function (PR1) 68 69Now we begin changing, testing, and submitting code. This step will result in 70the first pull request, PR1. 71 721. Extract the code for parsing op parameters out of the switch statement in 73 [`ParseOpDataTfLite()`][] in `lite/core/api/flatbuffer_conversions.cc` into 74 a standalone function, and call that function from the switch statement. 75 This standalone function is now available to be called by the Micro op 76 resolver, which also needs to parse the op parameters, in a future change. 77 A simple example is [PR #45307][], and a more complicated example is [PR 78 #46021][]. 79 801. Use `clang-format` to make sure the code is properly formatted. 81 82 ```shell 83 clang-format --style=google -i $(git ls-files -m | grep -E '\.cc|\.h') 84 ``` 85 861. Make sure your code is lint-free. 87 88 ```shell 89 cpplint.py $(git ls-files -m) 90 ``` 91 921. Create a single commit containing the change. Observe the guidelines for 93 good commit log messages found in the article [Providing Context][]. 94 A good example is commit [0664214](https://github.com/tensorflow/tensorflow/pull/45307/commits/0664214792ad2357f6224e7002661894775cb512). 95 961. Since this change modifies the op's implementation in Lite, test the change 97 with the relevant Lite unit tests. 98 99 ```shell 100 bazel test tensorflow/lite/kernels:all 101 ``` 102 1031. Create and submit the PR. Write a [good PR description][], and be sure to 104 link to the GitHub issue created to document the port. A good example is 105 [PR #45307][]. 106 107 [good PR description]: https://google.github.io/eng-practices/review/developer/cl-descriptions.html 108 109## 4. Extract the reference for the op to a standalone header (PR2) 110 111Move the reference implementation of the op in [reference_ops.h][] to a standalone header so that 112Micro can include it without including unrelated dependencies via 113reference_ops.h. 114 115A good example is [PR #45311][]. 116 1171. Copy an existing header from `tensorflow/lite/kernels/internal/reference/` 118 to `tensorflow/lite/kernels/internal/reference/NEW_OP.H` to create the 119 boilerplate. Replace `NEW_OP.H` with the name of the new operator. 120 1211. Move the implementation from 122 `tensorflow/lite/kernels/internal/reference/reference_ops.h` to 123 `tensorflow/lite/kernels/internal/reference/NEW_OP.H`. 124 1251. Add the new header to the build by adding to the library definitions 126 `reference_base` and `legacy_reference_base` in the file 127 `tensorflow/lite/kernels/internal/BUILD`. See, for example, 128 [this change for operator FILL](https://github.com/tensorflow/tensorflow/pull/45311/commits/92f459e6b917fa5099ef5317d14c5100d33a86f0#diff-0b0fc9e1affece3c5a141ee9326f882876b6b958bc8b12a7c01d7540dc04983e). 129 1301. Use the program `clang-format` to make sure the code is properly formatted. 131 132 ```shell 133 clang-format --style=google -i $(git ls-files -m | grep -E '\.cc|\.h') 134 ``` 135 136 Do not clang-format existing code in `BUILD` or `reference_ops.h`. 137 1381. Make sure your code is lint-free. 139 140 ```shell 141 cpplint.py $(git ls-files -m) 142 ``` 143 144 Do not modify code in `BUILD` or `reference_ops.h` to satisfy `cpplint.py`. 145 1461. Create a single commit containing the change. Observe the guidelines for 147 good commit log messages found in the article [Providing Context][]. 148 A good example is commit [92f459e](https://github.com/tensorflow/tensorflow/commit/92f459e6b917fa5099ef5317d14c5100d33a86f0). 149 1501. Since this change modifies the op's implementation in Lite, test the change 151 with the relevant Lite unit tests. 152 153 ```shell 154 bazel test tensorflow/lite/kernels:all 155 ``` 156 1571. Create and submit the PR. Write a [good PR description][], and be sure to 158 link to the GitHub issue created to document the port. A good example is 159 [PR #45311][]. 160 161## 5. Port the op from Lite to Micro (PR3) 162 1631. Copy the kernel and test from Lite to Micro. 164 165 In the first commit of this PR, copy the kernel and test from Lite to Micro 166 without making any modifications and without adding them to the build. 167 168 A good example is commit [a2ca1fd](https://github.com/tensorflow/tensorflow/commit/a2ca1fd7a174438f736c0435dd3e4e618612fdee). 169 170 This copy action is in its own commit in order to create readable, reviewable diffs 171 when modifications are made in later commits. If the files were copied and 172 modified in one step, the modifications would not appear as a diff of the Lite 173 version. Instead, the files would simply appear at the destination path in 174 their final form. 175 176 1771. Remove Lite-specific code from copies 178 179 In the second commit of this PR, remove the bulk of Lite-specific code from 180 the files copied to micro in the previous step. 181 182 A good example is commit [a5a87b4](https://github.com/tensorflow/tensorflow/commit/a5a87b420b87a1f832e241db3a5b724207ea700a). 183 184 This bulk-delete action is in its own commit for reasons similar to 185 those given in the step above: to produce a more readable, reviewable diff in this 186 step and in the next. Because the files are not yet added to the build, they 187 need not (and obviously won't) compiler or function. What to delete now as 188 opposed to deleting in the next commit is somewhat subjective, but make 189 deletes in order to: 190 191 - Flatten the namespace down to `tflite`. 192 - Stop resizing output tensors. 193 - Remove input and output types other than `int8` and `float32`. 194 - Stop using gmock and gtest. 195 - etc. 196 1971. Port the op and the test 198 199 Make the necessary changes to the micro kernel, header, and test to make the op 200 implementation suitable for micro. Include these in the build. 201 202 This step requires the most creativity, and may receive the most feedback 203 during review. Maintain good atomicity in your commits. Considering its 204 scope, this step will consist of more than one commit. A good example is 205 the changes made in [PR #45647][]. 206 2071. Use `clang-format` to make sure the code is properly formatted. 208 209 ```shell 210 $ clang-format --style=google -i $(git ls-files -m | grep -E '\.cc|\.h') 211 ``` 212 213 Do not clang-format existing code in `BUILD` or `reference_ops.h`. 214 2151. Make sure the code is lint-free. 216 217 ```shell 218 $ cpplint.py $(git ls-files -m) 219 ``` 220 221 Do not modify code in `BUILD` or `reference_ops.h` to satisfy `cpplint.py`. 222 2231. Make sure the port passes all applicable tests. 224 225 ```shell 226 $ bazel test tensorflow/lite/micro/kernels:${op}_test 227 $ bazel test tensorflow/lite/micro/kernels:all 228 $ make -f tensorflow/lite/micro/tools/make/Makefile test_kernel_${op}_test 229 $ make -f tensorflow/lite/micro/tools/make/Makefile test 230 ``` 231 232 See the general [Micro Contributing Guidelines][] for other testing ideas, 233 including the use of address sanitizers. 234 2351. Create and submit the PR. Write a [good PR description][], and be sure to 236 link to the GitHub issue created to document the port. A good example is 237 [PR #45647][]. 238 239# General Guidelines 240 241## Check each commit for formatting, lint, and unit-test passage 242 243Check each commit against the [pre-submit checklist][] in the micro 244Contributing Guidelines. Specifically, make sure your code: 245 2461. Is formatted with clang-format. 2471. Passes a lint check. 2481. Passes all unit tests. 249 250 ```shell 251 $ make -s -j8 -f tensorflow/lite/micro/tools/make/Makefile test 252 ``` 253 254CI runs these checks on all PRs, and will hold up your PR if any of these checks fail. 255 256## Add yourself as an asignee to PRs 257 258Feel free to add yourself as an additional assignee to PRs which you submit. 259Other assignees may be set by the project's various bots. 260 261## Maintain a 1:1 correspondence between Micro and Lite versions of unit tests 262 263To the extent possible, maintain a 1:1 correspondence between Micro and Lite 264versions of unit tests. Avoid cleanup of merely stylistic issues, e.g., by 265replacing the hardcoded literal `3.40282e+038` with 266`std::numeric_limits<float>::max()`. Any changes between the Micro and Lite 267versions of a test put a burden on future maintainers to figure out whether the 268differences are actually significant or just stylistic. 269 270## Sometimes CI checks on PRs are flakey and fail 271 272Sometimes CI checks on PRs don't fail because of the PRs contents, but because 273of some problem with the test infrastructure. Marking issues with the label 274`kokoro:force-run` causes the checks to be rerun. 275 276# Notes 277 278* There was discussion of commits vs. PRs in [#45387](https://github.com/tensorflow/tensorflow/issues/45387). 279 280* On Debian, running bazel required installing package bazel-3.1.0. 281 282* If you have permission, add the label `comp:micro` to these PRs. 283 284* If you have permission, the label `kokoro:force-run` can be applied to 285 manually trigger the CI builds. 286 287* [TensorFlow Lite 8-bit quantization specification](https://www.tensorflow.org/lite/performance/quantization_spec) 288