blob: 0ec2f1d9d2a58f311480ee5f9e97c4d2118f6e84 [file] [log] [blame]
Rob Elliott78b94122024-01-25 13:05:16 +00001# SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +02002#
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.
Rickard Bolinbc6ee582022-11-04 08:24:29 +000016#
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020017# Description:
18# TOSA mapping functions used by reader.
19# Contains a mapping from the various TOSA enums and options structs, generated by the FlatBuffer code
20# generator, to Vela's internal format.
Patrik Gustavssond15866c2021-08-10 13:56:34 +020021import numpy as np
22
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020023from .data_type import DataType
24from .operation import Op
25from .operation import TensorIndices
26from .tosa import ArithmeticRightShiftAttribute # noqa: F401
27from .tosa import AxisAttribute # noqa: F401
28from .tosa import ClampAttribute # noqa: F401
29from .tosa import CondIfAttribute # noqa: F401
Patrik Gustavsson85f61172021-10-01 08:15:06 +020030from .tosa import ConvAttribute # noqa: F401
Rob Elliott00a15db2023-08-17 14:27:06 +000031from .tosa import FullyConnectedAttribute # noqa: F401
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020032from .tosa import MulAttribute # noqa: F401
Patrik Gustavsson85f61172021-10-01 08:15:06 +020033from .tosa import PoolAttribute # noqa: F401
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020034from .tosa import RescaleAttribute # noqa: F401
35from .tosa import ReshapeAttribute # noqa: F401
36from .tosa import ResizeAttribute # noqa: F401
37from .tosa import SliceAttribute # noqa: F401
38from .tosa import TileAttribute # noqa: F401
Rob Elliott00a15db2023-08-17 14:27:06 +000039from .tosa import TransposeAttribute # noqa: F401
Patrik Gustavsson85f61172021-10-01 08:15:06 +020040from .tosa import TransposeConvAttribute # noqa: F401
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020041from .tosa import WhileLoopAttribute # noqa: F401
42from .tosa.DType import DType
43from .tosa.Op import Op as TosaOp
44
45
46datatype_map = {
47 DType.BOOL: DataType.bool,
48 DType.UINT8: DataType.uint8,
49 DType.INT4: DataType.int4,
50 DType.INT8: DataType.int8,
51 DType.INT16: DataType.int16,
52 DType.INT32: DataType.int32,
53 DType.INT48: DataType.int48,
Rob Elliott00a15db2023-08-17 14:27:06 +000054 DType.FP32: DataType.float32,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020055}
56
Patrik Gustavssond15866c2021-08-10 13:56:34 +020057datatype_map_numpy = {
Rickard Bolin5fdcf172022-12-19 12:56:17 +000058 DType.BOOL: bool,
Patrik Gustavssond15866c2021-08-10 13:56:34 +020059 DType.UINT8: np.uint8,
60 DType.INT8: np.int8,
61 DType.INT16: np.int16,
62 DType.INT32: np.int32,
Rob Elliott00a15db2023-08-17 14:27:06 +000063 DType.FP32: np.float32,
Patrik Gustavssond15866c2021-08-10 13:56:34 +020064}
65
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020066
67# TODO duplicate of tflite_mapping
68def underscore_to_camel_case(s):
69 return "".join(x.title() for x in s.split("_"))
70
71
72# TODO duplicate of tflite_mapping
73def identity(x):
74 return x
75
76
77class AttrSerializer:
78 def __init__(self, name, members=None):
79 self.name = name
80 self.module = globals()[self.name]
81 self.cls = getattr(self.module, self.name)
82 self.members = []
83 if members is not None:
84 for mem in members:
85 deserialize = identity
86 is_vector = False
87 if isinstance(mem, tuple):
88 if len(mem) == 2:
89 mem, is_vector = mem
90 deserialize = tuple
91 else:
92 assert 0
93 underscore_mem = mem
94 camelcase_mem = underscore_to_camel_case(mem)
95 self.members.append((underscore_mem, camelcase_mem, deserialize, is_vector))
96
97 def deserialize(self, op_data):
98 attr_type = op_data.AttributeType()
99 attr = op_data.Attribute()
100 attrs = {}
101 if attr_type:
102 tosa_attrs = self.cls()
103 tosa_attrs.Init(attr.Bytes, attr.Pos)
104 for underscore_mem, camelcase_mem, deserialize, is_vector in self.members:
105 fun = camelcase_mem
106 if is_vector:
107 fun += "AsNumpy"
108
109 attr = getattr(tosa_attrs, fun)()
110 try:
111 attrs[underscore_mem] = deserialize(attr)
112 except TypeError:
113 print("Warning: {0} could not read attribute '{1}'.".format(self.name, underscore_mem))
114
115 return attrs
116
117
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200118is_vec = True
Rob Elliott00a15db2023-08-17 14:27:06 +0000119pool_attrs = AttrSerializer(
120 "PoolAttribute",
121 (
122 ("pad", is_vec),
123 ("kernel", is_vec),
124 ("stride", is_vec),
125 ("input_zp"),
126 ("output_zp"),
127 ),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200128)
Rob Elliott00a15db2023-08-17 14:27:06 +0000129conv_attrs = AttrSerializer(
130 "ConvAttribute",
131 (
132 ("pad", is_vec),
133 ("stride", is_vec),
134 ("dilation", is_vec),
135 ("input_zp"),
136 ("weight_zp"),
137 ),
138)
139fc_attrs = AttrSerializer("FullyConnectedAttribute", (("input_zp"), ("weight_zp")))
140transpose_conv_attrs = AttrSerializer(
141 "TransposeConvAttribute",
142 (
143 ("outpad", is_vec),
144 ("stride", is_vec),
145 ("dilation", is_vec),
146 ("out_shape", is_vec),
147 ),
148)
149transpose_attrs = AttrSerializer("TransposeAttribute", (("perms", is_vec),))
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200150axis_attrs = AttrSerializer("AxisAttribute", ("axis",))
Rob Elliott78b94122024-01-25 13:05:16 +0000151reshape_attrs = AttrSerializer("ReshapeAttribute", (("new_shape", is_vec),))
Rob Elliott00a15db2023-08-17 14:27:06 +0000152slice_attrs = AttrSerializer("SliceAttribute", (("start", is_vec), ("size", is_vec)))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200153tile_attrs = AttrSerializer("TileAttribute", (("multiplies", is_vec),))
154resize_attrs = AttrSerializer(
Rob Elliott00a15db2023-08-17 14:27:06 +0000155 "ResizeAttribute",
156 (("output_size", is_vec), ("stride", is_vec), ("offset", is_vec), ("shift")),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200157)
158clamp_attrs = AttrSerializer("ClampAttribute", (("min_int"), ("max_int")))
159rescale_attrs = AttrSerializer(
160 "RescaleAttribute",
Rob Elliott00a15db2023-08-17 14:27:06 +0000161 (
162 "input_zp",
163 "output_zp",
164 ("multiplier", is_vec),
165 ("shift", is_vec),
166 "scale32",
167 "double_round",
168 "per_channel",
169 ),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200170)
Patrik Gustavssonb081d672021-08-25 13:49:25 +0200171mul_attrs = AttrSerializer("MulAttribute", ("shift",))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200172ars_attrs = AttrSerializer("ArithmeticRightShiftAttribute", ("round",))
173condif_attrs = AttrSerializer("CondIfAttribute", (("then_branch"), ("else_branch"))) # TODO these are references
174while_attrs = AttrSerializer("WhileLoopAttribute", (("cond_branch"), ("body_branch"))) # TODO these are references
175
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200176unsupported_tosa_operators = {
177 TosaOp.UNKNOWN,
178 TosaOp.ARGMAX,
179 TosaOp.CONV3D,
180 TosaOp.MATMUL,
181 TosaOp.TRANSPOSE_CONV2D,
182 TosaOp.SIGMOID,
183 TosaOp.TANH,
184 TosaOp.BITWISE_AND,
185 TosaOp.BITWISE_OR,
186 TosaOp.BITWISE_XOR,
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200187 TosaOp.INTDIV,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200188 TosaOp.LOGICAL_AND,
189 TosaOp.LOGICAL_LEFT_SHIFT,
190 TosaOp.LOGICAL_RIGHT_SHIFT,
191 TosaOp.LOGICAL_OR,
192 TosaOp.LOGICAL_XOR,
193 TosaOp.MAXIMUM,
194 TosaOp.MINIMUM,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200195 TosaOp.POW,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200196 TosaOp.ABS,
197 TosaOp.BITWISE_NOT,
198 TosaOp.CEIL,
199 TosaOp.CLZ,
200 TosaOp.EXP,
201 TosaOp.FLOOR,
202 TosaOp.LOG,
203 TosaOp.LOGICAL_NOT,
204 TosaOp.NEGATE,
205 TosaOp.RECIPROCAL,
206 TosaOp.RSQRT,
207 TosaOp.SELECT,
208 TosaOp.EQUAL,
209 TosaOp.GREATER,
210 TosaOp.GREATER_EQUAL,
211 TosaOp.REDUCE_ANY,
212 TosaOp.REDUCE_ALL,
213 TosaOp.REDUCE_MAX,
214 TosaOp.REDUCE_MIN,
215 TosaOp.REDUCE_PRODUCT,
216 TosaOp.REDUCE_SUM,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200217 TosaOp.REVERSE,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200218 TosaOp.TILE,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200219 TosaOp.GATHER,
220 TosaOp.SCATTER,
221 TosaOp.RESIZE,
222 TosaOp.CAST,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200223 TosaOp.CUSTOM,
224 TosaOp.COND_IF,
225 TosaOp.WHILE_LOOP,
226}
227
228
229TOSA_NO_INDICES = TensorIndices([], [], [])
230TOSA_IFM_INDICES = TensorIndices([0], [], [])
231# TOSA_IFM_WEIGHTS_INDICES = TensorIndices([0], [1], [])
232TOSA_IFM_WEIGHTS_BIAS_INDICES = TensorIndices([0], [1], [2])
233TOSA_IFM_IFM2_INDICES = TensorIndices([0, 1], [], [])
234# TOSA_CONV2D_BACKPROP_INDICES = TensorIndices([2], [1], [3])
235# TOSA_TRANSPOSE_CONV_INDICES = TensorIndices([0], [1], [3])
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200236TOSA_CONCAT_INDICES = TensorIndices([1, 2], [], [])
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200237# TOSA_SPLIT_IFM_INDICES = TensorIndices([1], [], [])
238# TOSA_BLOCK_LSTM_INDICES = TensorIndices([3], [4], [])
239
240
241tosa_operator_map = {
242 # TosaOp.UNKNOWN: (),
243 # TODO TosaOp.ARGMAX: (Op.ArgMax, axis_attrs, None),
Rob Elliott00a15db2023-08-17 14:27:06 +0000244 TosaOp.AVG_POOL2D: (Op.AvgPool, pool_attrs, None, TOSA_IFM_INDICES),
245 TosaOp.CONV2D: (Op.Conv2DBias, conv_attrs, None, TOSA_IFM_WEIGHTS_BIAS_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200246 # TODO TosaOp.CONV3D:
Rob Elliott00a15db2023-08-17 14:27:06 +0000247 TosaOp.DEPTHWISE_CONV2D: (
248 Op.DepthwiseConv2DBias,
249 conv_attrs,
250 None,
251 TOSA_IFM_WEIGHTS_BIAS_INDICES,
252 ),
253 TosaOp.FULLY_CONNECTED: (
254 Op.FullyConnected,
255 fc_attrs,
256 None,
257 TOSA_IFM_WEIGHTS_BIAS_INDICES,
258 ),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200259 # TODO TosaOp.MATMUL:
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200260 TosaOp.MAX_POOL2D: (Op.MaxPool, pool_attrs, None, TOSA_IFM_INDICES),
Rob Elliott00a15db2023-08-17 14:27:06 +0000261 # TODO TosaOp.TRANSPOSE_CONV2D: (Op.Conv2DBackpropInput, transpose_conv_attrs, None)
Patrik Gustavsson5e26eda2021-06-30 09:07:16 +0200262 TosaOp.CLAMP: (Op.Clamp, clamp_attrs, None, TOSA_IFM_INDICES),
Rob Elliott00a15db2023-08-17 14:27:06 +0000263 # TODO: BUG: No longer a relu - presumably a clamp - TosaOp.RELUN: (Op.ReluN, relun_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200264 # TODO TosaOp.SIGMOID
265 # TODO TosaOp.TANH
266 TosaOp.ADD: (Op.Add, None, None, TOSA_IFM_IFM2_INDICES),
267 TosaOp.ARITHMETIC_RIGHT_SHIFT: (Op.SHR, ars_attrs, None, TOSA_IFM_IFM2_INDICES),
268 # TODO TosaOp.BITWISE_AND
269 # TODO TosaOp.BITWISE_OR
270 # TODO TosaOp.BITWISE_XOR
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200271 # TODO TosaOp.INTDIV
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200272 # TODO TosaOp.LOGICAL_AND
273 # TODO TosaOp.LOGICAL_LEFT_SHIFT
274 # TODO TosaOp.LOGICAL_RIGHT_SHIFT
275 # TODO TosaOp.LOGICAL_OR
276 # TODO TosaOp.LOGICAL_XOR
277 # TODO TosaOp.MAXIMUM
278 # TODO TosaOp.MINIMUM
Patrik Gustavssonb081d672021-08-25 13:49:25 +0200279 TosaOp.MUL: (Op.Mul, mul_attrs, None, TOSA_IFM_IFM2_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200280 # TODO TosaOp.POW
281 TosaOp.SUB: (Op.Sub, None, None, TOSA_IFM_IFM2_INDICES),
Patrik Gustavssonf436ada2021-09-14 14:56:48 +0200282 # TODO is table content in input[1] always constant?
283 TosaOp.TABLE: (Op.Table, None, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200284 # TODO TosaOp.ABS
285 # TODO TosaOp.BITWISE_NOT
286 # TODO TosaOp.CEIL
287 # TODO TosaOp.CLZ
288 # TODO TosaOp.EXP
289 # TODO TosaOp.FLOOR
290 # TODO TosaOp.LOG
291 # TODO TosaOp.LOGICAL_NOT
292 # TODO TosaOp.NEGATE
293 # TODO TosaOp.RECIPROCAL
294 # TODO TosaOp.RSQRT
295 # TODO TosaOp.SELECT
296 # TODO TosaOp.EQUAL
297 # TODO TosaOp.GREATER
298 # TODO TosaOp.GREATER_EQUAL
299 # TODO TosaOp.REDUCE_ANY
300 # TODO TosaOp.REDUCE_ALL
301 # TODO TosaOp.REDUCE_MAX
302 # TODO TosaOp.REDUCE_MIN
303 # TODO TosaOp.REDUCE_PRODUCT
304 # TODO TosaOp.REDUCE_SUM
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200305 TosaOp.CONCAT: (Op.Concat, axis_attrs, None, TOSA_CONCAT_INDICES),
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200306 # TODO Is the padding intended to be dynamic input, TOSA spec state it as attribute
307 # Handled as for TFLite for now
Rob Elliott00a15db2023-08-17 14:27:06 +0000308 TosaOp.PAD: (Op.Pad, None, None, TOSA_IFM_INDICES),
Patrik Gustavssondf995102021-08-23 15:33:59 +0200309 TosaOp.RESHAPE: (Op.Reshape, reshape_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200310 # TODO TosaOp.REVERSE
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200311 TosaOp.SLICE: (Op.SplitSliceRead, slice_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200312 # TODO TosaOp.TILE
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200313 TosaOp.TRANSPOSE: (
314 Op.Transpose,
Rob Elliott00a15db2023-08-17 14:27:06 +0000315 transpose_attrs,
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200316 None,
Rob Elliott00a15db2023-08-17 14:27:06 +0000317 # TODO: why is this IFM2 indices but then overridden to TOSA_IFM_INDICES in _reader?
318 # TOSA_IFM_IFM2_INDICES,
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200319 TOSA_IFM_IFM2_INDICES,
320 ), # TODO Is the perms intended to be dynamic input, TOSA spec state it as attribute
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200321 # TODO TosaOp.GATHER
322 # TODO TosaOp.SCATTER
323 # TODO TosaOp.RESIZE
324 # TODO TosaOp.CAST
325 TosaOp.RESCALE: (Op.Rescale, rescale_attrs, None, TOSA_IFM_INDICES),
326 TosaOp.CONST: (Op.Const, None, None, TOSA_NO_INDICES),
Patrik Gustavssonef3ebdd2021-10-01 11:10:25 +0200327 TosaOp.IDENTITY: (Op.Identity, None, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200328 # TODO TosaOp.CUSTOM
329 # TODO TosaOp.COND_IF
330 # TODO TosaOp.WHILE_LOOP
331}
332
333tosa_operator_inv_map = {v[0]: (k, v[1]) for k, v in tosa_operator_map.items()}
334
Tim Halla3fe6652022-03-03 17:43:16 +0000335tosa_operator_name_map = {v: k for k, v in vars(TosaOp).items()}
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200336
337
338# TODO will return UNKNOWN for the once that have not yet been defined in tosa_operator_map
Tim Halla3fe6652022-03-03 17:43:16 +0000339def optype_to_tosa_op_type(op_type: Op):
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200340 if op_type in tosa_operator_inv_map:
Tim Halla3fe6652022-03-03 17:43:16 +0000341 return tosa_operator_name_map[tosa_operator_inv_map[op_type][0]]
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200342 else:
343 return TosaOp.UNKNOWN