Release 18.02

Change-Id: Id3c11dc5ee94ef664374a988fcc6901e9a232fa6
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp
new file mode 100644
index 0000000..4ee68b3
--- /dev/null
+++ b/src/armnn/Network.cpp
@@ -0,0 +1,335 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+#include "Network.hpp"
+#include "Graph.hpp"
+#include "Layer.hpp"
+#include "backends/CpuTensorHandle.hpp"
+#include "backends/WorkloadFactory.hpp"
+#include "Layers.hpp"
+#include "Optimizer.hpp"
+
+#include <armnn/Utils.hpp>
+
+#include <fcntl.h>
+#include <algorithm>
+#include <fstream>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/format.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/numeric/conversion/converter_policies.hpp>
+#include <boost/cast.hpp>
+
+namespace armnn
+{
+
+armnn::INetwork* INetwork::CreateRaw()
+{
+    return new Network();
+}
+
+armnn::INetworkPtr INetwork::Create()
+{
+    return INetworkPtr(CreateRaw(), &INetwork::Destroy);
+}
+
+void INetwork::Destroy(INetwork* network)
+{
+    delete boost::polymorphic_downcast<Network*>(network);
+}
+
+Status Network::PrintGraph()
+{
+    m_Graph->Print();
+    return Status::Success;
+}
+
+void IOptimizedNetwork::Destroy(IOptimizedNetwork* network)
+{
+    delete boost::polymorphic_downcast<OptimizedNetwork*>(network);
+}
+
+Status OptimizedNetwork::PrintGraph()
+{
+    m_Graph->Print();
+    return Status::Success;
+}
+
+IOptimizedNetworkPtr Optimize(const INetwork& inNetwork, const DeviceSpec& deviceSpec)
+{
+    const Network& network = *boost::polymorphic_downcast<const Network*>(&inNetwork);
+    std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph());
+
+    OptimizedNetwork* optNet = new OptimizedNetwork(std::move(graph));
+
+    Optimizer::Get().Optimize(optNet->GetGraph());
+
+    // Infer the tensor infos for all output slots. Throws an exception on failure.
+    optNet->GetGraph().InferTensorInfos();
+
+    // Assign a compute device for all nodes
+    for (auto&& layer : optNet->GetGraph())
+    {
+        DataType dataType = layer->GetDataType();
+
+        // Default to the user-requested compute device from the Runtime
+        layer->SetComputeDevice(deviceSpec.DefaultComputeDevice);
+
+        // If the layer is unsupported by this device, fall back to reference
+        std::string reasonIfUnsupported;
+        if (!IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported))
+        {
+            BOOST_LOG_TRIVIAL(warning) << "Layer of type " << GetLayerTypeAsCString(layer->GetType()) <<
+                " is not supported on requested backend " << layer->GetComputeDevice() << " (reason: " <<
+                reasonIfUnsupported << "), falling back to CpuRef backend.";
+            layer->SetComputeDevice(Compute::CpuRef);
+        }
+
+        BOOST_ASSERT_MSG(IWorkloadFactory::IsLayerSupported(*layer, dataType, reasonIfUnsupported),
+            "Layer has no valid compute device");
+    }
+
+    optNet->GetGraph().AddCopyLayers();
+
+    return {optNet, &IOptimizedNetwork::Destroy};
+}
+
+Network::Network()
+: m_Graph(std::make_unique<Graph>())
+{
+}
+
+Network::~Network()
+{
+}
+
+IConnectableLayer* Network::AddInputLayer(LayerBindingId id, const char* name)
+{
+    return m_Graph->AddLayer<InputLayer>(id, name);
+}
+
+IConnectableLayer* Network::AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor* biases,
+    const char* name)
+{
+    if (fullyConnectedDescriptor.m_BiasEnabled && (biases == nullptr))
+    {
+        throw InvalidArgumentException("AddFullyConnectedLayer: biases cannot be NULL");
+    }
+
+    const auto layer = m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name);
+
+    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
+
+    if (fullyConnectedDescriptor.m_BiasEnabled)
+    {
+        layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
+    }
+
+    return layer;
+}
+
+IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
+    const ConstTensor& weights,
+    const char* name)
+{
+    return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, nullptr, name);
+}
+
+IConnectableLayer* Network::AddFullyConnectedLayer(const FullyConnectedDescriptor& fullyConnectedDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor& biases,
+    const char* name)
+{
+    return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, &biases, name);
+}
+
+IConnectableLayer* Network::AddConvolution2dLayerImpl(const Convolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor* biases,
+    const char* name)
+{
+    if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
+    {
+        throw InvalidArgumentException("AddConvolution2dLayer: biases cannot be NULL");
+    }
+
+    const auto layer = m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name);
+
+    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
+
+    if (convolution2dDescriptor.m_BiasEnabled)
+    {
+        layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
+    }
+
+    return layer;
+}
+
+IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const char* name)
+{
+    return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
+}
+IConnectableLayer* Network::AddConvolution2dLayer(const Convolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor& biases,
+    const char* name)
+{
+    return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
+}
+
+IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl(
+    const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor* biases,
+    const char* name)
+{
+    if (convolution2dDescriptor.m_BiasEnabled && (biases == nullptr))
+    {
+        throw InvalidArgumentException("AddDepthwiseConvolution2dLayer: biases cannot be NULL");
+    }
+
+    const auto layer = m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name);
+
+    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
+
+    if (convolution2dDescriptor.m_BiasEnabled)
+    {
+        layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(*biases);
+    }
+
+    return layer;
+}
+
+IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
+    const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const char* name)
+{
+    return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, nullptr, name);
+}
+IConnectableLayer* Network::AddDepthwiseConvolution2dLayer(
+    const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
+    const ConstTensor& weights,
+    const ConstTensor& biases,
+    const char* name)
+{
+    return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, &biases, name);
+}
+
+IConnectableLayer* Network::AddPermuteLayer(const PermuteDescriptor& permuteDescriptor,
+                                            const char* name)
+{
+    return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name);
+}
+
+IConnectableLayer* Network::AddPooling2dLayer(const Pooling2dDescriptor& pooling2dDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name);
+}
+
+IConnectableLayer* Network::AddActivationLayer(const ActivationDescriptor& activationDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name);
+}
+
+IConnectableLayer* Network::AddNormalizationLayer(const NormalizationDescriptor& normalizationDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name);
+}
+
+IConnectableLayer* Network::AddSoftmaxLayer(const SoftmaxDescriptor& softmaxDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name);
+}
+
+IConnectableLayer* Network::AddSplitterLayer(const ViewsDescriptor& splitterDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name);
+}
+
+IConnectableLayer* Network::AddMergerLayer(const OriginsDescriptor& mergerDescriptor,
+    const char* name)
+{
+    return m_Graph->AddLayer<MergerLayer>(mergerDescriptor, name);
+}
+
+IConnectableLayer* Network::AddAdditionLayer(const char* name)
+{
+    return m_Graph->AddLayer<AdditionLayer>(name);
+}
+
+IConnectableLayer* Network::AddMultiplicationLayer(const char* name)
+{
+    return m_Graph->AddLayer<MultiplicationLayer>(name);
+}
+
+IConnectableLayer* Network::AddOutputLayer(LayerBindingId id, const char* name)
+{
+    return m_Graph->AddLayer<OutputLayer>(id, name);
+}
+
+IConnectableLayer* Network::AddBatchNormalizationLayer(const BatchNormalizationDescriptor& desc,
+                                                       const ConstTensor&                  mean,
+                                                       const ConstTensor&                  variance,
+                                                       const ConstTensor&                  beta,
+                                                       const ConstTensor&                  gamma,
+                                                       const char*                         name)
+{
+    const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name);
+
+    layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(mean);
+    layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(variance);
+    layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(beta);
+    layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(gamma);
+
+    return layer;
+}
+
+IConnectableLayer* Network::AddResizeBilinearLayer(const ResizeBilinearDescriptor& resizeDescriptor, const char* name)
+{
+    return m_Graph->AddLayer<ResizeBilinearLayer>(resizeDescriptor,name);
+}
+
+IConnectableLayer* Network::AddL2NormalizationLayer(const char* name)
+{
+    return m_Graph->AddLayer<L2NormalizationLayer>(name);
+}
+
+IConnectableLayer* Network::AddConstantLayer(const ConstTensor& input, const char* name)
+{
+    return m_Graph->AddLayer<ConstantLayer>(std::make_shared<ScopedCpuTensorHandle>(input), name);
+}
+
+IConnectableLayer* Network::AddReshapeLayer(const ReshapeDescriptor& reshapeDescriptor, const char* name)
+{
+    return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name);
+}
+
+IConnectableLayer* Network::AddFloorLayer(const char* name)
+{
+    return m_Graph->AddLayer<FloorLayer>(name);
+}
+
+OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
+    : m_Graph(std::move(graph))
+{
+}
+
+OptimizedNetwork::~OptimizedNetwork()
+{
+}
+
+} // namespace armnn
+