Files
retroSoC/tests/test_apu_kws.py
T
maksyuki 15f4dd555c feat: add KWS engine and related tests for APU-P7
- Implemented the KWS engine in the RTL and added necessary components including KWS SRAM client and model loader.
- Enhanced the APU ring scheduler testbench to validate KWS descriptors.
- Introduced new Python tests for KWS functionality, including model import validation, inference checks, and error handling for mutated models.
- Updated existing tests to include KWS components and ensure proper integration within the APU architecture.
- Refactored code for clarity and consistency, including adjustments to signal handling and memory management in test cases.
2026-09-12 22:11:49 +08:00

100 lines
3.3 KiB
Python

"""Locked APU-P7 APUM converter and container tests."""
from __future__ import annotations
import hashlib
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
from apu_kws import ( # noqa: E402
APUM_PAYLOAD_CRC,
APUM_SHA256,
crc32_iso_hdlc,
infer_apum,
parse_apum,
select_class,
)
from apu_kws_convert import TfliteError, import_tflite # noqa: E402
MODEL = (
ROOT
/ ".cache/retrosoc/sources/apu-mlperf-tiny/benchmark/training/keyword_spotting"
/ "trained_models/kws_ref_model.tflite"
)
def test_apu_p7_locked_tflite_import_matches_freeze() -> None:
if not MODEL.is_file():
pytest.skip("locked P7 model was not installed")
image = import_tflite(MODEL)
header = parse_apum(image)
assert len(image) == 32768
assert header.crc == APUM_PAYLOAD_CRC
assert crc32_iso_hdlc(image[64:]) == APUM_PAYLOAD_CRC
assert hashlib.sha256(image).hexdigest() == APUM_SHA256
def test_apu_p7_import_rejects_mutated_model(tmp_path: Path) -> None:
if not MODEL.is_file():
pytest.skip("locked P7 model was not installed")
mutated = tmp_path / "mutated.tflite"
data = bytearray(MODEL.read_bytes())
data[-1] ^= 1
mutated.write_bytes(data)
with pytest.raises(TfliteError, match="SHA-256"):
import_tflite(mutated)
def test_apu_p7_container_rejects_padding_and_crc_mutations() -> None:
if not MODEL.is_file():
pytest.skip("locked P7 model was not installed")
image = bytearray(import_tflite(MODEL))
image[0x4E0] = 1
with pytest.raises(ValueError, match="payload CRC"):
parse_apum(bytes(image))
def test_apu_p7_scalar_inference_matches_official_feature() -> None:
feature = (
ROOT
/ ".cache/retrosoc/sources/apu-kws-mfcc/datasets/kws01"
/ "tst_000000_Stop_7.bin"
)
if not MODEL.is_file() or not feature.is_file():
pytest.skip("locked P7 model or official MFCC feature was not installed")
layers = infer_apum(import_tflite(MODEL), feature.read_bytes())
assert [len(layer) for layer in layers] == [8000] * 9 + [64, 12, 12]
assert [
hashlib.sha256(bytes(value & 0xFF for value in layer)).hexdigest()
for layer in layers
] == [
"4ea162c5d6215d5f4531c63d044eedef1cad9526e2c4fdcae6709f7ac5ab5abb",
"9b3d9d6ba64079304f99477cd6689a44018e7ab6987d7611d8bfc0ec3be5d81d",
"877299da8c940c038a02e2b5adee0f47dbce2f419697648394dcb2f0317ddb8f",
"77bf309dcf7cdd0a8bf080748bb40929957a53a6ba3c3d8f83c87b26d540e183",
"7be9b616635d7f96458b3c5bb997f95e08fc5266288552df7367c83e33592b62",
"67c3b2a8ef7c342a7cc953594b544927881ea34290307d6716a65bb9e67cb81b",
"ffe495e62d171963549f5cfd937b126691d5173592b7b0e8d7ca00101a033354",
"7afa076d3e45a9f04ca36cdc0ff604acebc32c7a3a2ebeeda05f05e3b405a074",
"de0c2f7b0a1aa7e774e2a48cdcbe770ec3f1f26378fa6820210d55a62e3b30a2",
"d556d43668ea73c5a935ad4199967b53ac1c51245d4edaffe13fbe4d0e826fff",
"dcaf556579a9340e9065a137135dd52ee4e9f81568f71608a25a9a2db10cf44f",
"ebfee7fb52365b69ac386245459e7364533978a9a4996a988b4ba0fb83372959",
]
assert select_class(layers[-1]) == 7
image = bytearray(import_tflite(MODEL))
image[0x24] ^= 1
with pytest.raises(ValueError, match="payload CRC"):
parse_apum(bytes(image))