summaryrefslogtreecommitdiff
path: root/runtime/neurun/api/src
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/neurun/api/src')
-rw-r--r--runtime/neurun/api/src/CustomKernel.cc98
-rw-r--r--runtime/neurun/api/src/CustomKernel.h59
-rw-r--r--runtime/neurun/api/src/CustomKernelRegistry.cc64
-rw-r--r--runtime/neurun/api/src/CustomKernelRegistry.h64
-rw-r--r--runtime/neurun/api/src/OpMap.lst89
-rw-r--r--runtime/neurun/api/src/nnfw_api.cc267
-rw-r--r--runtime/neurun/api/src/nnfw_api_internal.cc435
-rw-r--r--runtime/neurun/api/src/nnfw_api_internal.h84
-rw-r--r--runtime/neurun/api/src/nnfw_debug.cc24
-rw-r--r--runtime/neurun/api/src/nnfw_debug_internal.cc25
-rw-r--r--runtime/neurun/api/src/nnfw_debug_internal.h29
11 files changed, 1238 insertions, 0 deletions
diff --git a/runtime/neurun/api/src/CustomKernel.cc b/runtime/neurun/api/src/CustomKernel.cc
new file mode 100644
index 000000000..60ddeedc2
--- /dev/null
+++ b/runtime/neurun/api/src/CustomKernel.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2019 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 "CustomKernel.h"
+
+namespace neurun
+{
+namespace frontend
+{
+namespace custom
+{
+
+using namespace backend::custom;
+
+class APIConverter
+{
+public:
+ static nnfw_operand convertOperand(void *alloc, const TypeInfo &type)
+ {
+ nnfw_operand api_operand;
+ api_operand.allocation = alloc;
+ api_operand.type = convertType(type);
+ return api_operand;
+ }
+
+ static nnfw_tensorinfo convertType(const TypeInfo &type)
+ {
+ nnfw_tensorinfo api_type;
+ api_type.rank = type.shape.rank();
+ assert(type.shape.rank() <= 6);
+ std::copy(type.shape.dims().begin(), type.shape.dims().end(), std::begin(api_type.dims));
+
+ switch (type.dtype)
+ {
+ case ir::DataType::FLOAT32:
+ api_type.dtype = NNFW_TYPE_TENSOR_FLOAT32;
+ break;
+ case ir::DataType::INT32:
+ api_type.dtype = NNFW_TYPE_TENSOR_INT32;
+ break;
+ case ir::DataType::QUANT8_ASYMM:
+ api_type.dtype = NNFW_TYPE_TENSOR_QUANT8_ASYMM;
+ break;
+ case ir::DataType::BOOL8:
+ api_type.dtype = NNFW_TYPE_TENSOR_BOOL;
+ break;
+ default:
+ throw std::runtime_error("Unsupported tensor datatype");
+ }
+ return api_type;
+ }
+};
+
+Kernel::Kernel(const nnfw_custom_eval evalFunction)
+ : _params(), _userdata(nullptr), _userdata_size(0), _evalFunction(evalFunction)
+{
+}
+
+void Kernel::configure(CustomKernelConfigParams &&inParams)
+{
+ _userdata = inParams.userdata;
+ _userdata_size = inParams.userdata_size;
+
+ _params.ninputs = inParams.input_allocations.size();
+ _params.inputs = new nnfw_operand[_params.ninputs];
+ for (size_t i = 0; i < _params.ninputs; ++i)
+ {
+ _params.inputs[i] =
+ APIConverter::convertOperand(inParams.input_allocations[i], inParams.input_types[i]);
+ }
+
+ _params.noutputs = inParams.output_allocations.size();
+ _params.outputs = new nnfw_operand[_params.noutputs];
+ for (size_t i = 0; i < _params.noutputs; ++i)
+ {
+ _params.outputs[i] =
+ APIConverter::convertOperand(inParams.output_allocations[i], inParams.output_types[i]);
+ }
+}
+
+void Kernel::run() { _evalFunction(&_params, _userdata, _userdata_size); }
+
+} // namespace custom
+} // namespace backend
+} // namespace neurun
diff --git a/runtime/neurun/api/src/CustomKernel.h b/runtime/neurun/api/src/CustomKernel.h
new file mode 100644
index 000000000..8cafc2061
--- /dev/null
+++ b/runtime/neurun/api/src/CustomKernel.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#ifndef __NEURUN_BACKEND_CUSTOM_KERNEL_H__
+#define __NEURUN_BACKEND_CUSTOM_KERNEL_H__
+
+#include "nnfw_dev.h"
+
+#include "backend/CustomKernelBuilder.h"
+
+#include <vector>
+
+namespace neurun
+{
+namespace frontend
+{
+namespace custom
+{
+
+class Kernel : public ::neurun::exec::IFunction
+{
+public:
+ explicit Kernel(nnfw_custom_eval evalFunction);
+
+ nnfw_custom_kernel_params _params;
+ char *_userdata;
+ size_t _userdata_size;
+
+ nnfw_custom_eval _evalFunction;
+ // nnfw_custom_type_infer _type_infer_function; //Unused for now
+
+ /**
+ * Fills _params field used later by user specified eval function
+ * @param inParams custom kernel parameters
+ */
+ virtual void configure(backend::custom::CustomKernelConfigParams &&inParams);
+
+ void run() override;
+ void runSync() override { run(); }
+};
+
+} // namespace custom
+} // namespace frontend
+} // namespace neurun
+
+#endif // __NEURUN_BACKEND_CUSTOM_KERNEL_H__
diff --git a/runtime/neurun/api/src/CustomKernelRegistry.cc b/runtime/neurun/api/src/CustomKernelRegistry.cc
new file mode 100644
index 000000000..b223682b8
--- /dev/null
+++ b/runtime/neurun/api/src/CustomKernelRegistry.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 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 "CustomKernelRegistry.h"
+
+#include "cpp14/memory.h"
+
+namespace neurun
+{
+namespace frontend
+{
+namespace custom
+{
+
+void KernelRegistry::registerKernel(const std::string &id, nnfw_custom_eval evalFunction)
+{
+ _storage.emplace(id, evalFunction);
+}
+
+std::shared_ptr<backend::custom::IKernelBuilder> KernelRegistry::getBuilder()
+{
+ return nnfw::cpp14::make_unique<KernelBuilder>(this);
+}
+
+std::unique_ptr<Kernel> KernelRegistry::buildKernelForOp(const std::string &id)
+{
+ auto it = _storage.find(id);
+ if (it == _storage.end())
+ {
+ throw std::runtime_error("Unable to find associated kernel for op");
+ }
+
+ return nnfw::cpp14::make_unique<Kernel>(it->second);
+}
+
+// Kernel builder
+std::unique_ptr<exec::IFunction>
+KernelBuilder::buildKernel(const std::string &id,
+ backend::custom::CustomKernelConfigParams &&params) const
+{
+ auto kernel = _registry->buildKernelForOp(id);
+ kernel->configure(std::move(params));
+
+ return kernel;
+}
+
+KernelBuilder::KernelBuilder(KernelRegistry *registry) : _registry(registry) {}
+
+} // namespace custom
+} // namespace frontend
+} // namespace neurun
diff --git a/runtime/neurun/api/src/CustomKernelRegistry.h b/runtime/neurun/api/src/CustomKernelRegistry.h
new file mode 100644
index 000000000..207a82a0a
--- /dev/null
+++ b/runtime/neurun/api/src/CustomKernelRegistry.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#ifndef __NEURUN_BACKEND_CUSTOM_KERNEL_REGISTRY_H__
+#define __NEURUN_BACKEND_CUSTOM_KERNEL_REGISTRY_H__
+
+#include "CustomKernel.h"
+
+#include <unordered_map>
+#include <functional>
+#include <memory>
+
+#include <iostream>
+
+namespace neurun
+{
+namespace frontend
+{
+namespace custom
+{
+
+class KernelRegistry
+{
+public:
+ void registerKernel(const std::string &id, nnfw_custom_eval evalFunction);
+
+ std::shared_ptr<backend::custom::IKernelBuilder> getBuilder();
+ std::unique_ptr<Kernel> buildKernelForOp(const std::string &id);
+
+private:
+ std::unordered_map<std::string, nnfw_custom_eval> _storage;
+};
+
+class KernelBuilder : public backend::custom::IKernelBuilder
+{
+public:
+ KernelBuilder(KernelRegistry *registry);
+
+ std::unique_ptr<exec::IFunction>
+ buildKernel(const std::string &id,
+ backend::custom::CustomKernelConfigParams &&params) const override;
+
+private:
+ KernelRegistry *_registry;
+};
+
+} // namespace custom
+} // namespace frontend
+} // namespace neurun
+
+#endif // __NEURUN_BACKEND_CUSTOM_KERNEL_REGISTRY_H__
diff --git a/runtime/neurun/api/src/OpMap.lst b/runtime/neurun/api/src/OpMap.lst
new file mode 100644
index 000000000..5e93275b8
--- /dev/null
+++ b/runtime/neurun/api/src/OpMap.lst
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef MAP_MACRO
+#error Define MAP_MACRO before including this file
+#endif
+
+// circle operation | neurun internal operation
+MAP_MACRO(ADD , Add)
+MAP_MACRO(SUB , Sub)
+MAP_MACRO(BATCH_TO_SPACE_ND , BatchToSpaceND)
+MAP_MACRO(CAST , Cast)
+MAP_MACRO(CONV_2D , Conv2D)
+MAP_MACRO(DEPTHWISE_CONV_2D , DepthwiseConv2D)
+MAP_MACRO(AVERAGE_POOL_2D , AvgPool2D)
+MAP_MACRO(MAX_POOL_2D , MaxPool2D)
+MAP_MACRO(CONCATENATION , Concat)
+MAP_MACRO(FULLY_CONNECTED , FullyConnected)
+MAP_MACRO(SUM , ReduceSum)
+MAP_MACRO(RESHAPE , Reshape)
+MAP_MACRO(MUL , Mul)
+MAP_MACRO(SOFTMAX , Softmax)
+MAP_MACRO(SQUEEZE , Squeeze)
+MAP_MACRO(SLICE , Slice)
+MAP_MACRO(STRIDED_SLICE , StridedSlice)
+MAP_MACRO(TANH , Tanh)
+MAP_MACRO(LOGISTIC , Logistic)
+MAP_MACRO(DIV , Div)
+MAP_MACRO(TRANSPOSE , Transpose)
+MAP_MACRO(EXP , Exp)
+MAP_MACRO(REDUCE_MAX , ReduceMax)
+// UNMATCHED
+//MAP_MACRO(Comparison)
+MAP_MACRO(LOGICAL_AND , LogicalAnd)
+MAP_MACRO(LOGICAL_OR , LogicalOr)
+MAP_MACRO(LOGICAL_NOT , LogicalNot)
+MAP_MACRO(LSTM , LSTM)
+MAP_MACRO(RSQRT , RSQRT)
+MAP_MACRO(RELU , ReLU)
+MAP_MACRO(RESIZE_BILINEAR , ResizeBilinear)
+MAP_MACRO(RELU_N1_TO_1 , ReLU1)
+MAP_MACRO(RELU6 , ReLU6)
+MAP_MACRO(RNN , RNN)
+MAP_MACRO(FLOOR , Floor)
+MAP_MACRO(SPACE_TO_BATCH_ND , SpaceToBatchND)
+MAP_MACRO(SPACE_TO_DEPTH , SpaceToDepth)
+MAP_MACRO(L2_POOL_2D , L2Pool2D)
+MAP_MACRO(EMBEDDING_LOOKUP , EmbeddingLookup)
+MAP_MACRO(L2_NORMALIZATION , L2Normalization)
+MAP_MACRO(HASHTABLE_LOOKUP , HashtableLookup)
+MAP_MACRO(INSTANCE_NORM , InstanceNorm)
+MAP_MACRO(PRELU , PReLU)
+MAP_MACRO(TRANSPOSE_CONV , TransposeConv)
+MAP_MACRO(SQRT , SQRT)
+MAP_MACRO(SQUARED_DIFFERENCE , SquaredDifference)
+MAP_MACRO(TOPK_V2 , TopKV2)
+MAP_MACRO(GATHER , Gather)
+MAP_MACRO(NEG , Neg)
+MAP_MACRO(ABS , Abs)
+MAP_MACRO(ARG_MAX , ArgMax)
+MAP_MACRO(DEQUANTIZE , Dequantize)
+MAP_MACRO(MEAN , Mean)
+MAP_MACRO(LOCAL_RESPONSE_NORMALIZATION , LocalResponseNormalization)
+// UNDEFINED IN CIRCLE
+//MAP_MACRO(DepthToSpace)
+MAP_MACRO(PACK , Pack)
+MAP_MACRO(REDUCE_MIN , ReduceMin)
+MAP_MACRO(SPLIT , Split)
+MAP_MACRO(UNPACK , Unpack)
+MAP_MACRO(PAD , Pad)
+MAP_MACRO(CUSTOM , Custom)
+// UNDEFINED IN CIRCLE
+//MAP_MACRO(Permute)
+MAP_MACRO(MINIMUM , Min)
+MAP_MACRO(MAXIMUM , Max)
+MAP_MACRO(ONE_HOT , OneHot)
diff --git a/runtime/neurun/api/src/nnfw_api.cc b/runtime/neurun/api/src/nnfw_api.cc
new file mode 100644
index 000000000..bdac4c89b
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_api.cc
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2019 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 "nnfw_api_internal.h"
+
+/*
+ * Create a new session instance
+ *
+ * @param session the session to be created
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_create_session(nnfw_session **session)
+{
+ *session = new nnfw_session();
+
+ return NNFW_STATUS_NO_ERROR;
+}
+
+/*
+ * Close a session instance
+ *
+ * @param session the session to be closed
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_close_session(nnfw_session *session)
+{
+ delete session;
+ return NNFW_STATUS_NO_ERROR;
+}
+
+#define NNFW_RETURN_ERROR_IF_NULL(p) \
+ do \
+ { \
+ if ((p) == NULL) \
+ return NNFW_STATUS_ERROR; \
+ } while (0)
+
+/*
+ * Load model from nnpackage file or directory
+ *
+ * @param session nnfw_session loading the given nnpackage file/dir
+ * @param package_file_path path to the nnpackage file or unzipped directory to be loaded
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *pacakge_file_path)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->load_model_from_file(pacakge_file_path);
+}
+
+/*
+ * Prepare session to be ready for inference
+ * This phase may finalize model compilation, scheduling, and additional settings.
+ *
+ * @param session the session to be prepared
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_prepare(nnfw_session *session)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->prepare();
+}
+
+/*
+ * Run inference
+ *
+ * @param session the session to run inference
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_run(nnfw_session *session)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->run();
+}
+
+/*
+ * Set input
+ *
+ * @param session session to the input is to be set
+ * @param index index of input to be set (0-indexed)
+ * @param type type of the input
+ * @param buffer raw buffer for input
+ * @param length size of bytes of output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_set_input(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+ const void *buffer, size_t length)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_input(index, type, buffer, length);
+}
+
+/*
+ * Set output
+ *
+ * @param session session from inference output is to be extracted
+ * @param index index of output to be set (0-indexed)
+ * @param type type of the output
+ * @param buffer raw buffer for output
+ * @param length size of bytes of output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type, void *buffer,
+ size_t length)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_output(index, type, buffer, length);
+}
+
+/*
+ * Get the number of inputs
+ *
+ * @param[in] session session from input information is to be extracted
+ * @param[out] number variable which the number of inputs is put into
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_input_size(nnfw_session *session, uint32_t *number)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->input_size(number);
+}
+
+/*
+ * Get the number of outputs
+ *
+ * @param[in] session session from output information is to be extracted
+ * @param[out] number variable which the number of outputs is put into
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_size(nnfw_session *session, uint32_t *number)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->output_size(number);
+}
+
+/*
+ * Set the layout of an input
+ * @note The input that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
+ *
+ * @param[in] session session from inference input is to be extracted
+ * @param[in] index index of input to be set (0-indexed)
+ * @param[in] layout layout to set to target input
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_input_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_input_layout(index, layout);
+}
+
+/*
+ * Set the layout of an output
+ * @note The output that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
+ *
+ * @param[in] session session from inference output is to be extracted
+ * @param[in] index index of output to be set (0-indexed)
+ * @param[in] layout layout to set to target output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_output_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_output_layout(index, layout);
+}
+
+/*
+ * Get i-th input tensor info
+ *
+ * @param[in] session session from input information is to be extracted
+ * @param[in] index index of input
+ * @param[out] tensor_info nnfw_tensor_info
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_input_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *tensor_info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->input_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Get i-th output tensor info
+ *
+ * @param[in] session session from output information is to be extracted
+ * @param[in] index index of output
+ * @param[out] tensor_info nnfw_tensor_info
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo *tensor_info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->output_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Register custom operation
+ * @param session session to register this operation
+ * @param id operation id
+ * @param info registration info ( eval function, etc. )
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_register_custom_op_info(nnfw_session *session, const char *id,
+ custom_kernel_registration_info *info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->register_custom_operation(id, info->eval_function);
+}
+
+NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *session, uint32_t index,
+ nnfw_tensorinfo tensor_info)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->apply_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Set available backends
+ *
+ * @param[in] session session to which a avilable backends are set
+ * @param[in] backends available backends on which nnfw uses
+ */
+NNFW_STATUS nnfw_set_available_backends(nnfw_session *session, const char *backends)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_available_backends(backends);
+}
+
+/*
+ * Set the operation's backend
+ *
+ * @param[in] session session to be modified
+ * @param[in] op operation to be set
+ * @param[in] backend bakcend on which operation run
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_op_backend(nnfw_session *session, const char *op, const char *backend)
+{
+ NNFW_RETURN_ERROR_IF_NULL(session);
+ return session->set_op_backend(op, backend);
+}
diff --git a/runtime/neurun/api/src/nnfw_api_internal.cc b/runtime/neurun/api/src/nnfw_api_internal.cc
new file mode 100644
index 000000000..037cd3bca
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_api_internal.cc
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2019 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 "nnfw_api_internal.h"
+#include "CustomKernelRegistry.h"
+#include "compiler/Compiler.h"
+#include "exec/Execution.h"
+#include "circle_loader.h"
+#include "tflite_loader.h"
+#include "json/json.h"
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <dirent.h>
+#include <util/ConfigSource.h>
+
+/*
+ * API does not accept string argument longer than max length below
+ */
+#define MAX_BACKEND_NAME_LENGTH 32
+#define MAX_OP_NAME_LENGTH 64
+
+// Is null-terminating in length ?
+static bool null_terminating(const char *str, uint32_t length)
+{
+ for (uint32_t i = 0; i < length; i++)
+ {
+ if (*(str + i) == '\0')
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static neurun::ir::Layout convertLayout(NNFW_LAYOUT layout)
+{
+ if (layout == NNFW_LAYOUT_CHANNELS_LAST)
+ {
+ return neurun::ir::Layout::NHWC;
+ }
+ else if (layout == NNFW_LAYOUT_CHANNELS_FIRST)
+ {
+ return neurun::ir::Layout::NCHW;
+ }
+ return neurun::ir::Layout::UNKNOWN;
+}
+
+nnfw_session::nnfw_session()
+ : _graph{nullptr}, _execution{nullptr},
+ _kernel_registry{std::make_shared<neurun::frontend::custom::KernelRegistry>()},
+ _source{nnfw::cpp14::make_unique<neurun::util::GeneralConfigSource>()}
+{
+ // DO NOTHING
+}
+
+NNFW_STATUS nnfw_session::load_model_from_file(const char *package_dir)
+{
+ // TODO : add support for zipped package file load
+ DIR *dir;
+ if (!(dir = opendir(package_dir)))
+ {
+ std::cerr << "invalid nnpackge directory: " << package_dir << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ closedir(dir);
+
+ try
+ {
+ std::string manifest_file_name(package_dir);
+ manifest_file_name += "/metadata/MANIFEST";
+ std::ifstream mfs(manifest_file_name);
+
+ // extract the filename of the first(index 0) model
+ // e.g. In MANIFEST file, { "models" : [ "firstmodel.tflite", "2nd.tflite" ] }
+ Json::Value root;
+ mfs >> root;
+ Json::Value models = root["models"];
+ Json::Value model_types = root["model-types"];
+
+ auto model_file_path = package_dir + std::string("/") + models[0].asString(); // first model
+ auto model_type = model_types[0].asString(); // first model's type
+ if (model_type == "tflite")
+ {
+ _graph = neurun::tflite_loader::loadModel(model_file_path.c_str());
+ }
+ else if (model_type == "circle")
+ {
+ _graph = neurun::circle_loader::loadModel(model_file_path.c_str());
+ }
+ else
+ {
+ std::cerr << "Unsupported model type in MANIFEST" << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ _graph->bindKernelBuilder(_kernel_registry->getBuilder());
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during model loading : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::prepare()
+{
+ // TODO : add additional setting routine(executor type, backend)
+ // Note that we assume acl_cl backend
+
+ try
+ {
+ // config_source setting
+ using neurun::util::config_source;
+ config_source(std::move(_source));
+
+ auto compiler = nnfw::cpp14::make_unique<neurun::compiler::Compiler>(_graph);
+ compiler->compile();
+ std::shared_ptr<neurun::exec::IExecutor> executor;
+ compiler->release(executor);
+ _execution = std::make_shared<neurun::exec::Execution>(executor);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during model prepare : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::run()
+{
+ try
+ {
+ _execution->execute();
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::run : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_input(uint32_t index, NNFW_TYPE /*type*/, const void *buffer,
+ size_t length)
+{
+ try
+ {
+ _execution->setInput(neurun::ir::IOIndex(index), buffer, length);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_input : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_output(uint32_t index, NNFW_TYPE /*type*/, void *buffer,
+ size_t length)
+{
+ try
+ {
+ _execution->setOutput(neurun::ir::IOIndex(index), buffer, length);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_output : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::input_size(uint32_t *number)
+{
+ try
+ {
+ if (number == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::input_size, number is null pointer." << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ *number = _graph->getInputs().size();
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::input_size : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::output_size(uint32_t *number)
+{
+ try
+ {
+ if (number == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::output_size, number is null pointer." << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ *number = _graph->getOutputs().size();
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::output_size" << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_input_layout(uint32_t index, NNFW_LAYOUT layout)
+{
+ try
+ {
+ if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
+ layout != NNFW_LAYOUT_CHANNELS_LAST)
+ {
+ std::cerr << "Error during nnfw_session::set_input_layout, not supported layout" << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ _execution->setInputLayout(neurun::ir::IOIndex(index), convertLayout(layout));
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_input_layout : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_output_layout(uint32_t index, NNFW_LAYOUT layout)
+{
+ try
+ {
+ if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
+ layout != NNFW_LAYOUT_CHANNELS_LAST)
+ {
+ std::cerr << "Error during nnfw_session::set_output_layout, not supported layout"
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ _execution->setOutputLayout(neurun::ir::IOIndex(index), convertLayout(layout));
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_output_layout : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+static NNFW_TYPE datatype_to_nnfw_dtype(neurun::ir::DataType dt)
+{
+ using neurun::ir::DataType;
+ switch (dt)
+ {
+ case DataType::FLOAT32:
+ return NNFW_TYPE_TENSOR_FLOAT32;
+ case DataType::INT32:
+ return NNFW_TYPE_TENSOR_INT32;
+ case DataType::QUANT8_ASYMM:
+ return NNFW_TYPE_TENSOR_QUANT8_ASYMM;
+ case DataType::BOOL8:
+ return NNFW_TYPE_TENSOR_BOOL;
+ case DataType::UINT8:
+ return NNFW_TYPE_TENSOR_UINT8;
+ case DataType::UINT32:
+ case DataType::QUANT8_SYMM:
+ default:
+ std::cerr << "Error: Model has type that runtime API does not support." << std::endl;
+ exit(-1);
+ }
+}
+
+NNFW_STATUS nnfw_session::apply_tensorinfo(uint32_t /*index*/, nnfw_tensorinfo /*ti*/)
+{
+ std::cerr << "Error: NYI" << std::endl;
+ return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_session::input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+ try
+ {
+ if (ti == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::input_tensorinfo, tensorinfo is null pointer."
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ if (index >= _graph->getInputs().size())
+ {
+ std::cerr << "Error during nnfw_session::input_tensorinfo, index is out of range."
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ auto opidx = _graph->getInputs().at(index);
+ auto shape = _graph->operands().at(opidx).shape();
+ ti->rank = shape.rank();
+ for (int j = 0; j < ti->rank; ++j)
+ {
+ ti->dims[j] = shape.dim(j);
+ }
+ ti->dtype = datatype_to_nnfw_dtype(_graph->operands().at(opidx).typeInfo().type());
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::input_tensorinfo : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+ try
+ {
+ if (ti == nullptr)
+ {
+ std::cerr << "Error during nnfw_session::output_tensorinfo, tensorinfo is null pointer."
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ if (index >= _graph->getOutputs().size())
+ {
+ std::cerr << "Error during nnfw_session::output_tensorinfo, index is out of range."
+ << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ auto opidx = _graph->getOutputs().at(index);
+ auto shape = _graph->operands().at(opidx).shape();
+ ti->rank = shape.rank();
+ for (int j = 0; j < ti->rank; ++j)
+ {
+ ti->dims[j] = shape.dim(j);
+ }
+ ti->dtype = datatype_to_nnfw_dtype(_graph->operands().at(opidx).typeInfo().type());
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::output_tensorinfo : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+NNFW_STATUS nnfw_session::register_custom_operation(const std::string &id,
+ nnfw_custom_eval eval_func)
+{
+ _kernel_registry->registerKernel(id, eval_func);
+ return NNFW_STATUS_NO_ERROR;
+}
+
+static std::string get_op_backend_string(std::string op)
+{
+#define MAP_MACRO(CircleName, NeurunName) {#CircleName, "OP_BACKEND_" #NeurunName},
+
+ static std::unordered_map<std::string, std::string> operation_map = {
+#include "OpMap.lst"
+ };
+
+#undef MAP_MACRO
+
+ auto n = operation_map.find(op);
+
+ if (n == operation_map.end())
+ {
+ // this return value is handled by a caller to return error code
+ return std::string("");
+ }
+ else
+ {
+ return n->second;
+ }
+}
+
+NNFW_STATUS nnfw_session::set_available_backends(const char *backends)
+{
+ try
+ {
+ if (!backends || null_terminating(backends, MAX_BACKEND_NAME_LENGTH) == false)
+ {
+ return NNFW_STATUS_ERROR;
+ }
+
+ _source->set("BACKENDS", backends);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_available_backends : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_op_backend(const char *op, const char *backend)
+{
+ try
+ {
+ if (!op || !null_terminating(op, MAX_OP_NAME_LENGTH) || !backend ||
+ !null_terminating(backend, MAX_BACKEND_NAME_LENGTH))
+ {
+ return NNFW_STATUS_ERROR;
+ }
+
+ auto key = get_op_backend_string(op);
+
+ if (key.empty())
+ {
+ return NNFW_STATUS_ERROR;
+ }
+
+ _source->set(key, backend);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error during nnfw_session::set_op_backend : " << e.what() << std::endl;
+ return NNFW_STATUS_ERROR;
+ }
+ return NNFW_STATUS_NO_ERROR;
+}
diff --git a/runtime/neurun/api/src/nnfw_api_internal.h b/runtime/neurun/api/src/nnfw_api_internal.h
new file mode 100644
index 000000000..40069cc55
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_api_internal.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#ifndef __API_NNFW_API_INTERNAL_H__
+#define __API_NNFW_API_INTERNAL_H__
+
+#include "nnfw.h"
+#include "nnfw_dev.h"
+
+#include <util/GeneralConfigSource.h>
+
+#include <string>
+#include <memory>
+
+namespace neurun
+{
+namespace frontend
+{
+namespace custom
+{
+class KernelRegistry;
+}
+} // namespace frontend
+namespace exec
+{
+class Execution;
+}
+namespace ir
+{
+class Graph;
+} // namespace ir
+} // namespace neurun
+
+struct nnfw_session
+{
+public:
+ nnfw_session();
+
+ NNFW_STATUS load_model_from_file(const char *package_file_path);
+ NNFW_STATUS prepare();
+ NNFW_STATUS run();
+
+ NNFW_STATUS set_input(uint32_t index, NNFW_TYPE type, const void *buffer, size_t length);
+ NNFW_STATUS set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length);
+
+ NNFW_STATUS input_size(uint32_t *number);
+ NNFW_STATUS output_size(uint32_t *number);
+
+ NNFW_STATUS set_input_layout(uint32_t index, NNFW_LAYOUT layout);
+ NNFW_STATUS set_output_layout(uint32_t index, NNFW_LAYOUT layout);
+
+ NNFW_STATUS apply_tensorinfo(uint32_t index, nnfw_tensorinfo ti);
+
+ NNFW_STATUS input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+ NNFW_STATUS output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+
+ NNFW_STATUS register_custom_operation(const std::string &id, nnfw_custom_eval eval_func);
+
+ NNFW_STATUS set_available_backends(const char *backends);
+ NNFW_STATUS set_op_backend(const char *op, const char *backend);
+
+private:
+ std::shared_ptr<neurun::ir::Graph> _graph;
+ std::shared_ptr<neurun::exec::Execution> _execution;
+ std::shared_ptr<neurun::frontend::custom::KernelRegistry> _kernel_registry;
+
+protected:
+ std::unique_ptr<neurun::util::GeneralConfigSource> _source;
+};
+
+#endif // __API_NNFW_API_INTERNAL_H__
diff --git a/runtime/neurun/api/src/nnfw_debug.cc b/runtime/neurun/api/src/nnfw_debug.cc
new file mode 100644
index 000000000..4ea0a203f
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_debug.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019 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 "nnfw_debug_internal.h"
+
+NNFW_STATUS nnfw_create_debug_session(nnfw_session **session)
+{
+ *session = new nnfw_debug_session();
+
+ return NNFW_STATUS_NO_ERROR;
+}
diff --git a/runtime/neurun/api/src/nnfw_debug_internal.cc b/runtime/neurun/api/src/nnfw_debug_internal.cc
new file mode 100644
index 000000000..778efbc5c
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_debug_internal.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 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 "nnfw_debug_internal.h"
+#include "util/EnvConfigSource.h"
+
+#include <cpp14/memory.h>
+
+nnfw_debug_session::nnfw_debug_session() : nnfw_session()
+{
+ _source = nnfw::cpp14::make_unique<neurun::util::EnvConfigSource>();
+}
diff --git a/runtime/neurun/api/src/nnfw_debug_internal.h b/runtime/neurun/api/src/nnfw_debug_internal.h
new file mode 100644
index 000000000..f4984e7a1
--- /dev/null
+++ b/runtime/neurun/api/src/nnfw_debug_internal.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#ifndef __API_NNFW_DEBUG_INTERNAL_H__
+#define __API_NNFW_DEBUG_INTERNAL_H__
+
+#include "nnfw_debug.h"
+#include "nnfw_api_internal.h"
+
+class nnfw_debug_session : public nnfw_session
+{
+public:
+ nnfw_debug_session();
+};
+
+#endif // __API_NNFW_DEBUG_INTERNAL_H__