Skip to content
Merged
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
94 changes: 94 additions & 0 deletions backends/cortex_m/test/models/test_silero_vad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

import torch
from executorch.backends.arm.test.common import parametrize
from executorch.backends.cortex_m.test.tester import CortexMTester, McuTestCase
from executorch.examples.models.silero_vad.export_silero_vad import (
CONTEXT_SIZE,
HIDDEN_DIM,
SileroVAD16k,
WINDOW_SIZE,
)


ops_before_transforms: dict[str, int] = {
"executorch_exir_dialects_edge__ops_aten_abs_default": 2,
"executorch_exir_dialects_edge__ops_aten_add_Tensor": 3,
"executorch_exir_dialects_edge__ops_aten_arange_start_step": 1,
"executorch_exir_dialects_edge__ops_aten_cat_default": 1,
"executorch_exir_dialects_edge__ops_aten_convolution_default": 6,
"executorch_exir_dialects_edge__ops_aten_index_Tensor": 1,
"executorch_exir_dialects_edge__ops_aten_linear_default": 2,
"executorch_exir_dialects_edge__ops_aten_mean_dim": 1,
"executorch_exir_dialects_edge__ops_aten_mul_Tensor": 3,
"executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar": 2,
"executorch_exir_dialects_edge__ops_aten_relu_default": 5,
"executorch_exir_dialects_edge__ops_aten_select_copy_int": 2,
"executorch_exir_dialects_edge__ops_aten_sigmoid_default": 4,
"executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor": 2,
"executorch_exir_dialects_edge__ops_aten_split_with_sizes_copy_default": 1,
"executorch_exir_dialects_edge__ops_aten_sqrt_default": 1,
"executorch_exir_dialects_edge__ops_aten_squeeze_copy_dims": 2,
"executorch_exir_dialects_edge__ops_aten_sub_Tensor": 2,
"executorch_exir_dialects_edge__ops_aten_tanh_default": 2,
"executorch_exir_dialects_edge__ops_aten_unsqueeze_copy_default": 2,
"executorch_exir_dialects_edge__ops_aten_view_copy_default": 1,
"executorch_exir_dialects_edge__ops_quantized_decomposed_dequantize_per_tensor_default": 12,
"executorch_exir_dialects_edge__ops_quantized_decomposed_quantize_per_tensor_default": 11,
}
ops_after_transforms: dict[str, int] = {
"executorch_exir_dialects_edge__ops_aten_abs_default": 2,
"executorch_exir_dialects_edge__ops_aten_add_Tensor": 2,
"executorch_exir_dialects_edge__ops_aten_arange_start_step": 1,
"executorch_exir_dialects_edge__ops_aten_cat_default": 1,
"executorch_exir_dialects_edge__ops_aten_convolution_default": 6,
"executorch_exir_dialects_edge__ops_aten_index_Tensor": 1,
"executorch_exir_dialects_edge__ops_aten_linear_default": 2,
"executorch_exir_dialects_edge__ops_aten_mean_dim": 1,
"executorch_exir_dialects_edge__ops_aten_mul_Tensor": 3,
"executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar": 2,
"executorch_exir_dialects_edge__ops_aten_relu_default": 5,
"executorch_exir_dialects_edge__ops_aten_select_copy_int": 2,
"executorch_exir_dialects_edge__ops_aten_sigmoid_default": 4,
"executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor": 2,
"executorch_exir_dialects_edge__ops_aten_split_with_sizes_copy_default": 1,
"executorch_exir_dialects_edge__ops_aten_sqrt_default": 1,
"executorch_exir_dialects_edge__ops_aten_squeeze_copy_dims": 2,
"executorch_exir_dialects_edge__ops_aten_sub_Tensor": 2,
"executorch_exir_dialects_edge__ops_aten_tanh_default": 2,
"executorch_exir_dialects_edge__ops_aten_unsqueeze_copy_default": 2,
"executorch_exir_dialects_edge__ops_aten_view_copy_default": 1,
"executorch_exir_dialects_edge__ops_cortex_m_dequantize_per_tensor_default": 6,
"executorch_exir_dialects_edge__ops_cortex_m_quantize_per_tensor_default": 6,
"executorch_exir_dialects_edge__ops_cortex_m_quantized_add_default": 1,
}


pt_model = SileroVAD16k().eval()

x = torch.randn(
1, CONTEXT_SIZE + WINDOW_SIZE
) # (1, 576) — 64 context + 512 audio samples
state = torch.zeros(2, 1, HIDDEN_DIM) # (2, 1, 128) — [h, c] LSTM state

test_cases = {
"silero_vad_16k": McuTestCase(
model=pt_model,
example_inputs=lambda: (x, state),
),
}


@parametrize("test_case", test_cases)
def test_dialect_silero_vad_16k(test_case):
"""This model currently does largely not lower to accelerated kernels due to missing LSTM and conv1d support, this test is to track development progress."""
inputs = test_case.get_example_inputs()
tester = CortexMTester(test_case.model, inputs)
tester.test_dialect(
ops_before_transforms,
ops_after_transforms,
qtol=10,
)
Comment on lines +85 to +94
34 changes: 34 additions & 0 deletions backends/cortex_m/test/models/test_wav2letter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

from executorch.backends.arm.test.common import parametrize
from executorch.backends.cortex_m.test.tester import CortexMTester, McuTestCase
Comment on lines +5 to +7
from executorch.examples.models.wav2letter.model import Wav2LetterModel


ops_before_transforms: dict[str, int] = {}
ops_after_transforms: dict[str, int] = {}

model = Wav2LetterModel()
pt_model = model.get_eager_model()

test_cases = {
"wav2letter": McuTestCase(
model=pt_model,
example_inputs=lambda: model.get_example_inputs(),
),
}


@parametrize("test_case", test_cases)
def test_dialect_wav2letter(test_case):
"""This model currently does largely not lower to accelerated kernels due to missing conv1d support, this test is to track development progress."""
inputs = test_case.get_example_inputs()
tester = CortexMTester(test_case.model, inputs)
tester.test_dialect(
ops_before_transforms,
ops_after_transforms,
qtol=10,
)
45 changes: 45 additions & 0 deletions backends/cortex_m/test/models/test_yolo11.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

import pytest
import torch
from executorch.backends.arm.test.common import parametrize

from executorch.backends.cortex_m.test.tester import CortexMTester, McuTestCase

YOLO = pytest.importorskip(
"ultralytics",
reason="ultralytics is optional; install it locally to run YOLO tests.",
).YOLO


ops_before_transforms: dict[str, int] = {}
ops_after_transforms: dict[str, int] = {}


WEIGHTS = "yolo11n.pt"
yolo = YOLO(WEIGHTS)
pt_model = yolo.model.eval()

test_cases = {
"yolo11n": McuTestCase(
model=pt_model,
example_inputs=lambda: (
torch.randn(1, 3, 640, 640).to(memory_format=torch.channels_last),
),
),
}


@parametrize("test_case", test_cases)
def test_dialect_yolo11(test_case):
"""This model currently does not lower in the cortex-m backend, this test is to track development progress."""
Comment on lines +23 to +38
inputs = test_case.get_example_inputs()
tester = CortexMTester(test_case.model, inputs)
tester.test_dialect(
ops_before_transforms,
ops_after_transforms,
qtol=10,
)
Loading