mirror of
https://github.com/vee1e/tflite-micro.git
synced 2026-09-03 10:47:33 +00:00
As the next step in the codegen experiment, we want to generate the invoke calls for each layer. This is slightly challenging with the existing sources, as kernels only expose a registration function, not their individual Eval functions. In an effort to keep the code churn to a minimum, this PR introduces an inference only registration structure and function. It includes just two function pointers: invoke and reset. For this CL, we've only introduced it for FullyConnected. In the code generator, this PR creates a new op_table array in the generated source, with an enum for lookup. It also generates an invoke function for each subgraph, that calls each operator's invoke function. BUG=295174388
136 lines
5.9 KiB
C++
136 lines
5.9 KiB
C++
/* Copyright 2017 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.
|
|
==============================================================================*/
|
|
|
|
/* Copyright 2020 The Qualcomm Innovation Center, Inc. All Rights Reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted (subject to the limitations in the disclaimer
|
|
below) provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
* Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
|
|
contributors may be used to endorse or promote products derived from this
|
|
software without specific prior written permission.
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
|
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
|
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
==============================================================================*/
|
|
|
|
#include "tensorflow/lite/micro/kernels/fully_connected.h"
|
|
|
|
#include "tensorflow/lite/c/builtin_op_data.h"
|
|
#include "tensorflow/lite/c/common.h"
|
|
#include "tensorflow/lite/kernels/internal/common.h"
|
|
#include "tensorflow/lite/kernels/internal/quantization_util.h"
|
|
#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
|
|
#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h"
|
|
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
|
|
#include "tensorflow/lite/kernels/kernel_util.h"
|
|
#include "tensorflow/lite/micro/kernels/kernel_util.h"
|
|
#include "tensorflow/lite/micro/micro_log.h"
|
|
#include "third_party/hexagon/hexagon_fully_connected.h"
|
|
#include "third_party/hexagon/hexagon_tflm_translation_fully_connected.h"
|
|
|
|
namespace tflite {
|
|
|
|
namespace {
|
|
|
|
TfLiteStatus EvalFloat(TfLiteContext* context, TfLiteNode* node,
|
|
TfLiteFusedActivation activation,
|
|
const TfLiteEvalTensor* input,
|
|
const TfLiteEvalTensor* filter,
|
|
const TfLiteEvalTensor* bias, TfLiteEvalTensor* output) {
|
|
float output_activation_min, output_activation_max;
|
|
CalculateActivationRange(activation, &output_activation_min,
|
|
&output_activation_max);
|
|
tflite::FullyConnectedParams op_params;
|
|
op_params.float_activation_min = output_activation_min;
|
|
op_params.float_activation_max = output_activation_max;
|
|
|
|
const float* bias_data =
|
|
nullptr != bias ? tflite::micro::GetTensorData<float>(bias) : nullptr;
|
|
|
|
tflite::reference_ops::FullyConnected(
|
|
op_params, tflite::micro::GetTensorShape(input),
|
|
tflite::micro::GetTensorData<float>(input),
|
|
tflite::micro::GetTensorShape(filter),
|
|
tflite::micro::GetTensorData<float>(filter),
|
|
tflite::micro::GetTensorShape(bias), bias_data,
|
|
tflite::micro::GetTensorShape(output),
|
|
tflite::micro::GetTensorData<float>(output));
|
|
return kTfLiteOk;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TfLiteStatus HexagonFullyConnectedEval(TfLiteContext* context,
|
|
TfLiteNode* node) {
|
|
TFLITE_DCHECK(node->builtin_data != nullptr);
|
|
const auto* params =
|
|
static_cast<const TfLiteFullyConnectedParams*>(node->builtin_data);
|
|
|
|
const TfLiteEvalTensor* input =
|
|
tflite::micro::GetEvalInput(context, node, kFullyConnectedInputTensor);
|
|
const TfLiteEvalTensor* filter =
|
|
tflite::micro::GetEvalInput(context, node, kFullyConnectedWeightsTensor);
|
|
const TfLiteEvalTensor* bias =
|
|
tflite::micro::GetEvalInput(context, node, kFullyConnectedBiasTensor);
|
|
TfLiteEvalTensor* output =
|
|
tflite::micro::GetEvalOutput(context, node, kFullyConnectedOutputTensor);
|
|
|
|
TFLITE_DCHECK(node->user_data != nullptr);
|
|
|
|
// Checks in Prepare ensure input, output and filter types are all the same.
|
|
switch (input->type) {
|
|
case kTfLiteFloat32:
|
|
return EvalFloat(context, node, params->activation, input, filter, bias,
|
|
output);
|
|
|
|
case kTfLiteInt8:
|
|
return HexagonFullyConnectedEvalInt8(context, node);
|
|
|
|
default:
|
|
MicroPrintf( "Type %s (%d) not supported.",
|
|
TfLiteTypeGetName(input->type), input->type);
|
|
return kTfLiteError;
|
|
}
|
|
return kTfLiteOk;
|
|
}
|
|
|
|
TFLMRegistration Register_FULLY_CONNECTED() {
|
|
return tflite::micro::RegisterOp(HexagonFullyConnectedInit,
|
|
HexagonFullyConnectedPrepare,
|
|
HexagonFullyConnectedEval);
|
|
}
|
|
|
|
TFLMInferenceRegistration RegisterInference_FULLY_CONNECTED() {
|
|
return tflite::micro::RegisterOp(HexagonFullyConnectedEval);
|
|
}
|
|
|
|
} // namespace tflite
|