Skip to content

Commit 416f16b

Browse files
committed
Merge branch 'ci/sync_gh_tflite-micro' into 'master'
Sync esp-tflite-micro from github - 942638 See merge request app-frameworks/esp-tflite-micro!172
2 parents 416d371 + d25d3bb commit 416f16b

16 files changed

+463
-223
lines changed

tensorflow/lite/micro/kernels/activations.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -54,14 +54,23 @@ TfLiteStatus ReluEval(TfLiteContext* context, TfLiteNode* node) {
5454
return kTfLiteOk;
5555
}
5656
case kTfLiteInt8: {
57-
tflite::ReluQuantized(data, tflite::micro::GetTensorShape(input),
58-
tflite::micro::GetTensorShape(output),
59-
tflite::micro::GetTensorData<int8_t>(input),
60-
tflite::micro::GetTensorData<int8_t>(output));
57+
tflite::ReluQuantized<int8_t>(
58+
data, tflite::micro::GetTensorShape(input),
59+
tflite::micro::GetTensorShape(output),
60+
tflite::micro::GetTensorData<int8_t>(input),
61+
tflite::micro::GetTensorData<int8_t>(output));
62+
return kTfLiteOk;
63+
}
64+
case kTfLiteInt16: {
65+
tflite::ReluQuantized<int16_t>(
66+
data, tflite::micro::GetTensorShape(input),
67+
tflite::micro::GetTensorShape(output),
68+
tflite::micro::GetTensorData<int16_t>(input),
69+
tflite::micro::GetTensorData<int16_t>(output));
6170
return kTfLiteOk;
6271
}
6372
default: {
64-
MicroPrintf("Only float32 is supported currently, got %s",
73+
MicroPrintf("Only float32/int8/int16 is supported currently, got %s",
6574
TfLiteTypeGetName(input->type));
6675
return kTfLiteError;
6776
}
@@ -109,7 +118,7 @@ TfLiteStatus Relu6Eval(TfLiteContext* context, TfLiteNode* node) {
109118
return kTfLiteOk;
110119
}
111120
default: {
112-
MicroPrintf("Only float32 is supported currently, got %s",
121+
MicroPrintf("Only float32/int8/int16 is supported currently, got %s",
113122
TfLiteTypeGetName(input->type));
114123
return kTfLiteError;
115124
}

tensorflow/lite/micro/kernels/activations.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ limitations under the License.
2020

2121
#include "tensorflow/lite/c/builtin_op_data.h"
2222
#include "tensorflow/lite/c/common.h"
23+
#include "tensorflow/lite/kernels/internal/common.h"
2324
#include "tensorflow/lite/kernels/internal/types.h"
2425

2526
namespace tflite {
@@ -36,9 +37,23 @@ struct Relu6OpData {
3637
int32_t zero;
3738
};
3839

40+
template <typename T>
3941
void ReluQuantized(const ReluOpData& data, const RuntimeShape& input_shape,
40-
const RuntimeShape& output_shape, const int8_t* input_data,
41-
int8_t* output_data);
42+
const RuntimeShape& output_shape, const T* input_data,
43+
T* output_data) {
44+
const int flat_size = MatchingFlatSize(input_shape, output_shape);
45+
for (int i = 0; i < flat_size; ++i) {
46+
const int32_t val = static_cast<int32_t>(input_data[i]);
47+
int32_t clamped =
48+
data.params.output_offset +
49+
MultiplyByQuantizedMultiplier(val - data.params.input_offset,
50+
data.params.output_multiplier,
51+
data.params.output_shift);
52+
clamped = std::max(data.params.quantized_activation_min, clamped);
53+
clamped = std::min(data.params.quantized_activation_max, clamped);
54+
output_data[i] = static_cast<T>(clamped);
55+
}
56+
}
4257

4358
template <typename T>
4459
void CalculateReluOpData(const TfLiteTensor* input, TfLiteTensor* output,

tensorflow/lite/micro/kernels/activations_common.cc

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -33,23 +33,6 @@ namespace tflite {
3333
const int kActivationsInputTensor = 0;
3434
const int kActivationsOutputTensor = 0;
3535

36-
void ReluQuantized(const ReluOpData& data, const RuntimeShape& input_shape,
37-
const RuntimeShape& output_shape, const int8_t* input_data,
38-
int8_t* output_data) {
39-
const int flat_size = MatchingFlatSize(input_shape, output_shape);
40-
for (int i = 0; i < flat_size; ++i) {
41-
const int32_t val = static_cast<int32_t>(input_data[i]);
42-
int32_t clamped =
43-
data.params.output_offset +
44-
MultiplyByQuantizedMultiplier(val - data.params.input_offset,
45-
data.params.output_multiplier,
46-
data.params.output_shift);
47-
clamped = std::max(data.params.quantized_activation_min, clamped);
48-
clamped = std::min(data.params.quantized_activation_max, clamped);
49-
output_data[i] = static_cast<int8_t>(clamped);
50-
}
51-
}
52-
5336
template <typename T>
5437
void CalculateReluOpData(const TfLiteTensor* input, TfLiteTensor* output,
5538
ReluOpData* data) {
@@ -116,6 +99,10 @@ TfLiteStatus ReluPrepare(TfLiteContext* context, TfLiteNode* node) {
11699

117100
if (input->type == kTfLiteInt8) {
118101
CalculateReluOpData<int8_t>(input, output, data);
102+
} else if (input->type == kTfLiteInt16) {
103+
TF_LITE_ENSURE_EQ(context, input->params.zero_point, 0);
104+
TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0);
105+
CalculateReluOpData<int16_t>(input, output, data);
119106
}
120107

121108
micro_context->DeallocateTempTfLiteTensor(input);

tensorflow/lite/micro/kernels/comparisons.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -286,6 +286,19 @@ TfLiteStatus GreaterEval(TfLiteContext* context, TfLiteNode* node) {
286286
tflite::micro::GetTensorData<int8_t>(input2), output_shape,
287287
output_data);
288288
break;
289+
case kTfLiteInt16:
290+
requires_broadcast
291+
? reference_ops::Broadcast4DSlowGreaterWithScaling(
292+
data->params, input1_shape,
293+
tflite::micro::GetTensorData<int16_t>(input1), input2_shape,
294+
tflite::micro::GetTensorData<int16_t>(input2), output_shape,
295+
output_data)
296+
: reference_ops::GreaterWithScaling(
297+
data->params, input1_shape,
298+
tflite::micro::GetTensorData<int16_t>(input1), input2_shape,
299+
tflite::micro::GetTensorData<int16_t>(input2), output_shape,
300+
output_data);
301+
break;
289302
default:
290303
MicroPrintf("Type %s (%d) not supported.",
291304
TfLiteTypeGetName(input1->type), input1->type);

tensorflow/lite/micro/kernels/fully_connected.cc

Lines changed: 89 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -238,25 +238,97 @@ TfLiteStatus FullyConnectedEval(TfLiteContext* context, TfLiteNode* node) {
238238
case kTfLiteInt16: {
239239
switch (filter->type) {
240240
case kTfLiteInt8: {
241-
tflite::reference_integer_ops::FullyConnected(
242-
FullyConnectedParamsQuantized(data),
243-
tflite::micro::GetTensorShape(input),
244-
tflite::micro::GetTensorData<int16_t>(input),
245-
tflite::micro::GetTensorShape(filter),
241+
if (bias == nullptr || bias->type == kTfLiteInt32) {
242+
data.is_per_channel
243+
? tflite::reference_integer_ops::FullyConnectedPerChannel(
244+
FullyConnectedParamsQuantized(data),
245+
data.per_channel_output_multiplier,
246+
reinterpret_cast<const int*>(
247+
data.per_channel_output_shift),
248+
tflite::micro::GetTensorShape(input),
249+
tflite::micro::GetTensorData<int16_t>(input),
250+
tflite::micro::GetTensorShape(filter),
246251
#ifdef USE_TFLM_COMPRESSION
247-
tflite::micro::GetTensorData<int8_t>(micro_context, filter,
248-
weights_comp_td,
249-
data.weights_scratch_index),
250-
tflite::micro::GetTensorShape(bias),
251-
tflite::micro::GetOptionalTensorData<int64_t>(
252-
micro_context, bias, bias_comp_td, data.bias_scratch_index),
252+
tflite::micro::GetTensorData<int8_t>(
253+
micro_context, filter, weights_comp_td,
254+
data.weights_scratch_index),
255+
tflite::micro::GetTensorShape(bias),
256+
tflite::micro::GetOptionalTensorData<int32_t>(
257+
micro_context, bias, bias_comp_td,
258+
data.bias_scratch_index),
253259
#else // USE_TFLM_COMPRESSION
254-
tflite::micro::GetTensorData<int8_t>(filter),
255-
tflite::micro::GetTensorShape(bias),
256-
tflite::micro::GetOptionalTensorData<int64_t>(bias),
260+
tflite::micro::GetTensorData<int8_t>(filter),
261+
tflite::micro::GetTensorShape(bias),
262+
tflite::micro::GetOptionalTensorData<int32_t>(bias),
257263
#endif // USE_TFLM_COMPRESSION
258-
tflite::micro::GetTensorShape(output),
259-
tflite::micro::GetTensorData<int16_t>(output));
264+
tflite::micro::GetTensorShape(output),
265+
tflite::micro::GetTensorData<int16_t>(output))
266+
: tflite::reference_integer_ops::FullyConnected(
267+
FullyConnectedParamsQuantized(data),
268+
tflite::micro::GetTensorShape(input),
269+
tflite::micro::GetTensorData<int16_t>(input),
270+
tflite::micro::GetTensorShape(filter),
271+
#ifdef USE_TFLM_COMPRESSION
272+
tflite::micro::GetTensorData<int8_t>(
273+
micro_context, filter, weights_comp_td,
274+
data.weights_scratch_index),
275+
tflite::micro::GetTensorShape(bias),
276+
tflite::micro::GetOptionalTensorData<int32_t>(
277+
micro_context, bias, bias_comp_td,
278+
data.bias_scratch_index),
279+
#else // USE_TFLM_COMPRESSION
280+
tflite::micro::GetTensorData<int8_t>(filter),
281+
tflite::micro::GetTensorShape(bias),
282+
tflite::micro::GetOptionalTensorData<int32_t>(bias),
283+
#endif // USE_TFLM_COMPRESSION
284+
tflite::micro::GetTensorShape(output),
285+
tflite::micro::GetTensorData<int16_t>(output));
286+
} else if (bias->type == kTfLiteInt64) {
287+
data.is_per_channel
288+
? tflite::reference_integer_ops::FullyConnectedPerChannel(
289+
FullyConnectedParamsQuantized(data),
290+
data.per_channel_output_multiplier,
291+
reinterpret_cast<const int*>(
292+
data.per_channel_output_shift),
293+
tflite::micro::GetTensorShape(input),
294+
tflite::micro::GetTensorData<int16_t>(input),
295+
tflite::micro::GetTensorShape(filter),
296+
#ifdef USE_TFLM_COMPRESSION
297+
tflite::micro::GetTensorData<int8_t>(
298+
micro_context, filter, weights_comp_td,
299+
data.weights_scratch_index),
300+
tflite::micro::GetTensorShape(bias),
301+
tflite::micro::GetOptionalTensorData<int64_t>(
302+
micro_context, bias, bias_comp_td,
303+
data.bias_scratch_index),
304+
#else // USE_TFLM_COMPRESSION
305+
tflite::micro::GetTensorData<int8_t>(filter),
306+
tflite::micro::GetTensorShape(bias),
307+
tflite::micro::GetOptionalTensorData<int64_t>(bias),
308+
#endif // USE_TFLM_COMPRESSION
309+
tflite::micro::GetTensorShape(output),
310+
tflite::micro::GetTensorData<int16_t>(output))
311+
: tflite::reference_integer_ops::FullyConnected(
312+
FullyConnectedParamsQuantized(data),
313+
tflite::micro::GetTensorShape(input),
314+
tflite::micro::GetTensorData<int16_t>(input),
315+
tflite::micro::GetTensorShape(filter),
316+
#ifdef USE_TFLM_COMPRESSION
317+
tflite::micro::GetTensorData<int8_t>(
318+
micro_context, filter, weights_comp_td,
319+
data.weights_scratch_index),
320+
tflite::micro::GetTensorShape(bias),
321+
tflite::micro::GetOptionalTensorData<int64_t>(
322+
micro_context, bias, bias_comp_td,
323+
data.bias_scratch_index),
324+
#else // USE_TFLM_COMPRESSION
325+
tflite::micro::GetTensorData<int8_t>(filter),
326+
tflite::micro::GetTensorShape(bias),
327+
tflite::micro::GetOptionalTensorData<int64_t>(bias),
328+
#endif // USE_TFLM_COMPRESSION
329+
tflite::micro::GetTensorShape(output),
330+
tflite::micro::GetTensorData<int16_t>(output));
331+
}
260332
break;
261333
}
262334
default: {

tensorflow/lite/micro/kernels/fully_connected_common.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
1+
/* Copyright 2025 The TensorFlow Authors. All Rights Reserved.
22
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
@@ -95,9 +95,14 @@ TfLiteStatus CalculateOpDataFullyConnected(
9595
filter->quantization.params);
9696
const int per_channel_quantization_size = affine_quantization->scale->size;
9797

98-
// Currently only Int8 is supported for per channel quantization.
99-
TF_LITE_ENSURE(context,
100-
input->type == kTfLiteInt8 && filter->type != kTfLiteInt4);
98+
// Currently only Int8/Int16 are supported for per channel quantization.
99+
TF_LITE_ENSURE(
100+
context,
101+
(input->type == kTfLiteInt8 && filter->type != kTfLiteInt4) ||
102+
(input->type == kTfLiteInt16 && filter->type != kTfLiteInt4));
103+
104+
TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size,
105+
per_channel_quantization_size);
101106

102107
TF_LITE_ENSURE_EQ(
103108
context, per_channel_quantization_size,

0 commit comments

Comments
 (0)