diff --git a/tensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc b/tensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc index 7b4e1319532..62a741ed2a9 100644 --- a/tensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc +++ b/tensorflow/lite/micro/kernels/cmsis_nn/fully_connected.cc @@ -151,9 +151,9 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { data->kernel_sums = nullptr; #if defined(KERNELS_OPTIMIZED_FOR_SPEED) - const int8_t* filter_data = GetTensorData(filter); - - if (buf_size > 0 && filter_data != nullptr) { + if (buf_size > 0 && IsConstantTensor(filter) && + (bias == nullptr || IsConstantTensor(bias))) { + const int8_t* filter_data = GetTensorData(filter); const int32_t input_offset = -data->reference_op_data.input_zero_point; const int32_t filter_offset = -data->reference_op_data.filter_zero_point; diff --git a/tensorflow/lite/micro/kernels/cmsis_nn/svdf.cc b/tensorflow/lite/micro/kernels/cmsis_nn/svdf.cc index b48dcb4a69d..5cdf6f38303 100644 --- a/tensorflow/lite/micro/kernels/cmsis_nn/svdf.cc +++ b/tensorflow/lite/micro/kernels/cmsis_nn/svdf.cc @@ -193,6 +193,7 @@ TfLiteStatus CmsisNnPrepareSvdf(TfLiteContext* context, TfLiteNode* node) { if (buf_size > 0) { #if defined(KERNELS_OPTIMIZED_FOR_SPEED) + TF_LITE_ENSURE(context, IsConstantTensor(weights_feature)); data->kernel_sums = static_cast( context->AllocatePersistentBuffer(context, buf_size)); @@ -210,6 +211,12 @@ TfLiteStatus CmsisNnPrepareSvdf(TfLiteContext* context, TfLiteNode* node) { "Either KERNELS_OPTIMIZED_FOR_SIZE or KERNELS_OPTIMIZED_FOR_SPEED " "must be defined"); return kTfLiteError; +#endif + } else { + // safety first! + data->kernel_sums = nullptr; +#if defined(KERNELS_OPTIMIZED_FOR_SIZE) + data->scratch_weight_tensor_index = -1; #endif } @@ -310,6 +317,7 @@ TfLiteStatus EvalIntegerSVDF(TfLiteContext* context, TfLiteNode* node, #if defined(KERNELS_OPTIMIZED_FOR_SPEED) ctx.buf = data.kernel_sums; #elif defined(KERNELS_OPTIMIZED_FOR_SIZE) + TF_LITE_ENSURE(context, data.scratch_weight_tensor_index != -1); ctx.buf = static_cast( context->GetScratchBuffer(context, data.scratch_weight_tensor_index)); diff --git a/tensorflow/lite/micro/kernels/cmsis_nn/unidirectional_sequence_lstm.cc b/tensorflow/lite/micro/kernels/cmsis_nn/unidirectional_sequence_lstm.cc index fbbdab33ca0..9c27cc45ffd 100644 --- a/tensorflow/lite/micro/kernels/cmsis_nn/unidirectional_sequence_lstm.cc +++ b/tensorflow/lite/micro/kernels/cmsis_nn/unidirectional_sequence_lstm.cc @@ -344,6 +344,18 @@ TfLiteStatus UnidirectionalSequenceLstmPrepare(TfLiteContext* context, // All TempTfLiteTensors will be deallocated through the destructor. LstmTensors lstm_tensors(context, node); TF_LITE_ENSURE_OK(context, lstm_tensors.ValidateTensorStatus(context)); + // Additional validation of weights and biases. + // ValidateTensorStatus() ensures no tensor is . + for (size_t i = 1; i < 9; i++) { + // check weight + TF_LITE_ENSURE(context, + IsConstantTensor(lstm_tensors.GetInternalTensor(i))); + } + for (size_t i = 12; i < 16; i++) { + // check bias + TF_LITE_ENSURE(context, + IsConstantTensor(lstm_tensors.GetInternalTensor(i))); + } op_data_lstm->cell_gate_nonlinear_type = builtin_data->activation; op_data_lstm->size_info = diff --git a/tensorflow/lite/micro/kernels/fully_connected_test.cc b/tensorflow/lite/micro/kernels/fully_connected_test.cc index 2ceed9ae983..955f3205227 100644 --- a/tensorflow/lite/micro/kernels/fully_connected_test.cc +++ b/tensorflow/lite/micro/kernels/fully_connected_test.cc @@ -307,6 +307,11 @@ TfLiteStatus ValidateFullyConnectedGoldens( TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data); TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data); + tensors[1].allocation_type = kTfLiteMmapRo; + if (!null_bias) { + tensors[2].allocation_type = kTfLiteMmapRo; + } + #ifdef USE_TFLM_COMPRESSION TestCompressedList tcl; diff --git a/tensorflow/lite/micro/kernels/svdf_test.cc b/tensorflow/lite/micro/kernels/svdf_test.cc index ae8fadc1139..3e9a82d433e 100644 --- a/tensorflow/lite/micro/kernels/svdf_test.cc +++ b/tensorflow/lite/micro/kernels/svdf_test.cc @@ -498,6 +498,8 @@ void ValidateSVDFGoldens(const int batch_size, const int num_units, int outputs_array_data[] = {1, 5}; TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data); + tensors[1].allocation_type = kTfLiteMmapRo; + const TFLMRegistration registration = Register_SVDF(); micro::KernelRunner runner(registration, tensors, tensor_count, inputs_array, outputs_array, ¶ms); diff --git a/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test.cc b/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test.cc index 1e5a86808f4..77443191033 100644 --- a/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test.cc +++ b/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test.cc @@ -29,6 +29,18 @@ namespace { constexpr int kLstmMaxNumInputOutputTensors = 24 + 1; +// Set weights and biases to be const-tensors +void SetConstTensors(TfLiteTensor* tensors) { + for (size_t i = 1; i < 9; i++) { + // weights + tensors[i].allocation_type = kTfLiteMmapRo; + } + for (size_t i = 12; i < 16; i++) { + // biases + tensors[i].allocation_type = kTfLiteMmapRo; + } +} + // Validate the output result array with golden values template void ValidateResultGoldens(const T* golden, const T* output_data, @@ -49,6 +61,7 @@ void TestUnidirectionalLSTMInteger( LstmNodeContent& node_contents) { + SetConstTensors(node_contents.GetTensors()); const TFLMRegistration registration = Register_UNIDIRECTIONAL_SEQUENCE_LSTM(); auto buildin_data = node_contents.BuiltinData(); micro::KernelRunner runner( @@ -101,6 +114,7 @@ void TestUnidirectionalLSTMFloat( const float hidden_state_tolerance, const float cell_state_tolerance, LstmNodeContent& node_contents) { + SetConstTensors(node_contents.GetTensors()); const TFLMRegistration registration = Register_UNIDIRECTIONAL_SEQUENCE_LSTM(); auto buildin_data = node_contents.BuiltinData(); micro::KernelRunner runner(