mlonmcu 0.3.0.dev0__3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mlonmcu/__init__.py +26 -0
- mlonmcu/artifact.py +172 -0
- mlonmcu/cli/__init__.py +19 -0
- mlonmcu/cli/build.py +119 -0
- mlonmcu/cli/cleanup.py +75 -0
- mlonmcu/cli/common.py +227 -0
- mlonmcu/cli/compile.py +87 -0
- mlonmcu/cli/env.py +68 -0
- mlonmcu/cli/export.py +93 -0
- mlonmcu/cli/flow.py +67 -0
- mlonmcu/cli/helper/__init__.py +18 -0
- mlonmcu/cli/helper/filter.py +25 -0
- mlonmcu/cli/helper/parse.py +159 -0
- mlonmcu/cli/init.py +130 -0
- mlonmcu/cli/load.py +87 -0
- mlonmcu/cli/main.py +116 -0
- mlonmcu/cli/models.py +48 -0
- mlonmcu/cli/run.py +56 -0
- mlonmcu/cli/setup.py +136 -0
- mlonmcu/cli/tune.py +48 -0
- mlonmcu/config.py +219 -0
- mlonmcu/context/__init__.py +22 -0
- mlonmcu/context/context.py +545 -0
- mlonmcu/context/read_write_filelock.py +327 -0
- mlonmcu/environment/__init__.py +18 -0
- mlonmcu/environment/config.py +214 -0
- mlonmcu/environment/environment.py +501 -0
- mlonmcu/environment/init.py +191 -0
- mlonmcu/environment/list.py +81 -0
- mlonmcu/environment/loader.py +250 -0
- mlonmcu/environment/templates.py +69 -0
- mlonmcu/environment/writer.py +117 -0
- mlonmcu/feature/__init__.py +18 -0
- mlonmcu/feature/feature.py +230 -0
- mlonmcu/feature/features.py +1537 -0
- mlonmcu/feature/type.py +33 -0
- mlonmcu/flow/__init__.py +61 -0
- mlonmcu/flow/backend.py +234 -0
- mlonmcu/flow/framework.py +69 -0
- mlonmcu/flow/tflm/__init__.py +23 -0
- mlonmcu/flow/tflm/backend/__init__.py +23 -0
- mlonmcu/flow/tflm/backend/backend.py +47 -0
- mlonmcu/flow/tflm/backend/tflmc.py +129 -0
- mlonmcu/flow/tflm/backend/tflmi.py +385 -0
- mlonmcu/flow/tflm/framework.py +81 -0
- mlonmcu/flow/tvm/__init__.py +23 -0
- mlonmcu/flow/tvm/backend/__init__.py +26 -0
- mlonmcu/flow/tvm/backend/backend.py +282 -0
- mlonmcu/flow/tvm/backend/model_info.py +307 -0
- mlonmcu/flow/tvm/backend/python_utils.py +36 -0
- mlonmcu/flow/tvm/backend/tuner.py +41 -0
- mlonmcu/flow/tvm/backend/tvmaot.py +162 -0
- mlonmcu/flow/tvm/backend/tvmaotplus.py +51 -0
- mlonmcu/flow/tvm/backend/tvmc_utils.py +172 -0
- mlonmcu/flow/tvm/backend/tvmcg.py +102 -0
- mlonmcu/flow/tvm/backend/tvmllvm.py +106 -0
- mlonmcu/flow/tvm/backend/tvmrt.py +151 -0
- mlonmcu/flow/tvm/backend/wrapper.py +645 -0
- mlonmcu/flow/tvm/framework.py +96 -0
- mlonmcu/logging.py +79 -0
- mlonmcu/mlonmcu.py +19 -0
- mlonmcu/models/__init__.py +31 -0
- mlonmcu/models/convert_data.py +107 -0
- mlonmcu/models/frontend.py +571 -0
- mlonmcu/models/group.py +29 -0
- mlonmcu/models/lookup.py +345 -0
- mlonmcu/models/metadata.py +133 -0
- mlonmcu/models/model.py +104 -0
- mlonmcu/models/options.py +64 -0
- mlonmcu/models/utils.py +136 -0
- mlonmcu/platform/__init__.py +27 -0
- mlonmcu/platform/_platform.py +46 -0
- mlonmcu/platform/espidf/__init__.py +25 -0
- mlonmcu/platform/espidf/espidf.py +489 -0
- mlonmcu/platform/espidf/espidf_target.py +257 -0
- mlonmcu/platform/lookup.py +126 -0
- mlonmcu/platform/microtvm/__init__.py +25 -0
- mlonmcu/platform/microtvm/microtvm.py +580 -0
- mlonmcu/platform/microtvm/microtvm_arduino_target.py +68 -0
- mlonmcu/platform/microtvm/microtvm_backend.py +64 -0
- mlonmcu/platform/microtvm/microtvm_espidf_target.py +94 -0
- mlonmcu/platform/microtvm/microtvm_etissvp_target.py +98 -0
- mlonmcu/platform/microtvm/microtvm_host_target.py +46 -0
- mlonmcu/platform/microtvm/microtvm_spike_target.py +230 -0
- mlonmcu/platform/microtvm/microtvm_target.py +189 -0
- mlonmcu/platform/microtvm/microtvm_template_target.py +55 -0
- mlonmcu/platform/microtvm/microtvm_zephyr_target.py +91 -0
- mlonmcu/platform/mlif/__init__.py +25 -0
- mlonmcu/platform/mlif/mlif.py +300 -0
- mlonmcu/platform/mlif/mlif_target.py +86 -0
- mlonmcu/platform/platform.py +244 -0
- mlonmcu/platform/tvm/__init__.py +25 -0
- mlonmcu/platform/tvm/tvm.py +429 -0
- mlonmcu/platform/tvm/tvm_backend.py +57 -0
- mlonmcu/platform/tvm/tvm_target.py +165 -0
- mlonmcu/platform/zephyr/__init__.py +25 -0
- mlonmcu/platform/zephyr/zephyr.py +450 -0
- mlonmcu/platform/zephyr/zephyr_target.py +110 -0
- mlonmcu/plugins.py +26 -0
- mlonmcu/report.py +99 -0
- mlonmcu/session/__init__.py +18 -0
- mlonmcu/session/postprocess/__init__.py +43 -0
- mlonmcu/session/postprocess/postprocess.py +62 -0
- mlonmcu/session/postprocess/postprocesses.py +487 -0
- mlonmcu/session/run.py +1008 -0
- mlonmcu/session/session.py +373 -0
- mlonmcu/setup/__init__.py +18 -0
- mlonmcu/setup/cache.py +147 -0
- mlonmcu/setup/gen_requirements.py +619 -0
- mlonmcu/setup/setup.py +285 -0
- mlonmcu/setup/task.py +380 -0
- mlonmcu/setup/tasks/__init__.py +40 -0
- mlonmcu/setup/tasks/arm_gcc.py +58 -0
- mlonmcu/setup/tasks/cmsisnn.py +151 -0
- mlonmcu/setup/tasks/common.py +36 -0
- mlonmcu/setup/tasks/corstone300.py +64 -0
- mlonmcu/setup/tasks/espidf.py +87 -0
- mlonmcu/setup/tasks/etiss.py +147 -0
- mlonmcu/setup/tasks/llvm.py +67 -0
- mlonmcu/setup/tasks/mlif.py +49 -0
- mlonmcu/setup/tasks/muriscvnn.py +166 -0
- mlonmcu/setup/tasks/pulp.py +192 -0
- mlonmcu/setup/tasks/riscv_gcc.py +146 -0
- mlonmcu/setup/tasks/spike.py +190 -0
- mlonmcu/setup/tasks/tf.py +92 -0
- mlonmcu/setup/tasks/tflite.py +59 -0
- mlonmcu/setup/tasks/tflmc.py +141 -0
- mlonmcu/setup/tasks/tvm.py +172 -0
- mlonmcu/setup/tasks/utvmcg.py +96 -0
- mlonmcu/setup/tasks/zephyr.py +119 -0
- mlonmcu/setup/utils.py +374 -0
- mlonmcu/target/__init__.py +37 -0
- mlonmcu/target/_target.py +41 -0
- mlonmcu/target/arm/__init__.py +3 -0
- mlonmcu/target/arm/corstone300.py +235 -0
- mlonmcu/target/arm/util.py +109 -0
- mlonmcu/target/common.py +194 -0
- mlonmcu/target/elf.py +256 -0
- mlonmcu/target/host_x86.py +84 -0
- mlonmcu/target/metrics.py +75 -0
- mlonmcu/target/riscv/__init__.py +7 -0
- mlonmcu/target/riscv/etiss_pulpino.py +462 -0
- mlonmcu/target/riscv/gvsoc_pulp.py +215 -0
- mlonmcu/target/riscv/ovpsim.py +301 -0
- mlonmcu/target/riscv/riscv.py +185 -0
- mlonmcu/target/riscv/riscv_qemu.py +166 -0
- mlonmcu/target/riscv/spike.py +243 -0
- mlonmcu/target/riscv/util.py +134 -0
- mlonmcu/target/target.py +200 -0
- mlonmcu/utils.py +49 -0
- mlonmcu/version.py +21 -0
- mlonmcu-0.3.0.dev0.dist-info/LICENSE +202 -0
- mlonmcu-0.3.0.dev0.dist-info/METADATA +343 -0
- mlonmcu-0.3.0.dev0.dist-info/NOTICE +8 -0
- mlonmcu-0.3.0.dev0.dist-info/RECORD +376 -0
- mlonmcu-0.3.0.dev0.dist-info/WHEEL +5 -0
- mlonmcu-0.3.0.dev0.dist-info/entry_points.txt +3 -0
- mlonmcu-0.3.0.dev0.dist-info/top_level.txt +1 -0
- resources/frameworks/tvm/crt_config/README.md +7 -0
- resources/frameworks/tvm/crt_config/crt_config.h +53 -0
- resources/frameworks/tvm/tuning_records/riscv_cpu_v0.01.log.best +46 -0
- resources/patches/fix_esp32c3_march.patch +20 -0
- resources/patches/pulp_freertos_support.patch +55 -0
- resources/platforms/espidf/micro_speech_esp32devboard/CMakeLists.txt +29 -0
- resources/platforms/espidf/micro_speech_esp32devboard/README.md +70 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/CMakeLists.txt +78 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/Kconfig +76 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/default_data.c +26 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/default_model_support/process_input.c +35 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/default_model_support/process_output.c +45 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/include/exit.h +26 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/include/ml_interface.h +70 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/include/printing.h +31 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/ml_interface.c +74 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/ml_interface_tflm.cc +64 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/mlif2/ml_interface_tvm.c +53 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/tflite-lib/CMakeLists.txt +140 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/tflite-lib/Kconfig +8 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/tvm-lib/CMakeLists.txt +66 -0
- resources/platforms/espidf/micro_speech_esp32devboard/components/tvm-lib/Kconfig +7 -0
- resources/platforms/espidf/micro_speech_esp32devboard/example_test.py +38 -0
- resources/platforms/espidf/micro_speech_esp32devboard/info.txt +9 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/CMakeLists.txt +58 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/audio_provider.cc +193 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/audio_provider.h +49 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/command_responder.cc +53 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/command_responder.h +35 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/feature_provider.cc +132 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/feature_provider.cc.orig +145 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/feature_provider.h +55 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/COPYING +11 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/_kiss_fft_guts.h +168 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/kiss_fft.c +408 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/kiss_fft.h +124 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/tools/kiss_fftr.c +159 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/kissfft/tools/kiss_fftr.h +46 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/main.cc +63 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/main_functions.cc +204 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/main_functions.h +37 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/micro_features_generator.cc +121 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/micro_features_generator.h +38 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/micro_model_settings.cc +23 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/micro_model_settings.h +43 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/bits.h +102 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/fft.cc +52 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/fft.h +50 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/fft_util.cc +69 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/fft_util.h +34 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/filterbank.c +134 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/filterbank.h +63 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/filterbank_util.c +220 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/filterbank_util.h +50 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/frontend.c +72 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/frontend.h +64 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/frontend_util.c +85 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/frontend_util.h +52 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/kiss_fft_common.h +48 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/kiss_fft_int16.cc +8 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/kiss_fft_int16.h +34 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_lut.c +30 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_lut.h +40 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_scale.c +83 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_scale.h +39 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_scale_util.c +27 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/log_scale_util.h +45 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/noise_reduction.c +51 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/noise_reduction.h +46 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/noise_reduction_util.c +45 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/noise_reduction_util.h +50 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/pcan_gain_control.c +56 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/pcan_gain_control.h +47 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/pcan_gain_control_util.c +92 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/pcan_gain_control_util.h +57 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/window.c +70 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/window.h +49 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/window_util.c +73 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/microfrontend/lib/window_util.h +45 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/pins.c +14 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/pins.h +30 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/recognize_commands.cc +150 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/recognize_commands.h +173 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/ringbuf.c +333 -0
- resources/platforms/espidf/micro_speech_esp32devboard/main/ringbuf.h +74 -0
- resources/platforms/espidf/micro_speech_esp32devboard/sdkconfig.defaults +36 -0
- resources/platforms/espidf/project/CMakeLists.txt +29 -0
- resources/platforms/espidf/project/README.md +70 -0
- resources/platforms/espidf/project/components/mlif/CMakeLists.txt +77 -0
- resources/platforms/espidf/project/components/mlif/Kconfig +76 -0
- resources/platforms/espidf/project/components/mlif/default_data.c +26 -0
- resources/platforms/espidf/project/components/mlif/default_model_support/process_input.c +35 -0
- resources/platforms/espidf/project/components/mlif/default_model_support/process_output.c +45 -0
- resources/platforms/espidf/project/components/mlif/include/exit.h +26 -0
- resources/platforms/espidf/project/components/mlif/include/ml_interface.h +60 -0
- resources/platforms/espidf/project/components/mlif/include/printing.h +31 -0
- resources/platforms/espidf/project/components/mlif/ml_interface.c +54 -0
- resources/platforms/espidf/project/components/mlif/ml_interface_tflm.cc +40 -0
- resources/platforms/espidf/project/components/mlif/ml_interface_tvm.c +40 -0
- resources/platforms/espidf/project/components/tflite-lib/CMakeLists.txt +142 -0
- resources/platforms/espidf/project/components/tflite-lib/Kconfig +8 -0
- resources/platforms/espidf/project/components/tvm-lib/CMakeLists.txt +66 -0
- resources/platforms/espidf/project/components/tvm-lib/Kconfig +7 -0
- resources/platforms/espidf/project/example_test.py +38 -0
- resources/platforms/espidf/project/main/CMakeLists.txt +25 -0
- resources/platforms/espidf/project/main/main.c +57 -0
- resources/platforms/espidf/project/sdkconfig.defaults +26 -0
- resources/platforms/zephyr/project/CMakeLists.txt +22 -0
- resources/platforms/zephyr/project/Kconfig +101 -0
- resources/platforms/zephyr/project/README.rst +33 -0
- resources/platforms/zephyr/project/cmake/AddAllSubdirs.cmake +21 -0
- resources/platforms/zephyr/project/cmake/ChooseTarget.cmake +22 -0
- resources/platforms/zephyr/project/cmake/LinkTFLite.cmake +223 -0
- resources/platforms/zephyr/project/cmake/LinkTVM.cmake +68 -0
- resources/platforms/zephyr/project/cmake/LookupClang.cmake +41 -0
- resources/platforms/zephyr/project/cmake/backends/tflmc.cmake +5 -0
- resources/platforms/zephyr/project/cmake/backends/tflmi.cmake +5 -0
- resources/platforms/zephyr/project/cmake/backends/tvmaot.cmake +10 -0
- resources/platforms/zephyr/project/cmake/backends/tvmaotplus.cmake +10 -0
- resources/platforms/zephyr/project/cmake/backends/tvmcg.cmake +10 -0
- resources/platforms/zephyr/project/cmake/backends/tvmllvm.cmake +8 -0
- resources/platforms/zephyr/project/cmake/backends/tvmrt.cmake +8 -0
- resources/platforms/zephyr/project/cmake/extras.cmake +9 -0
- resources/platforms/zephyr/project/cmake/features/auto_vectorize_gcc.cmake +65 -0
- resources/platforms/zephyr/project/cmake/features/auto_vectorize_llvm.cmake +20 -0
- resources/platforms/zephyr/project/cmake/features/cmsisnn.cmake +86 -0
- resources/platforms/zephyr/project/cmake/features/muriscvnn.cmake +87 -0
- resources/platforms/zephyr/project/cmake/frameworks/tflm.cmake +1 -0
- resources/platforms/zephyr/project/cmake/frameworks/tflm_mlif.cmake +8 -0
- resources/platforms/zephyr/project/cmake/frameworks/tvm.cmake +1 -0
- resources/platforms/zephyr/project/cmake/frameworks/tvm_mlif.cmake +37 -0
- resources/platforms/zephyr/project/lib/CMakeLists.txt +13 -0
- resources/platforms/zephyr/project/lib/drivers/fake_input.c +10 -0
- resources/platforms/zephyr/project/lib/drivers/fake_input.h +8 -0
- resources/platforms/zephyr/project/lib/ml_interface/CMakeLists.txt +31 -0
- resources/platforms/zephyr/project/lib/ml_interface/default_data.c +8 -0
- resources/platforms/zephyr/project/lib/ml_interface/default_model_support/CMakeLists.txt +2 -0
- resources/platforms/zephyr/project/lib/ml_interface/default_model_support/process_input.c +17 -0
- resources/platforms/zephyr/project/lib/ml_interface/default_model_support/process_output.c +27 -0
- resources/platforms/zephyr/project/lib/ml_interface/ml_interface.c +36 -0
- resources/platforms/zephyr/project/lib/ml_interface/ml_interface.h +47 -0
- resources/platforms/zephyr/project/lib/ml_interface/ml_interface_tflm.cc +22 -0
- resources/platforms/zephyr/project/lib/ml_interface/ml_interface_tvm.c +22 -0
- resources/platforms/zephyr/project/lib/support/CMakeLists.txt +2 -0
- resources/platforms/zephyr/project/lib/support/dummy.c +0 -0
- resources/platforms/zephyr/project/lib/support/exit.h +8 -0
- resources/platforms/zephyr/project/lib/support/printing.h +11 -0
- resources/platforms/zephyr/project/lib/support/quantize.h +23 -0
- resources/platforms/zephyr/project/lib/targets/corstone300.c +62 -0
- resources/platforms/zephyr/project/lib/targets/default.c +2 -0
- resources/platforms/zephyr/project/lib/targets/etiss_pulpino.c +112 -0
- resources/platforms/zephyr/project/lib/targets/generic_riscv.c +112 -0
- resources/platforms/zephyr/project/lib/targets/riscv_qemu.c +112 -0
- resources/platforms/zephyr/project/lib/targets/target.h +2 -0
- resources/platforms/zephyr/project/prj.conf +11 -0
- resources/platforms/zephyr/project/sample.yaml +19 -0
- resources/platforms/zephyr/project/src/main.c +71 -0
- resources/platforms/zephyr/project2/CMakeLists.txt +72 -0
- resources/platforms/zephyr/project2/Kconfig +101 -0
- resources/platforms/zephyr/project2/README.rst +33 -0
- resources/platforms/zephyr/project2/cmake/AddAllSubdirs.cmake +21 -0
- resources/platforms/zephyr/project2/cmake/ChooseTarget.cmake +22 -0
- resources/platforms/zephyr/project2/cmake/LinkTFLite.cmake +223 -0
- resources/platforms/zephyr/project2/cmake/LinkTVM.cmake +68 -0
- resources/platforms/zephyr/project2/cmake/LookupClang.cmake +41 -0
- resources/platforms/zephyr/project2/cmake/backends/tflmc.cmake +5 -0
- resources/platforms/zephyr/project2/cmake/backends/tflmi.cmake +5 -0
- resources/platforms/zephyr/project2/cmake/backends/tvmaot.cmake +10 -0
- resources/platforms/zephyr/project2/cmake/backends/tvmaotplus.cmake +10 -0
- resources/platforms/zephyr/project2/cmake/backends/tvmcg.cmake +10 -0
- resources/platforms/zephyr/project2/cmake/backends/tvmllvm.cmake +8 -0
- resources/platforms/zephyr/project2/cmake/backends/tvmrt.cmake +8 -0
- resources/platforms/zephyr/project2/cmake/extras.cmake +9 -0
- resources/platforms/zephyr/project2/cmake/features/auto_vectorize_gcc.cmake +65 -0
- resources/platforms/zephyr/project2/cmake/features/auto_vectorize_llvm.cmake +20 -0
- resources/platforms/zephyr/project2/cmake/features/cmsisnn.cmake +86 -0
- resources/platforms/zephyr/project2/cmake/features/muriscvnn.cmake +87 -0
- resources/platforms/zephyr/project2/cmake/frameworks/tflm.cmake +1 -0
- resources/platforms/zephyr/project2/cmake/frameworks/tflm_mlif.cmake +8 -0
- resources/platforms/zephyr/project2/cmake/frameworks/tvm.cmake +1 -0
- resources/platforms/zephyr/project2/cmake/frameworks/tvm_mlif.cmake +37 -0
- resources/platforms/zephyr/project2/default_data.c +8 -0
- resources/platforms/zephyr/project2/default_model_support/CMakeLists.txt +3 -0
- resources/platforms/zephyr/project2/default_model_support/process_input.c +17 -0
- resources/platforms/zephyr/project2/default_model_support/process_output.c +27 -0
- resources/platforms/zephyr/project2/lib/CMakeLists.txt +13 -0
- resources/platforms/zephyr/project2/lib/drivers/fake_input.c +10 -0
- resources/platforms/zephyr/project2/lib/drivers/fake_input.h +8 -0
- resources/platforms/zephyr/project2/lib/support/CMakeLists.txt +2 -0
- resources/platforms/zephyr/project2/lib/support/dummy.c +0 -0
- resources/platforms/zephyr/project2/lib/support/exit.h +8 -0
- resources/platforms/zephyr/project2/lib/support/printing.h +11 -0
- resources/platforms/zephyr/project2/lib/support/quantize.h +23 -0
- resources/platforms/zephyr/project2/lib/targets/corstone300.c +62 -0
- resources/platforms/zephyr/project2/lib/targets/default.c +2 -0
- resources/platforms/zephyr/project2/lib/targets/etiss_pulpino.c +112 -0
- resources/platforms/zephyr/project2/lib/targets/generic_riscv.c +112 -0
- resources/platforms/zephyr/project2/lib/targets/riscv_qemu.c +112 -0
- resources/platforms/zephyr/project2/lib/targets/target.h +2 -0
- resources/platforms/zephyr/project2/ml_interface.c +36 -0
- resources/platforms/zephyr/project2/ml_interface.h +47 -0
- resources/platforms/zephyr/project2/ml_interface_tflm.cc +22 -0
- resources/platforms/zephyr/project2/ml_interface_tvm.c +22 -0
- resources/platforms/zephyr/project2/prj.conf +13 -0
- resources/platforms/zephyr/project2/sample.yaml +19 -0
- resources/platforms/zephyr/project2/settings.json +6 -0
- resources/platforms/zephyr/project2/src/main.c +35 -0
- resources/pycharm/.run/README.md +73 -0
- resources/pycharm/.run/step1_ init env.run.xml +24 -0
- resources/pycharm/.run/step2_ setup.run.xml +25 -0
- resources/pycharm/.run/step3_ run resnet on pulpxpulpissimo.run.xml +25 -0
- resources/templates/default.yml.j2 +258 -0
- resources/templates/dev.yml.j2 +212 -0
- resources/templates/minimal.yml.j2 +234 -0
- resources/templates/phi.yml.j2 +282 -0
- resources/templates/pulp.yml.j2 +267 -0
- resources/templates/research.yml.j2 +237 -0
- resources/templates/tumeda.yml.j2 +239 -0
|
@@ -0,0 +1,1537 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2022 TUM Department of Electrical and Computer Engineering.
|
|
3
|
+
#
|
|
4
|
+
# This file is part of MLonMCU.
|
|
5
|
+
# See https://github.com/tum-ei-eda/mlonmcu.git for further info.
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
"""Definition of MLonMCU features and the feature registry."""
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
import pandas as pd
|
|
23
|
+
from typing import Union
|
|
24
|
+
|
|
25
|
+
from mlonmcu.utils import is_power_of_two
|
|
26
|
+
from mlonmcu.config import str2bool
|
|
27
|
+
from mlonmcu.artifact import Artifact, ArtifactFormat
|
|
28
|
+
from .feature import (
|
|
29
|
+
BackendFeature,
|
|
30
|
+
FrameworkFeature,
|
|
31
|
+
PlatformFeature,
|
|
32
|
+
FrontendFeature,
|
|
33
|
+
TargetFeature,
|
|
34
|
+
SetupFeature,
|
|
35
|
+
RunFeature,
|
|
36
|
+
FeatureBase,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# from mlonmcu.flow import SUPPORTED_TVM_BACKENDS
|
|
40
|
+
SUPPORTED_TVM_BACKENDS = [
|
|
41
|
+
"tvmaot",
|
|
42
|
+
"tvmaotplus",
|
|
43
|
+
"tvmrt",
|
|
44
|
+
"tvmcg",
|
|
45
|
+
"tvmllvm",
|
|
46
|
+
] # Workaround for cirvular import until we have a backend registry
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def filter_none(data):
|
|
50
|
+
"""Helper function which drop dict items with a None value."""
|
|
51
|
+
assert isinstance(data, dict), "Dict only"
|
|
52
|
+
out = {key: value for key, value in data.items() if value is not None}
|
|
53
|
+
return out
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
REGISTERED_FEATURES = {}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def register_feature(name):
|
|
60
|
+
"""Decorator for adding a feature to the global registry."""
|
|
61
|
+
|
|
62
|
+
def real_decorator(obj):
|
|
63
|
+
REGISTERED_FEATURES[name] = obj
|
|
64
|
+
|
|
65
|
+
return real_decorator
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_available_feature_names(feature_type=None):
|
|
69
|
+
"""Utility for getting feature names."""
|
|
70
|
+
ret = []
|
|
71
|
+
if feature_type is None:
|
|
72
|
+
return REGISTERED_FEATURES.keys()
|
|
73
|
+
|
|
74
|
+
for name, feature in REGISTERED_FEATURES.items():
|
|
75
|
+
if feature_type in list(feature.types()):
|
|
76
|
+
ret.append(name)
|
|
77
|
+
return ret
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_available_features(feature_type=None, feature_name=None):
|
|
81
|
+
"""Utility for looking up features."""
|
|
82
|
+
names = get_available_feature_names(feature_type=feature_type)
|
|
83
|
+
return [REGISTERED_FEATURES[name] for name in names if feature_name is None or name == feature_name]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def get_matching_features(features, feature_type):
|
|
87
|
+
return [feature for feature in features if feature_type in feature.types()]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@register_feature("debug_arena")
|
|
91
|
+
class DebugArena(BackendFeature):
|
|
92
|
+
"""Enable verbose printing of arena usage for debugging."""
|
|
93
|
+
|
|
94
|
+
def __init__(self, features=None, config=None):
|
|
95
|
+
super().__init__("debug_arena", features=features, config=config)
|
|
96
|
+
|
|
97
|
+
def get_backend_config(self, backend):
|
|
98
|
+
assert backend in [
|
|
99
|
+
"tvmaot",
|
|
100
|
+
"tvmaotplus",
|
|
101
|
+
"tvmrt",
|
|
102
|
+
"tflmi",
|
|
103
|
+
], f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
104
|
+
return {f"{backend}.debug_arena": self.enabled}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@register_feature("validate")
|
|
108
|
+
class Validate(FrontendFeature, PlatformFeature):
|
|
109
|
+
"""Enable validaton of inout and output tensors."""
|
|
110
|
+
|
|
111
|
+
DEFAULTS = {
|
|
112
|
+
**FeatureBase.DEFAULTS,
|
|
113
|
+
"allow_missing": True,
|
|
114
|
+
"fail_on_error": None,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
def __init__(self, features=None, config=None):
|
|
118
|
+
super().__init__("validate", features=features, config=config)
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def allow_missing(self):
|
|
122
|
+
value = self.config["allow_missing"]
|
|
123
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def fail_on_error(self):
|
|
127
|
+
return self.config["fail_on_error"]
|
|
128
|
+
|
|
129
|
+
def get_frontend_config(self, frontend):
|
|
130
|
+
if not self.allow_missing:
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
return {f"{frontend}.use_inout_data": True}
|
|
133
|
+
|
|
134
|
+
def get_platform_config(self, platform):
|
|
135
|
+
assert platform == "mlif", f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
136
|
+
return filter_none(
|
|
137
|
+
{
|
|
138
|
+
f"{platform}.ignore_data": False,
|
|
139
|
+
f"{platform}.fail_on_error": self.fail_on_error,
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@register_feature("muriscvnn")
|
|
145
|
+
class Muriscvnn(SetupFeature, FrameworkFeature, PlatformFeature):
|
|
146
|
+
"""muRISCV-V NN wrappers for TFLite Micro"""
|
|
147
|
+
|
|
148
|
+
REQUIRED = ["muriscvnn.src_dir"]
|
|
149
|
+
|
|
150
|
+
def __init__(self, features=None, config=None):
|
|
151
|
+
super().__init__("muriscvnn", features=features, config=config)
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def muriscvnn_dir(self):
|
|
155
|
+
return str(self.config["muriscvnn.src_dir"])
|
|
156
|
+
|
|
157
|
+
def add_framework_config(self, framework, config):
|
|
158
|
+
assert framework == "tflm", f"Unsupported feature '{self.name}' for framework '{framework}'"
|
|
159
|
+
if f"{framework}.optimized_kernel" in config and config[f"{framework}.optimized_kernel"] not in [
|
|
160
|
+
None,
|
|
161
|
+
"cmsis_nn",
|
|
162
|
+
]:
|
|
163
|
+
RuntimeError(f"There is already a optimized_kernel selected for framework '{framework}'")
|
|
164
|
+
else:
|
|
165
|
+
config[f"{framework}.optimized_kernel"] = "cmsis_nn"
|
|
166
|
+
|
|
167
|
+
def get_platform_defs(self, platform):
|
|
168
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
169
|
+
return {
|
|
170
|
+
"MURISCVNN": self.enabled,
|
|
171
|
+
"MURISCVNN_DIR": self.muriscvnn_dir,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
def get_required_cache_flags(self):
|
|
175
|
+
ret = {}
|
|
176
|
+
|
|
177
|
+
ret["tflmc.exe"] = ["muriscvnn"]
|
|
178
|
+
return ret
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@register_feature("cmsisnn")
|
|
182
|
+
class Cmsisnn(SetupFeature, FrameworkFeature, PlatformFeature):
|
|
183
|
+
"""CMSIS-NN kernels for TFLite Micro"""
|
|
184
|
+
|
|
185
|
+
DEFAULTS = {
|
|
186
|
+
**FeatureBase.DEFAULTS,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
REQUIRED = ["cmsisnn.dir"]
|
|
190
|
+
|
|
191
|
+
def __init__(self, features=None, config=None):
|
|
192
|
+
super().__init__("cmsisnn", features=features, config=config)
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def cmsisnn_dir(self):
|
|
196
|
+
return str(self.config["cmsisnn.dir"])
|
|
197
|
+
|
|
198
|
+
def add_framework_config(self, framework, config):
|
|
199
|
+
assert framework == "tflm", f"Unsupported feature '{self.name}' for framework '{framework}'"
|
|
200
|
+
if f"{framework}.optimized_kernel" in config and config[f"{framework}.optimized_kernel"] not in [
|
|
201
|
+
None,
|
|
202
|
+
"cmsis_nn",
|
|
203
|
+
]:
|
|
204
|
+
RuntimeError(f"There is already a optimized_kernel selected for framework '{framework}'")
|
|
205
|
+
else:
|
|
206
|
+
config[f"{framework}.optimized_kernel"] = "cmsis_nn"
|
|
207
|
+
|
|
208
|
+
def get_platform_defs(self, platform):
|
|
209
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
210
|
+
return {
|
|
211
|
+
"CMSISNN": self.enabled,
|
|
212
|
+
"CMSISNN_DIR": self.cmsisnn_dir,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
def get_required_cache_flags(self):
|
|
216
|
+
ret = {}
|
|
217
|
+
ret["tflmc.exe"] = ["cmsisnn"]
|
|
218
|
+
return ret
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@register_feature("cmsisnnbyoc")
|
|
222
|
+
class CmsisnnByoc(SetupFeature, BackendFeature, PlatformFeature):
|
|
223
|
+
"""CMSIS-NN kernels for TVM using BYOC wrappers."""
|
|
224
|
+
|
|
225
|
+
DEFAULTS = {
|
|
226
|
+
**FeatureBase.DEFAULTS,
|
|
227
|
+
"mcpu": None, # mve: cortex-m55, dsp: cortex-m4, cortex-m7, cortex-m33, cortex-m35p
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
REQUIRED = ["cmsisnn.dir"]
|
|
231
|
+
|
|
232
|
+
def __init__(self, features=None, config=None):
|
|
233
|
+
super().__init__("cmsisnnbyoc", features=features, config=config)
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def cmsisnn_dir(self):
|
|
237
|
+
return str(self.config["cmsisnn.dir"])
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def mcpu(self):
|
|
241
|
+
return self.config["mcpu"]
|
|
242
|
+
|
|
243
|
+
def add_backend_config(self, backend, config):
|
|
244
|
+
assert backend in SUPPORTED_TVM_BACKENDS, f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
245
|
+
extras = config.get(f"{backend}.extra_target", [])
|
|
246
|
+
if "cmsis-nn" not in extras:
|
|
247
|
+
if isinstance(extras, str):
|
|
248
|
+
extras = [extras]
|
|
249
|
+
extras.append("cmsis-nn")
|
|
250
|
+
config[f"{backend}.extra_target"] = extras
|
|
251
|
+
if self.mcpu:
|
|
252
|
+
# Ideally cmsisnnbyoc would have a mvei/dsp feature which could be used to set this automatically
|
|
253
|
+
config[f"{backend}.extra_target_mcpu"] = self.mcpu
|
|
254
|
+
|
|
255
|
+
def get_platform_defs(self, platform):
|
|
256
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
257
|
+
return {
|
|
258
|
+
"CMSISNN": self.enabled,
|
|
259
|
+
"CMSISNN_DIR": self.cmsisnn_dir,
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
def get_required_cache_flags(self):
|
|
263
|
+
ret = {}
|
|
264
|
+
ret["tvm.build_dir"] = ["cmsisnn"]
|
|
265
|
+
return ret
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@register_feature("muriscvnnbyoc")
|
|
269
|
+
class MuriscvnnByoc(SetupFeature, BackendFeature, PlatformFeature):
|
|
270
|
+
"""MuRiscvNN kernels for TVM using BYOC wrappers."""
|
|
271
|
+
|
|
272
|
+
DEFAULTS = {
|
|
273
|
+
**FeatureBase.DEFAULTS,
|
|
274
|
+
"mcpu": None, # mve: cortex-m55, dsp: cortex-m4, cortex-m7, cortex-m33, cortex-m35p
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
REQUIRED = ["muriscvnn.src_dir"]
|
|
278
|
+
|
|
279
|
+
def __init__(self, features=None, config=None):
|
|
280
|
+
super().__init__("muriscvnnbyoc", features=features, config=config)
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def muriscvnn_dir(self):
|
|
284
|
+
return str(self.config["muriscvnn.src_dir"])
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def mcpu(self):
|
|
288
|
+
return self.config["mcpu"]
|
|
289
|
+
|
|
290
|
+
def add_backend_config(self, backend, config):
|
|
291
|
+
assert backend in SUPPORTED_TVM_BACKENDS, f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
292
|
+
extras = config.get(f"{backend}.extra_target", [])
|
|
293
|
+
if "cmsis-nn" not in extras:
|
|
294
|
+
if isinstance(extras, str):
|
|
295
|
+
extras = [extras]
|
|
296
|
+
extras.append("cmsis-nn")
|
|
297
|
+
config[f"{backend}.extra_target"] = extras
|
|
298
|
+
if self.mcpu:
|
|
299
|
+
# Ideally muriscvnnbyoc would have a vext/pext feature which could be used to set this automatically
|
|
300
|
+
config[f"{backend}.extra_target_mcpu"] = self.mcpu
|
|
301
|
+
|
|
302
|
+
def get_platform_defs(self, platform):
|
|
303
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
304
|
+
return {
|
|
305
|
+
"MURISCVNN": self.enabled,
|
|
306
|
+
"MURISCVNN_DIR": self.muriscvnn_dir,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
def get_required_cache_flags(self):
|
|
310
|
+
ret = {}
|
|
311
|
+
ret["tvm.build_dir"] = ["cmsisnn"]
|
|
312
|
+
return ret
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# @before_feature("muriscvnn") # TODO: implement something like this
|
|
316
|
+
@register_feature("vext")
|
|
317
|
+
class Vext(SetupFeature, TargetFeature, PlatformFeature):
|
|
318
|
+
"""Enable vector extension for supported RISC-V targets"""
|
|
319
|
+
|
|
320
|
+
DEFAULTS = {
|
|
321
|
+
**FeatureBase.DEFAULTS,
|
|
322
|
+
"vlen": 64, # TODO; define reasonable default? (Or put defaults in target and overwrite of not None)
|
|
323
|
+
"elen": 32,
|
|
324
|
+
# use target-side settings by default
|
|
325
|
+
"spec": None,
|
|
326
|
+
"embedded": None,
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
REQUIRED = []
|
|
330
|
+
|
|
331
|
+
def __init__(self, features=None, config=None):
|
|
332
|
+
super().__init__("vext", features=features, config=config)
|
|
333
|
+
|
|
334
|
+
@property
|
|
335
|
+
def vlen(self):
|
|
336
|
+
return int(self.config["vlen"])
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def elen(self):
|
|
340
|
+
return int(self.config["elen"])
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def spec(self):
|
|
344
|
+
return self.config["spec"]
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def embedded(self):
|
|
348
|
+
return self.config["embedded"]
|
|
349
|
+
|
|
350
|
+
def get_target_config(self, target):
|
|
351
|
+
# TODO: enforce llvm toolchain using add_compile_config and CompileFeature?
|
|
352
|
+
assert is_power_of_two(self.vlen)
|
|
353
|
+
return filter_none(
|
|
354
|
+
{
|
|
355
|
+
f"{target}.enable_vext": True,
|
|
356
|
+
f"{target}.vlen": self.vlen,
|
|
357
|
+
f"{target}.elen": self.elen,
|
|
358
|
+
f"{target}.vext_spec": self.spec,
|
|
359
|
+
f"{target}.embedded_vext": self.embedded,
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
# It would be great if we could enforce an llvm toolchain here
|
|
364
|
+
# def add_compile_config(self, config):
|
|
365
|
+
# # TODO: enforce llvm toolchain using add_compile_config and CompileFeature?
|
|
366
|
+
# if "mlif.toolchain" in config:
|
|
367
|
+
# assert "mlif.toolchain" == "llvm", "Vext requires LLVM target sw"
|
|
368
|
+
# else:
|
|
369
|
+
# config["mlif.toolchain"] = "llvm"
|
|
370
|
+
|
|
371
|
+
def get_platform_defs(self, platform):
|
|
372
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
373
|
+
return {"RISCV_VEXT": self.enabled}
|
|
374
|
+
|
|
375
|
+
def get_required_cache_flags(self):
|
|
376
|
+
return {
|
|
377
|
+
"muriscvnn.lib": ["vext"],
|
|
378
|
+
"tflmc.exe": ["vext"],
|
|
379
|
+
"riscv_gcc.install_dir": ["vext"],
|
|
380
|
+
"riscv_gcc.name": ["vext"],
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
@register_feature("pext")
|
|
385
|
+
class Pext(SetupFeature, TargetFeature, PlatformFeature):
|
|
386
|
+
"""Enable packed SIMD extension for supported RISC-V targets"""
|
|
387
|
+
|
|
388
|
+
DEFAULTS = {
|
|
389
|
+
**FeatureBase.DEFAULTS,
|
|
390
|
+
# use target-side settings by default
|
|
391
|
+
"spec": None,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
REQUIRED = []
|
|
395
|
+
|
|
396
|
+
def __init__(self, features=None, config=None):
|
|
397
|
+
super().__init__("pext", features=features, config=config)
|
|
398
|
+
|
|
399
|
+
@property
|
|
400
|
+
def spec(self):
|
|
401
|
+
return self.config["spec"]
|
|
402
|
+
|
|
403
|
+
def get_target_config(self, target):
|
|
404
|
+
return filter_none(
|
|
405
|
+
{
|
|
406
|
+
f"{target}.enable_pext": True, # Handle via arch characters in the future
|
|
407
|
+
f"{target}.pext_spec": self.spec,
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
def get_platform_defs(self, platform):
|
|
412
|
+
assert platform in ["mlif"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
413
|
+
return {"RISCV_PEXT": self.enabled}
|
|
414
|
+
|
|
415
|
+
def get_required_cache_flags(self):
|
|
416
|
+
# These will be merged automatically with existing ones
|
|
417
|
+
return {
|
|
418
|
+
"muriscvnn.lib": ["pext"],
|
|
419
|
+
"tflmc.exe": ["pext"],
|
|
420
|
+
"riscv_gcc.install_dir": ["pext"],
|
|
421
|
+
"riscv_gcc.name": ["pext"],
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
@register_feature("debug")
|
|
426
|
+
class Debug(SetupFeature, PlatformFeature):
|
|
427
|
+
"""Enable debugging ability of target software."""
|
|
428
|
+
|
|
429
|
+
def __init__(self, features=None, config=None):
|
|
430
|
+
super().__init__("debug", features=features, config=config)
|
|
431
|
+
|
|
432
|
+
def get_required_cache_flags(self):
|
|
433
|
+
return {} if self.enabled else {} # TODO: remove?
|
|
434
|
+
|
|
435
|
+
def get_platform_config(self, platform):
|
|
436
|
+
return {f"{platform}.debug": self.enabled}
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
@register_feature("gdbserver")
|
|
440
|
+
class GdbServer(TargetFeature):
|
|
441
|
+
"""Start debugging session for target software using gdbserver."""
|
|
442
|
+
|
|
443
|
+
DEFAULTS = {
|
|
444
|
+
**FeatureBase.DEFAULTS,
|
|
445
|
+
"attach": None,
|
|
446
|
+
"port": None,
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
def __init__(self, features=None, config=None):
|
|
450
|
+
super().__init__("gdbserver", features=features, config=config)
|
|
451
|
+
|
|
452
|
+
@property
|
|
453
|
+
def attach(self):
|
|
454
|
+
value = self.config["attach"]
|
|
455
|
+
return str2bool(value, allow_none=True) if not isinstance(value, (bool, int)) else value
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def port(self):
|
|
459
|
+
return int(self.config["port"]) if self.config["port"] is not None else None
|
|
460
|
+
|
|
461
|
+
def get_target_config(self, target):
|
|
462
|
+
assert target in ["host_x86", "etiss_pulpino", "ovpsim"]
|
|
463
|
+
return filter_none(
|
|
464
|
+
{
|
|
465
|
+
f"{target}.gdbserver_enable": self.enabled,
|
|
466
|
+
f"{target}.gdbserver_attach": self.attach,
|
|
467
|
+
f"{target}.gdbserver_port": self.port,
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
@register_feature("etissdbg")
|
|
473
|
+
class ETISSDebug(SetupFeature, TargetFeature):
|
|
474
|
+
"""Debug ETISS internals."""
|
|
475
|
+
|
|
476
|
+
def __init__(self, features=None, config=None):
|
|
477
|
+
super().__init__("etissdbg", features=features, config=config)
|
|
478
|
+
|
|
479
|
+
def get_required_cache_flags(self):
|
|
480
|
+
return {"etiss.install_dir": ["dbg"], "etissvp.script": ["dbg"]} if self.enabled else {}
|
|
481
|
+
|
|
482
|
+
def get_target_config(self, target):
|
|
483
|
+
assert target in ["etiss_pulpino"]
|
|
484
|
+
return {"etiss_pulpino.debug_etiss": self.enabled}
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
@register_feature("trace")
|
|
488
|
+
class Trace(TargetFeature):
|
|
489
|
+
"""Enable tracing of all memory accesses in ETISS."""
|
|
490
|
+
|
|
491
|
+
# TODO: support ovpsim --trace --tracemem SA
|
|
492
|
+
|
|
493
|
+
def __init__(self, features=None, config=None):
|
|
494
|
+
super().__init__("trace", features=features, config=config)
|
|
495
|
+
|
|
496
|
+
def get_target_config(self, target):
|
|
497
|
+
assert target in ["etiss_pulpino"]
|
|
498
|
+
return {"etiss_pulpino.trace_memory": self.enabled}
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
@register_feature("unpacked_api")
|
|
502
|
+
class UnpackedApi(BackendFeature): # TODO: should this be a feature or config only?
|
|
503
|
+
"""Use unpacked interface api for TVMAOT backend to reduce stack usage."""
|
|
504
|
+
|
|
505
|
+
def __init__(self, features=None, config=None):
|
|
506
|
+
super().__init__("unpacked_api", features=features, config=config)
|
|
507
|
+
|
|
508
|
+
def get_backend_config(self, backend):
|
|
509
|
+
assert backend in ["tvmaot"], f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
510
|
+
return {f"{backend}.unpacked_api": self.enabled}
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
@register_feature("packed")
|
|
514
|
+
class Packed(FrameworkFeature, FrontendFeature, BackendFeature, SetupFeature):
|
|
515
|
+
"""Sub-8-bit and sparsity feature for TFLite Micro kernels."""
|
|
516
|
+
|
|
517
|
+
def __init__(self, features=None, config=None):
|
|
518
|
+
super().__init__("packed", features=features, config=config)
|
|
519
|
+
|
|
520
|
+
def get_framework_config(self, framework):
|
|
521
|
+
raise NotImplementedError
|
|
522
|
+
|
|
523
|
+
def get_frontend_config(self, frontend):
|
|
524
|
+
assert frontend in ["tflm"], f"Unsupported feature '{self.name} for frontend '{frontend}''"
|
|
525
|
+
return {f"{frontend}.use_packed_weights": self.enabled}
|
|
526
|
+
|
|
527
|
+
def get_backend_config(self, backend):
|
|
528
|
+
raise NotImplementedError
|
|
529
|
+
|
|
530
|
+
def get_required_cache_flags(self):
|
|
531
|
+
return {"tflmc.exe": ["packed"]}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
@register_feature("packing")
|
|
535
|
+
class Packing(FrontendFeature):
|
|
536
|
+
"""Sub-8-bit and sparse weight packing for TFLite Frontend."""
|
|
537
|
+
|
|
538
|
+
def __init__(self, features=None, config=None):
|
|
539
|
+
super().__init__("packing", features=features, config=config)
|
|
540
|
+
|
|
541
|
+
def get_frontend_config(self, frontend):
|
|
542
|
+
assert frontend in ["tflm"], f"Unsupported feature '{self.name} for frontend '{frontend}''"
|
|
543
|
+
raise NotImplementedError
|
|
544
|
+
return {f"{frontend}.pack_weights": self.enabled}
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
@register_feature("usmp")
|
|
548
|
+
class Usmp(BackendFeature):
|
|
549
|
+
"""Unified Static Memory Planning algorithm integrated in TVM"""
|
|
550
|
+
|
|
551
|
+
DEFAULTS = {
|
|
552
|
+
**FeatureBase.DEFAULTS,
|
|
553
|
+
"algorithm": "greedy_by_conflicts", # options: greedy_by_conflicts, greedy_by_size, hill_climb
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
def __init__(self, features=None, config=None):
|
|
557
|
+
super().__init__("usmp", features=features, config=config)
|
|
558
|
+
|
|
559
|
+
@property
|
|
560
|
+
def algorithm(self):
|
|
561
|
+
return str(self.config["algorithm"])
|
|
562
|
+
|
|
563
|
+
def add_backend_config(self, backend, config):
|
|
564
|
+
assert backend in ["tvmaot"], f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
565
|
+
if f"{backend}.extra_pass_config" in config:
|
|
566
|
+
tmp = config[f"{backend}.extra_pass_config"]
|
|
567
|
+
elif "extra_pass_config" in config:
|
|
568
|
+
tmp = config["extra_pass_config"]
|
|
569
|
+
else:
|
|
570
|
+
tmp = {}
|
|
571
|
+
if isinstance(tmp, str):
|
|
572
|
+
import ast
|
|
573
|
+
|
|
574
|
+
tmp = ast.literal_eval(tmp)
|
|
575
|
+
assert isinstance(tmp, dict)
|
|
576
|
+
tmp["tir.usmp.enable"] = self.enabled
|
|
577
|
+
if self.algorithm in ["greedy_by_size", "greedy_by_conflicts", "hill_climb"]:
|
|
578
|
+
tmp["tir.usmp.algorithm"] = self.algorithm
|
|
579
|
+
else:
|
|
580
|
+
tmp["tir.usmp.custom_algorithm"] = self.algorithm
|
|
581
|
+
config.update(
|
|
582
|
+
{f"{backend}.extra_pass_config": tmp, f"{backend}.arena_size": 0}
|
|
583
|
+
) # In recent TVM versions USMP will have it's own arena.
|
|
584
|
+
|
|
585
|
+
# -> enable this via backend
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
@register_feature("moiopt")
|
|
589
|
+
class MOIOPT(BackendFeature):
|
|
590
|
+
"""Memory-Optimizing, Inter-Operator Tiling - currently only supported with custom TVM"""
|
|
591
|
+
|
|
592
|
+
DEFAULTS = {
|
|
593
|
+
**FeatureBase.DEFAULTS,
|
|
594
|
+
"noftp": False,
|
|
595
|
+
"onlyftp": False,
|
|
596
|
+
"norecurse": False,
|
|
597
|
+
"maxpartitions": 0,
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
def __init__(self, features=None, config=None):
|
|
601
|
+
super().__init__("moiopt", features=features, config=config)
|
|
602
|
+
|
|
603
|
+
def add_backend_config(self, backend, config):
|
|
604
|
+
assert backend in ["tvmaot", "tvmrt"], f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
605
|
+
if f"{backend}.extra_pass_config" in config:
|
|
606
|
+
tmp = config[f"{backend}.extra_pass_config"]
|
|
607
|
+
elif "extra_pass_config" in config:
|
|
608
|
+
tmp = config["extra_pass_config"]
|
|
609
|
+
else:
|
|
610
|
+
tmp = {}
|
|
611
|
+
tmp["relay.moiopt.enable"] = self.enabled
|
|
612
|
+
tmp["relay.moiopt.noftp"] = self.config["noftp"]
|
|
613
|
+
tmp["relay.moiopt.onlyftp"] = self.config["onlyftp"]
|
|
614
|
+
tmp["relay.moiopt.norecurse"] = self.config["norecurse"]
|
|
615
|
+
tmp["relay.moiopt.maxpartitions"] = self.config["maxpartitions"]
|
|
616
|
+
config.update({f"{backend}.extra_pass_config": tmp})
|
|
617
|
+
|
|
618
|
+
# -> enable this via backend
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
@register_feature("visualize")
|
|
622
|
+
class Visualize(FrontendFeature):
|
|
623
|
+
"""Visualize TFLite models."""
|
|
624
|
+
|
|
625
|
+
DEFAULTS = {
|
|
626
|
+
**FeatureBase.DEFAULTS,
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
REQUIRED = ["tflite_visualize.exe"]
|
|
630
|
+
|
|
631
|
+
def __init__(self, features=None, config=None):
|
|
632
|
+
super().__init__("visualize", features=features, config=config)
|
|
633
|
+
|
|
634
|
+
@property
|
|
635
|
+
def tflite_visualize_exe(self):
|
|
636
|
+
return self.config["tflite_visualize.exe"]
|
|
637
|
+
|
|
638
|
+
def get_frontend_config(self, frontend):
|
|
639
|
+
assert frontend in ["tflite"], f"Unsupported feature '{self.name}' for frontend '{frontend}'"
|
|
640
|
+
return filter_none(
|
|
641
|
+
{
|
|
642
|
+
f"{frontend}.visualize_enable": self.enabled,
|
|
643
|
+
f"{frontend}.visualize_script": self.tflite_visualize_exe,
|
|
644
|
+
}
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
def update_formats(self, frontend, input_formats, output_formats):
|
|
648
|
+
assert frontend in ["tflite"], f"Unsupported feature '{self.name}' for frontend '{frontend}'"
|
|
649
|
+
if self.enabled:
|
|
650
|
+
output_formats.append(ArtifactFormat.TEXT)
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
@register_feature("relayviz")
|
|
654
|
+
class Relayviz(FrontendFeature):
|
|
655
|
+
"""Visualize TVM relay models."""
|
|
656
|
+
|
|
657
|
+
DEFAULTS = {
|
|
658
|
+
**FeatureBase.DEFAULTS,
|
|
659
|
+
"plotter": "term", # Alternative: dot
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
def __init__(self, features=None, config=None):
|
|
663
|
+
super().__init__("relayviz", features=features, config=config)
|
|
664
|
+
|
|
665
|
+
@property
|
|
666
|
+
def plotter(self):
|
|
667
|
+
return self.config.get("plotter", None)
|
|
668
|
+
|
|
669
|
+
def get_frontend_config(self, frontend):
|
|
670
|
+
assert frontend in ["relay"], f"Unsupported feature '{self.name}' for frontend '{frontend}'"
|
|
671
|
+
return filter_none(
|
|
672
|
+
{
|
|
673
|
+
f"{frontend}.visualize_graph": self.enabled,
|
|
674
|
+
f"{frontend}.relayviz_plotter": self.plotter,
|
|
675
|
+
}
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
def update_formats(self, frontend, input_formats, output_formats):
|
|
679
|
+
assert frontend in ["relay"], f"Unsupported feature '{self.name}' for frontend '{frontend}'"
|
|
680
|
+
if self.enabled:
|
|
681
|
+
output_formats.append(ArtifactFormat.TEXT)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
@register_feature("autotuned")
|
|
685
|
+
class Autotuned(BackendFeature):
|
|
686
|
+
"""Use existing TVM autotuning logs in backend."""
|
|
687
|
+
|
|
688
|
+
# TODO: FronendFeature to collect tuning logs or will we store them somewhere else?
|
|
689
|
+
|
|
690
|
+
DEFAULTS = {
|
|
691
|
+
**FeatureBase.DEFAULTS,
|
|
692
|
+
"results_file": None,
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
def __init__(self, features=None, config=None):
|
|
696
|
+
super().__init__("autotuned", features=features, config=config)
|
|
697
|
+
|
|
698
|
+
@property
|
|
699
|
+
def results_file(self):
|
|
700
|
+
return self.config["results_file"] if "results_file" in self.config else None
|
|
701
|
+
|
|
702
|
+
def get_backend_config(self, backend):
|
|
703
|
+
assert backend in SUPPORTED_TVM_BACKENDS
|
|
704
|
+
# TODO: error handling her eor on backend?
|
|
705
|
+
return filter_none(
|
|
706
|
+
{
|
|
707
|
+
f"{backend}.use_tuning_results": self.enabled,
|
|
708
|
+
f"{backend}.autotuning_results_file": self.results_file,
|
|
709
|
+
}
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
@register_feature("autotune")
|
|
714
|
+
class Autotune(PlatformFeature, RunFeature):
|
|
715
|
+
"""Use the TVM autotuner inside the backend to generate tuning logs."""
|
|
716
|
+
|
|
717
|
+
DEFAULTS = {
|
|
718
|
+
**FeatureBase.DEFAULTS,
|
|
719
|
+
"results_file": None,
|
|
720
|
+
"append": None,
|
|
721
|
+
"tuner": None,
|
|
722
|
+
"trials": None,
|
|
723
|
+
"early_stopping": None,
|
|
724
|
+
"num_workers": None,
|
|
725
|
+
"max_parallel": None,
|
|
726
|
+
"use_rpc": None,
|
|
727
|
+
"timeout": None,
|
|
728
|
+
"mode": None,
|
|
729
|
+
"visualize": None,
|
|
730
|
+
"tasks": None,
|
|
731
|
+
# All None to use the defaults defined in the backend instead
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
def __init__(self, features=None, config=None):
|
|
735
|
+
super().__init__("autotune", features=features, config=config)
|
|
736
|
+
|
|
737
|
+
@property
|
|
738
|
+
def results_file(self):
|
|
739
|
+
return self.config["results_file"] if "results_file" in self.config else None
|
|
740
|
+
|
|
741
|
+
@property
|
|
742
|
+
def append(self):
|
|
743
|
+
return self.config["append"] if "append" in self.config else None
|
|
744
|
+
|
|
745
|
+
@property
|
|
746
|
+
def tuner(self):
|
|
747
|
+
return self.config["tuner"] if "tuner" in self.config else None
|
|
748
|
+
|
|
749
|
+
@property
|
|
750
|
+
def trials(self):
|
|
751
|
+
return self.config["trials"] if "trials" in self.config else None
|
|
752
|
+
|
|
753
|
+
@property
|
|
754
|
+
def early_stopping(self):
|
|
755
|
+
return self.config["early_stopping"] if "early_stopping" in self.config else None
|
|
756
|
+
|
|
757
|
+
@property
|
|
758
|
+
def num_workers(self):
|
|
759
|
+
return self.config["num_workers"] if "num_workers" in self.config else None
|
|
760
|
+
|
|
761
|
+
@property
|
|
762
|
+
def max_parallel(self):
|
|
763
|
+
return self.config["max_parallel"] if "max_parallel" in self.config else None
|
|
764
|
+
|
|
765
|
+
@property
|
|
766
|
+
def use_rpc(self):
|
|
767
|
+
return self.config["use_rpc"] if "use_rpc" in self.config else None
|
|
768
|
+
|
|
769
|
+
@property
|
|
770
|
+
def timeout(self):
|
|
771
|
+
return self.config["timeout"] if "timeout" in self.config else None
|
|
772
|
+
|
|
773
|
+
@property
|
|
774
|
+
def mode(self):
|
|
775
|
+
return self.config["mode"]
|
|
776
|
+
|
|
777
|
+
@property
|
|
778
|
+
def visualize(self):
|
|
779
|
+
return self.config["visualize"]
|
|
780
|
+
|
|
781
|
+
@property
|
|
782
|
+
def tasks(self):
|
|
783
|
+
return self.config["tasks"]
|
|
784
|
+
|
|
785
|
+
def get_platform_config(self, platform):
|
|
786
|
+
assert platform in ["tvm", "microtvm"]
|
|
787
|
+
# TODO: figure out a default path automatically
|
|
788
|
+
return filter_none(
|
|
789
|
+
{
|
|
790
|
+
f"{platform}.autotuning_enable": self.enabled,
|
|
791
|
+
f"{platform}.autotuning_results_file": self.results_file,
|
|
792
|
+
f"{platform}.autotuning_append": self.append,
|
|
793
|
+
f"{platform}.autotuning_tuner": self.tuner,
|
|
794
|
+
f"{platform}.autotuning_trials": self.trials,
|
|
795
|
+
f"{platform}.autotuning_early_stopping": self.early_stopping,
|
|
796
|
+
f"{platform}.autotuning_num_workers": self.num_workers,
|
|
797
|
+
f"{platform}.autotuning_max_parallel": self.max_parallel,
|
|
798
|
+
f"{platform}.autotuning_timeout": self.timeout,
|
|
799
|
+
f"{platform}.autotuning_mode": self.mode,
|
|
800
|
+
f"{platform}.autotuning_visualize": self.visualize,
|
|
801
|
+
f"{platform}.autotuning_tasks": self.tasks,
|
|
802
|
+
}
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
def get_run_config(self):
|
|
806
|
+
return {"run.tune_enabled": self.enabled}
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
@register_feature("disable_legalize")
|
|
810
|
+
class DisableLegalize(BackendFeature, SetupFeature):
|
|
811
|
+
"""Enable transformation to reduces sizes of intermediate buffers by skipping legalization passes."""
|
|
812
|
+
|
|
813
|
+
REQUIRED = ["tvm_extensions.wrapper"]
|
|
814
|
+
|
|
815
|
+
def __init__(self, features=None, config=None):
|
|
816
|
+
super().__init__("disable_legalize", features=features, config=config)
|
|
817
|
+
|
|
818
|
+
@property
|
|
819
|
+
def tvm_extensions_wrapper(self):
|
|
820
|
+
return self.config["tvm_extensions.wrapper"]
|
|
821
|
+
|
|
822
|
+
def add_backend_config(self, backend, config):
|
|
823
|
+
assert backend in SUPPORTED_TVM_BACKENDS, f"Unsupported feature '{self.name}' for backend '{backend}'"
|
|
824
|
+
if f"{backend}.tvmc_extra_args" in config:
|
|
825
|
+
config[f"{backend}.tvmc_extra_args"].append("--disable-legalize")
|
|
826
|
+
else:
|
|
827
|
+
config[f"{backend}.tvmc_extra_args"] = ["--disable-legalize"]
|
|
828
|
+
if f"{backend}.tvmc_custom_script" in config:
|
|
829
|
+
assert config[f"{backend}.tvmc_custom_script"] is None or str(
|
|
830
|
+
config[f"{backend}.tvmc_custom_script"]
|
|
831
|
+
) == str(
|
|
832
|
+
self.tvm_extensions_wrapper
|
|
833
|
+
), f"{backend}.tvmc_custom_script is already set. Can't enable feature: {self.name}"
|
|
834
|
+
config[f"{backend}.tvmc_custom_script"] = self.tvm_extensions_wrapper
|
|
835
|
+
|
|
836
|
+
def get_required_cache_flags(self):
|
|
837
|
+
ret = {}
|
|
838
|
+
|
|
839
|
+
ret["tvm.pythonpath"] = ["patch"]
|
|
840
|
+
return ret
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
@register_feature("demo")
|
|
844
|
+
class Demo(PlatformFeature):
|
|
845
|
+
"""Run demo application instead of benchmarking code."""
|
|
846
|
+
|
|
847
|
+
DEFAULTS = {
|
|
848
|
+
**FeatureBase.DEFAULTS,
|
|
849
|
+
"board": None,
|
|
850
|
+
"print_stats": False,
|
|
851
|
+
"print_interval_ms": 5000,
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
REQUIRED = []
|
|
855
|
+
|
|
856
|
+
def __init__(self, features=None, config=None):
|
|
857
|
+
super().__init__("demo", features=features, config=config)
|
|
858
|
+
|
|
859
|
+
@property
|
|
860
|
+
def board(self):
|
|
861
|
+
return self.config["board"]
|
|
862
|
+
|
|
863
|
+
@property
|
|
864
|
+
def print_stats(self):
|
|
865
|
+
return self.config["print_stats"]
|
|
866
|
+
|
|
867
|
+
@property
|
|
868
|
+
def print_interval_ms(self):
|
|
869
|
+
return self.config["print_interval_ms"]
|
|
870
|
+
|
|
871
|
+
def get_platform_defs(self, platform):
|
|
872
|
+
assert platform in ["espidf"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
873
|
+
# TODO: espidf.demo_mode, disable wdt, runtime stats,
|
|
874
|
+
return {}
|
|
875
|
+
|
|
876
|
+
def get_platform_config(self, platform):
|
|
877
|
+
assert platform in ["espidf"], f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
878
|
+
# TODO: espidf.demo_mode, disable wdt, runtime stats,
|
|
879
|
+
return {}
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
@register_feature("cachesim")
|
|
883
|
+
class CacheSim(TargetFeature):
|
|
884
|
+
"""Collect information on cache misses etc. with spike target"""
|
|
885
|
+
|
|
886
|
+
DEFAULTS = {
|
|
887
|
+
**FeatureBase.DEFAULTS,
|
|
888
|
+
"ic_enable": False,
|
|
889
|
+
"ic_config": "64:8:32",
|
|
890
|
+
"dc_enable": False,
|
|
891
|
+
"dc_config": "64:8:32",
|
|
892
|
+
"l2_enable": False,
|
|
893
|
+
"l2_config": "262144:8:32", # TODO: find a meaningful value
|
|
894
|
+
"log_misses": False,
|
|
895
|
+
"detailed": False,
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
REQUIRED = []
|
|
899
|
+
|
|
900
|
+
def __init__(self, features=None, config=None):
|
|
901
|
+
super().__init__("cachesim", features=features, config=config)
|
|
902
|
+
|
|
903
|
+
@property
|
|
904
|
+
def ic_enable(self):
|
|
905
|
+
value = self.config["ic_enable"]
|
|
906
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
907
|
+
|
|
908
|
+
@property
|
|
909
|
+
def ic_config(self):
|
|
910
|
+
return self.config["ic_config"]
|
|
911
|
+
|
|
912
|
+
@property
|
|
913
|
+
def dc_enable(self):
|
|
914
|
+
value = self.config["dc_enable"]
|
|
915
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
916
|
+
|
|
917
|
+
@property
|
|
918
|
+
def dc_config(self):
|
|
919
|
+
return self.config["dc_config"]
|
|
920
|
+
|
|
921
|
+
@property
|
|
922
|
+
def l2_enable(self):
|
|
923
|
+
value = self.config["l2_enable"]
|
|
924
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
925
|
+
|
|
926
|
+
@property
|
|
927
|
+
def l2_config(self):
|
|
928
|
+
return self.config["l2_config"]
|
|
929
|
+
|
|
930
|
+
@property
|
|
931
|
+
def log_misses(self):
|
|
932
|
+
value = self.config["log_misses"]
|
|
933
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
934
|
+
|
|
935
|
+
@property
|
|
936
|
+
def detailed(self):
|
|
937
|
+
value = self.config["detailed"]
|
|
938
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
939
|
+
|
|
940
|
+
def add_target_config(self, target, config):
|
|
941
|
+
assert target in ["spike"], f"Unsupported feature '{self.name}' for target '{target}'"
|
|
942
|
+
if self.enabled:
|
|
943
|
+
spike_args = config.get(f"{target}.extra_args", [])
|
|
944
|
+
if self.ic_enable:
|
|
945
|
+
assert self.ic_config is not None and len(self.ic_config) > 0
|
|
946
|
+
spike_args.append(f"--ic={self.ic_config}")
|
|
947
|
+
if self.dc_enable:
|
|
948
|
+
assert self.dc_config is not None and len(self.dc_config) > 0
|
|
949
|
+
spike_args.append(f"--dc={self.dc_config}")
|
|
950
|
+
if self.l2_enable:
|
|
951
|
+
assert self.l2_config is not None and len(self.l2_config) > 0
|
|
952
|
+
spike_args.append(f"--l2={self.l2_config}")
|
|
953
|
+
if self.log_misses:
|
|
954
|
+
spike_args.append("--log-cache-miss")
|
|
955
|
+
config.update({f"{target}.extra_args": spike_args})
|
|
956
|
+
|
|
957
|
+
def get_target_callbacks(self, target):
|
|
958
|
+
assert target in ["spike"], f"Unsupported feature '{self.name}' for target '{target}'"
|
|
959
|
+
if self.enabled:
|
|
960
|
+
|
|
961
|
+
def cachesim_callback(stdout, metrics, artifacts):
|
|
962
|
+
"""Callback which parses the targets output and updates the generated metrics and artifacts."""
|
|
963
|
+
expr = (
|
|
964
|
+
r"(D|I|L2)\$ ((?:Bytes (?:Read|Written))|(?:Read|Write) "
|
|
965
|
+
r"(?:Accesses|Misses)|(?:Writebacks)|(?:Miss Rate)):\s*(\d+\.?\d*%?)*"
|
|
966
|
+
)
|
|
967
|
+
matches = re.compile(expr).findall(stdout)
|
|
968
|
+
prefixes = [
|
|
969
|
+
x for (x, y) in zip(["I", "D", "L2"], [self.ic_enable, self.dc_enable, self.l2_enable]) if y
|
|
970
|
+
]
|
|
971
|
+
for groups in matches:
|
|
972
|
+
assert len(groups) == 3
|
|
973
|
+
prefix, label, value = groups
|
|
974
|
+
if not self.detailed:
|
|
975
|
+
if "Rate" not in label:
|
|
976
|
+
continue
|
|
977
|
+
value = int(value) if "%" not in value else float(value[:-1]) / 100
|
|
978
|
+
if prefix in prefixes:
|
|
979
|
+
for m in metrics:
|
|
980
|
+
m.add(f"{prefix}-Cache {label}", value)
|
|
981
|
+
return stdout
|
|
982
|
+
|
|
983
|
+
return None, cachesim_callback
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
@register_feature("log_instrs")
|
|
987
|
+
class LogInstructions(TargetFeature):
|
|
988
|
+
"""Enable logging of the executed instructions of a simulator-based target."""
|
|
989
|
+
|
|
990
|
+
DEFAULTS = {**FeatureBase.DEFAULTS, "to_file": False}
|
|
991
|
+
|
|
992
|
+
def __init__(self, features=None, config=None):
|
|
993
|
+
super().__init__("log_instrs", features=features, config=config)
|
|
994
|
+
|
|
995
|
+
@property
|
|
996
|
+
def to_file(self):
|
|
997
|
+
value = self.config["to_file"]
|
|
998
|
+
return str2bool(value, allow_none=True) if not isinstance(value, (bool, int)) else value
|
|
999
|
+
|
|
1000
|
+
def add_target_config(self, target, config):
|
|
1001
|
+
assert target in ["spike", "etiss_pulpino", "ovpsim", "gvsoc_pulp"]
|
|
1002
|
+
if not self.enabled:
|
|
1003
|
+
return
|
|
1004
|
+
if target == "spike":
|
|
1005
|
+
extra_args_new = config.get("extra_args", [])
|
|
1006
|
+
extra_args_new.append("-l")
|
|
1007
|
+
# if self.to_file:
|
|
1008
|
+
# extra_args_new.append("--log=?")
|
|
1009
|
+
config.update({f"{target}.extra_args": extra_args_new})
|
|
1010
|
+
elif target == "etiss_pulpino":
|
|
1011
|
+
plugins_new = config.get("plugins", [])
|
|
1012
|
+
plugins_new.append("PrintInstruction")
|
|
1013
|
+
config.update({f"{target}.plugins": plugins_new})
|
|
1014
|
+
elif target == "ovpsim":
|
|
1015
|
+
extra_args_new = config.get("extra_args", [])
|
|
1016
|
+
extra_args_new.append("--trace")
|
|
1017
|
+
# if self.to_file:
|
|
1018
|
+
# extra_args_new.append("--tracefile")
|
|
1019
|
+
config.update({f"{target}.extra_args": extra_args_new})
|
|
1020
|
+
elif target == "gvsoc_pulp":
|
|
1021
|
+
extra_args_new = config.get("extra_args", [])
|
|
1022
|
+
if self.to_file:
|
|
1023
|
+
extra_args_new.append(f"--trace=insn:{target}_instrs.log")
|
|
1024
|
+
"""
|
|
1025
|
+
TODO: The above code will generate a instruction log.
|
|
1026
|
+
But it will not be recorded by Artifact (which should be done in get_target_callbacks).
|
|
1027
|
+
The code to let it be recorded by Artifact is currently not added because of the following reasons:
|
|
1028
|
+
1. This feature is rarely used.
|
|
1029
|
+
2. GVSOC can directly write the instruction log into a file which should be much faster than
|
|
1030
|
+
read/write from the output. This makes GVSOC special and difficult to be adapted in the current
|
|
1031
|
+
code.
|
|
1032
|
+
3. This difficulty reflected in that the methods add_target_config and get_target_callbacks should
|
|
1033
|
+
have a consensus about where in the system file system the instruction log is written to and can be
|
|
1034
|
+
read from. This is not feasible in current code and the realization requires a workaround.
|
|
1035
|
+
"""
|
|
1036
|
+
else:
|
|
1037
|
+
extra_args_new.append("--trace=insn")
|
|
1038
|
+
config.update({f"{target}.extra_args": extra_args_new})
|
|
1039
|
+
|
|
1040
|
+
def get_target_callbacks(self, target):
|
|
1041
|
+
assert target in [
|
|
1042
|
+
"spike",
|
|
1043
|
+
"etiss_pulpino",
|
|
1044
|
+
"ovpsim",
|
|
1045
|
+
"gvsoc_pulp",
|
|
1046
|
+
], f"Unsupported feature '{self.name}' for target '{target}'"
|
|
1047
|
+
if self.enabled:
|
|
1048
|
+
if not target == "gvsoc_pulp":
|
|
1049
|
+
|
|
1050
|
+
def log_instrs_callback(stdout, metrics, artifacts):
|
|
1051
|
+
"""Callback which parses the targets output and updates the generated metrics and artifacts."""
|
|
1052
|
+
new_lines = []
|
|
1053
|
+
if self.to_file:
|
|
1054
|
+
# TODO: update stdout and remove log_instrs lines
|
|
1055
|
+
instrs = []
|
|
1056
|
+
for line in stdout.split("\n"):
|
|
1057
|
+
if target == "etiss_pulpino":
|
|
1058
|
+
expr = re.compile(r"0x[a-fA-F0-9]+: .* \[.*\]")
|
|
1059
|
+
elif target == "spike":
|
|
1060
|
+
expr = re.compile(r"core\s+\d+: 0x[a-fA-F0-9]+ \(0x[a-fA-F0-9]+\) .*")
|
|
1061
|
+
elif target == "ovpsim":
|
|
1062
|
+
expr = re.compile(
|
|
1063
|
+
r"Info 'riscvOVPsim\/cpu',\s0x[0-9abcdef]+\(.*\):\s[0-9abcdef]+\s+\w+\s+.*"
|
|
1064
|
+
)
|
|
1065
|
+
match = expr.match(line)
|
|
1066
|
+
if match is not None:
|
|
1067
|
+
instrs.append(line)
|
|
1068
|
+
else:
|
|
1069
|
+
new_lines.append(line)
|
|
1070
|
+
instrs_artifact = Artifact(
|
|
1071
|
+
f"{target}_instrs.log",
|
|
1072
|
+
content="\n".join(instrs),
|
|
1073
|
+
fmt=ArtifactFormat.TEXT,
|
|
1074
|
+
flags=(self.name, target),
|
|
1075
|
+
)
|
|
1076
|
+
artifacts.append(instrs_artifact)
|
|
1077
|
+
return "\n".join(new_lines)
|
|
1078
|
+
else:
|
|
1079
|
+
return stdout
|
|
1080
|
+
|
|
1081
|
+
return None, log_instrs_callback
|
|
1082
|
+
return None, None
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
@register_feature("arm_mvei")
|
|
1086
|
+
class ArmMvei(SetupFeature, TargetFeature, PlatformFeature):
|
|
1087
|
+
"""Enable MVEI extension for supported ARM targets"""
|
|
1088
|
+
|
|
1089
|
+
def __init__(self, features=None, config=None):
|
|
1090
|
+
super().__init__("arm_mvei", features=features, config=config)
|
|
1091
|
+
|
|
1092
|
+
def get_target_config(self, target):
|
|
1093
|
+
assert target in ["corstone300"]
|
|
1094
|
+
return {
|
|
1095
|
+
f"{target}.enable_mvei": True, # TODO: remove if not required (only enforce m33/m55)
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
def get_required_cache_flags(self):
|
|
1099
|
+
return {
|
|
1100
|
+
"cmsisnn.lib": ["mvei"],
|
|
1101
|
+
"tflmc.exe": ["mvei"],
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
def get_platform_defs(self, platform):
|
|
1105
|
+
return {"ARM_MVEI": self.enabled}
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
@register_feature("arm_dsp")
|
|
1109
|
+
class ArmDsp(SetupFeature, TargetFeature, PlatformFeature):
|
|
1110
|
+
"""Enable DSP extension for supported ARM targets"""
|
|
1111
|
+
|
|
1112
|
+
def __init__(self, features=None, config=None):
|
|
1113
|
+
super().__init__("arm_dsp", features=features, config=config)
|
|
1114
|
+
|
|
1115
|
+
def get_target_config(self, target):
|
|
1116
|
+
assert target in ["corstone300"]
|
|
1117
|
+
return {
|
|
1118
|
+
f"{target}.enable_dsp": True, # TODO: remove if not required (only enforce m33/m55)
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
def get_required_cache_flags(self):
|
|
1122
|
+
# These will be merged automatically with existing ones
|
|
1123
|
+
return {
|
|
1124
|
+
"cmsisnn.lib": ["dsp"],
|
|
1125
|
+
"tflmc.exe": ["dsp"],
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
def get_platform_defs(self, platform):
|
|
1129
|
+
return {"ARM_DSP": self.enabled}
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@register_feature("target_optimized")
|
|
1133
|
+
class TargetOptimized(RunFeature):
|
|
1134
|
+
"""Overwrite backend options according to chosen target."""
|
|
1135
|
+
|
|
1136
|
+
DEFAULTS = {
|
|
1137
|
+
**FeatureBase.DEFAULTS,
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
def __init__(self, features=None, config=None):
|
|
1141
|
+
super().__init__("target_optimized", features=features, config=config)
|
|
1142
|
+
|
|
1143
|
+
def get_run_config(self):
|
|
1144
|
+
return {"run.target_to_backend": self.enabled}
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
# Needs: vext
|
|
1148
|
+
# RISC-V only
|
|
1149
|
+
# Warning: Auto-vectorization is turned on by default quite low optimization levels
|
|
1150
|
+
# Therfore this feature is mainly for debugging the auto-vectorization procedure
|
|
1151
|
+
@register_feature("auto_vectorize")
|
|
1152
|
+
class AutoVectorize(PlatformFeature):
|
|
1153
|
+
"""Enable auto_vectorization for supported MLIF platform targets."""
|
|
1154
|
+
|
|
1155
|
+
DEFAULTS = {
|
|
1156
|
+
**FeatureBase.DEFAULTS,
|
|
1157
|
+
"verbose": False,
|
|
1158
|
+
"loop": True,
|
|
1159
|
+
"slp": True,
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
def __init__(self, features=None, config=None):
|
|
1163
|
+
super().__init__("auto_vectorize", features=features, config=config)
|
|
1164
|
+
|
|
1165
|
+
@property
|
|
1166
|
+
def verbose(self):
|
|
1167
|
+
value = self.config["verbose"]
|
|
1168
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
1169
|
+
|
|
1170
|
+
@property
|
|
1171
|
+
def loop(self):
|
|
1172
|
+
value = self.config["loop"]
|
|
1173
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
1174
|
+
|
|
1175
|
+
@property
|
|
1176
|
+
def slp(self):
|
|
1177
|
+
value = self.config["slp"]
|
|
1178
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
1179
|
+
|
|
1180
|
+
def get_platform_defs(self, platform):
|
|
1181
|
+
return {
|
|
1182
|
+
"RISCV_AUTO_VECTORIZE": self.enabled,
|
|
1183
|
+
"RISCV_AUTO_VECTORIZE_VERBOSE": self.verbose,
|
|
1184
|
+
"RISCV_AUTO_VECTORIZE_LOOP": self.loop and self.enabled,
|
|
1185
|
+
"RISCV_AUTO_VECTORIZE_SLP": self.slp and self.enabled,
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
@register_feature("benchmark")
|
|
1190
|
+
class Benchmark(PlatformFeature, TargetFeature):
|
|
1191
|
+
"""Profile code using supported platforms."""
|
|
1192
|
+
|
|
1193
|
+
# TODO: would make sense to move end_to_end here as well!
|
|
1194
|
+
|
|
1195
|
+
DEFAULTS = {
|
|
1196
|
+
**FeatureBase.DEFAULTS,
|
|
1197
|
+
"num_runs": 1,
|
|
1198
|
+
"num_repeat": 1,
|
|
1199
|
+
"total": False,
|
|
1200
|
+
"aggregate": "avg", # Allowed: avg, max, min, none, all
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
REQUIRED = []
|
|
1204
|
+
|
|
1205
|
+
def __init__(self, features=None, config=None):
|
|
1206
|
+
super().__init__("benchmark", features=features, config=config)
|
|
1207
|
+
|
|
1208
|
+
@property
|
|
1209
|
+
def num_runs(self):
|
|
1210
|
+
return int(self.config["num_runs"])
|
|
1211
|
+
|
|
1212
|
+
@property
|
|
1213
|
+
def num_repeat(self):
|
|
1214
|
+
return int(self.config["num_repeat"])
|
|
1215
|
+
|
|
1216
|
+
@property
|
|
1217
|
+
def total(self):
|
|
1218
|
+
value = self.config["total"]
|
|
1219
|
+
return str2bool(value) if not isinstance(value, (bool, int)) else value
|
|
1220
|
+
|
|
1221
|
+
@property
|
|
1222
|
+
def aggregate(self):
|
|
1223
|
+
value = self.config["aggregate"]
|
|
1224
|
+
assert value in ["avg", "all", "max", "min", "none"]
|
|
1225
|
+
return value
|
|
1226
|
+
|
|
1227
|
+
def get_platform_config(self, platform):
|
|
1228
|
+
supported = ["mlif", "tvm"] # TODO: support microtvm and espidf
|
|
1229
|
+
assert platform in supported, f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
1230
|
+
|
|
1231
|
+
if platform in ["tvm", "microtvm"]:
|
|
1232
|
+
return {
|
|
1233
|
+
f"{platform}.number": self.num_runs,
|
|
1234
|
+
f"{platform}.repeat": self.num_repeat,
|
|
1235
|
+
f"{platform}.aggregate": self.aggregate,
|
|
1236
|
+
f"{platform}.total_time": self.total,
|
|
1237
|
+
}
|
|
1238
|
+
else:
|
|
1239
|
+
return {}
|
|
1240
|
+
|
|
1241
|
+
def get_target_config(self, target):
|
|
1242
|
+
return {
|
|
1243
|
+
f"{target}.repeat": self.num_repeat,
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
def get_platform_defs(self, platform):
|
|
1247
|
+
supported = ["mlif", "espidf", "tvm", "microtvm", "zephyr"] # TODO: support microtvm and espidf
|
|
1248
|
+
assert platform in supported, f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
1249
|
+
|
|
1250
|
+
if platform == "mlif":
|
|
1251
|
+
return {"NUM_RUNS": self.num_runs}
|
|
1252
|
+
elif platform == "espidf":
|
|
1253
|
+
return {"MLONMCU_NUM_RUNS": self.num_runs}
|
|
1254
|
+
else:
|
|
1255
|
+
return {}
|
|
1256
|
+
|
|
1257
|
+
def get_target_callbacks(self, target):
|
|
1258
|
+
if self.enabled:
|
|
1259
|
+
|
|
1260
|
+
def benchmark_callback(stdout, metrics, artifacts):
|
|
1261
|
+
if len(metrics) <= 1:
|
|
1262
|
+
return
|
|
1263
|
+
metrics_ = metrics[1:] # drop first run (warmup)
|
|
1264
|
+
|
|
1265
|
+
# TODO: this currently processes all numeric metrics, should probably ignore stuff like MIPS etc.
|
|
1266
|
+
data_ = [
|
|
1267
|
+
{
|
|
1268
|
+
key: (float(value) / self.num_runs) if self.num_runs > 1 else value
|
|
1269
|
+
for key, value in m.data.items()
|
|
1270
|
+
if "cycle" in key.lower() or "time" in key.lower()
|
|
1271
|
+
}
|
|
1272
|
+
for m in metrics_
|
|
1273
|
+
]
|
|
1274
|
+
|
|
1275
|
+
df = pd.DataFrame(data_)
|
|
1276
|
+
|
|
1277
|
+
if self.aggregate == "all":
|
|
1278
|
+
aggs = ["mean", "min", "max"]
|
|
1279
|
+
elif self.aggregate in ["avg", "mean"]:
|
|
1280
|
+
aggs = ["mean"]
|
|
1281
|
+
elif self.aggregate == "min":
|
|
1282
|
+
aggs = ["min"]
|
|
1283
|
+
elif self.aggregate == "max":
|
|
1284
|
+
aggs = ["max"]
|
|
1285
|
+
elif self.aggregate == "none":
|
|
1286
|
+
aggs = []
|
|
1287
|
+
|
|
1288
|
+
if len(aggs) == 0:
|
|
1289
|
+
data = {}
|
|
1290
|
+
else:
|
|
1291
|
+
df_ = df.agg(aggs)
|
|
1292
|
+
|
|
1293
|
+
# rename columns
|
|
1294
|
+
index_mapping = {
|
|
1295
|
+
"mean": "Average",
|
|
1296
|
+
"min": "Min",
|
|
1297
|
+
"max": "Max",
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
df_ = df_.rename(index=index_mapping)
|
|
1301
|
+
|
|
1302
|
+
data = df_.to_dict()
|
|
1303
|
+
|
|
1304
|
+
data = {f"{prefix} {key}": value for key, temp in data.items() for prefix, value in temp.items()}
|
|
1305
|
+
if self.total:
|
|
1306
|
+
data.update(
|
|
1307
|
+
{
|
|
1308
|
+
f"Total {key}": ((value * self.num_runs) if self.num_runs > 1 else value)
|
|
1309
|
+
for key, value in data_[-1].items()
|
|
1310
|
+
if "cycle" in key.lower() or "time" in key.lower()
|
|
1311
|
+
}
|
|
1312
|
+
)
|
|
1313
|
+
metrics_ = metrics_[-1]
|
|
1314
|
+
metrics_.data.update(data)
|
|
1315
|
+
|
|
1316
|
+
for key in data_[-1].keys():
|
|
1317
|
+
if key in metrics_.order:
|
|
1318
|
+
if self.total:
|
|
1319
|
+
metrics_.order.append(f"Total {key}")
|
|
1320
|
+
metrics_.order.remove(key)
|
|
1321
|
+
for key in data.keys():
|
|
1322
|
+
if key not in metrics_.order:
|
|
1323
|
+
metrics_.order.append(key)
|
|
1324
|
+
metrics.clear()
|
|
1325
|
+
metrics.append(metrics_)
|
|
1326
|
+
return stdout
|
|
1327
|
+
|
|
1328
|
+
benchmark_callback.priority = 0
|
|
1329
|
+
|
|
1330
|
+
return None, benchmark_callback
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
@register_feature("tvm_rpc")
|
|
1334
|
+
class TvmRpc(PlatformFeature):
|
|
1335
|
+
"""Run TVM models on a RPC device."""
|
|
1336
|
+
|
|
1337
|
+
DEFAULTS = {**FeatureBase.DEFAULTS, "hostname": None, "port": None, "key": None} # tracker
|
|
1338
|
+
|
|
1339
|
+
def __init__(self, features=None, config=None):
|
|
1340
|
+
super().__init__("tvm_rpc", features=features, config=config)
|
|
1341
|
+
|
|
1342
|
+
@property
|
|
1343
|
+
def use_rpc(self):
|
|
1344
|
+
return self.config["use_rpc"]
|
|
1345
|
+
|
|
1346
|
+
@property
|
|
1347
|
+
def hostname(self):
|
|
1348
|
+
return self.config["hostname"]
|
|
1349
|
+
|
|
1350
|
+
@property
|
|
1351
|
+
def port(self):
|
|
1352
|
+
return self.config["port"]
|
|
1353
|
+
|
|
1354
|
+
@property
|
|
1355
|
+
def key(self):
|
|
1356
|
+
return self.config["key"]
|
|
1357
|
+
|
|
1358
|
+
def get_platform_config(self, platform):
|
|
1359
|
+
assert platform in ["tvm", "microtvm"]
|
|
1360
|
+
return filter_none(
|
|
1361
|
+
{
|
|
1362
|
+
f"{platform}.use_rpc": self.enabled,
|
|
1363
|
+
f"{platform}.rpc_hostname": self.hostname,
|
|
1364
|
+
f"{platform}.rpc_port": self.port,
|
|
1365
|
+
f"{platform}.rpc_key": self.key,
|
|
1366
|
+
}
|
|
1367
|
+
)
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
@register_feature("tvm_profile")
|
|
1371
|
+
class TvmProfile(PlatformFeature):
|
|
1372
|
+
"""Profile code using TVM Platform."""
|
|
1373
|
+
|
|
1374
|
+
DEFAULTS = {
|
|
1375
|
+
**FeatureBase.DEFAULTS,
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
REQUIRED = []
|
|
1379
|
+
|
|
1380
|
+
def __init__(self, features=None, config=None):
|
|
1381
|
+
super().__init__("tvm_profile", features=features, config=config)
|
|
1382
|
+
|
|
1383
|
+
def get_platform_config(self, platform):
|
|
1384
|
+
supported = ["tvm", "microtvm"]
|
|
1385
|
+
assert platform in supported, f"Unsupported feature '{self.name}' for platform '{platform}'"
|
|
1386
|
+
return {
|
|
1387
|
+
f"{platform}.profile": self.enabled,
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
@register_feature("xpulp")
|
|
1392
|
+
class Xpulp(TargetFeature, PlatformFeature, SetupFeature):
|
|
1393
|
+
DEFAULTS = {
|
|
1394
|
+
**FeatureBase.DEFAULTS,
|
|
1395
|
+
"xpulp_version": 2,
|
|
1396
|
+
"nopostmod": False,
|
|
1397
|
+
"noindregreg": False,
|
|
1398
|
+
"novect": False,
|
|
1399
|
+
"nohwloop": False,
|
|
1400
|
+
"hwloopmin": 2,
|
|
1401
|
+
"hwloopalign": False,
|
|
1402
|
+
"nomac": False,
|
|
1403
|
+
"nopartmac": False,
|
|
1404
|
+
"nominmax": False,
|
|
1405
|
+
"noabs": False,
|
|
1406
|
+
"nobitop": False,
|
|
1407
|
+
"nosext": False,
|
|
1408
|
+
"noclip": False,
|
|
1409
|
+
"noaddsubnormround": False,
|
|
1410
|
+
"noshufflepack": False,
|
|
1411
|
+
"nomulmacnormround": False,
|
|
1412
|
+
"noshufflepack": False,
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
REQUIRED = ["pulp_gcc.install_dir", "pulp_gcc.name"]
|
|
1416
|
+
|
|
1417
|
+
def __init__(self, features=None, config=None):
|
|
1418
|
+
super().__init__("xpulp", features=features, config=config)
|
|
1419
|
+
|
|
1420
|
+
# Except the "enabled" in FeatureBase.DEFAULTS and "xpulp_version"
|
|
1421
|
+
# every key in DEFAULTS should in principle have a getter function with the same name as the key
|
|
1422
|
+
# These getter functions will be stored in getter_functions array.
|
|
1423
|
+
# Default getter function for the keys whose corresponding value has bool type:
|
|
1424
|
+
# def getter_bool(self, key_name):
|
|
1425
|
+
# return self.generalized_str2bool(self.config[key_name])
|
|
1426
|
+
# Default getter function for the keys whose corresponding value has int type:
|
|
1427
|
+
# def getter_int(self, key_name):
|
|
1428
|
+
# return int(self.config["<key_name>"])
|
|
1429
|
+
# No default, i.e. customized getter functions are defined separately
|
|
1430
|
+
|
|
1431
|
+
# Default getter functions:
|
|
1432
|
+
@staticmethod
|
|
1433
|
+
def generalized_str2bool(input: Union[str, bool, int]) -> bool:
|
|
1434
|
+
return str2bool(input) if isinstance(input, str) else input
|
|
1435
|
+
|
|
1436
|
+
def getter_bool(self, key_name: Union[str, bool, int]) -> bool:
|
|
1437
|
+
return self.generalized_str2bool(self.config[key_name])
|
|
1438
|
+
|
|
1439
|
+
def getter_int(self, key_name: Union[str, bool, int]) -> int:
|
|
1440
|
+
return int(self.config[key_name])
|
|
1441
|
+
|
|
1442
|
+
# No default, i.e. customized getter functions are defined in the following (now empty)
|
|
1443
|
+
|
|
1444
|
+
# custom_config_getter contains customized @property function which do not follow the pattern above.
|
|
1445
|
+
getter_functions = {
|
|
1446
|
+
"nopostmod": getter_bool,
|
|
1447
|
+
"noindregreg": getter_bool,
|
|
1448
|
+
"novect": getter_bool,
|
|
1449
|
+
"nohwloop": getter_bool,
|
|
1450
|
+
"hwloopmin": getter_int,
|
|
1451
|
+
"hwloopalign": getter_bool,
|
|
1452
|
+
"nomac": getter_bool,
|
|
1453
|
+
"nopartmac": getter_bool,
|
|
1454
|
+
"nominmax": getter_bool,
|
|
1455
|
+
"noabs": getter_bool,
|
|
1456
|
+
"nobitop": getter_bool,
|
|
1457
|
+
"nosext": getter_bool,
|
|
1458
|
+
"noclip": getter_bool,
|
|
1459
|
+
"noaddsubnormround": getter_bool,
|
|
1460
|
+
"noshufflepack": getter_bool,
|
|
1461
|
+
"nomulmacnormround": getter_bool,
|
|
1462
|
+
"noshufflepack": getter_bool,
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
@property
|
|
1466
|
+
def xpulp_version(self):
|
|
1467
|
+
value = self.config["xpulp_version"]
|
|
1468
|
+
value = int(value) if not isinstance(value, int) else value # convert to int
|
|
1469
|
+
assert value in [None, 2, 3], f"xpulp_version must be None, 2 or 3, but get {value}"
|
|
1470
|
+
return value
|
|
1471
|
+
|
|
1472
|
+
def get_platform_defs(self, platform):
|
|
1473
|
+
# The following create EXTRA_FLAGS (type is str) for gcc
|
|
1474
|
+
# example
|
|
1475
|
+
# {"nopostmod": True, "novect": True, ...} ==> EXTRA_FLAGS = "-mnopostmod -mnovect ..."
|
|
1476
|
+
EXTRA_FLAGS = ""
|
|
1477
|
+
for key in self.getter_functions:
|
|
1478
|
+
if isinstance(self.getter_functions[key](self, key), bool):
|
|
1479
|
+
if self.getter_functions[key](self, key):
|
|
1480
|
+
EXTRA_FLAGS += f" -m{key}"
|
|
1481
|
+
continue
|
|
1482
|
+
if isinstance(self.getter_functions[key](self, key), int):
|
|
1483
|
+
EXTRA_FLAGS += f" -m{key}={self.getter_functions[key](self, key)}"
|
|
1484
|
+
continue
|
|
1485
|
+
EXTRA_FLAGS = "'" + EXTRA_FLAGS.strip() + "'"
|
|
1486
|
+
return {
|
|
1487
|
+
# EXTRA_CMAKE_C_FLAGS will be directly append to CMAKE_C_FLAGS in mlonmcu_sw/mlif/tootchains/Pulp.cmake
|
|
1488
|
+
"EXTRA_CMAKE_C_FLAGS": EXTRA_FLAGS,
|
|
1489
|
+
# EXTRA_CMAKE_CXX_FLAGS will be directly append to CMAKE_CXX_FLAGS in mlonmcu_sw/mlif/tootchains/Pulp.cmake
|
|
1490
|
+
"EXTRA_CMAKE_CXX_FLAGS": EXTRA_FLAGS,
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
def add_platform_defs(self, platform, defs):
|
|
1494
|
+
addition_defs = self.get_platform_defs(platform)
|
|
1495
|
+
self.merge_dicts(defs, addition_defs)
|
|
1496
|
+
|
|
1497
|
+
@staticmethod
|
|
1498
|
+
def merge_dicts(dict1, dict2):
|
|
1499
|
+
"""
|
|
1500
|
+
This function tries to merge dict1 and dict2 into dict1
|
|
1501
|
+
:param dict1: A dictionary
|
|
1502
|
+
:param dict2: A dictionary to be added
|
|
1503
|
+
:return: Void
|
|
1504
|
+
Example 1:
|
|
1505
|
+
dict1 = {"a": 1, "b": "hello", "c": [1, 2, 3]}
|
|
1506
|
+
dict2 = {"f": 3, "b": "world", "c": [4, 5, 6]}
|
|
1507
|
+
merge_dicts(dict1, dict2)
|
|
1508
|
+
print(dict1)
|
|
1509
|
+
==>
|
|
1510
|
+
{"a": 1, "b": "hello world", "c": [1, 2, 3, 4, 5, 6], "f":3}
|
|
1511
|
+
Note: Here "hello" and "world" are merged as two string join.
|
|
1512
|
+
Here [1,2,3] and [4,5,6] are merged as list addition
|
|
1513
|
+
Example 2:
|
|
1514
|
+
dict1 = {"a": 1}
|
|
1515
|
+
dict2 = {"a": 3}
|
|
1516
|
+
merge_dicts(dict1, dict2)
|
|
1517
|
+
==>
|
|
1518
|
+
RuntimeError: The method to merge a: 1 and a: 3 is not defined
|
|
1519
|
+
"""
|
|
1520
|
+
for key in dict2.keys():
|
|
1521
|
+
if key in dict1.keys():
|
|
1522
|
+
dict1_value = dict1[key]
|
|
1523
|
+
dict2_value = dict2[key]
|
|
1524
|
+
if isinstance(dict1_value, (str, list)) and type(dict1_value) == type(dict2_value):
|
|
1525
|
+
if isinstance(dict1_value, str):
|
|
1526
|
+
dict1[key] = dict1_value + " " + dict2_value
|
|
1527
|
+
else:
|
|
1528
|
+
dict1[key] = dict1_value + dict2_value
|
|
1529
|
+
else:
|
|
1530
|
+
raise RuntimeError(
|
|
1531
|
+
f"The method to merge {key}: {dict1_value} and {key}: {dict2_value} is not defined"
|
|
1532
|
+
)
|
|
1533
|
+
else:
|
|
1534
|
+
dict1[key] = dict2[key]
|
|
1535
|
+
|
|
1536
|
+
def get_target_config(self, target):
|
|
1537
|
+
return filter_none({f"{target}.xpulp_version": self.xpulp_version})
|