xref: /aosp_15_r20/external/armnn/delegate/classic/src/MultiLayerFacade.hpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
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