blob: 9909e66a7dce13c707a51a6d80c0eff1f41123f6 [file] [log] [blame]
Nikhil Raj9a339462022-12-05 11:24:35 +00001//
2// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3// 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,
11 const std::vector<const TensorInfo*>& outputs)
12{
13 std::string input0Name = std::string("input0_");
14 std::string input1Name = std::string("input1_");
15 std::string outputName = std::string("output0_");
16 std::string blockName;
17
18 // If a layer is present then the block will be used for execution, so input and output names need to be determined
19 // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
20 if(layer != nullptr)
21 {
22 // Get the layers connected to the input slots and determine unique tensor names.
23 Layer& connectedLayer0 = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
24 input0Name = GenerateUniqueName(connectedLayer0, 0);
25
26 Layer& connectedLayer1 = layer->GetInputSlot(1).GetConnectedOutputSlot()->GetOwningLayer();
27 input1Name = GenerateUniqueName(connectedLayer1, 1);
28
29 // Determine unique output tensor name.
30 outputName = GenerateUniqueOutputName(*layer, 0);
31 }
32
33 TosaSerializationOperator* op = nullptr;
34 switch(type)
35 {
36 case LayerType::Addition:
37 {
38 op = new TosaSerializationOperator(Op_ADD,
39 Attribute_NONE,
40 nullptr,
41 {input0Name, input1Name},
42 {outputName});
43 blockName = std::string("Op_ADD_block_") + GetUniqueTosaMappingID();
44 break;
45 }
46 case LayerType::Multiplication:
47 {
48 int32_t shift = 0;
49 TosaMulAttribute mulAttribute(shift);
50 op = new TosaSerializationOperator(Op_MUL,
51 Attribute_MulAttribute,
52 &mulAttribute,
53 {input0Name, input1Name},
54 {outputName});
55 blockName = std::string("Op_MUL_block_") + GetUniqueTosaMappingID();
56 break;
57 }
58 case LayerType::Subtraction:
59 {
60 op = new TosaSerializationOperator(Op_SUB,
61 Attribute_NONE,
62 nullptr,
63 {input0Name, input1Name},
64 {outputName});
65 blockName = std::string("Op_SUB_block_") + GetUniqueTosaMappingID();
66 break;
67 }
68 default:
69 throw armnn::Exception("ConvertElementwiseBinaryToTosaOperator: Unsupported layer type.");
70 }
71 ARMNN_ASSERT(op != nullptr);
72
73 std::vector<TosaSerializationTensor*> tensors;
74 // Only add input tensors if connected layer is an input layer.
75 // As intermediate or constant tensors will be created separately.
76 // There also can't be duplicate tensor.
77 if(input0Name.find("input0_") != std::string::npos)
78 {
79 std::vector<int32_t> inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
80 DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());
81 tensors.push_back(new TosaSerializationTensor(input0Name, inputShape0, inputDType0, {}));
82 }
83 if(input1Name.find("input1_") != std::string::npos)
84 {
85 std::vector<int32_t> inputShape1 = GetTosaTensorShape(inputs[1]->GetShape());
86 DType inputDType1 = ArmNNToDType(inputs[1]->GetDataType());
87 tensors.push_back(new TosaSerializationTensor(input1Name, inputShape1, inputDType1, {}));
88 }
89
90 std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
91 DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());
92
93 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
94
95 // operatorInputNames/operatorOutputNames ends up being the same as
96 // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
97 return new TosaSerializationBasicBlock(blockName, // name
98 {op}, // operators
99 tensors, // tensors
100 {input0Name, input1Name}, // inputs
101 {outputName}); // outputs
102}
103