1 // 2 // Copyright © 2021,2022-2023 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #pragma once 7 8 // NOTE: the MultiLayerFacade class is a utility class which makes a chain 9 // of operators look like a single IConnectableLayer with the first 10 // layer in the chain supplying the input slots and the last supplying 11 // the output slots. It enables us, for example, to simulate a 12 // Tensorflow Lite FloorDiv operator by chaining a Div layer followed 13 // by a Floor layer and pass them as a single unit to the code that 14 // connects up the graph as the delegate proceeds to build up the 15 // Arm NN subgraphs. 16 // 17 18 #include <common/include/ProfilingGuid.hpp> 19 #include <armnn/INetwork.hpp> 20 21 namespace armnnDelegate 22 { 23 24 class MultiLayerFacade : public armnn::IConnectableLayer 25 { 26 public: MultiLayerFacade()27 MultiLayerFacade() : 28 m_FirstLayer(nullptr), m_LastLayer(nullptr) {} 29 MultiLayerFacade(armnn::IConnectableLayer * firstLayer,armnn::IConnectableLayer * lastLayer)30 MultiLayerFacade(armnn::IConnectableLayer* firstLayer, armnn::IConnectableLayer* lastLayer) : 31 m_FirstLayer(firstLayer), m_LastLayer(lastLayer) {} 32 MultiLayerFacade(const MultiLayerFacade & obj)33 MultiLayerFacade(const MultiLayerFacade& obj) : 34 m_FirstLayer(obj.m_FirstLayer), m_LastLayer(obj.m_LastLayer) {} 35 ~MultiLayerFacade()36 ~MultiLayerFacade() {} // we don't own the pointers 37 operator =(const MultiLayerFacade & obj)38 MultiLayerFacade& operator=(const MultiLayerFacade& obj) 39 { 40 m_FirstLayer = obj.m_FirstLayer; 41 m_LastLayer = obj.m_LastLayer; 42 return *this; 43 } 44 AssignValues(armnn::IConnectableLayer * firstLayer,armnn::IConnectableLayer * lastLayer)45 void AssignValues(armnn::IConnectableLayer* firstLayer, armnn::IConnectableLayer* lastLayer) 46 { 47 m_FirstLayer = firstLayer; 48 m_LastLayer = lastLayer; 49 } 50 GetName() const51 virtual const char* GetName() const override 52 { 53 return m_FirstLayer->GetName(); 54 } 55 GetNumInputSlots() const56 virtual unsigned int GetNumInputSlots() const override 57 { 58 return m_FirstLayer->GetNumInputSlots(); 59 } 60 GetNumOutputSlots() const61 virtual unsigned int GetNumOutputSlots() const override 62 { 63 return m_LastLayer->GetNumOutputSlots(); 64 } 65 GetInputSlot(unsigned int index) const66 virtual const armnn::IInputSlot& GetInputSlot(unsigned int index) const override 67 { 68 return m_FirstLayer->GetInputSlot(index); 69 } 70 GetInputSlot(unsigned int index)71 virtual armnn::IInputSlot& GetInputSlot(unsigned int index) override 72 { 73 return m_FirstLayer->GetInputSlot(index); 74 } 75 GetOutputSlot(unsigned int index) const76 virtual const armnn::IOutputSlot& GetOutputSlot(unsigned int index) const override 77 { 78 return m_LastLayer->GetOutputSlot(index); 79 } 80 GetOutputSlot(unsigned int index)81 virtual armnn::IOutputSlot& GetOutputSlot(unsigned int index) override 82 { 83 return m_LastLayer->GetOutputSlot(index); 84 } 85 InferOutputShapes(const std::vector<armnn::TensorShape> & inputShapes) const86 virtual std::vector<armnn::TensorShape> InferOutputShapes( 87 const std::vector<armnn::TensorShape>& inputShapes) const override 88 { 89 // NOTE: do not expect this function to be used. Likely that if it is it might need to be overridden 90 // for particular sequences of operators. 91 return m_FirstLayer->InferOutputShapes(inputShapes); 92 } 93 GetGuid() const94 virtual LayerGuid GetGuid() const override 95 { 96 return m_FirstLayer->GetGuid(); 97 } 98 ExecuteStrategy(armnn::IStrategy & strategy) const99 virtual void ExecuteStrategy(armnn::IStrategy& strategy) const override 100 { 101 // Do not expect this function to be used so not providing an implementation 102 // if an implementation is required and the chain contains more than two operators 103 // would have to provide a way to record the intermediate layers so they could be 104 // visited... the same applies to the BackendSelectionHint 105 // below. 106 } 107 BackendSelectionHint(armnn::Optional<armnn::BackendId> backend)108 virtual void BackendSelectionHint(armnn::Optional<armnn::BackendId> backend) override 109 { 110 // Do not expect this function to be used so not providing an implementation 111 } 112 GetType() const113 virtual armnn::LayerType GetType() const override 114 { 115 return m_FirstLayer->GetType(); 116 } 117 GetParameters() const118 virtual const armnn::BaseDescriptor& GetParameters() const override { return m_NullDescriptor; } 119 SetBackendId(const armnn::BackendId & id)120 void SetBackendId(const armnn::BackendId& id) override {} 121 122 protected: 123 /// Retrieve the handles to the constant values stored by the layer. 124 /// @return A vector of the constant tensors stored by this layer. GetConstantTensorsByRef()125 ConstantTensors GetConstantTensorsByRef() override { return {}; } GetConstantTensorsByRef() const126 ImmutableConstantTensors GetConstantTensorsByRef() const override { return {}; } 127 128 private: 129 armnn::IConnectableLayer* m_FirstLayer; 130 armnn::IConnectableLayer* m_LastLayer; 131 132 // to satisfy the GetParameters method need to hand back a NullDescriptor 133 armnn::NullDescriptor m_NullDescriptor; 134 }; 135 136 } // namespace armnnDelegate 137