| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- // Copyright 2022 Espressif Systems (Shanghai) PTE LTD
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "softmax_common.h"
- int32_t esp_nn_get_softmax_scratch_size_ansi(const int32_t width, const int32_t height)
- {
- (void) width;
- (void) height;
- return 0;
- }
- void esp_nn_set_softmax_scratch_buf_ansi(void *buffer)
- {
- (void) buffer;
- return;
- }
- void esp_nn_softmax_s8_ansi(const int8_t *input_data,
- const int32_t height,
- const int32_t width,
- const int32_t mult,
- const int32_t shift,
- const int32_t diff_min,
- int8_t *output_data)
- {
- // The representation chosen for the input to the exp() function is Q5.26.
- // We need to leave extra space since values that we skip might be as large as
- // -32 before multiplying by input mult, and therefore as large as
- // -16 afterwards. Note that exp(-8) is definitely not insignificant to
- // accumulation, but exp(-16) definitely is.
- #define ACCUM_BITS 12
- #define DIFF_BITS 5
- const int32_t mask = (1 << shift);
- int32_t col = 0;
- const int8_t *in_ptr = input_data;
- int8_t *out_ptr = output_data;
- for (int row_idx = 0; row_idx < height; row_idx++) {
- int8_t max_in_row = in_ptr[0];
- for (col = 1; col < width; col++) {
- max_in_row = max(max_in_row, in_ptr[col]);
- }
- int32_t input_diff = 0;
- int32_t sum_of_exps = 0;
- for (col = 0; col < width; col++) {
- input_diff = in_ptr[col] - max_in_row;
- if (input_diff >= diff_min) {
- const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult);
- const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled);
- sum_of_exps += DIV_POW2(exp_raw, ACCUM_BITS);
- }
- }
- const int32_t headroom_plus1 = esp_nn_clz32((uint32_t) sum_of_exps);
- const int32_t shifted_scale = ONE_OVER_ONE_X((sum_of_exps << headroom_plus1) - (1 << 31));
- const int32_t bits_over_unit = ACCUM_BITS - headroom_plus1 + 31 - sizeof(int8_t) * 8;
- for (col = 0; col < width; col++) {
- input_diff = in_ptr[col] - max_in_row;
- if (input_diff >= diff_min) {
- const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult);
- const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled);
- const int32_t shifted_output = SAT_HIGH_MUL(shifted_scale, exp_raw);
- const int32_t result = DIV_POW2(shifted_output, bits_over_unit) - 128;
- out_ptr[col] = (int8_t) esp_nn_saturate8(result);
- } else {
- out_ptr[col] = -128;
- }
- }
- in_ptr += width;
- out_ptr += width;
- }
- }
|