blob: a9af2496739d1a3d65b213fbe5947a9ca41093db [file] [log] [blame]
Nikhil Raj9a339462022-12-05 11:24:35 +00001//
Colm Donelanb4ef1632024-02-01 15:00:43 +00002// Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
Nikhil Raj9a339462022-12-05 11:24:35 +00003// SPDX-License-Identifier: MIT
4//
5
6#include "ElementwiseBinaryOperator.hpp"
7
8TosaSerializationBasicBlock* ConvertElementwiseBinaryToTosaOperator(const Layer* layer,
9 const LayerType type,
10 const std::vector<const TensorInfo*>& inputs,
Tianle Cheng7790dc62023-12-12 13:52:22 +000011 const std::vector<const TensorInfo*>& outputs,
12 const ElementwiseBinaryDescriptor* descriptor)
Nikhil Raj9a339462022-12-05 11:24:35 +000013{
14 std::string input0Name = std::string("input0_");
15 std::string input1Name = std::string("input1_");
16 std::string outputName = std::string("output0_");
17 std::string blockName;
18
19 // If a layer is present then the block will be used for execution, so input and output names need to be determined
20 // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
21 if(layer != nullptr)
22 {
23 // Get the layers connected to the input slots and determine unique tensor names.
24 Layer& connectedLayer0 = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
25 input0Name = GenerateUniqueName(connectedLayer0, 0);
26
27 Layer& connectedLayer1 = layer->GetInputSlot(1).GetConnectedOutputSlot()->GetOwningLayer();
28 input1Name = GenerateUniqueName(connectedLayer1, 1);
29
30 // Determine unique output tensor name.
31 outputName = GenerateUniqueOutputName(*layer, 0);
32 }
33
34 TosaSerializationOperator* op = nullptr;
35 switch(type)
36 {
37 case LayerType::Addition:
38 {
39 op = new TosaSerializationOperator(Op_ADD,
40 Attribute_NONE,
41 nullptr,
42 {input0Name, input1Name},
43 {outputName});
44 blockName = std::string("Op_ADD_block_") + GetUniqueTosaMappingID();
45 break;
46 }
Tianle Cheng7790dc62023-12-12 13:52:22 +000047 case LayerType::ElementwiseBinary:
48 {
49 switch (descriptor->m_Operation)
50 {
51 case armnn::BinaryOperation::Maximum:
52 {
53 op = new TosaSerializationOperator(Op_MAXIMUM,
54 Attribute_NONE,
55 nullptr,
56 {input0Name, input1Name},
57 {outputName});
58 blockName = std::string("Op_MAXIMUM_block_") + GetUniqueTosaMappingID();
59 break;
60 }
61 default:
62 throw armnn::Exception("ConvertElementwiseBinaryToTosaOperator: Unsupported layer type.");
63 }
64 break;
65 }
Nikhil Raj9a339462022-12-05 11:24:35 +000066 case LayerType::Multiplication:
67 {
68 int32_t shift = 0;
69 TosaMulAttribute mulAttribute(shift);
70 op = new TosaSerializationOperator(Op_MUL,
71 Attribute_MulAttribute,
72 &mulAttribute,
73 {input0Name, input1Name},
74 {outputName});
75 blockName = std::string("Op_MUL_block_") + GetUniqueTosaMappingID();
76 break;
77 }
78 case LayerType::Subtraction:
79 {
80 op = new TosaSerializationOperator(Op_SUB,
81 Attribute_NONE,
82 nullptr,
83 {input0Name, input1Name},
84 {outputName});
85 blockName = std::string("Op_SUB_block_") + GetUniqueTosaMappingID();
86 break;
87 }
88 default:
89 throw armnn::Exception("ConvertElementwiseBinaryToTosaOperator: Unsupported layer type.");
90 }
Nikhil Raj9a339462022-12-05 11:24:35 +000091
92 std::vector<TosaSerializationTensor*> tensors;
93 // Only add input tensors if connected layer is an input layer.
94 // As intermediate or constant tensors will be created separately.
95 // There also can't be duplicate tensor.
96 if(input0Name.find("input0_") != std::string::npos)
97 {
98 std::vector<int32_t> inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
99 DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());
100 tensors.push_back(new TosaSerializationTensor(input0Name, inputShape0, inputDType0, {}));
101 }
102 if(input1Name.find("input1_") != std::string::npos)
103 {
104 std::vector<int32_t> inputShape1 = GetTosaTensorShape(inputs[1]->GetShape());
105 DType inputDType1 = ArmNNToDType(inputs[1]->GetDataType());
106 tensors.push_back(new TosaSerializationTensor(input1Name, inputShape1, inputDType1, {}));
107 }
108
109 std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
110 DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());
111
112 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
113
114 // operatorInputNames/operatorOutputNames ends up being the same as
115 // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
116 return new TosaSerializationBasicBlock(blockName, // name
Narumol Prangnawaratad323af2023-09-29 17:00:38 +0100117 mainName, // region name
Nikhil Raj9a339462022-12-05 11:24:35 +0000118 {op}, // operators
119 tensors, // tensors
120 {input0Name, input1Name}, // inputs
121 {outputName}); // outputs
122}
123