Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Optimized algorithm implementations demonstrating how to leverage E1x's architec
* **fft** - Fast Fourier Transform (DSP)
* **jpeg** - JPEG Image Encoder (Multimedia)
* **ldpc** - LDPC Encoder/Decoder (Communications)
* **mlperftiny** - MLPerfTiny neural network benchmark suite
* **quickstart** - Simple "Hello World" example

---
Expand Down
3 changes: 2 additions & 1 deletion app_examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ add_subdirectory(dmm)
add_subdirectory(fft)
add_subdirectory(jpeg)
add_subdirectory(ldpc)
add_subdirectory(quickstart)
add_subdirectory(mlperftiny)
add_subdirectory(quickstart)
6 changes: 6 additions & 0 deletions app_examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project provides example apps demonstrating optimized algorithms running on
* **fft** - Fast Fourier Transform (DSP)
* **jpeg** - JPEG Image Encoder (Multimedia)
* **ldpc** - LDPC Encoder/Decoder (Communications)
* **mlperftiny** - MLPerfTiny neural network benchmark suite
* **quickstart** - Simple "Hello World" example

## Getting Started
Expand All @@ -22,6 +23,11 @@ If you haven't already, please make sure you've set up your board and developmen

Additional details are contained within each app's folder.

The **mlperftiny** folder contains five MLPerfTiny benchmark apps:
anomaly detection, image classification, keyword spotting, streaming wake word,
and visual wake words. Each benchmark has its own README with model, input,
target, and validation details.

### App Configuration

Each app is contained in its own directory with a `CMakeLists.txt` for building. Refer to the individual app README and source files for detailed usage and configuration options.
Expand Down
5 changes: 5 additions & 0 deletions app_examples/mlperftiny/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_subdirectory(mlperftiny_ad)
add_subdirectory(mlperftiny_ic)
add_subdirectory(mlperftiny_kws)
add_subdirectory(mlperftiny_vww)
add_subdirectory(mlperftiny_sww)
92 changes: 92 additions & 0 deletions app_examples/mlperftiny/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# MLPerfTiny Benchmarks

This folder contains E1/E1x examples for the MLPerfTiny benchmark suite. Each
app builds a quantized TensorFlow Lite model with the EFF SDK, converts the
model through `eff-import`, runs a deterministic test input, and prints a
`[mlperftiny_<name>] PASS` or `FAIL` result.

Source snapshot: `EfficientComputer/apps` `main` at commit `46301721a6da`.

