blob: 807785a534661ff85faa8800f986cacfdf23a80a [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"
Michele Di Giorgio9c700372020-01-08 11:33:44 +000027#include "arm_compute/core/Validate.h"
Michalis Spyrouebcebf12020-10-21 00:04:14 +010028#include "src/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ScaleKernel.h"
29#include "src/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel.h"
30#include "src/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel.h"
31#include "src/core/NEON/kernels/NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel.h"
Gian Marcoe75a02b2017-11-08 12:24:09 +000032
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010033namespace arm_compute
34{
Michalis Spyrouebcebf12020-10-21 00:04:14 +010035NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint::~NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint() = default;
36
Gian Marco58c57942017-11-28 09:10:03 +000037void NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift,
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000038 int result_offset_after_shift, int min, int max)
Gian Marco58c57942017-11-28 09:10:03 +000039{
Georgios Pinitas40f51a62020-11-21 03:04:18 +000040 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel>();
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000041 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
Gian Marco58c57942017-11-28 09:10:03 +000042 _kernel = std::move(k);
43}
44
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000045Status NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
Gian Marco58c57942017-11-28 09:10:03 +000046{
Georgios Pinitasbb081ca2018-11-08 10:22:01 +000047 return NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel::validate(input, bias, output, min, max);
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010048}
49
Michalis Spyrouebcebf12020-10-21 00:04:14 +010050NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint::~NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint() = default;
51
Georgios Pinitas448a81f2019-11-21 14:10:25 +000052void NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift,
53 int result_offset_after_shift, int min, int max)
54{
Georgios Pinitas40f51a62020-11-21 03:04:18 +000055 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel>();
Georgios Pinitas448a81f2019-11-21 14:10:25 +000056 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
57 _kernel = std::move(k);
58}
59
60Status NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
61{
62 return NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel::validate(input, bias, output, min, max);
63}
64
Michalis Spyrouebcebf12020-10-21 00:04:14 +010065NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint::~NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint() = default;
66
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010067void NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint::configure(const ITensor *input, const ITensor *bias, ITensor *output, int result_fixedpoint_multiplier, int result_shift, int min, int max)
68{
Georgios Pinitas40f51a62020-11-21 03:04:18 +000069 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel>();
Gian Marco Iodicebc415af2019-06-13 15:58:32 +010070 k->configure(input, bias, output, result_fixedpoint_multiplier, result_shift, min, max);
71 _kernel = std::move(k);
72}
73
74Status NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPoint::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, int min, int max)
75{
76 return NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel::validate(input, bias, output, min, max);
77}
Michele Di Giorgio9c700372020-01-08 11:33:44 +000078
Michalis Spyrouebcebf12020-10-21 00:04:14 +010079NEGEMMLowpOutputStage::~NEGEMMLowpOutputStage() = default;
80
Michele Di Giorgio9c700372020-01-08 11:33:44 +000081void NEGEMMLowpOutputStage::configure(const ITensor *input, const ITensor *bias, ITensor *output, const GEMMLowpOutputStageInfo &info)
82{
83 // Perform validate step
84 ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
85 ARM_COMPUTE_ERROR_THROW_ON(NEGEMMLowpOutputStage::validate(input->info(), bias != nullptr ? bias->info() : nullptr, output->info(), info));
86
Luca Foschiani4b869532020-02-13 15:07:36 +000087 switch(info.type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +000088 {
Luca Foschiani4b869532020-02-13 15:07:36 +000089 case GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT:
Michele Di Giorgio9c700372020-01-08 11:33:44 +000090 {
Luca Foschiani4b869532020-02-13 15:07:36 +000091 switch(info.output_data_type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +000092 {
Luca Foschiani4b869532020-02-13 15:07:36 +000093 case DataType::QASYMM8:
94 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +000095 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel>();
Luca Foschiani4b869532020-02-13 15:07:36 +000096 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::QASYMM8_SIGNED:
101 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000102 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel>();
Luca Foschiani4b869532020-02-13 15:07:36 +0000103 k->configure(input, bias, output, info.gemmlowp_multiplier, info.gemmlowp_shift, info.gemmlowp_offset, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
104 _kernel = std::move(k);
105 break;
106 }
107 case DataType::QSYMM16:
108 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000109 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel>();
Luca Foschiani4b869532020-02-13 15:07:36 +0000110 k->configure(input, bias, output, info.gemmlowp_multiplier, info.gemmlowp_shift, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
111 _kernel = std::move(k);
112 break;
113 }
114 default:
115 {
116 ARM_COMPUTE_ERROR("Unsupported output data type.");
117 break;
118 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000119 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000120 break;
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000121 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000122 case GEMMLowpOutputStageType::QUANTIZE_DOWN:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000123 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000124 switch(info.output_data_type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000125 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000126 case DataType::QASYMM8:
127 case DataType::QASYMM8_SIGNED:
128 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000129 auto k = std::make_unique<NEGEMMLowpQuantizeDownInt32ScaleKernel>();
Luca Foschiani4b869532020-02-13 15:07:36 +0000130 k->configure(input, bias, output, &info);
131 _kernel = std::move(k);
132 break;
133 }
134 default:
135 {
136 ARM_COMPUTE_ERROR("Unsupported output data type.");
137 break;
138 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000139 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000140 break;
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000141 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000142 default:
143 ARM_COMPUTE_ERROR("Unsupported GEMMLowpOutputStage type.");
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000144 }
145}
146
147Status NEGEMMLowpOutputStage::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const GEMMLowpOutputStageInfo &info)
148{
149 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
150 ARM_COMPUTE_RETURN_ERROR_ON_MSG(output->data_type() == DataType::UNKNOWN, "NEGEMMLowpQuantizeDownScaleByFixedPoint cannot be used with UNKNOWN output data type.");
151 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::QSYMM16);
152
153 ARM_COMPUTE_RETURN_ERROR_ON((info.type != GEMMLowpOutputStageType::QUANTIZE_DOWN) && (info.type != GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT));
154
Luca Foschiani4b869532020-02-13 15:07:36 +0000155 switch(info.type)
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000156 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000157 case GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000158 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000159 switch(output->data_type())
160 {
161 case DataType::QASYMM8:
162 return NEGEMMLowpQuantizeDownInt32ToUint8ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
163 case DataType::QASYMM8_SIGNED:
164 return NEGEMMLowpQuantizeDownInt32ToInt8ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
165 case DataType::QSYMM16:
166 return NEGEMMLowpQuantizeDownInt32ToInt16ScaleByFixedPointKernel::validate(input, bias, output, info.gemmlowp_min_bound, info.gemmlowp_max_bound);
167 default:
168 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported output data type.");
169 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000170 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000171 case GEMMLowpOutputStageType::QUANTIZE_DOWN:
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000172 {
Luca Foschiani4b869532020-02-13 15:07:36 +0000173 switch(output->data_type())
174 {
175 case DataType::QASYMM8:
176 case DataType::QASYMM8_SIGNED:
177 return NEGEMMLowpQuantizeDownInt32ScaleKernel::validate(input, bias, output, &info);
178 default:
179 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported output data type.");
180 }
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000181 }
Luca Foschiani4b869532020-02-13 15:07:36 +0000182 default:
183 return ARM_COMPUTE_CREATE_ERROR(ErrorCode::RUNTIME_ERROR, "Unsupported GEMMLowpOutputStage type.");
Michele Di Giorgio9c700372020-01-08 11:33:44 +0000184 }
185}
Gian Marco Iodicebc415af2019-06-13 15:58:32 +0100186} // namespace arm_compute