blob: 87819d6d3bab8dc83e2a9da2aaa6e2d938d850f7 [file] [log] [blame]
Rickard Bolinbc6ee582022-11-04 08:24:29 +00001# SPDX-FileCopyrightText: Copyright 2021-2022 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
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020031from .tosa import ConvQuantInfo # noqa: F401
32from .tosa import MatMulQuantInfo # noqa: F401
33from .tosa import MulAttribute # noqa: F401
34from .tosa import PadQuantInfo # noqa: F401
Patrik Gustavsson85f61172021-10-01 08:15:06 +020035from .tosa import PoolAttribute # noqa: F401
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020036from .tosa import ReluNAttribute # noqa: F401
37from .tosa import RescaleAttribute # noqa: F401
38from .tosa import ReshapeAttribute # noqa: F401
39from .tosa import ResizeAttribute # noqa: F401
40from .tosa import SliceAttribute # noqa: F401
41from .tosa import TileAttribute # noqa: F401
Patrik Gustavsson85f61172021-10-01 08:15:06 +020042from .tosa import TransposeConvAttribute # noqa: F401
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020043from .tosa import UnaryQuantInfo # noqa: F401
44from .tosa import WhileLoopAttribute # noqa: F401
45from .tosa.DType import DType
46from .tosa.Op import Op as TosaOp
47
48
49datatype_map = {
50 DType.BOOL: DataType.bool,
51 DType.UINT8: DataType.uint8,
52 DType.INT4: DataType.int4,
53 DType.INT8: DataType.int8,
54 DType.INT16: DataType.int16,
55 DType.INT32: DataType.int32,
56 DType.INT48: DataType.int48,
57 DType.FLOAT: DataType.float32,
58}
59
Patrik Gustavssond15866c2021-08-10 13:56:34 +020060datatype_map_numpy = {
61 DType.BOOL: np.bool,
62 DType.UINT8: np.uint8,
63 DType.INT8: np.int8,
64 DType.INT16: np.int16,
65 DType.INT32: np.int32,
66 DType.FLOAT: np.float32,
67}
68
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +020069
70# TODO duplicate of tflite_mapping
71def underscore_to_camel_case(s):
72 return "".join(x.title() for x in s.split("_"))
73
74
75# TODO duplicate of tflite_mapping
76def identity(x):
77 return x
78
79
80class AttrSerializer:
81 def __init__(self, name, members=None):
82 self.name = name
83 self.module = globals()[self.name]
84 self.cls = getattr(self.module, self.name)
85 self.members = []
86 if members is not None:
87 for mem in members:
88 deserialize = identity
89 is_vector = False
90 if isinstance(mem, tuple):
91 if len(mem) == 2:
92 mem, is_vector = mem
93 deserialize = tuple
94 else:
95 assert 0
96 underscore_mem = mem
97 camelcase_mem = underscore_to_camel_case(mem)
98 self.members.append((underscore_mem, camelcase_mem, deserialize, is_vector))
99
100 def deserialize(self, op_data):
101 attr_type = op_data.AttributeType()
102 attr = op_data.Attribute()
103 attrs = {}
104 if attr_type:
105 tosa_attrs = self.cls()
106 tosa_attrs.Init(attr.Bytes, attr.Pos)
107 for underscore_mem, camelcase_mem, deserialize, is_vector in self.members:
108 fun = camelcase_mem
109 if is_vector:
110 fun += "AsNumpy"
111
112 attr = getattr(tosa_attrs, fun)()
113 try:
114 attrs[underscore_mem] = deserialize(attr)
115 except TypeError:
116 print("Warning: {0} could not read attribute '{1}'.".format(self.name, underscore_mem))
117
118 return attrs
119
120
121class QuantSerializer:
122 def __init__(self, name, members=None):
123 self.name = name
124 self.module = globals()[self.name]
125 self.cls = getattr(self.module, self.name)
126 self.members = []
127 if members is not None:
128 for mem in members:
129 deserialize = identity
130 underscore_mem = mem
131 camelcase_mem = underscore_to_camel_case(mem)
132 self.members.append((underscore_mem, camelcase_mem, deserialize))
133
134 def deserialize(self, op_data):
135 quant_info_type = op_data.QuantInfoType()
136 quant_info = op_data.QuantInfo()
137 quant = {}
138 if quant_info_type:
139 tosa_quant = self.cls()
140 tosa_quant.Init(quant_info.Bytes, quant_info.Pos)
141 for underscore_mem, camelcase_mem, deserialize in self.members:
142 attr = getattr(tosa_quant, camelcase_mem)()
143 try:
144 quant[underscore_mem] = deserialize(attr)
145 except TypeError:
146 print("Warning: {0} could not read quant info '{1}'.".format(self.name, underscore_mem))
147
148 return quant
149
150
151is_vec = True
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200152pool_attrs = AttrSerializer("PoolAttribute", (("padding", is_vec), ("kernel", is_vec), ("stride", is_vec)))
153conv_attrs = AttrSerializer("ConvAttribute", (("padding", is_vec), ("stride", is_vec), ("dilation", is_vec)))
154transpose_conv_attrs = AttrSerializer(
155 "TransposeConvAttribute", (("outpad", is_vec), ("stride", is_vec), ("dilation", is_vec), ("out_shape", is_vec))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200156)
157relun_attrs = AttrSerializer("ReluNAttribute", ("max_int"))
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200158axis_attrs = AttrSerializer("AxisAttribute", ("axis",))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200159reshape_attrs = AttrSerializer("ReshapeAttribute", (("shape", is_vec),))
160slice_attrs = AttrSerializer("SliceAttribute", (("begin", is_vec), ("size", is_vec)))
161tile_attrs = AttrSerializer("TileAttribute", (("multiplies", is_vec),))
162resize_attrs = AttrSerializer(
163 "ResizeAttribute", (("output_size", is_vec), ("stride", is_vec), ("offset", is_vec), ("shift"))
164)
165clamp_attrs = AttrSerializer("ClampAttribute", (("min_int"), ("max_int")))
166rescale_attrs = AttrSerializer(
167 "RescaleAttribute",
168 ("input_zp", "output_zp", ("multiplier", is_vec), ("shift", is_vec), "scale32", "double_round", "per_channel"),
169)
Patrik Gustavssonb081d672021-08-25 13:49:25 +0200170mul_attrs = AttrSerializer("MulAttribute", ("shift",))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200171ars_attrs = AttrSerializer("ArithmeticRightShiftAttribute", ("round",))
172condif_attrs = AttrSerializer("CondIfAttribute", (("then_branch"), ("else_branch"))) # TODO these are references
173while_attrs = AttrSerializer("WhileLoopAttribute", (("cond_branch"), ("body_branch"))) # TODO these are references
174
175unary_quant_info = QuantSerializer("UnaryQuantInfo", ("input_zp", "output_zp"))
176conv_quant_info = QuantSerializer("ConvQuantInfo", ("input_zp", "weight_zp"))
177matmul_quant_info = QuantSerializer("MatMulQuantInfo", ("a_zp", "b_zp"))
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200178pad_quant_info = QuantSerializer("PadQuantInfo", ("input_zp",))
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200179
180unsupported_tosa_operators = {
181 TosaOp.UNKNOWN,
182 TosaOp.ARGMAX,
183 TosaOp.CONV3D,
184 TosaOp.MATMUL,
185 TosaOp.TRANSPOSE_CONV2D,
186 TosaOp.SIGMOID,
187 TosaOp.TANH,
188 TosaOp.BITWISE_AND,
189 TosaOp.BITWISE_OR,
190 TosaOp.BITWISE_XOR,
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200191 TosaOp.INTDIV,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200192 TosaOp.LOGICAL_AND,
193 TosaOp.LOGICAL_LEFT_SHIFT,
194 TosaOp.LOGICAL_RIGHT_SHIFT,
195 TosaOp.LOGICAL_OR,
196 TosaOp.LOGICAL_XOR,
197 TosaOp.MAXIMUM,
198 TosaOp.MINIMUM,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200199 TosaOp.POW,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200200 TosaOp.ABS,
201 TosaOp.BITWISE_NOT,
202 TosaOp.CEIL,
203 TosaOp.CLZ,
204 TosaOp.EXP,
205 TosaOp.FLOOR,
206 TosaOp.LOG,
207 TosaOp.LOGICAL_NOT,
208 TosaOp.NEGATE,
209 TosaOp.RECIPROCAL,
210 TosaOp.RSQRT,
211 TosaOp.SELECT,
212 TosaOp.EQUAL,
213 TosaOp.GREATER,
214 TosaOp.GREATER_EQUAL,
215 TosaOp.REDUCE_ANY,
216 TosaOp.REDUCE_ALL,
217 TosaOp.REDUCE_MAX,
218 TosaOp.REDUCE_MIN,
219 TosaOp.REDUCE_PRODUCT,
220 TosaOp.REDUCE_SUM,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200221 TosaOp.REVERSE,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200222 TosaOp.TILE,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200223 TosaOp.GATHER,
224 TosaOp.SCATTER,
225 TosaOp.RESIZE,
226 TosaOp.CAST,
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200227 TosaOp.CUSTOM,
228 TosaOp.COND_IF,
229 TosaOp.WHILE_LOOP,
230}
231
232
233TOSA_NO_INDICES = TensorIndices([], [], [])
234TOSA_IFM_INDICES = TensorIndices([0], [], [])
235# TOSA_IFM_WEIGHTS_INDICES = TensorIndices([0], [1], [])
236TOSA_IFM_WEIGHTS_BIAS_INDICES = TensorIndices([0], [1], [2])
237TOSA_IFM_IFM2_INDICES = TensorIndices([0, 1], [], [])
238# TOSA_CONV2D_BACKPROP_INDICES = TensorIndices([2], [1], [3])
239# TOSA_TRANSPOSE_CONV_INDICES = TensorIndices([0], [1], [3])
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200240TOSA_CONCAT_INDICES = TensorIndices([1, 2], [], [])
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200241# TOSA_SPLIT_IFM_INDICES = TensorIndices([1], [], [])
242# TOSA_BLOCK_LSTM_INDICES = TensorIndices([3], [4], [])
243
244
245tosa_operator_map = {
246 # TosaOp.UNKNOWN: (),
247 # TODO TosaOp.ARGMAX: (Op.ArgMax, axis_attrs, None),
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200248 TosaOp.AVG_POOL2D: (Op.AvgPool, pool_attrs, unary_quant_info, TOSA_IFM_INDICES),
249 TosaOp.CONV2D: (Op.Conv2DBias, conv_attrs, conv_quant_info, TOSA_IFM_WEIGHTS_BIAS_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200250 # TODO TosaOp.CONV3D:
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200251 TosaOp.DEPTHWISE_CONV2D: (Op.DepthwiseConv2DBias, conv_attrs, conv_quant_info, TOSA_IFM_WEIGHTS_BIAS_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200252 TosaOp.FULLY_CONNECTED: (Op.FullyConnected, None, conv_quant_info, TOSA_IFM_WEIGHTS_BIAS_INDICES),
253 # TODO TosaOp.MATMUL:
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200254 TosaOp.MAX_POOL2D: (Op.MaxPool, pool_attrs, None, TOSA_IFM_INDICES),
255 # TODO TosaOp.TRANSPOSE_CONV2D: (Op.Conv2DBackpropInput, transpose_conv_attrs, conv_quant_info)
Patrik Gustavsson5e26eda2021-06-30 09:07:16 +0200256 TosaOp.CLAMP: (Op.Clamp, clamp_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200257 TosaOp.RELUN: (Op.ReluN, relun_attrs, None, TOSA_IFM_INDICES),
258 # TODO TosaOp.SIGMOID
259 # TODO TosaOp.TANH
260 TosaOp.ADD: (Op.Add, None, None, TOSA_IFM_IFM2_INDICES),
261 TosaOp.ARITHMETIC_RIGHT_SHIFT: (Op.SHR, ars_attrs, None, TOSA_IFM_IFM2_INDICES),
262 # TODO TosaOp.BITWISE_AND
263 # TODO TosaOp.BITWISE_OR
264 # TODO TosaOp.BITWISE_XOR
Patrik Gustavsson85f61172021-10-01 08:15:06 +0200265 # TODO TosaOp.INTDIV
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200266 # TODO TosaOp.LOGICAL_AND
267 # TODO TosaOp.LOGICAL_LEFT_SHIFT
268 # TODO TosaOp.LOGICAL_RIGHT_SHIFT
269 # TODO TosaOp.LOGICAL_OR
270 # TODO TosaOp.LOGICAL_XOR
271 # TODO TosaOp.MAXIMUM
272 # TODO TosaOp.MINIMUM
Patrik Gustavssonb081d672021-08-25 13:49:25 +0200273 TosaOp.MUL: (Op.Mul, mul_attrs, None, TOSA_IFM_IFM2_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200274 # TODO TosaOp.POW
275 TosaOp.SUB: (Op.Sub, None, None, TOSA_IFM_IFM2_INDICES),
Patrik Gustavssonf436ada2021-09-14 14:56:48 +0200276 # TODO is table content in input[1] always constant?
277 TosaOp.TABLE: (Op.Table, None, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200278 # TODO TosaOp.ABS
279 # TODO TosaOp.BITWISE_NOT
280 # TODO TosaOp.CEIL
281 # TODO TosaOp.CLZ
282 # TODO TosaOp.EXP
283 # TODO TosaOp.FLOOR
284 # TODO TosaOp.LOG
285 # TODO TosaOp.LOGICAL_NOT
286 # TODO TosaOp.NEGATE
287 # TODO TosaOp.RECIPROCAL
288 # TODO TosaOp.RSQRT
289 # TODO TosaOp.SELECT
290 # TODO TosaOp.EQUAL
291 # TODO TosaOp.GREATER
292 # TODO TosaOp.GREATER_EQUAL
293 # TODO TosaOp.REDUCE_ANY
294 # TODO TosaOp.REDUCE_ALL
295 # TODO TosaOp.REDUCE_MAX
296 # TODO TosaOp.REDUCE_MIN
297 # TODO TosaOp.REDUCE_PRODUCT
298 # TODO TosaOp.REDUCE_SUM
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200299 TosaOp.CONCAT: (Op.Concat, axis_attrs, None, TOSA_CONCAT_INDICES),
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200300 # TODO Is the padding intended to be dynamic input, TOSA spec state it as attribute
301 # Handled as for TFLite for now
302 TosaOp.PAD: (Op.Pad, None, pad_quant_info, TOSA_IFM_INDICES),
Patrik Gustavssondf995102021-08-23 15:33:59 +0200303 TosaOp.RESHAPE: (Op.Reshape, reshape_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200304 # TODO TosaOp.REVERSE
Patrik Gustavssonf1580f02021-09-01 12:43:02 +0200305 TosaOp.SLICE: (Op.SplitSliceRead, slice_attrs, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200306 # TODO TosaOp.TILE
Patrik Gustavssone2bfa7e2021-09-08 15:04:11 +0200307 TosaOp.TRANSPOSE: (
308 Op.Transpose,
309 None,
310 None,
311 TOSA_IFM_IFM2_INDICES,
312 ), # TODO Is the perms intended to be dynamic input, TOSA spec state it as attribute
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200313 # TODO TosaOp.GATHER
314 # TODO TosaOp.SCATTER
315 # TODO TosaOp.RESIZE
316 # TODO TosaOp.CAST
317 TosaOp.RESCALE: (Op.Rescale, rescale_attrs, None, TOSA_IFM_INDICES),
318 TosaOp.CONST: (Op.Const, None, None, TOSA_NO_INDICES),
Patrik Gustavssonef3ebdd2021-10-01 11:10:25 +0200319 TosaOp.IDENTITY: (Op.Identity, None, None, TOSA_IFM_INDICES),
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200320 # TODO TosaOp.CUSTOM
321 # TODO TosaOp.COND_IF
322 # TODO TosaOp.WHILE_LOOP
323}
324
325tosa_operator_inv_map = {v[0]: (k, v[1]) for k, v in tosa_operator_map.items()}
326
Tim Halla3fe6652022-03-03 17:43:16 +0000327tosa_operator_name_map = {v: k for k, v in vars(TosaOp).items()}
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200328
329
330# TODO will return UNKNOWN for the once that have not yet been defined in tosa_operator_map
Tim Halla3fe6652022-03-03 17:43:16 +0000331def optype_to_tosa_op_type(op_type: Op):
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200332 if op_type in tosa_operator_inv_map:
Tim Halla3fe6652022-03-03 17:43:16 +0000333 return tosa_operator_name_map[tosa_operator_inv_map[op_type][0]]
Patrik Gustavsson8f1f9aa2021-06-28 07:41:58 +0200334 else:
335 return TosaOp.UNKNOWN