blob: acf35fe3f65a62a53b0d48c9500c1818df792cf9 [file] [log] [blame]
Rickard Bolinbc6ee582022-11-04 08:24:29 +00001# SPDX-FileCopyrightText: Copyright 2020-2021 Arm Limited and/or its affiliates <open-source-office@arm.com>
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.
Rickard Bolinbc6ee582022-11-04 08:24:29 +000016#
Louis Verhaard0b8268a2020-08-05 16:11:29 +020017# Description:
18# Utilities used in vela unit tests
19import numpy as np
20
21from ethosu.vela import architecture_features
22from ethosu.vela.data_type import DataType
Louis Verhaardc822d622021-03-11 14:59:06 +010023from ethosu.vela.nn_graph import Graph
24from ethosu.vela.nn_graph import PassPlacement
Louis Verhaard0b8268a2020-08-05 16:11:29 +020025from ethosu.vela.nn_graph import Subgraph
Dwight Lidman0dd21c72020-11-24 13:45:50 +010026from ethosu.vela.operation import Op
Louis Verhaard0b8268a2020-08-05 16:11:29 +020027from ethosu.vela.operation import Operation
28from ethosu.vela.tensor import create_const_tensor
Dwight Lidman8359a472020-09-28 15:53:40 +020029from ethosu.vela.tensor import QuantizationParameters
Louis Verhaard0b8268a2020-08-05 16:11:29 +020030from ethosu.vela.tensor import Tensor
31
32
33def create_arch():
Louis Verhaard52078302020-11-18 13:35:06 +010034 return architecture_features.create_default_arch(architecture_features.Accelerator.Ethos_U55_128)
Louis Verhaard0b8268a2020-08-05 16:11:29 +020035
36
Michael McGeagh65fd9982020-10-20 11:49:28 +010037def default_quant_params():
38 qp = QuantizationParameters()
39 qp.scale_f32 = np.float32(1)
40 qp.zero_point = 0
41 return qp
42
43
Dwight Lidman8359a472020-09-28 15:53:40 +020044def create_elemwise_op(
Michael McGeagh65fd9982020-10-20 11:49:28 +010045 op_type,
Dwight Lidman8359a472020-09-28 15:53:40 +020046 name,
47 ifm_shape,
48 ifm2_shape,
49 ofm_shape,
50 datatype=DataType.uint8,
Michael McGeagh65fd9982020-10-20 11:49:28 +010051 ifm_quant=default_quant_params(),
52 ifm2_quant=default_quant_params(),
53 ofm_quant=default_quant_params(),
Dwight Lidman8359a472020-09-28 15:53:40 +020054):
Louis Verhaard0b8268a2020-08-05 16:11:29 +020055 # Creates elementwise operation with constant IFM/IFM2
56 if datatype.size_in_bytes() == 1:
57 np_type = np.uint8
58 elif datatype.size_in_bytes() == 2:
59 np_type = np.int16
60 else:
61 np_type = np.int32
Michael McGeagh65fd9982020-10-20 11:49:28 +010062 op = Operation(op_type, name)
Dwight Lidman8359a472020-09-28 15:53:40 +020063 op.add_input_tensor(
64 create_const_tensor(name + "_ifm", ifm_shape, datatype, np.zeros(ifm_shape), np_type, quantization=ifm_quant)
65 )
Michael McGeagh65fd9982020-10-20 11:49:28 +010066 if ifm2_shape is not None:
67 op.add_input_tensor(
68 create_const_tensor(
69 name + "_ifm2", ifm2_shape, datatype, np.zeros(ifm2_shape), np_type, quantization=ifm2_quant
70 )
Dwight Lidman8359a472020-09-28 15:53:40 +020071 )
Louis Verhaard0b8268a2020-08-05 16:11:29 +020072 ofm = Tensor(ofm_shape, datatype, name + "_ofm")
Dwight Lidman8359a472020-09-28 15:53:40 +020073 ofm.quantization = ofm_quant
Louis Verhaard0b8268a2020-08-05 16:11:29 +020074 op.set_output_tensor(ofm)
Patrik Gustavsson2349d422020-12-01 16:02:29 +010075 op.set_ifm_ofm_shapes()
76
Louis Verhaard0b8268a2020-08-05 16:11:29 +020077 return op
78
79
Dwight Lidmanc7187432020-11-16 17:40:46 +010080def create_op_with_quant_tensors(
patrik.gustavssoneeb85152020-12-21 17:10:40 +000081 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 +010082):
Michael McGeagh1f951fc2020-10-14 09:30:02 +010083 ifm = Tensor(ifm_shape, datatype, "in")
Michael McGeagh65fd9982020-10-20 11:49:28 +010084 ifm.quantization = default_quant_params()
Michael McGeagh1f951fc2020-10-14 09:30:02 +010085 ofm = Tensor(ofm_shape, datatype, "out")
Michael McGeagh65fd9982020-10-20 11:49:28 +010086 ofm.quantization = default_quant_params()
Michael McGeagh1f951fc2020-10-14 09:30:02 +010087 op = Operation(op_type, "op")
88 op.add_input_tensor(ifm)
89 op.set_output_tensor(ofm)
90 # Optional weight tensor
91 if weights_shape is not None:
92 if datatype.size_in_bytes() == 1:
93 np_type = np.uint8
94 elif datatype.size_in_bytes() == 2:
95 np_type = np.int16
96 else:
97 np_type = np.int32
Michael McGeagh65fd9982020-10-20 11:49:28 +010098 qp = default_quant_params()
Dwight Lidman0dd21c72020-11-24 13:45:50 +010099 if op.type is not Op.FullyConnected:
100 qp.zero_point = np.zeros(weights_shape)
Michael McGeagh1f951fc2020-10-14 09:30:02 +0100101 weights = create_const_tensor(
102 "weights", weights_shape, datatype, np.zeros(weights_shape), np_type, quantization=qp
103 )
104 op.add_input_tensor(weights)
Dwight Lidmanc7187432020-11-16 17:40:46 +0100105 # Optional bias tensor
106 if bias_shape is not None:
107 qp = default_quant_params()
Dwight Lidman0dd21c72020-11-24 13:45:50 +0100108 if op.type is not Op.FullyConnected:
109 qp.zero_point = np.zeros(bias_shape)
Dwight Lidmanc7187432020-11-16 17:40:46 +0100110 bias = create_const_tensor("bias", bias_shape, DataType.int32, np.zeros(bias_shape), np.int32, quantization=qp)
111 op.add_input_tensor(bias)
Patrik Gustavsson2349d422020-12-01 16:02:29 +0100112
patrik.gustavssoneeb85152020-12-21 17:10:40 +0000113 if set_ifm_ofm_shapes:
114 op.set_ifm_ofm_shapes()
115
Michael McGeagh1f951fc2020-10-14 09:30:02 +0100116 return op
117
118
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100119def create_op(op_type, inputs, output, attrs=None, set_ifm_ofm_shapes=True):
Louis Verhaardfa2f92a2020-09-21 11:56:18 +0200120 op = Operation(op_type, output.name + "_op")
Louis Verhaardae2d5532020-12-11 17:19:54 +0100121 for input in inputs:
122 op.add_input_tensor(input)
123 op.set_output_tensor(output)
Michael McGeagh6f725262020-12-03 15:21:36 +0000124 if attrs is not None:
125 op.attrs = attrs
Patrik Gustavsson3a269202021-01-21 08:28:55 +0100126 if set_ifm_ofm_shapes:
127 op.set_ifm_ofm_shapes()
Louis Verhaardfa2f92a2020-09-21 11:56:18 +0200128 return op
129
130
Louis Verhaard0b8268a2020-08-05 16:11:29 +0200131def create_subgraph(op_list):
132 # Creates subgraph using the given list of operations
133 sg = Subgraph()
Louis Verhaardc822d622021-03-11 14:59:06 +0100134 sg.placement = PassPlacement.Npu
Louis Verhaard0b8268a2020-08-05 16:11:29 +0200135 all_inputs = set(tens for op in op_list for tens in op.inputs)
136 # Reversing, so that the resulting subgraph has same order as op_list
137 for op in op_list[::-1]:
138 for tens in op.outputs:
139 if tens not in all_inputs and tens not in sg.output_tensors:
140 sg.output_tensors.append(tens)
141 return sg
Louis Verhaardc822d622021-03-11 14:59:06 +0100142
143
144def create_graph(op_list):
145 # Creates subgraph using the given list of operations
146 nng = Graph()
147 sg = create_subgraph(op_list)
148 nng.subgraphs.append(sg)
149 return nng