blob: 239a8e668a91e447be5b83e2d63051c3d6729ced [file] [log] [blame]
Gian Marcoe75a02b2017-11-08 12:24:09 +00001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 Arm Limited.
Gian Marcoe75a02b2017-11-08 12:24:09 +00003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/runtime/NEON/functions/NEGEMMLowpOutputStage.h"
25
26#include "arm_compute/core/ITensor.h"
Luca Foschiani4b869532020-02-13 15:07:36 +000027#include "arm_compute/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ScaleKernel.h"
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010028#include "arm_compute/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel.h"
Georgios Pinitas448a81f2019-11-21 14:10:25 +000029#include "arm_compute/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel.h"
Gian Marco58c57942017-11-28 09:10:03 +000030#include "arm_compute/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel.h"
Michele Di Giorgio9c700372020-01-08 11:33:44 +000031#include "arm_compute/core/Validate.h"
Matthew Bentham758b5ba2020-03-05 23:37:48 +000032#include "support/MemorySupport.h"
Gian Marcoe75a02b2017-11-08 12:24:09 +000033
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010034namespace arm_compute
35{
Gian Marco58c57942017-11-28 09:10:03 +000036void NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift,
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000037 int result_offset_after_shift, int min, int max)
Gian Marco58c57942017-11-28 09:10:03 +000038{
39 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel>();
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000040 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
Gian Marco58c57942017-11-28 09:10:03 +000041 _kernel = std::move(k);
42}
43
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000044Status NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
Gian Marco58c57942017-11-28 09:10:03 +000045{
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000046 return NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel::validate(input, bias, output, min, max);
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010047}
48
Georgios Pinitas448a81f2019-11-21 14:10:25 +000049void NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift,
50 int result_offset_after_shift, int min, int max)
51{
52 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel>();
53 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
54 _kernel = std::move(k);
55}
56
57Status NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
58{
59 return NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel::validate(input, bias, output, min, max);
60}
61
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010062void NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift, int min, int max)
63{
64 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel>();
65 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, min, max);
66 _kernel = std::move(k);
67}
68
69Status NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
70{
71 return NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel::validate(input, bias, output, min, max);
72}
Michele Di Giorgio9c700372020-01-08 11:33:44 +000073
74void NEGEMMLowpOutputStage::configure(const ITensor *input, const ITensor *bias, ITensor *output, const GEMMLowpOutputStageInfo &info)
75{
76 // Perform validate step
77 ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
78 ARM_COMPUTE_ERROR_THROW_ON(NEGEMMLowpOutputStage::validate(input->info(), bias != nullptr ? bias->info() : nullptr, output->info(), info));
79
Luca Foschiani4b869532020-02-13 15:07:36 +000080 switch(info.type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +000081 {
Luca Foschiani4b869532020-02-13 15:07:36 +000082 case GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT:
Michele Di Giorgio9c700372020-01-08 11:33:44 +000083 {
Luca Foschiani4b869532020-02-13 15:07:36 +000084 switch(info.output_data_type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +000085 {
Luca Foschiani4b869532020-02-13 15:07:36 +000086 case DataType::QASYMM8:
87 {
88 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel>();
89 k->configure(input, bias, output, info.gemmlowp_multiplier, info.gemmlowp_shift, info.gemmlowp_offset, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
90 _kernel = std::move(k);
91 break;
92 }
93 case DataType::QASYMM8_SIGNED:
94 {
95 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel>();
96 k->configure(input, bias, output, info.gemmlowp_multiplier, info.gemmlowp_shift, info.gemmlowp_offset, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
97 _kernel = std::move(k);
98 break;
99 }
100 case DataType::QSYMM16:
101 {
102 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel>();
103 k->configure(input, bias, output, info.gemmlowp_multiplier, info.gemmlowp_shift, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
104 _kernel = std::move(k);
105 break;
106 }
107 default:
108 {
109 ARM_COMPUTE_ERROR("Unsupported output data type.");
110 break;
111 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000112 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000113 break;
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000114 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000115 case GEMMLowpOutputStageType::QUANTIZE_DOWN:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000116 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000117 switch(info.output_data_type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000118 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000119 case DataType::QASYMM8:
120 case DataType::QASYMM8_SIGNED:
121 {
122 auto k = arm_compute::support::cpp14::make_unique<NEGEMMLowpQuantizeDownInt32ScaleKernel>();
123 k->configure(input, bias, output, &info);
124 _kernel = std::move(k);
125 break;
126 }
127 default:
128 {
129 ARM_COMPUTE_ERROR("Unsupported output data type.");
130 break;
131 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000132 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000133 break;
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000134 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000135 default:
136 ARM_COMPUTE_ERROR("Unsupported GEMMLowpOutputStage type.");
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000137 }
138}
139
140Status NEGEMMLowpOutputStage::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const GEMMLowpOutputStageInfo &info)
141{
142 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
143 ARM_COMPUTE_RETURN_ERROR_ON_MSG(output->data_type() == DataType::UNKNOWN, "NEGEMMLowpQuantizeDownScaleByFixedPoint cannot be used with UNKNOWN output data type.");
144 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::QSYMM16);
145
146 ARM_COMPUTE_RETURN_ERROR_ON((info.type != GEMMLowpOutputStageType::QUANTIZE_DOWN) && (info.type != GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT));
147
Luca Foschiani4b869532020-02-13 15:07:36 +0000148 switch(info.type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000149 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000150 case GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000151 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000152 switch(output->data_type())
153 {
154 case DataType::QASYMM8:
155 return NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
156 case DataType::QASYMM8_SIGNED:
157 return NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
158 case DataType::QSYMM16:
159 return NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
160 default:
161 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported output data type.");
162 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000163 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000164 case GEMMLowpOutputStageType::QUANTIZE_DOWN:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000165 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000166 switch(output->data_type())
167 {
168 case DataType::QASYMM8:
169 case DataType::QASYMM8_SIGNED:
170 return NEGEMMLowpQuantizeDownInt32ScaleKernel::validate(input, bias, output, &info);
171 default:
172 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported output data type.");
173 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000174 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000175 default:
176 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported GEMMLowpOutputStage type.");
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000177 }
178}
Gian Marco Iodicebc415af2019-06-13 15:58:32 +0100179} // namespace arm_compute