1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "QLstmLayer.hpp"
6
7 #include "LayerCloneBase.hpp"
8
9 #include <armnn/LstmParams.hpp>
10 #include <armnn/TypesUtils.hpp>
11 #include <backendsCommon/CpuTensorHandle.hpp>
12 #include <backendsCommon/WorkloadFactory.hpp>
13
14 namespace armnn
15 {
16
QLstmLayer(const QLstmDescriptor & param,const char * name)17 QLstmLayer::QLstmLayer(const QLstmDescriptor& param, const char* name)
18 : LayerWithParameters(3, 3, LayerType::QLstm, param, name)
19 {
20 }
21
CreateWorkload(const IWorkloadFactory & factory) const22 std::unique_ptr<IWorkload> QLstmLayer::CreateWorkload(const IWorkloadFactory& factory) const
23 {
24 QLstmQueueDescriptor descriptor;
25
26 // Basic parameters
27 descriptor.m_InputToForgetWeights = m_BasicParameters.m_InputToForgetWeights.get();
28 descriptor.m_InputToCellWeights = m_BasicParameters.m_InputToCellWeights.get();
29 descriptor.m_InputToOutputWeights = m_BasicParameters.m_InputToOutputWeights.get();
30 descriptor.m_RecurrentToForgetWeights = m_BasicParameters.m_RecurrentToForgetWeights.get();
31 descriptor.m_RecurrentToCellWeights = m_BasicParameters.m_RecurrentToCellWeights.get();
32 descriptor.m_RecurrentToOutputWeights = m_BasicParameters.m_RecurrentToOutputWeights.get();
33 descriptor.m_ForgetGateBias = m_BasicParameters.m_ForgetGateBias.get();
34 descriptor.m_CellBias = m_BasicParameters.m_CellBias.get();
35 descriptor.m_OutputGateBias = m_BasicParameters.m_OutputGateBias.get();
36
37 // CIFG parameters
38 if (!m_Param.m_CifgEnabled)
39 {
40 descriptor.m_InputToInputWeights = m_CifgParameters.m_InputToInputWeights.get();
41 descriptor.m_RecurrentToInputWeights = m_CifgParameters.m_RecurrentToInputWeights.get();
42 descriptor.m_InputGateBias = m_CifgParameters.m_InputGateBias.get();
43 }
44
45 // Projection parameters
46 if (m_Param.m_ProjectionEnabled)
47 {
48 descriptor.m_ProjectionWeights = m_ProjectionParameters.m_ProjectionWeights.get();
49 descriptor.m_ProjectionBias = m_ProjectionParameters.m_ProjectionBias.get();
50 }
51
52 // Peephole parameters
53 if (m_Param.m_PeepholeEnabled)
54 {
55 if (!m_Param.m_CifgEnabled)
56 {
57 descriptor.m_CellToInputWeights = m_PeepholeParameters.m_CellToInputWeights.get();
58 }
59
60 descriptor.m_CellToForgetWeights = m_PeepholeParameters.m_CellToForgetWeights.get();
61 descriptor.m_CellToOutputWeights = m_PeepholeParameters.m_CellToOutputWeights.get();
62 }
63
64 // Layer normalisation parameters
65 if(m_Param.m_LayerNormEnabled)
66 {
67 if (!m_Param.m_CifgEnabled)
68 {
69 descriptor.m_InputLayerNormWeights = m_LayerNormParameters.m_InputLayerNormWeights.get();
70 }
71 descriptor.m_ForgetLayerNormWeights = m_LayerNormParameters.m_ForgetLayerNormWeights.get();
72 descriptor.m_CellLayerNormWeights = m_LayerNormParameters.m_CellLayerNormWeights.get();
73 descriptor.m_OutputLayerNormWeights = m_LayerNormParameters.m_OutputLayerNormWeights.get();
74 }
75
76 SetAdditionalInfo(descriptor);
77
78 return factory.CreateQLstm(descriptor, PrepInfoAndDesc(descriptor));
79 }
80
Clone(Graph & graph) const81 QLstmLayer* QLstmLayer::Clone(Graph& graph) const
82 {
83 auto layer = CloneBase<QLstmLayer>(graph, m_Param, GetName());
84
85 layer->m_BasicParameters.m_InputToForgetWeights = m_BasicParameters.m_InputToForgetWeights ?
86 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_InputToForgetWeights) : nullptr;
87 layer->m_BasicParameters.m_InputToCellWeights = m_BasicParameters.m_InputToCellWeights ?
88 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_InputToCellWeights) : nullptr;
89 layer->m_BasicParameters.m_InputToOutputWeights = m_BasicParameters.m_InputToOutputWeights ?
90 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_InputToOutputWeights) : nullptr;
91 layer->m_BasicParameters.m_RecurrentToForgetWeights = m_BasicParameters.m_RecurrentToForgetWeights ?
92 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_RecurrentToForgetWeights) : nullptr;
93 layer->m_BasicParameters.m_RecurrentToCellWeights = m_BasicParameters.m_RecurrentToCellWeights ?
94 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_RecurrentToCellWeights) : nullptr;
95 layer->m_BasicParameters.m_RecurrentToOutputWeights = m_BasicParameters.m_RecurrentToOutputWeights ?
96 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_RecurrentToOutputWeights) : nullptr;
97 layer->m_BasicParameters.m_ForgetGateBias = m_BasicParameters.m_ForgetGateBias ?
98 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_ForgetGateBias) : nullptr;
99 layer->m_BasicParameters.m_CellBias = m_BasicParameters.m_CellBias ?
100 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_CellBias) : nullptr;
101 layer->m_BasicParameters.m_OutputGateBias = m_BasicParameters.m_OutputGateBias ?
102 std::make_unique<ScopedCpuTensorHandle>(*m_BasicParameters.m_OutputGateBias) : nullptr;
103
104 if (!m_Param.m_CifgEnabled)
105 {
106 layer->m_CifgParameters.m_InputToInputWeights = m_CifgParameters.m_InputToInputWeights ?
107 std::make_unique<ScopedCpuTensorHandle>(*m_CifgParameters.m_InputToInputWeights) : nullptr;
108 layer->m_CifgParameters.m_RecurrentToInputWeights = m_CifgParameters.m_RecurrentToInputWeights ?
109 std::make_unique<ScopedCpuTensorHandle>(*m_CifgParameters.m_RecurrentToInputWeights) : nullptr;
110 layer->m_CifgParameters.m_InputGateBias = m_CifgParameters.m_InputGateBias ?
111 std::make_unique<ScopedCpuTensorHandle>(*m_CifgParameters.m_InputGateBias) : nullptr;
112 }
113
114 if (m_Param.m_ProjectionEnabled)
115 {
116 layer->m_ProjectionParameters.m_ProjectionWeights = m_ProjectionParameters.m_ProjectionWeights ?
117 std::make_unique<ScopedCpuTensorHandle>(*m_ProjectionParameters.m_ProjectionWeights) : nullptr;
118 layer->m_ProjectionParameters.m_ProjectionBias = m_ProjectionParameters.m_ProjectionBias ?
119 std::make_unique<ScopedCpuTensorHandle>(*m_ProjectionParameters.m_ProjectionBias) : nullptr;
120 }
121
122 if (m_Param.m_PeepholeEnabled)
123 {
124 if (!m_Param.m_CifgEnabled) {
125 layer->m_PeepholeParameters.m_CellToInputWeights = m_PeepholeParameters.m_CellToInputWeights ?
126 std::make_unique<ScopedCpuTensorHandle>(*m_PeepholeParameters.m_CellToInputWeights) : nullptr;
127 }
128
129 layer->m_PeepholeParameters.m_CellToForgetWeights = m_PeepholeParameters.m_CellToForgetWeights ?
130 std::make_unique<ScopedCpuTensorHandle>(*m_PeepholeParameters.m_CellToForgetWeights) : nullptr;
131 layer->m_PeepholeParameters.m_CellToOutputWeights = m_PeepholeParameters.m_CellToOutputWeights ?
132 std::make_unique<ScopedCpuTensorHandle>(*m_PeepholeParameters.m_CellToOutputWeights) : nullptr;
133 }
134
135 if (m_Param.m_LayerNormEnabled)
136 {
137 if (!m_Param.m_CifgEnabled) {
138 layer->m_LayerNormParameters.m_InputLayerNormWeights = m_LayerNormParameters.m_InputLayerNormWeights ?
139 std::make_unique<ScopedCpuTensorHandle>(*m_LayerNormParameters.m_InputLayerNormWeights) : nullptr;
140 }
141
142 layer->m_LayerNormParameters.m_ForgetLayerNormWeights = m_LayerNormParameters.m_ForgetLayerNormWeights ?
143 std::make_unique<ScopedCpuTensorHandle>(*m_LayerNormParameters.m_ForgetLayerNormWeights) : nullptr;
144 layer->m_LayerNormParameters.m_CellLayerNormWeights = m_LayerNormParameters.m_CellLayerNormWeights ?
145 std::make_unique<ScopedCpuTensorHandle>(*m_LayerNormParameters.m_CellLayerNormWeights) : nullptr;
146 layer->m_LayerNormParameters.m_OutputLayerNormWeights = m_LayerNormParameters.m_OutputLayerNormWeights ?
147 std::make_unique<ScopedCpuTensorHandle>(*m_LayerNormParameters.m_OutputLayerNormWeights) : nullptr;
148 }
149
150 return std::move(layer);
151 }
152
InferOutputShapes(const std::vector<TensorShape> & inputShapes) const153 std::vector<TensorShape> QLstmLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
154 {
155 ARMNN_ASSERT(inputShapes.size() == 3);
156
157 // Get input values for validation
158 unsigned int batchSize = inputShapes[0][0];
159 unsigned int outputSize = inputShapes[1][1];
160 unsigned int numUnits = inputShapes[2][1];
161
162 std::vector<TensorShape> outShapes;
163 outShapes.push_back(TensorShape({ batchSize, outputSize })); // outputStateOut
164 outShapes.push_back(TensorShape({ batchSize, numUnits })); // cellStateOut
165 outShapes.push_back(TensorShape({ batchSize, outputSize })); // output
166
167 return outShapes;
168 }
169
ValidateTensorShapesFromInputs()170 void QLstmLayer::ValidateTensorShapesFromInputs()
171 {
172 VerifyLayerConnections(3, CHECK_LOCATION());
173
174 const TensorShape& outputShape = GetOutputSlot(0).GetTensorInfo().GetShape();
175
176 VerifyShapeInferenceType(outputShape, m_ShapeInferenceMethod);
177
178 auto inferredShapes = InferOutputShapes(
179 {
180 GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(), // input
181 GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape(), // previousOutputIn
182 GetInputSlot(2).GetConnection()->GetTensorInfo().GetShape() // previousCellStateIn
183 });
184
185 ARMNN_ASSERT(inferredShapes.size() == 3);
186
187 // Check if the weights are nullptr for basic params
188 ARMNN_ASSERT_MSG(m_BasicParameters.m_InputToForgetWeights != nullptr,
189 "QLstmLayer: m_BasicParameters.m_InputToForgetWeights should not be null.");
190 ARMNN_ASSERT_MSG(m_BasicParameters.m_InputToCellWeights != nullptr,
191 "QLstmLayer: m_BasicParameters.m_InputToCellWeights should not be null.");
192 ARMNN_ASSERT_MSG(m_BasicParameters.m_InputToOutputWeights != nullptr,
193 "QLstmLayer: m_BasicParameters.m_InputToOutputWeights should not be null.");
194 ARMNN_ASSERT_MSG(m_BasicParameters.m_RecurrentToForgetWeights != nullptr,
195 "QLstmLayer: m_BasicParameters.m_RecurrentToForgetWeights should not be null.");
196 ARMNN_ASSERT_MSG(m_BasicParameters.m_RecurrentToCellWeights != nullptr,
197 "QLstmLayer: m_BasicParameters.m_RecurrentToCellWeights should not be null.");
198 ARMNN_ASSERT_MSG(m_BasicParameters.m_RecurrentToOutputWeights != nullptr,
199 "QLstmLayer: m_BasicParameters.m_RecurrentToOutputWeights should not be null.");
200 ARMNN_ASSERT_MSG(m_BasicParameters.m_ForgetGateBias != nullptr,
201 "QLstmLayer: m_BasicParameters.m_ForgetGateBias should not be null.");
202 ARMNN_ASSERT_MSG(m_BasicParameters.m_CellBias != nullptr,
203 "QLstmLayer: m_BasicParameters.m_CellBias should not be null.");
204 ARMNN_ASSERT_MSG(m_BasicParameters.m_OutputGateBias != nullptr,
205 "QLstmLayer: m_BasicParameters.m_OutputGateBias should not be null.");
206
207 if (!m_Param.m_CifgEnabled)
208 {
209 ARMNN_ASSERT_MSG(m_CifgParameters.m_InputToInputWeights != nullptr,
210 "QLstmLayer: m_CifgParameters.m_InputToInputWeights should not be null.");
211 ARMNN_ASSERT_MSG(m_CifgParameters.m_RecurrentToInputWeights != nullptr,
212 "QLstmLayer: m_CifgParameters.m_RecurrentToInputWeights should not be null.");
213 ARMNN_ASSERT_MSG(m_CifgParameters.m_InputGateBias != nullptr,
214 "QLstmLayer: m_CifgParameters.m_InputGateBias should not be null.");
215
216 ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "QLstmLayer");
217 }
218 else
219 {
220 ARMNN_ASSERT_MSG(m_CifgParameters.m_InputToInputWeights == nullptr,
221 "QLstmLayer: m_CifgParameters.m_InputToInputWeights should not have a value when CIFG is enabled.");
222 ARMNN_ASSERT_MSG(m_CifgParameters.m_RecurrentToInputWeights == nullptr,
223 "QLstmLayer: m_CifgParameters.m_RecurrentToInputWeights should "
224 "not have a value when CIFG is enabled.");
225 ARMNN_ASSERT_MSG(m_CifgParameters.m_InputGateBias == nullptr,
226 "QLstmLayer: m_CifgParameters.m_InputGateBias should not have a value when CIFG is enabled.");
227
228 ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "QLstmLayer");
229 }
230
231 if (m_Param.m_ProjectionEnabled)
232 {
233 ARMNN_ASSERT_MSG(m_ProjectionParameters.m_ProjectionWeights != nullptr,
234 "QLstmLayer: m_ProjectionParameters.m_ProjectionWeights should not be null.");
235 }
236
237 if (m_Param.m_PeepholeEnabled)
238 {
239 if (!m_Param.m_CifgEnabled) {
240 ARMNN_ASSERT_MSG(m_PeepholeParameters.m_CellToInputWeights != nullptr,
241 "QLstmLayer: m_PeepholeParameters.m_CellToInputWeights should not be null "
242 "when Peephole is enabled and CIFG is disabled.");
243 }
244
245 ARMNN_ASSERT_MSG(m_PeepholeParameters.m_CellToForgetWeights != nullptr,
246 "QLstmLayer: m_PeepholeParameters.m_CellToForgetWeights should not be null.");
247 ARMNN_ASSERT_MSG(m_PeepholeParameters.m_CellToOutputWeights != nullptr,
248 "QLstmLayer: m_PeepholeParameters.m_CellToOutputWeights should not be null.");
249 }
250
251 ValidateAndCopyShape(
252 GetOutputSlot(1).GetTensorInfo().GetShape(), inferredShapes[1], m_ShapeInferenceMethod, "QLstmLayer", 1);
253 ValidateAndCopyShape(
254 GetOutputSlot(2).GetTensorInfo().GetShape(), inferredShapes[2], m_ShapeInferenceMethod, "QLstmLayer", 2);
255
256 if (m_Param.m_LayerNormEnabled)
257 {
258 if(!m_Param.m_CifgEnabled)
259 {
260 ARMNN_ASSERT_MSG(m_LayerNormParameters.m_InputLayerNormWeights != nullptr,
261 "QLstmLayer: m_LayerNormParameters.m_InputLayerNormWeights should not be null.");
262 }
263 ARMNN_ASSERT_MSG(m_LayerNormParameters.m_ForgetLayerNormWeights != nullptr,
264 "QLstmLayer: m_LayerNormParameters.m_ForgetLayerNormWeights should not be null.");
265 ARMNN_ASSERT_MSG(m_LayerNormParameters.m_CellLayerNormWeights != nullptr,
266 "QLstmLayer: m_LayerNormParameters.m_CellLayerNormWeights should not be null.");
267 ARMNN_ASSERT_MSG(m_LayerNormParameters.m_OutputLayerNormWeights != nullptr,
268 "QLstmLayer: m_LayerNormParameters.m_UutputLayerNormWeights should not be null.");
269 }
270 }
271
GetConstantTensorsByRef()272 Layer::ConstantTensors QLstmLayer::GetConstantTensorsByRef()
273 {
274 return {m_BasicParameters.m_InputToForgetWeights,
275 m_BasicParameters.m_InputToCellWeights,
276 m_BasicParameters.m_InputToOutputWeights,
277 m_BasicParameters.m_RecurrentToForgetWeights,
278 m_BasicParameters.m_RecurrentToCellWeights,
279 m_BasicParameters.m_RecurrentToOutputWeights,
280 m_BasicParameters.m_ForgetGateBias,
281 m_BasicParameters.m_CellBias,
282 m_BasicParameters.m_OutputGateBias,
283
284 // Cifg parameters
285 m_CifgParameters.m_InputToInputWeights,
286 m_CifgParameters.m_RecurrentToInputWeights,
287 m_CifgParameters.m_InputGateBias,
288
289 // Projection parameters
290 m_ProjectionParameters.m_ProjectionWeights,
291 m_ProjectionParameters.m_ProjectionBias,
292
293 // Peephole parameters
294 m_PeepholeParameters.m_CellToInputWeights,
295 m_PeepholeParameters.m_CellToForgetWeights,
296 m_PeepholeParameters.m_CellToOutputWeights,
297
298 // Layer normalisation parameters
299 m_LayerNormParameters.m_InputLayerNormWeights,
300 m_LayerNormParameters.m_ForgetLayerNormWeights,
301 m_LayerNormParameters.m_CellLayerNormWeights,
302 m_LayerNormParameters.m_OutputLayerNormWeights};
303 }
304
Accept(ILayerVisitor & visitor) const305 void QLstmLayer::Accept(ILayerVisitor& visitor) const
306 {
307 LstmInputParams inputParams;
308
309 ConstTensor inputToInputWeightsTensor;
310 if (m_CifgParameters.m_InputToInputWeights != nullptr)
311 {
312 ConstTensor inputToInputWeightsTensorCopy(m_CifgParameters.m_InputToInputWeights->GetTensorInfo(),
313 m_CifgParameters.m_InputToInputWeights->Map(true));
314 inputToInputWeightsTensor = inputToInputWeightsTensorCopy;
315 inputParams.m_InputToInputWeights = &inputToInputWeightsTensor;
316 }
317
318 ConstTensor inputToForgetWeightsTensor;
319 if (m_BasicParameters.m_InputToForgetWeights != nullptr)
320 {
321 ConstTensor inputToForgetWeightsTensorCopy(m_BasicParameters.m_InputToForgetWeights->GetTensorInfo(),
322 m_BasicParameters.m_InputToForgetWeights->Map(true));
323 inputToForgetWeightsTensor = inputToForgetWeightsTensorCopy;
324 inputParams.m_InputToForgetWeights = &inputToForgetWeightsTensor;
325 }
326
327 ConstTensor inputToCellWeightsTensor;
328 if (m_BasicParameters.m_InputToCellWeights != nullptr)
329 {
330 ConstTensor inputToCellWeightsTensorCopy(m_BasicParameters.m_InputToCellWeights->GetTensorInfo(),
331 m_BasicParameters.m_InputToCellWeights->Map(true));
332 inputToCellWeightsTensor = inputToCellWeightsTensorCopy;
333 inputParams.m_InputToCellWeights = &inputToCellWeightsTensor;
334 }
335
336 ConstTensor inputToOutputWeightsTensor;
337 if (m_BasicParameters.m_InputToOutputWeights != nullptr)
338 {
339 ConstTensor inputToOutputWeightsTensorCopy(m_BasicParameters.m_InputToOutputWeights->GetTensorInfo(),
340 m_BasicParameters.m_InputToOutputWeights->Map(true));
341 inputToOutputWeightsTensor = inputToOutputWeightsTensorCopy;
342 inputParams.m_InputToOutputWeights = &inputToOutputWeightsTensor;
343 }
344
345 ConstTensor recurrentToInputWeightsTensor;
346 if (m_CifgParameters.m_RecurrentToInputWeights != nullptr)
347 {
348 ConstTensor recurrentToInputWeightsTensorCopy(
349 m_CifgParameters.m_RecurrentToInputWeights->GetTensorInfo(),
350 m_CifgParameters.m_RecurrentToInputWeights->Map(true));
351 recurrentToInputWeightsTensor = recurrentToInputWeightsTensorCopy;
352 inputParams.m_RecurrentToInputWeights = &recurrentToInputWeightsTensor;
353 }
354
355 ConstTensor recurrentToForgetWeightsTensor;
356 if (m_BasicParameters.m_RecurrentToForgetWeights != nullptr)
357 {
358 ConstTensor recurrentToForgetWeightsTensorCopy(
359 m_BasicParameters.m_RecurrentToForgetWeights->GetTensorInfo(),
360 m_BasicParameters.m_RecurrentToForgetWeights->Map(true));
361 recurrentToForgetWeightsTensor = recurrentToForgetWeightsTensorCopy;
362 inputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeightsTensor;
363 }
364
365 ConstTensor recurrentToCellWeightsTensor;
366 if (m_BasicParameters.m_RecurrentToCellWeights != nullptr)
367 {
368 ConstTensor recurrentToCellWeightsTensorCopy(
369 m_BasicParameters.m_RecurrentToCellWeights->GetTensorInfo(),
370 m_BasicParameters.m_RecurrentToCellWeights->Map(true));
371 recurrentToCellWeightsTensor = recurrentToCellWeightsTensorCopy;
372 inputParams.m_RecurrentToCellWeights = &recurrentToCellWeightsTensor;
373 }
374
375 ConstTensor recurrentToOutputWeightsTensor;
376 if (m_BasicParameters.m_RecurrentToOutputWeights != nullptr)
377 {
378 ConstTensor recurrentToOutputWeightsTensorCopy(
379 m_BasicParameters.m_RecurrentToOutputWeights->GetTensorInfo(),
380 m_BasicParameters.m_RecurrentToOutputWeights->Map(true));
381 recurrentToOutputWeightsTensor = recurrentToOutputWeightsTensorCopy;
382 inputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeightsTensor;
383 }
384
385 ConstTensor cellToInputWeightsTensor;
386 if (m_PeepholeParameters.m_CellToInputWeights != nullptr)
387 {
388 ConstTensor cellToInputWeightsTensorCopy(m_PeepholeParameters.m_CellToInputWeights->GetTensorInfo(),
389 m_PeepholeParameters.m_CellToInputWeights->Map(true));
390 cellToInputWeightsTensor = cellToInputWeightsTensorCopy;
391 inputParams.m_CellToInputWeights = &cellToInputWeightsTensor;
392 }
393
394 ConstTensor cellToForgetWeightsTensor;
395 if (m_PeepholeParameters.m_CellToForgetWeights != nullptr)
396 {
397 ConstTensor cellToForgetWeightsTensorCopy(m_PeepholeParameters.m_CellToForgetWeights->GetTensorInfo(),
398 m_PeepholeParameters.m_CellToForgetWeights->Map(true));
399 cellToForgetWeightsTensor = cellToForgetWeightsTensorCopy;
400 inputParams.m_CellToForgetWeights = &cellToForgetWeightsTensor;
401 }
402
403 ConstTensor cellToOutputWeightsTensor;
404 if (m_PeepholeParameters.m_CellToOutputWeights != nullptr)
405 {
406 ConstTensor cellToOutputWeightsTensorCopy(m_PeepholeParameters.m_CellToOutputWeights->GetTensorInfo(),
407 m_PeepholeParameters.m_CellToOutputWeights->Map(true));
408 cellToOutputWeightsTensor = cellToOutputWeightsTensorCopy;
409 inputParams.m_CellToOutputWeights = &cellToOutputWeightsTensor;
410 }
411
412 ConstTensor inputGateBiasTensor;
413 if (m_CifgParameters.m_InputGateBias != nullptr)
414 {
415 ConstTensor inputGateBiasTensorCopy(m_CifgParameters.m_InputGateBias->GetTensorInfo(),
416 m_CifgParameters.m_InputGateBias->Map(true));
417 inputGateBiasTensor = inputGateBiasTensorCopy;
418 inputParams.m_InputGateBias = &inputGateBiasTensor;
419 }
420
421 ConstTensor forgetGateBiasTensor;
422 if (m_BasicParameters.m_ForgetGateBias != nullptr)
423 {
424 ConstTensor forgetGateBiasTensorCopy(m_BasicParameters.m_ForgetGateBias->GetTensorInfo(),
425 m_BasicParameters.m_ForgetGateBias->Map(true));
426 forgetGateBiasTensor = forgetGateBiasTensorCopy;
427 inputParams.m_ForgetGateBias = &forgetGateBiasTensor;
428 }
429
430 ConstTensor cellBiasTensor;
431 if (m_BasicParameters.m_CellBias != nullptr)
432 {
433 ConstTensor cellBiasTensorCopy(m_BasicParameters.m_CellBias->GetTensorInfo(),
434 m_BasicParameters.m_CellBias->Map(true));
435 cellBiasTensor = cellBiasTensorCopy;
436 inputParams.m_CellBias = &cellBiasTensor;
437 }
438
439 ConstTensor outputGateBias;
440 if (m_BasicParameters.m_OutputGateBias != nullptr)
441 {
442 ConstTensor outputGateBiasCopy(m_BasicParameters.m_OutputGateBias->GetTensorInfo(),
443 m_BasicParameters.m_OutputGateBias->Map(true));
444 outputGateBias = outputGateBiasCopy;
445 inputParams.m_OutputGateBias = &outputGateBias;
446 }
447
448 ConstTensor projectionWeightsTensor;
449 if (m_ProjectionParameters.m_ProjectionWeights != nullptr)
450 {
451 ConstTensor projectionWeightsTensorCopy(m_ProjectionParameters.m_ProjectionWeights->GetTensorInfo(),
452 m_ProjectionParameters.m_ProjectionWeights->Map(true));
453 projectionWeightsTensor = projectionWeightsTensorCopy;
454 inputParams.m_ProjectionWeights = &projectionWeightsTensor;
455 }
456
457 ConstTensor projectionBiasTensor;
458 if (m_ProjectionParameters.m_ProjectionBias != nullptr)
459 {
460 ConstTensor projectionBiasTensorCopy(m_ProjectionParameters.m_ProjectionBias->GetTensorInfo(),
461 m_ProjectionParameters.m_ProjectionBias->Map(true));
462 projectionBiasTensor = projectionBiasTensorCopy;
463 inputParams.m_ProjectionBias = &projectionBiasTensor;
464 }
465
466 ConstTensor inputLayerNormTensor;
467 if (m_LayerNormParameters.m_InputLayerNormWeights != nullptr)
468 {
469 ConstTensor inputLayerNormTensorCopy(m_LayerNormParameters.m_InputLayerNormWeights->GetTensorInfo(),
470 m_LayerNormParameters.m_InputLayerNormWeights->Map(true));
471 inputLayerNormTensor = inputLayerNormTensorCopy;
472 inputParams.m_InputLayerNormWeights = &inputLayerNormTensor;
473 }
474
475 ConstTensor forgetLayerNormTensor;
476 if (m_LayerNormParameters.m_ForgetLayerNormWeights != nullptr)
477 {
478 ConstTensor forgetLayerNormTensorCopy(m_LayerNormParameters.m_ForgetLayerNormWeights->GetTensorInfo(),
479 m_LayerNormParameters.m_ForgetLayerNormWeights->Map(true));
480 forgetLayerNormTensor = forgetLayerNormTensorCopy;
481 inputParams.m_ForgetLayerNormWeights = &forgetLayerNormTensor;
482 }
483
484 ConstTensor cellLayerNormTensor;
485 if (m_LayerNormParameters.m_CellLayerNormWeights != nullptr)
486 {
487 ConstTensor cellLayerNormTensorCopy(m_LayerNormParameters.m_CellLayerNormWeights->GetTensorInfo(),
488 m_LayerNormParameters.m_CellLayerNormWeights->Map(true));
489 cellLayerNormTensor = cellLayerNormTensorCopy;
490 inputParams.m_CellLayerNormWeights = &cellLayerNormTensor;
491 }
492
493 ConstTensor outputLayerNormTensor;
494 if (m_LayerNormParameters.m_OutputLayerNormWeights != nullptr)
495 {
496 ConstTensor outputLayerNormTensorCopy(m_LayerNormParameters.m_OutputLayerNormWeights->GetTensorInfo(),
497 m_LayerNormParameters.m_OutputLayerNormWeights->Map(true));
498 outputLayerNormTensor = outputLayerNormTensorCopy;
499 inputParams.m_OutputLayerNormWeights = &outputLayerNormTensor;
500 }
501
502
503 visitor.VisitQLstmLayer(this, GetParameters(), inputParams, GetName());
504 }
505
506 } // namespace armnn
507