lstm
Classes
UnidirectionalSequenceLstmOperator
UnidirectionalSequenceLstmOperator(op: AirOperator, model: AirModel, platform: SocPlatform, prefix: str = 'aot', attributes: dict[str, str] | None = None)
AOT operator for UNIDIRECTIONAL_SEQUENCE_LSTM.
Lowers to the CMSIS-NN arm_lstm_unidirectional_* kernels for the
standard Keras LSTM subset (TANH cell activation, no projection clipping,
no diagonal/peephole tensors).
Statefulness (int8 and float paths): the recurrent state persists across
invocations. output_state/cell_state arrive as LiteRT variable
tensors, which parse as :attr:AirTensorKind.PERSISTENT, and codegen points
cmsis_nn_lstm_context::hidden_state at the persistent output_state
slot. A non-NULL hidden_state selects the kernel's state-carry path: the
stored state seeds timestep 0, the cell state is treated as in/out rather
than re-zeroed, and the final hidden state is written back on return. State
therefore survives across model_run calls exactly as it does in the
LiteRT reference interpreter.
output_state/cell_state must not be model inputs. Statefulness is
delivered entirely through the persistent slots above, so externally
supplied recurrent state is a separate capability that codegen does not
implement: the generated test harness re-copies every graph input before
each iteration (templates/test_case.c.j2) whereas the reference
interpreter sets inputs once and carries the mutated state, so the two
would silently disagree.
:meth:~helia_aot.aot.operators.operator.AotOperator._reject_runtime_recurrent_state_input
rejects that configuration rather than emitting code that cannot be
verified.
A second restriction is
:meth:~helia_aot.aot.operators.operator.AotOperator._require_zero_initialized_state:
baked-in
initial state values are rejected because context_init() resets every
persistent slot (see templates/context.c.j2), so such a value could not
be honored. This is a persistent-arena contract, not an LSTM limitation.
:meth:~helia_aot.aot.operators.operator.AotOperator._require_persistent_state
enforces the other half of that contract:
both state tensors must actually be persistent, since a scratch slot may be
aliased with unrelated activations and is never initialized.
Minimum kernel version: hidden_state landed in the int8 context in
ns-cmsis-nn v7.28.0 and in the float contexts in v7.29.0. Both are
satisfied by :data:helia_aot.aot.defines.CMSIS_NN_VERSION, which sits
higher for reasons unrelated to this operator, so no per-operator floor is
declared here.
UNIDIRECTIONAL_SEQUENCE_LSTM operator for CMSIS-NN int8/float paths.