ArmNN
 25.11
Loading...
Searching...
No Matches
TosaRefLayerSupport.cpp
Go to the documentation of this file.
1//
2// Copyright © 2022-2025 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
7
9
10#include <armnn/Types.hpp>
12
13#include <graph_status.h>
14#include <model_runner.h>
15
16#include <vector>
17
18namespace armnn
19{
20
22 const std::vector<TensorInfo>& infos,
23 const BaseDescriptor& descriptor,
24 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
25 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmInputParamsInfo,
26 Optional<std::string&> reasonIfUnsupported) const
27{
28 for (const auto& info : infos)
29 {
30 if (info.GetDataType() == DataType::Signed64)
31 {
32 reasonIfUnsupported.value() = "TOSA does not have INT64 support for TOSARef backend";
33 return false;
34 }
35
36 // ArmNN U8 tensors are supported for TOSA if they are followed or preceeded by a Quantize layer
37 if (info.GetDataType() == DataType::QAsymmU8 &&
38 type != LayerType::Input &&
39 type != LayerType::Quantize &&
40 type != LayerType::Output)
41 {
42 reasonIfUnsupported.value() = "Must use a Quantize layer to/from unsigned INT for TOSARef backend";
43 return false;
44 }
45 }
46
47 IgnoreUnused(lstmParamsInfo);
48 IgnoreUnused(quantizedLstmInputParamsInfo);
49 IgnoreUnused(reasonIfUnsupported);
50
51 std::vector<const TensorInfo*> inputInfos;
52 std::vector<const TensorInfo*> outputInfos;
53
54 switch (type)
55 {
58 return true;
66 // Setup inputs and outputs
67 inputInfos.push_back(&infos[0]);
68 inputInfos.push_back(&infos[1]);
69 outputInfos.push_back(&infos[2]);
70 break;
72 for (unsigned int i = 0; i < infos.size() - 1; ++i)
73 {
74 inputInfos.push_back(&infos[i]);
75 }
76 outputInfos.push_back(&infos.back());
77 break;
79 outputInfos.push_back(&infos[0]);
80 break;
82 {
83 inputInfos.push_back(&infos[0]); // input
84 outputInfos.push_back(&infos[1]); // output
85 inputInfos.push_back(&infos[2]); // weights
86
87 auto conv2dDesc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
88 if(conv2dDesc->m_BiasEnabled)
89 {
90 inputInfos.push_back(&infos[3]); // bias
91 }
92 break;
93 }
95 {
96 inputInfos.push_back(&infos[0]); // input
97 outputInfos.push_back(&infos[1]); // output
98 inputInfos.push_back(&infos[2]); // weights
99
100 auto conv3dDesc = PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor);
101 if(conv3dDesc->m_BiasEnabled)
102 {
103 inputInfos.push_back(&infos[3]); // bias
104 }
105 break;
106 }
108 {
109 inputInfos.push_back(&infos[0]); // input
110 outputInfos.push_back(&infos[1]); // output
111 inputInfos.push_back(&infos[2]); // weights
112
114 if(conv2dDesc->m_BiasEnabled)
115 {
116 inputInfos.push_back(&infos[3]); // bias
117 }
118 break;
119 }
121 {
122 inputInfos.push_back(&infos[0]); // input
123 outputInfos.push_back(&infos[1]); // output
124 inputInfos.push_back(&infos[2]); // weights
125 auto fullyConnectedDesc = PolymorphicDowncast<const FullyConnectedDescriptor*>(&descriptor);
126 if(fullyConnectedDesc->m_BiasEnabled)
127 {
128 inputInfos.push_back(&infos[3]); // bias
129 }
130 break;
131 }
136 case LayerType::Pad:
138 case LayerType::Mean:
143 case LayerType::Slice:
149 {
150 inputInfos.push_back(&infos[0]);
151 outputInfos.push_back(&infos[1]);
152 break;
153 }
155 {
156 inputInfos.push_back(&infos[0]);
157 for (unsigned int i = 1; i < infos.size(); ++i)
158 {
159 outputInfos.push_back(&infos[i]);
160 }
161 break;
162 }
164 {
165 inputInfos.push_back(&infos[0]); // input
166 outputInfos.push_back(&infos[1]); // output
167 inputInfos.push_back(&infos[2]); // weights
168
170 if(conv2dDesc->m_BiasEnabled)
171 {
172 inputInfos.push_back(&infos[3]); // bias
173 }
174 break;
175 }
176 case LayerType::Stack:
177 {
178 auto stackDesc = PolymorphicDowncast<const StackDescriptor*>(&descriptor);
179 for (unsigned int i = 0; i < stackDesc->m_NumInputs; ++i)
180 {
181 inputInfos.emplace_back(&infos[i]);
182 }
183 outputInfos.emplace_back(&infos[stackDesc->m_NumInputs]);
184 break;
185 }
186 default:
187 // Default to false for all unsupported layers.
188 return false;
189 }
190
191 auto mappings = GetTosaMapping(nullptr, type, inputInfos, outputInfos, descriptor);
192 if (mappings->GetName() == "")
193 {
194 // There currently isn't a TOSA mapping for this layer, as the default was returned.
195 return false;
196 }
197
198 TosaSerializationHandler handler;
199
200 // Add all mappings to main block.
201 auto* block = new TosaSerializationBasicBlock("main",
202 "main",
203 mappings->GetOperators(),
204 mappings->GetTensors(),
205 mappings->GetInputs(),
206 mappings->GetOutputs());
207
208 std::vector<TosaSerializationBasicBlock*> blocks;
209 blocks.emplace_back(block);
210
211 // Add blocks to the main region.
212 auto* region = new TosaSerializationRegion("main", blocks);
213 handler.GetRegions().emplace_back(region);
214
215 GraphStatus status;
216 TosaReference::IModelRunner runner;
217
218#if !defined(TOSA_REFERENCE_MODEL_OUTPUT)
219 // There currently isn't a way to disable the output from the TOSA Reference Model, but it does have a file pointer
220 // to write debug output to, so set this to /dev/null (if it exists on the system) to hide the output.
221 func_debug_t funcDebug;
222
223 FILE* file = fopen("/dev/null", "w");
224 funcDebug.func_debug_file = (file == nullptr) ? stderr : file;
225
226 runner.setFuncDebug(funcDebug);
227#endif
228
229 // Initialise the model runner with the TosaSerializationHandler, which runs validation on the mapping.
230 status = runner.initialize(handler);
231
232#if !defined(TOSA_REFERENCE_MODEL_OUTPUT)
233 // Reset FuncDebug as they can persist across multiple IModelRunner instances.
234 funcDebug.func_debug_file = stderr;
235 runner.setFuncDebug(funcDebug);
236#endif
237
238 if(status == GraphStatus::TOSA_ERROR || status == GraphStatus::TOSA_UNPREDICTABLE)
239 {
240 return false;
241 }
242 else
243 {
244 return true;
245 }
246}
247
248} // namespace armnn
TosaSerializationBasicBlock * GetTosaMapping(const Layer *layer, const LayerType type, const std::vector< const TensorInfo * > &inputs, const std::vector< const TensorInfo * > &outputs, const BaseDescriptor &descriptor)
bool IsLayerSupported(const LayerType &type, const std::vector< TensorInfo > &infos, const BaseDescriptor &descriptor, const Optional< LstmInputParamsInfo > &lstmParamsInfo, const Optional< QuantizedLstmInputParamsInfo > &, Optional< std::string & > reasonIfUnsupported) const override
Default implementation of the ILayerSupport interface, Backends should implement this as a switch sta...
Copyright (c) 2021 ARM Limited and Contributors.
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below.
Definition Types.hpp:494
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.
void IgnoreUnused(Ts &&...)
Base class for all descriptors.