summaryrefslogtreecommitdiff
path: root/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp')
-rw-r--r--compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
new file mode 100644
index 000000000..8ec9ce491
--- /dev/null
+++ b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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 "ConvBackend.h"
+
+#include <nncc/core/ADT/kernel/Overlay.h>
+#include <nncc/core/ADT/kernel/NHWCLayout.h>
+
+#include <tensorflow/contrib/lite/kernels/register.h>
+#include <tensorflow/contrib/lite/model.h>
+#include <tensorflow/contrib/lite/builtin_op_data.h>
+
+#include <cstdlib>
+#include <stdexcept>
+
+using namespace ::tflite;
+using namespace ::tflite::ops::builtin;
+
+/**
+ * @brief Allocate memory with malloc and return a typed pointer
+ *
+ * NOTE This function throws std::bac_alloc exception on allocation failure
+ */
+template <typename T> T *typed_malloc(void)
+{
+ if (auto res = reinterpret_cast<T *>(malloc(sizeof(T))))
+ {
+ return res;
+ }
+ throw std::bad_alloc{};
+}
+
+// Comment from 'context.h'
+//
+// Parameters for asymmetric quantization. Quantized values can be converted
+// back to float using:
+// real_value = scale * (quantized_value - zero_point);
+static inline TfLiteQuantizationParams make_default_quantization(void)
+{
+ return TfLiteQuantizationParams{1.0f, 0};
+}
+
+static inline std::vector<int> as_dims(const nncc::core::ADT::feature::Shape &shape)
+{
+ const int N = 1;
+ const int C = static_cast<int>(shape.depth());
+ const int H = static_cast<int>(shape.height());
+ const int W = static_cast<int>(shape.width());
+
+ return std::vector<int>{N, H, W, C};
+}
+
+static inline std::vector<int> as_dims(const nncc::core::ADT::kernel::Shape &shape)
+{
+ const int N = static_cast<int>(shape.count());
+ const int C = static_cast<int>(shape.depth());
+ const int H = static_cast<int>(shape.height());
+ const int W = static_cast<int>(shape.width());
+
+ return std::vector<int>{N, H, W, C};
+}
+
+ConvBackend::ConvBackend(const nnsuite::conv::Model &model)
+ : _ifm_name{model.ifm_name()}, _ofm_name{model.ofm_name()}
+{
+ using nncc::core::ADT::kernel::Overlay;
+ using nncc::core::ADT::kernel::NHWCLayout;
+
+ using nncc::core::ADT::kernel::make_overlay;
+ using nncc::core::ADT::kernel::num_elements;
+
+ // Set kernel data
+ const auto &ker_shape = model.ker_shape();
+
+ _kernel.resize(num_elements(ker_shape));
+
+ auto kernel_overlay = make_overlay<float, NHWCLayout>(ker_shape, _kernel.data());
+
+ for (uint32_t n = 0; n < ker_shape.count(); ++n)
+ {
+ for (uint32_t ch = 0; ch < ker_shape.depth(); ++ch)
+ {
+ for (uint32_t row = 0; row < ker_shape.height(); ++row)
+ {
+ for (uint32_t col = 0; col < ker_shape.width(); ++col)
+ {
+ kernel_overlay.at(n, ch, row, col) = model.ker_data().at(n, ch, row, col);
+ }
+ }
+ }
+ }
+
+ // Set bias data
+ _bias.resize(ker_shape.count(), 0.0f);
+
+ // Initialize interpreter
+ auto quantization = make_default_quantization();
+
+ // Create Tensors
+ // 0 -> OFM
+ // 1 -> IFM
+ // 2 -> Kernel
+ // 3 -> Bias
+ _interp.AddTensors(4);
+
+ _interp.SetTensorParametersReadWrite(0, kTfLiteFloat32 /* type */, _ofm_name.c_str(),
+ as_dims(model.ofm_shape()), quantization);
+
+ _interp.SetTensorParametersReadWrite(1, kTfLiteFloat32 /* type */, _ifm_name.c_str(),
+ as_dims(model.ifm_shape()), quantization);
+
+ _interp.SetTensorParametersReadOnly(
+ 2, kTfLiteFloat32 /* type */, "kernel" /* name */, as_dims(model.ker_shape()), quantization,
+ reinterpret_cast<const char *>(_kernel.data()), _kernel.size() * sizeof(float));
+
+ _interp.SetTensorParametersReadOnly(
+ 3, kTfLiteFloat32 /* type */, "bias" /* name */, {static_cast<int>(_bias.size())},
+ quantization, reinterpret_cast<const char *>(_bias.data()), _bias.size() * sizeof(float));
+
+ auto param = typed_malloc<TfLiteConvParams>();
+
+ param->padding = kTfLitePaddingValid;
+ param->stride_width = 1;
+ param->stride_height = 1;
+ param->activation = kTfLiteActNone;
+
+ _interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
+ BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D));
+
+ _interp.SetInputs({1});
+ _interp.SetOutputs({0});
+}