Upstream benchmark source: [mlcommons/tiny](https://github.com/mlcommons/tiny).
Pre-trained models were downloaded on April 6, 2026.

## Included Apps

| App | MLPerfTiny task | Active model | Input | Output | Build targets |
|-----|-----------------|--------------|-------|--------|---------------|
| `mlperftiny_ad` | Anomaly detection | `ad01_int8.tflite` | `[1][640]` int8 | `[1][640]` int8 reconstruction | `fabric`, `scalar` |
| `mlperftiny_ic` | Image classification | `models/v1.1/pretrainedResnet_quant.tflite` | `[1][32][32][3]` int8 image | `[1][10]` int8 logits | `fabric`, `optimized_fabric`, `scalar` |
| `mlperftiny_kws` | Keyword spotting | `kws_ref_model.tflite` | `[1][49][10][1]` int8 features | `[1][12]` int8 logits | `fabric`, `optimized_fabric`, `scalar` |
| `mlperftiny_sww` | Streaming wake word | `str_ww_ref_model.tflite` | 16000-sample int16 audio, then `[1][30][1][40]` int8 features | `[1][3]` int8 logits | `fabric`, `optimized_fabric`, `scalar` |
| `mlperftiny_vww` | Visual wake words | `vww_96_int8.tflite` | `[1][96][96][3]` int8 image | `[1][2]` int8 logits | `fabric`, `optimized_fabric`, `scalar` |

## Model Provenance

| Benchmark | Model file | Upstream commit | MD5 |
|-----------|------------|-----------------|-----|
| AD | [ad01_int8.tflite](https://github.com/mlcommons/tiny/blob/master/benchmark/training/anomaly_detection/trained_models/ad01_int8.tflite) | `bceb91c` | `361fa1b1b871e2068b2ab38d9805ef56` |
| IC v1.1 | [pretrainedResnet_quant.tflite](https://github.com/mlcommons/tiny/blob/360bf095/benchmark/training/image_classification/trained_models/pretrainedResnet_quant.tflite) | `360bf09` | `2d6dd48722471313e4c4528249205ae3` |
| IC v1.4-pre | [pretrainedResnet_quant.tflite](https://github.com/mlcommons/tiny/blob/eb78d0e/benchmark/training/image_classification/trained_models/pretrainedResnet_quant.tflite) | `eb78d0e` | `bd6cec63e4337ac66fb5ed5594b0df48` |
| KWS | [kws_ref_model.tflite](https://github.com/mlcommons/tiny/blob/master/benchmark/training/keyword_spotting/trained_models/kws_ref_model.tflite) | `bceb91c` | `618aeb155673dae92fa6a7f26608add5` |
| SWW | [str_ww_ref_model.tflite](https://github.com/mlcommons/tiny/blob/master/benchmark/training/streaming_wakeword/trained_models/str_ww_ref_model.tflite) | `904de6f` | `9643512e0b8a0b6e643e70c2fec496ee` |
| VWW | [vww_96_int8.tflite](https://github.com/mlcommons/tiny/blob/master/benchmark/training/visual_wake_words/trained_models/vww_96_int8.tflite) | `bceb91c` | `f0b011416abee0343a5d130cb1f4c18f` |

The image-classification folder includes both the v1.1 and v1.4-pre ResNet
models. The CMake file currently selects the v1.1 model; the v1.4-pre path is
kept next to it so developers can switch model revisions intentionally.

## Building

Build from `app_examples` using the same flow as the other E1x examples:

```sh
mkdir bld
cd bld
cmake -G Ninja .. -DEFF_STDIO_PORT=3
ninja
```

The MLPerfTiny apps are added through `app_examples/mlperftiny/CMakeLists.txt`,
which includes the five app subdirectories. Each app CMake file invokes
`eff-import` from the selected EFF compiler toolchain to translate the active
`.tflite` model into generated TOSA MLIR for the requested target.

## Running and Validation

Each app embeds a deterministic input tensor or sample, runs the model for the
configured number of profiling iterations, and compares the final output tensor
against an expected int8 result. A successful run prints:

```text
[mlperftiny_<name>] PASS
```

The examples are intended for normal EFF SDK simulator, scalar, and fabric
workflows. Optimized variants use custom rule files and hand-written kernels
where present.

## Folder Structure

Each app follows the same layout:

| Path | Purpose |
|------|---------|
| `CMakeLists.txt` | Selects the model, generated MLIR, targets, and sources. |
| `main.c` | Minimal entry point that calls `benchmarkModel()`. |
| `eff/benchmark.c` | Deterministic input, output validation, and profiling loop. |
| `eff/optimized_kernels*.c` | E1/E1x optimized kernels for apps with optimized builds. |
| `*.mlir`, `*.pdl` | Hand-written MLIR helpers and custom TOSA rewrite rules. |
| `arm/` | Reference ARM/CMSIS or Ethos-U ports retained from the source tree; not used by the E1x CMake targets. |

## TOSA Conversion

The app builds call `eff-import` automatically. For manual inspection, a
standalone TFLite to TOSA conversion can be attempted with:

```sh
pip install tosa-converter-for-tflite
tosa-converter-for-tflite --text <input.tflite> -o <output.tosa>
```

Manual output should be compared with `eff-import` output before it is used as a
replacement in these examples.
67 changes: 67 additions & 0 deletions app_examples/mlperftiny/mlperftiny_ad/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# @OPT_LEVEL=0
# @OPT_TAGS=
# @OPT_COMMENT=
# @TYPE_TAGS=ml,benchmark
# @OP_COUNTS=1:{529416}
# @AUTOBENCH=all
# @AUTOBENCH_SIZES=1

set(MODEL_NAME ad)

get_filename_component(RIPTOOLS_BINARY_PATH "${CMAKE_C_COMPILER}" DIRECTORY)
set(EFF_IMPORT_PATH ${RIPTOOLS_BINARY_PATH}/eff-import)
set(MODEL_INPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/ad01_int8.tflite)

# --- eff-import: TFLite -> MLIR ---

set(MODEL_OUTPUT_FABRIC_MLIR ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.tosa.fabric.mlir)
add_custom_command(
OUTPUT ${MODEL_OUTPUT_FABRIC_MLIR}
COMMAND ${EFF_IMPORT_PATH} ${MODEL_INPUT_PATH}
-o ${MODEL_OUTPUT_FABRIC_MLIR}
-S
DEPENDS ${MODEL_INPUT_PATH}
VERBATIM
)
add_custom_target(${MODEL_NAME}-tosa-fabric DEPENDS ${MODEL_OUTPUT_FABRIC_MLIR})

set(MODEL_OUTPUT_SCALAR_MLIR ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.tosa.scalar.mlir)
add_custom_command(
OUTPUT ${MODEL_OUTPUT_SCALAR_MLIR}
COMMAND ${EFF_IMPORT_PATH} ${MODEL_INPUT_PATH}
-o ${MODEL_OUTPUT_SCALAR_MLIR}
--no-rip-region
-S
DEPENDS ${MODEL_INPUT_PATH}
VERBATIM
)
add_custom_target(${MODEL_NAME}-tosa-scalar DEPENDS ${MODEL_OUTPUT_SCALAR_MLIR})

# --- Build ---

add_eff_app(mlperftiny_ad
TYPE exe
ARCHS e1x e1
TARGETS fabric scalar # sim
SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/eff/benchmark.c
${CMAKE_CURRENT_SOURCE_DIR}/main.c
)

eff_subtarget_sources(mlperftiny_${MODEL_NAME}_fabric ${MODEL_OUTPUT_FABRIC_MLIR})
eff_subtarget_sources(mlperftiny_${MODEL_NAME}_sim ${MODEL_OUTPUT_FABRIC_MLIR})
set_source_files_properties(${MODEL_OUTPUT_FABRIC_MLIR} PROPERTIES LANGUAGE C)

eff_subtarget_sources(mlperftiny_${MODEL_NAME}_scalar ${MODEL_OUTPUT_SCALAR_MLIR})
set_source_files_properties(${MODEL_OUTPUT_SCALAR_MLIR} PROPERTIES LANGUAGE C)

include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(TARGET mlperftiny_${MODEL_NAME}_fabric)
add_dependencies(mlperftiny_${MODEL_NAME}_fabric ${MODEL_NAME}-tosa-fabric)
endif()
if(TARGET mlperftiny_${MODEL_NAME}_sim)
add_dependencies(mlperftiny_${MODEL_NAME}_sim ${MODEL_NAME}-tosa-fabric)
endif()
if(TARGET mlperftiny_${MODEL_NAME}_scalar)
add_dependencies(mlperftiny_${MODEL_NAME}_scalar ${MODEL_NAME}-tosa-scalar)
endif()
75 changes: 75 additions & 0 deletions app_examples/mlperftiny/mlperftiny_ad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# MLPerfTiny Anomaly Detection

`mlperftiny_ad` is the MLPerfTiny anomaly-detection example for E1/E1x. It runs
the quantized `ad01_int8.tflite` autoencoder on a deterministic 640-sample int8
input vector and validates the reconstructed 640-sample output.

## What This App Demonstrates

Anomaly detection is a small neural network workload with a relatively compact
input and output tensor. It is useful for validating the end-to-end EFF model
flow because the output is a full reconstruction tensor rather than only a small
classification vector.

This app demonstrates:

- importing a quantized TFLite model with `eff-import`;
- generating separate fabric and scalar MLIR outputs;
- running the model inside an EFF profiling region;
- comparing every output element against a fixed expected tensor.

## Model and Tensor Contract

| Item | Value |
|------|-------|
| Model file | `ad01_int8.tflite` |
| Model source | MLCommons Tiny anomaly detection |
| Input tensor | `int8_t input[1][640]` |
| Output tensor | `int8_t output[1][640]` |
| Expected output | 640-element int8 reconstruction in `eff/benchmark.c` |
| Build targets | `fabric`, `scalar` |
| Architectures | `e1x`, `e1` |
| Operation count tag | `529416` |

## Build Flow

`CMakeLists.txt` locates `eff-import` next to the configured EFF C compiler and
uses it to generate:

- `ad.tosa.fabric.mlir` for the fabric target;
- `ad.tosa.scalar.mlir` for the scalar target.

The application sources are:

- `main.c`, which calls `benchmarkModel()`;
- `eff/benchmark.c`, which owns the input data, expected output, validation, and
profiling loop;
- generated MLIR from the selected TFLite model.

## Running and Validation

Build from the parent `app_examples` folder:

```sh
mkdir bld
cd bld
cmake -G Ninja ..
ninja mlperftiny_ad_fabric
```

The app enters the `model` profile region, runs `run_model()` for the configured
profiling iteration count, and then compares all 640 output values. A passing
run prints:

```text
[mlperftiny_ad] PASS
```

Any output mismatch prints `FAIL` and returns a non-zero exit code.

## Customizing the Example

To try a different anomaly-detection model, replace `ad01_int8.tflite` and keep
the same input and output tensor contract, or update `eff/benchmark.c` to match
the new model shape. Regenerate the expected output from a known-good reference
run before using the app for validation.
Binary file not shown.
Loading