• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/kernels/internal/reference/hard_swish.h"
17 
18 #include "tensorflow/lite/c/builtin_op_data.h"
19 #include "tensorflow/lite/c/common.h"
20 #include "tensorflow/lite/kernels/internal/common.h"
21 #include "tensorflow/lite/kernels/internal/quantization_util.h"
22 #include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
23 #include "tensorflow/lite/kernels/internal/types.h"
24 #include "tensorflow/lite/kernels/kernel_util.h"
25 #include "tensorflow/lite/kernels/op_macros.h"
26 #include "tensorflow/lite/micro/kernels/kernel_util.h"
27 #include "tensorflow/lite/micro/micro_utils.h"
28 
29 namespace tflite {
30 namespace ops {
31 namespace micro {
32 namespace hard_swish {
33 
34 constexpr int kInputTensor = 0;
35 constexpr int kOutputTensor = 0;
36 
HardSwishInit(TfLiteContext * context,const char * buffer,size_t length)37 void* HardSwishInit(TfLiteContext* context, const char* buffer, size_t length) {
38   TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
39   return context->AllocatePersistentBuffer(context, sizeof(HardSwishParams));
40 }
41 
HardSwishPrepare(TfLiteContext * context,TfLiteNode * node)42 TfLiteStatus HardSwishPrepare(TfLiteContext* context, TfLiteNode* node) {
43   TFLITE_DCHECK(node->user_data != nullptr);
44   TF_LITE_ENSURE_EQ(context, NumInputs(node), 1);
45   TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
46 
47   const TfLiteTensor* input = GetInput(context, node, kInputTensor);
48   TF_LITE_ENSURE(context, input != nullptr);
49   TfLiteTensor* output = GetOutput(context, node, kOutputTensor);
50   TF_LITE_ENSURE(context, output != nullptr);
51 
52   if (input->type == kTfLiteUInt8 || input->type == kTfLiteInt8) {
53     HardSwishParams* params = static_cast<HardSwishParams*>(node->user_data);
54 
55     params->input_zero_point = input->params.zero_point;
56     params->output_zero_point = output->params.zero_point;
57 
58     const float input_scale = input->params.scale;
59     const float hires_input_scale = (1.0f / 128.0f) * input_scale;
60     const float reluish_scale = 3.0f / 32768.0f;
61     const float output_scale = output->params.scale;
62 
63     const double output_multiplier =
64         static_cast<double>(hires_input_scale / output_scale);
65     int32_t output_multiplier_fixedpoint_int32;
66     QuantizeMultiplier(output_multiplier, &output_multiplier_fixedpoint_int32,
67                        &params->output_multiplier_exponent);
68     DownScaleInt32ToInt16Multiplier(
69         output_multiplier_fixedpoint_int32,
70         &params->output_multiplier_fixedpoint_int16);
71 
72     TF_LITE_ENSURE(context, params->output_multiplier_exponent <= 0);
73 
74     const double reluish_multiplier =
75         static_cast<double>(hires_input_scale / reluish_scale);
76     int32_t reluish_multiplier_fixedpoint_int32;
77     QuantizeMultiplier(reluish_multiplier, &reluish_multiplier_fixedpoint_int32,
78                        &params->reluish_multiplier_exponent);
79     DownScaleInt32ToInt16Multiplier(
80         reluish_multiplier_fixedpoint_int32,
81         &params->reluish_multiplier_fixedpoint_int16);
82   }
83 
84   return kTfLiteOk;
85 }
86 
HardSwishEval(TfLiteContext * context,TfLiteNode * node)87 TfLiteStatus HardSwishEval(TfLiteContext* context, TfLiteNode* node) {
88   const TfLiteEvalTensor* input =
89       tflite::micro::GetEvalInput(context, node, kInputTensor);
90   TfLiteEvalTensor* output =
91       tflite::micro::GetEvalOutput(context, node, kOutputTensor);
92   HardSwishParams* params = static_cast<HardSwishParams*>(node->user_data);
93 
94   switch (input->type) {
95     case kTfLiteFloat32: {
96       tflite::reference_ops::HardSwish<float>(
97           tflite::micro::GetTensorShape(input),
98           tflite::micro::GetTensorData<float>(input),
99           tflite::micro::GetTensorShape(output),
100           tflite::micro::GetTensorData<float>(output));
101     } break;
102     case kTfLiteUInt8: {
103       tflite::reference_ops::HardSwish<uint8_t>(
104           *params, tflite::micro::GetTensorShape(input),
105           tflite::micro::GetTensorData<uint8_t>(input),
106           tflite::micro::GetTensorShape(output),
107           tflite::micro::GetTensorData<uint8_t>(output));
108     } break;
109     case kTfLiteInt8: {
110       tflite::reference_ops::HardSwish<int8_t>(
111           *params, tflite::micro::GetTensorShape(input),
112           tflite::micro::GetTensorData<int8_t>(input),
113           tflite::micro::GetTensorShape(output),
114           tflite::micro::GetTensorData<int8_t>(output));
115     } break;
116     default: {
117       TF_LITE_KERNEL_LOG(
118           context,
119           "Only float32/int8_t/uint8_t are supported currently, got %s",
120           TfLiteTypeGetName(input->type));
121       return kTfLiteError;
122     }
123   }
124   return kTfLiteOk;
125 }
126 
127 }  // namespace hard_swish
128 
Register_HARD_SWISH()129 TfLiteRegistration Register_HARD_SWISH() {
130   return {/*init=*/hard_swish::HardSwishInit,
131           /*free=*/nullptr,
132           /*prepare=*/hard_swish::HardSwishPrepare,
133           /*invoke=*/hard_swish::HardSwishEval,
134           /*profiling_string=*/nullptr,
135           /*builtin_code=*/0,
136           /*custom_name=*/nullptr,
137           /*version=*/0};
138 }
139 
140 }  // namespace micro
141 }  // namespace ops
142 }  // namespace tflite
143