168 lines
6.8 KiB
C++
168 lines
6.8 KiB
C++
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==============================================================================*/
|
|
|
|
#include "tensorflow/lite/kernels/internal/reference/dequantize.h"
|
|
|
|
#include "tensorflow/lite/c/builtin_op_data.h"
|
|
#include "tensorflow/lite/c/common.h"
|
|
#include "tensorflow/lite/kernels/internal/quantization_util.h"
|
|
#include "tensorflow/lite/kernels/internal/reference/quantize.h"
|
|
#include "tensorflow/lite/kernels/internal/reference/requantize.h"
|
|
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
|
|
#include "tensorflow/lite/kernels/kernel_util.h"
|
|
#include "tensorflow/lite/micro/kernels/dequantize.h"
|
|
#include "tensorflow/lite/micro/kernels/kernel_util.h"
|
|
#include "tensorflow/lite/micro/micro_log.h"
|
|
|
|
namespace tflite {
|
|
|
|
void* DequantizeInit(TfLiteContext* context, const char* buffer,
|
|
size_t length) {
|
|
TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
|
|
return context->AllocatePersistentBuffer(context, sizeof(DequantizeOpData));
|
|
}
|
|
|
|
TfLiteStatus DequantizeEval(TfLiteContext* context, TfLiteNode* node) {
|
|
TFLITE_DCHECK(node->user_data != nullptr);
|
|
DequantizeOpData* data = static_cast<DequantizeOpData*>(node->user_data);
|
|
|
|
const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
|
|
TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0);
|
|
|
|
// Output type ensured to be kTfLiteFloat32 at the Prepare stage
|
|
TFLITE_DCHECK(output->type == kTfLiteFloat32);
|
|
|
|
switch (input->type) {
|
|
case kTfLiteInt8:
|
|
reference_ops::Dequantize(data->quantization_params,
|
|
tflite::micro::GetTensorShape(input),
|
|
tflite::micro::GetTensorData<int8_t>(input),
|
|
tflite::micro::GetTensorShape(output),
|
|
tflite::micro::GetTensorData<float>(output));
|
|
break;
|
|
case kTfLiteInt16:
|
|
reference_ops::Dequantize(data->quantization_params,
|
|
tflite::micro::GetTensorShape(input),
|
|
tflite::micro::GetTensorData<int16_t>(input),
|
|
tflite::micro::GetTensorShape(output),
|
|
tflite::micro::GetTensorData<float>(output));
|
|
break;
|
|
case kTfLiteUInt8:
|
|
reference_ops::Dequantize(data->quantization_params,
|
|
tflite::micro::GetTensorShape(input),
|
|
tflite::micro::GetTensorData<uint8_t>(input),
|
|
tflite::micro::GetTensorShape(output),
|
|
tflite::micro::GetTensorData<float>(output));
|
|
break;
|
|
default:
|
|
MicroPrintf("Input %s, output %s not supported.",
|
|
TfLiteTypeGetName(input->type),
|
|
TfLiteTypeGetName(output->type));
|
|
return kTfLiteError;
|
|
}
|
|
|
|
return kTfLiteOk;
|
|
}
|
|
|
|
TfLiteStatus DequantizeEvalInt8(TfLiteContext* context, TfLiteNode* node) {
|
|
TFLITE_DCHECK(node->user_data != nullptr);
|
|
DequantizeOpData* data = static_cast<DequantizeOpData*>(node->user_data);
|
|
|
|
const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
|
|
TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0);
|
|
|
|
TFLITE_DCHECK(input->type == kTfLiteInt8 && output->type == kTfLiteFloat32);
|
|
reference_ops::Dequantize(data->quantization_params,
|
|
tflite::micro::GetTensorShape(input),
|
|
tflite::micro::GetTensorData<int8_t>(input),
|
|
tflite::micro::GetTensorShape(output),
|
|
tflite::micro::GetTensorData<float>(output));
|
|
return kTfLiteOk;
|
|
}
|
|
|
|
#ifdef TFLITE_MODEL_COMPILER
|
|
TfLiteStatus DequantizeCompileInt8(TfLiteContext* context, TfLiteNode* node,
|
|
TfLiteCompileStep step, std::ofstream& ofs) {
|
|
switch (step) {
|
|
case kTfLiteCompileStepInclude:
|
|
ofs << "#include \"tensorflow/lite/micro/kernels/dequantize.h\"" << std::endl
|
|
<< "#include \"tensorflow/lite/kernels/internal/reference/dequantize.h\""
|
|
<< std::endl;
|
|
break;
|
|
|
|
case kTfLiteCompileStepEval: {
|
|
TFLITE_DCHECK(node->user_data != nullptr);
|
|
DequantizeOpData* data = static_cast<DequantizeOpData*>(node->user_data);
|
|
|
|
const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
|
|
TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0);
|
|
TFLITE_DCHECK(input->type == kTfLiteInt8 && output->type == kTfLiteFloat32);
|
|
|
|
ofs << "{ // dequantize int8 to float" << std::endl;
|
|
|
|
tflite::micro::CompileAddress(ofs, "input_data", input->data.data);
|
|
tflite::micro::CompileAddress(ofs, "output_data", output->data.data);
|
|
|
|
ofs << "static const tflite::DequantizationParams op_params = {"
|
|
<< ".scale = " << data->quantization_params.scale
|
|
<< ", .zero_point = " << data->quantization_params.zero_point
|
|
<< "};"
|
|
<< std::endl;
|
|
|
|
tflite::micro::CompileArray(ofs, "const int32_t", "input_dims_data",
|
|
input->dims->data, input->dims->size);
|
|
|
|
tflite::micro::CompileArray(ofs, "const int32_t", "output_dims_data",
|
|
output->dims->data, output->dims->size);
|
|
|
|
ofs << "tflite::reference_ops::Dequantize(op_params, "
|
|
"tflite::RuntimeShape("
|
|
<< input->dims->size
|
|
<< ", input_dims_data), "
|
|
"reinterpret_cast<int8_t*>(input_data), "
|
|
"tflite::RuntimeShape("
|
|
<< output->dims->size
|
|
<< ", output_dims_data), "
|
|
"reinterpret_cast<float*>(output_data));"
|
|
<< std::endl;
|
|
|
|
ofs << "}" << std::endl;
|
|
} break;
|
|
|
|
default:
|
|
return kTfLiteError;
|
|
}
|
|
|
|
return kTfLiteOk;
|
|
}
|
|
#endif
|
|
|
|
TFLMRegistration Register_DEQUANTIZE() {
|
|
return tflite::micro::RegisterOp(DequantizeInit, DequantizePrepare,
|
|
DequantizeEval);
|
|
}
|
|
|
|
TFLMRegistration Register_DEQUANTIZE_INT8() {
|
|
#ifdef TFLITE_MODEL_COMPILER
|
|
return tflite::micro::CompileOp(DequantizeInit, DequantizePrepare,
|
|
DequantizeEvalInt8, DequantizeCompileInt8);
|
|
#else
|
|
return tflite::micro::RegisterOp(DequantizeInit, DequantizePrepare,
|
|
DequantizeEvalInt8);
|
|
#endif
|
|
}
|
|
|
|
} // namespace tflite
|