blob: 417f27ef0e43385552779066018039ebb9103fdf [file] [log] [blame]
erik.andersson@arm.com460c6892021-02-24 14:38:09 +01001# Copyright (C) 2020-2021 Arm Limited or its affiliates. All rights reserved.
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +01002#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the License); you may
6# not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an AS IS BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# Description:
17# Utility functions for creating Network Operations.
18from typing import Optional
Fredrik Svedberge82be7c2021-01-18 15:21:03 +010019from typing import Tuple
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010020
21from .data_type import DataType
22from .high_level_command_to_npu_op import ifm_ifm2_correct_order
23from .operation import ActivationFunction
24from .operation import Op
25from .operation import Operation
Michael McGeagh16895482020-12-14 15:51:20 +000026from .operation import Padding
Patrik Gustavsson3a269202021-01-21 08:28:55 +010027from .shape4d import Shape4D
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010028from .tensor import QuantizationParameters
29from .tensor import Tensor
30
31
32def create_avgpool_nop(name: str) -> Operation:
33 op = Operation(Op.AvgPool, name)
Michael McGeagh16895482020-12-14 15:51:20 +000034 op.attrs["padding"] = Padding.VALID
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010035 op.attrs["stride_w"] = 1
36 op.attrs["stride_h"] = 1
37 op.attrs["filter_width"] = 1
38 op.attrs["filter_height"] = 1
39 op.attrs["strides"] = [1, 1, 1, 1]
40 op.attrs["ksize"] = [1, 1, 1, 1]
41 op.attrs["skirt"] = [0, 0, 0, 0]
42 op.attrs["explicit_padding"] = [0, 0, 0, 0]
Louis Verhaardc822d622021-03-11 14:59:06 +010043 op.run_on_npu = True
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010044 return op
45
46
47def create_depthwise_maxpool(
Patrik Gustavsson3a269202021-01-21 08:28:55 +010048 name: str,
49 ifm: Tensor,
50 inp_shape: Shape4D,
51 quantization: QuantizationParameters,
52 activation: Optional[ActivationFunction] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010053) -> Operation:
54 op = Operation(Op.MaxPool, name)
Patrik Gustavsson3a269202021-01-21 08:28:55 +010055 height = inp_shape.height * inp_shape.width
56 width = inp_shape.depth
57 ifm_shape = Shape4D([1, height, width, 1])
58
Michael McGeagh16895482020-12-14 15:51:20 +000059 op.attrs["padding"] = Padding.VALID
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010060 op.attrs["stride_w"] = 1
61 op.attrs["stride_h"] = 1
62 op.attrs["filter_width"] = width
63 op.attrs["filter_height"] = 1
64 op.attrs["strides"] = [1, op.attrs["stride_h"], op.attrs["stride_w"], 1]
65 op.attrs["ksize"] = [1, op.attrs["filter_height"], op.attrs["filter_width"], 1]
66 op.activation = activation
Patrik Gustavsson3a269202021-01-21 08:28:55 +010067 op.inputs = [ifm]
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010068 ofm = Tensor([1, height, 1, 1], ifm.dtype, op.name + "_tens0")
69 ofm.quantization = quantization
70 op.set_output_tensor(ofm)
Patrik Gustavsson3a269202021-01-21 08:28:55 +010071 op.ifm_shapes.append(ifm_shape)
72 op.ofm_shapes.append(Shape4D(ofm.shape))
73 op.ifm.avoid_NHCWB16 = True
74 op.ofm.avoid_NHCWB16 = True
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010075 return op
76
77
78def create_reduce_sum(
79 name: str, ifm: Tensor, quantization: QuantizationParameters, activation: Optional[ActivationFunction] = None
80) -> Operation:
81 op = Operation(Op.ReduceSum, name)
Michael McGeagh16895482020-12-14 15:51:20 +000082 op.attrs["padding"] = Padding.VALID
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010083 op.attrs["stride_w"] = 1
84 op.attrs["stride_h"] = 1
85 op.attrs["filter_width"] = 1
86 op.attrs["filter_height"] = 1
87 op.attrs["strides"] = [1, op.attrs["stride_h"], op.attrs["stride_w"], 1]
88 op.attrs["ksize"] = [1, op.attrs["filter_height"], op.attrs["filter_width"], 1]
89 op.add_input_tensor(ifm)
90 op.activation = activation
91 ofm_shape = [1, ifm.shape[1], ifm.shape[2], 1]
92 sum_of_exp = Tensor(ofm_shape, DataType.int32, op.name + "_tens0")
93 sum_of_exp.quantization = quantization
94 op.set_output_tensor(sum_of_exp)
Patrik Gustavsson2349d422020-12-01 16:02:29 +010095 op.set_ifm_ofm_shapes()
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +010096 return op
97
98
99def create_add(
100 name: str,
101 ifm: Tensor,
102 ifm2: Tensor,
103 quantization: QuantizationParameters,
104 activation: Optional[ActivationFunction] = None,
105 dtype: Optional[DataType] = None,
106 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100107 ifm_shape: Optional[Shape4D] = None,
108 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100109) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100110 return create_binary_elementwise(
111 Op.Add, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
112 )
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100113
114
Fredrik Svedberge82be7c2021-01-18 15:21:03 +0100115def create_rescale_add(
116 name: str,
117 ifm: Tensor,
118 ifm2: Tensor,
119 rescale: Tuple[int, int],
120 quantization: QuantizationParameters,
121 activation: Optional[ActivationFunction] = None,
122 dtype: Optional[DataType] = None,
123 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100124 ifm_shape: Optional[Shape4D] = None,
125 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedberge82be7c2021-01-18 15:21:03 +0100126) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100127 op = create_binary_elementwise(
128 Op.RescaleAdd, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
129 )
Fredrik Svedberge82be7c2021-01-18 15:21:03 +0100130 op.rescale = rescale
131 return op
132
133
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100134def create_clz(
135 name: str,
136 ifm: Tensor,
137 quantization: QuantizationParameters,
138 activation: Optional[ActivationFunction] = None,
139 dtype: Optional[DataType] = None,
140 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100141 ifm_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100142) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100143 return create_unary_elementwise(Op.CLZ, name, ifm, quantization, activation, dtype, attrs, ifm_shape)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100144
145
146def create_mul(
147 name: str,
148 ifm: Tensor,
149 ifm2: Tensor,
150 quantization: QuantizationParameters,
151 activation: Optional[ActivationFunction] = None,
152 dtype: Optional[DataType] = None,
153 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100154 ifm_shape: Optional[Shape4D] = None,
155 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100156) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100157 return create_binary_elementwise(
158 Op.Mul, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
159 )
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100160
161
162def create_shl(
163 name: str,
164 ifm: Tensor,
165 ifm2: Tensor,
166 quantization: QuantizationParameters,
167 activation: Optional[ActivationFunction] = None,
168 dtype: Optional[DataType] = None,
169 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100170 ifm_shape: Optional[Shape4D] = None,
171 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100172) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100173 return create_binary_elementwise(
174 Op.SHL, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
175 )
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100176
177
178def create_shr(
179 name: str,
180 ifm: Tensor,
181 ifm2: Tensor,
182 quantization: QuantizationParameters,
183 activation: Optional[ActivationFunction] = None,
184 dtype: Optional[DataType] = None,
185 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100186 ifm_shape: Optional[Shape4D] = None,
187 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100188) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100189 return create_binary_elementwise(
190 Op.SHR, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
191 )
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100192
193
194def create_sub(
195 name: str,
196 ifm: Tensor,
197 ifm2: Tensor,
198 quantization: QuantizationParameters,
199 activation: Optional[ActivationFunction] = None,
200 dtype: Optional[DataType] = None,
201 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100202 ifm_shape: Optional[Shape4D] = None,
203 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100204) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100205 return create_binary_elementwise(
206 Op.Sub, name, ifm, ifm2, quantization, activation, dtype, attrs, ifm_shape, ifm2_shape
207 )
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100208
209
210def create_unary_elementwise(
211 op_type: Op,
212 name: str,
213 ifm: Tensor,
214 quantization: QuantizationParameters,
215 activation: Optional[ActivationFunction] = None,
216 dtype: Optional[DataType] = None,
217 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100218 ifm_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100219) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100220 return create_binary_elementwise(op_type, name, ifm, None, quantization, activation, dtype, attrs, ifm_shape, None)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100221
222
223def create_binary_elementwise(
224 op_type: Op,
225 name: str,
226 ifm: Tensor,
227 ifm2: Tensor,
228 quantization: QuantizationParameters,
229 activation: Optional[ActivationFunction] = None,
230 dtype: Optional[DataType] = None,
231 attrs: Optional[dict] = None,
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100232 ifm_shape: Optional[Shape4D] = None,
233 ifm2_shape: Optional[Shape4D] = None,
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100234) -> Operation:
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100235 if ifm_shape is None:
236 ifm_shape = Shape4D(ifm.shape)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100237 op = Operation(op_type, name)
238 op.add_input_tensor(ifm)
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100239 op.ifm_shapes.append(ifm_shape)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100240 if ifm2:
241 op.add_input_tensor(ifm2)
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100242 if ifm2_shape is None:
243 ifm2_shape = Shape4D(ifm2.shape)
244 op.ifm_shapes.append(ifm2_shape)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100245 op.activation = activation
246 if not dtype:
247 dtype = ifm.dtype
248 if attrs:
249 op.attrs.update(attrs)
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100250
251 if ifm2 is None:
252 ofm_shape = ifm_shape
253 else:
254 in_shape = [] if ifm.shape == [] else ifm_shape.as_list()
255 in2_shape = [] if ifm2.shape == [] else ifm2_shape.as_list()
256 ofm_shape = ifm_shape if ifm_ifm2_correct_order(in_shape, in2_shape) else ifm2_shape
257
258 ofm = Tensor(ofm_shape.as_list(), dtype, f"{op.name}_tens0")
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100259 ofm.quantization = quantization
260 op.set_output_tensor(ofm)
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100261 op.ofm_shapes.append(ofm_shape)
Fredrik Svedbergd9c2c422020-12-01 16:33:45 +0100262 return op
Louis Verhaardc822d622021-03-11 14:59:06 +0100263
264
265def get_pad_values_from_input(padding) -> Tuple:
266 """Returns top, left, bottom, right padding from input values in a Pad input tensor"""
267 return (padding[-3][0], padding[-2][0], padding[-3][1], padding[-2][1])