diff options
author | Eric Kunze <eric.kunze@arm.com> | 2023-07-18 15:20:53 -0700 |
---|---|---|
committer | Eric Kunze <eric.kunze@arm.com> | 2023-08-17 09:32:28 -0700 |
commit | fb0284e2912bd5fd73bf6f476901490e04c330a2 (patch) | |
tree | 1784e40ad84a91e751679a4cbdf6cd33be1eefdb /chapters/type_conversion.adoc | |
parent | b5b067819e5de11153b41cf3d26da4f3f9dd23e8 (diff) | |
download | specification-fb0284e2912bd5fd73bf6f476901490e04c330a2.tar.gz |
Change TOSA specification to signless types
Integer inputs and outputs to TOSA operators are now defined as signless
values. In most instances the operator will used signed arithmetic as
indicated in previous versions of the specification resulting in little
functional change to the specification.
New attributes have been added to the RESCALE operator to indicate
whether the input and output values should be treated as signed or unsigned.
Explicit use of static_cast, sign_extend, zero_extend and truncate are added
to the pseudocode to avoid ambiguity.
Change-Id: I71c67d3e5aeaabc418c768f821fce6ee3eebb65b
Diffstat (limited to 'chapters/type_conversion.adoc')
-rw-r--r-- | chapters/type_conversion.adoc | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/chapters/type_conversion.adoc b/chapters/type_conversion.adoc index 415c5d9..90aca2d 100644 --- a/chapters/type_conversion.adoc +++ b/chapters/type_conversion.adoc @@ -1,7 +1,7 @@ // // This confidential and proprietary software may be used only as // authorised by a licensing agreement from ARM Limited -// (C) COPYRIGHT 2020-2022 ARM Limited +// (C) COPYRIGHT 2020-2023 ARM Limited // ALL RIGHTS RESERVED // The entire notice above must be reproduced on all authorised // copies and copies may only be made to the extent permitted @@ -29,7 +29,7 @@ for_each(index in shape) { } else if (in_t == fp16_t || in_t == bf16_t || in_t == fp32_t) { out = apply_clip<out_t>(round_to_nearest_int(in), minimum<out_t>, maximum<out_t>); } else if (sizeof(out_t) >= sizeof(in_t)) { - out = sign_extend(in); + out = sign_extend<out_t>(in); } else { out = truncate(in); } @@ -49,24 +49,49 @@ for_each(index in shape) { // uint16 values can have zero_point 0 or 32768 // int8/uint8 can have zero point within their valid range // No other types can have zero point != 0 - ERROR_IF(in_t != int8_t && - in_t != uint8_t && - in_t != uint16_t && input_zp != 0); - ERROR_IF(out_t != int8_t && - out_t != uint8_t && - out_t != uint16_t && output_zp != 0); - ERROR_IF(in_t == uint16_t && input_zp != 0 && input_zp != 32768); - ERROR_IF(out_t == uint16_t && output_zp != 0 && output_zp != 32768); - ERROR_IF(scale32 && in_t == int48_t); + ERROR_IF(in_t != i8_t && + (in_t != i16_t || input_unsigned == False) && input_zp != 0); + ERROR_IF(out_t != i8_t && + (out_t != i16_t || output_unsigned == False) && output_zp != 0); + ERROR_IF(in_t == i16_t && input_unsigned == True && input_zp != 0 && input_zp != 32768); + ERROR_IF(out_t == i16_t && output_unsigned == True && output_zp != 0 && output_zp != 32768); + ERROR_IF(scale32 && in_t == i48_t); ERROR_IF(!scale32 && double_round); - int48_t value = tensor_read<in_t>(input, shape, index); - value = value - input_zp; + ERROR_IF(in_t == i16_t && out_t == i32_t && input_unsigned); + ERROR_IF(in_t == i32_t && out_t == i16_t && output_unsigned); + + in_t in_value = tensor_read<in_t>(input, shape, index); + + int48_t value, extended_in_zp; + if (input_unsigned) { + value = zero_extend<int48_t>(in_value); + extended_in_zp = zero_extend<int48_t>(input_zp); + } + else { + value = sign_extend<int48_t>(value); + extended_in_zp = sign_extend<int48_t>(input_zp); + } + + value = value - extended_in_zp; int c = (per_channel) ? index[rank(input) - 1] : 0; int32_t result = (scale32) ? apply_scale_32(value, multiplier[c], shift[c], double_round) : apply_scale_16(value, multiplier[c], shift[c]); - result = apply_add<int32_t>(result, output_zp); - out_t out = (out_t)apply_clip<int32_t>(result, minimum<out_t>, maximum<out_t>); + + if (output_unsigned) { + int32_t extended_out_zp = zero_extend<int32_t>(output_zp); + result = apply_add_s<int32_t>(result, extended_out_zp); + out_t out = static_cast<out_t>(apply_clip<int32_t>(result, + minimum_u<out_t>, + maximum_u<out_t>)); + } + else { + int32_t extended_out_zp = sign_extend<int32_t>(output_zp); + result = apply_add_s<int32_t>(result, extended_out_zp); + out_t out = static_cast<out_t>(apply_clip<int32_t>(result, + minimum_s<out_t>, + maximum_s<out_t>)); + } tensor_write<out_t>(output, shape, index, out); } ---- |