blob: 25dc801bcc0f49659b42755cd40d2127028e45f7 [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.
Louis Verhaard0b8268a2020-08-05 16:11:29 +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.
16# Description:
17# Utilities used in vela unit tests
18import numpy as np
19
20from ethosu.vela import architecture_features
21from ethosu.vela.data_type import DataType
Louis Verhaardc822d622021-03-11 14:59:06 +010022from ethosu.vela.nn_graph import Graph
23from ethosu.vela.nn_graph import PassPlacement
Louis Verhaard0b8268a2020-08-05 16:11:29 +020024from ethosu.vela.nn_graph import Subgraph
Dwight Lidman0dd21c72020-11-24 13:45:50 +010025from ethosu.vela.operation import Op
Louis Verhaard0b8268a2020-08-05 16:11:29 +020026from ethosu.vela.operation import Operation
27from ethosu.vela.tensor import create_const_tensor
Dwight Lidman8359a472020-09-28 15:53:40 +020028from ethosu.vela.tensor import QuantizationParameters
Louis Verhaard0b8268a2020-08-05 16:11:29 +020029from ethosu.vela.tensor import Tensor
30
31
32def create_arch():
Louis Verhaard52078302020-11-18 13:35:06 +010033 return architecture_features.create_default_arch(architecture_features.Accelerator.Ethos_U55_128)
Louis Verhaard0b8268a2020-08-05 16:11:29 +020034
35
Michael McGeagh65fd9982020-10-20 11:49:28 +010036def default_quant_params():
37 qp = QuantizationParameters()
38 qp.scale_f32 = np.float32(1)
39 qp.zero_point = 0
40 return qp
41
42
Dwight Lidman8359a472020-09-28 15:53:40 +020043def create_elemwise_op(
Michael McGeagh65fd9982020-10-20 11:49:28 +010044 op_type,
Dwight Lidman8359a472020-09-28 15:53:40 +020045 name,
46 ifm_shape,
47 ifm2_shape,
48 ofm_shape,
49 datatype=DataType.uint8,
Michael McGeagh65fd9982020-10-20 11:49:28 +010050 ifm_quant=default_quant_params(),
51 ifm2_quant=default_quant_params(),
52 ofm_quant=default_quant_params(),
Dwight Lidman8359a472020-09-28 15:53:40 +020053):
Louis Verhaard0b8268a2020-08-05 16:11:29 +020054 # Creates elementwise operation with constant IFM/IFM2
55 if datatype.size_in_bytes() == 1:
56 np_type = np.uint8
57 elif datatype.size_in_bytes() == 2:
58 np_type = np.int16
59 else:
60 np_type = np.int32
Michael McGeagh65fd9982020-10-20 11:49:28 +010061 op = Operation(op_type, name)
Dwight Lidman8359a472020-09-28 15:53:40 +020062 op.add_input_tensor(
63 create_const_tensor(name + "_ifm", ifm_shape, datatype, np.zeros(ifm_shape), np_type, quantization=ifm_quant)
64 )
Michael McGeagh65fd9982020-10-20 11:49:28 +010065 if ifm2_shape is not None:
66 op.add_input_tensor(
67 create_const_tensor(
68 name + "_ifm2", ifm2_shape, datatype, np.zeros(ifm2_shape), np_type, quantization=ifm2_quant
69 )
Dwight Lidman8359a472020-09-28 15:53:40 +020070 )
Louis Verhaard0b8268a2020-08-05 16:11:29 +020071 ofm = Tensor(ofm_shape, datatype, name + "_ofm")
Dwight Lidman8359a472020-09-28 15:53:40 +020072 ofm.quantization = ofm_quant
Louis Verhaard0b8268a2020-08-05 16:11:29 +020073 op.set_output_tensor(ofm)
Patrik Gustavsson2349d422020-12-01 16:02:29 +010074 op.set_ifm_ofm_shapes()
75
Louis Verhaard0b8268a2020-08-05 16:11:29 +020076 return op
77
78
Dwight Lidmanc7187432020-11-16 17:40:46 +010079def create_op_with_quant_tensors(
patrik.gustavssoneeb85152020-12-21 17:10:40 +000080 op_type, ifm_shape, ofm_shape, weights_shape=None, bias_shape=None, datatype=DataType.uint8, set_ifm_ofm_shapes=True
Dwight Lidmanc7187432020-11-16 17:40:46 +010081):
Michael McGeagh1f951fc2020-10-14 09:30:02 +010082 ifm = Tensor(ifm_shape, datatype, "in")
Michael McGeagh65fd9982020-10-20 11:49:28 +010083 ifm.quantization = default_quant_params()
Michael McGeagh1f951fc2020-10-14 09:30:02 +010084 ofm = Tensor(ofm_shape, datatype, "out")
Michael McGeagh65fd9982020-10-20 11:49:28 +010085 ofm.quantization = default_quant_params()
Michael McGeagh1f951fc2020-10-14 09:30:02 +010086 op = Operation(op_type, "op")
87 op.add_input_tensor(ifm)
88 op.set_output_tensor(ofm)
89 # Optional weight tensor
90 if weights_shape is not None:
91 if datatype.size_in_bytes() == 1:
92 np_type = np.uint8
93 elif datatype.size_in_bytes() == 2:
94 np_type = np.int16
95 else:
96 np_type = np.int32
Michael McGeagh65fd9982020-10-20 11:49:28 +010097 qp = default_quant_params()
Dwight Lidman0dd21c72020-11-24 13:45:50 +010098 if op.type is not Op.FullyConnected:
99 qp.zero_point = np.zeros(weights_shape)
Michael McGeagh1f951fc2020-10-14 09:30:02 +0100100 weights = create_const_tensor(
101 "weights", weights_shape, datatype, np.zeros(weights_shape), np_type, quantization=qp
102 )
103 op.add_input_tensor(weights)
Dwight Lidmanc7187432020-11-16 17:40:46 +0100104 # Optional bias tensor
105 if bias_shape is not None:
106 qp = default_quant_params()
Dwight Lidman0dd21c72020-11-24 13:45:50 +0100107 if op.type is not Op.FullyConnected:
108 qp.zero_point = np.zeros(bias_shape)
Dwight Lidmanc7187432020-11-16 17:40:46 +0100109 bias = create_const_tensor("bias", bias_shape, DataType.int32, np.zeros(bias_shape), np.int32, quantization=qp)
110 op.add_input_tensor(bias)
Patrik Gustavsson2349d422020-12-01 16:02:29 +0100111
patrik.gustavssoneeb85152020-12-21 17:10:40 +0000112 if set_ifm_ofm_shapes:
113 op.set_ifm_ofm_shapes()
114
Michael McGeagh1f951fc2020-10-14 09:30:02 +0100115 return op
116
117
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100118def create_op(op_type, inputs, output, attrs=None, set_ifm_ofm_shapes=True):
Louis Verhaardfa2f92a2020-09-21 11:56:18 +0200119 op = Operation(op_type, output.name + "_op")
Louis Verhaardae2d5532020-12-11 17:19:54 +0100120 for input in inputs:
121 op.add_input_tensor(input)
122 op.set_output_tensor(output)
Michael McGeagh6f725262020-12-03 15:21:36 +0000123 if attrs is not None:
124 op.attrs = attrs
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100125 if set_ifm_ofm_shapes:
126 op.set_ifm_ofm_shapes()
Louis Verhaardfa2f92a2020-09-21 11:56:18 +0200127 return op
128
129
Louis Verhaard0b8268a2020-08-05 16:11:29 +0200130def create_subgraph(op_list):
131 # Creates subgraph using the given list of operations
132 sg = Subgraph()
Louis Verhaardc822d622021-03-11 14:59:06 +0100133 sg.placement = PassPlacement.Npu
Louis Verhaard0b8268a2020-08-05 16:11:29 +0200134 all_inputs = set(tens for op in op_list for tens in op.inputs)
135 # Reversing, so that the resulting subgraph has same order as op_list
136 for op in op_list[::-1]:
137 for tens in op.outputs:
138 if tens not in all_inputs and tens not in sg.output_tensors:
139 sg.output_tensors.append(tens)
140 return sg
Louis Verhaardc822d622021-03-11 14:59:06 +0100141
142
143def create_graph(op_list):
144 # Creates subgraph using the given list of operations
145 nng = Graph()
146 sg = create_subgraph(op_list)
147 nng.subgraphs.append(sg)
148 return nng