blob: 3922d13c6e00bb03bed31033a49e9721e5406f56 [file] [log] [blame]
Eric Kunze3309a532020-10-01 18:50:46 -07001//
2// This confidential and proprietary software may be used only as
3// authorised by a licensing agreement from ARM Limited
Eric Kunze18acfe32024-01-03 10:55:00 -08004// (C) COPYRIGHT 2020-2024 ARM Limited
Eric Kunze3309a532020-10-01 18:50:46 -07005// ALL RIGHTS RESERVED
6// The entire notice above must be reproduced on all authorised
7// copies and copies may only be made to the extent permitted
8// by a licensing agreement from ARM Limited.
9
10== Introduction
11
12=== Overview
13
Eric Kunzefa1b3242020-11-09 13:53:23 -080014Tensor Operator Set Architecture (TOSA) provides a set of whole-tensor
15operations commonly employed by Deep Neural Networks. The intent is to enable a
16variety of implementations running on a diverse range of processors, with the
17results at the TOSA level consistent across those implementations. Applications
18or frameworks which target TOSA can therefore be deployed on a wide range of
19different processors, such as SIMD CPUs, GPUs and custom hardware such as
20NPUs/TPUs, with defined accuracy and compatibility constraints. Most operators
21from the common ML frameworks (TensorFlow, PyTorch, etc.) should be expressible
22in TOSA. It is expected that there will be tools to lower from ML frameworks
23into TOSA.
24
25=== Goals
26
27The goals of TOSA include the following:
28
29* A minimal and stable set of tensor-level operators to which machine learning
30framework operators can be reduced.
31
32* Full support for both quantized integer and floating-point content.
33
34* Precise functional description of the behavior of every operator, including
35the treatment of their numerical behavior in the case of precision, saturation,
36scaling, and range as required by quantized datatypes.
37
38* Agnostic to any single high-level framework, compiler backend stack or
39particular target.
40
41* The detailed functional and numerical description enables precise code
42construction for a diverse range of targets – SIMD CPUs, GPUs and custom
43hardware such as NPUs/TPUs.
44
45=== Specification
46
47The TOSA Specification is written as AsciiDoc mark-up and developed in its raw
48mark-up form, managed through a git repository here:
Eric Kunzef9e5ba92022-05-26 16:38:40 -070049https://git.mlplatform.org/tosa/specification.git/.
50The specification is developed and versioned much like software.
51While the mark-up is legible and can be read fairly easily in its raw form, it is recommended to build or “render” the mark-up into PDF or HTML.
52To do this, please follow the instructions in the README.md in the root of the specification repository.
53
54=== Operator Selection Principles
55
56TOSA defines a set of primitive operators to which higher level operators can be lowered in a consistent way.
57To remain effective and efficient to implement, the set of operators must be constrained to a reasonably small set of primitive operations out of which others can be constructed.
58The following principles govern the selection of operators within TOSA.
59
60.Principles
61[cols="1,5,5"]
62|===
63|ID|Principle|Reason for this
64
65|P0
66|An operator shall be a primitive operation or building block that cannot be decomposed into simpler whole tensor operations.
67|If the operator can be broken down, then we should look at the component operators.
68
69|P1
70|An operator shall be a usable as a component out of which more complex operations can be constructed.
71|Single use operators have a high architectural cost and a more reusable version should be considered instead.
72
73|P2
74|Precision should be appropriate for the input and output data types.
75|Precision higher than that needed to calculate the result leads to extra implementation cost.
76
77|P3
78|Numerical definition of common sub-operations should be consistent between operators (for example: value scaling).
79|Consistent sub-operation definition reduces the operator implementation cost.
80
81|P4
Kevin Petit5333c252023-05-16 09:08:48 +010082|The valid input and output ranges for all arguments shall be specified.
Eric Kunzef9e5ba92022-05-26 16:38:40 -070083|Ranges are required to make consistent (numerically agreeing) implementations possible.
84
85|P5
86|Integer operators shall be implementable in a bit-exact form with good efficiency on CPU, GPU and hardware targets.
87|Reduces implementation cost and gives consistent inference results.
88|===
Eric Kunze3309a532020-10-01 18:50:46 -070089
90=== Profiles
91
Eric Kunzef9e5ba92022-05-26 16:38:40 -070092TOSA supports three profiles that enable efficient implementation on different classes of device.
93The Base Inference profile is intended for embedded integer/fixed-point designs performing inference only.
94The Main Inference profile is intended for general inference functionality including integer and floating-point data types.
95The Main Training profile adds training operators in addition to inference operators.
96This version of the specification covers the Base Inference and Main Inference profiles.
97Main Training profile is expected in a later version of the specification.
Eric Kunze3309a532020-10-01 18:50:46 -070098The following table summarizes the three profiles:
99
100.Profiles
101|===
102|Profile|Name|Integer Inference|Floating-point Inference|Training
103
104|Base Inference|TOSA-BI|Yes|No|No
105|Main Inference|TOSA-MI|Yes|Yes|No
106|Main Training|TOSA-MT|Yes|Yes|Yes
107|===
108
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000109=== Levels
110
Kevin Petit5333c252023-05-16 09:08:48 +0100111A TOSA level defines operator argument ranges that an implementation shall support.
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000112This is distinct from a profile that defines the operations and data-types supported.
113This version of the specification defines two TOSA levels:
114
Kevin Petit5333c252023-05-16 09:08:48 +0100115* No level : allows the full range of arguments specified by the operations according to the operation data types.
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000116* Level 8K : ranges are expected to be sufficient for applications with frame sizes up to 8K.
117
118Later versions of the specification may define additional levels.
119The following table defines the value ranges for Level 1.0.
120These ranges are checked using the LEVEL_CHECK() function with the operator descriptions.
121
122.Level maximums
Kevin Petit211c5f52023-04-26 16:25:52 +0100123include::{generated}/levels.adoc[]
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000124
Eric Kunze42229d02022-04-07 16:54:46 -0700125=== Status
126
127The TOSA specification is a work in progress.
128
129* The Base Inference profile should be considered to be near release quality, with conformance tests available.
130* The Main Inference profile has most of the expected operators in place, but is still subject to change.
131* The reference model and conformance tests do not yet support all of the floating point types that have been defined.
132* There is not currently a conformance test suite available for Main Inference.
133* Main Training profile is pre-alpha, significant work still needs to be done for the profile, and no conformance tests are available.
134
Dominic Symesca2a8542021-03-19 13:56:27 +0000135=== Compliance
136
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000137This section defines when a TOSA implementation is compliant to a given TOSA specification profile and level.
Dominic Symes5b936a32023-03-01 11:34:40 +0000138To be compliant an implementation must achieve the results and accuracy defined by this specification.
139TOSA also defines a set of conformance tests.
140A compliant implementation must pass the conformance tests.
141The conformance tests are not exhaustive, so an implementation that passes the conformance tests may not be compliant if there is a non-compliance that is undetected by the tests.
Dominic Symesca2a8542021-03-19 13:56:27 +0000142
Dominic Symesc386a052023-01-20 16:09:31 +0000143==== Base Inference Profile Compliance
Dominic Symesca2a8542021-03-19 13:56:27 +0000144
Eric Kunzea3eded02021-12-13 15:40:04 -0800145The <<Operator Graphs>> section of this specification defines a TOSA graph and the behavior defined for a TOSA graph.
146This behavior is captured in the pseudo-code function tosa_execute_graph().
Dominic Symesca2a8542021-03-19 13:56:27 +0000147For a given input graph (with attributes) and input tensors there are three possible tosa_graph_result values after executing the graph:
148
149* tosa_unpredictable: The result of the graph on the given inputs cannot be relied upon.
150* tosa_error: The graph does not meet the specification and is recognised as an illegal graph.
151* tosa_valid: The result is defined and predictable and the list of output tensors defines the result.
152
153An implementation is compliant to the TOSA Baseline Inference Profile if it matches the above results as follows:
154
155* For tosa_unpredictable, the implementation can return whatever result it chooses (including error)
156* For tosa_error, the implementation must return an error result (and there is no requirement on how much of the graph is executed, if any)
157* For tosa_valid, the implementation must execute the entire graph without error and return the result defined by this specification.
158
159In terms of psuedo-code, if *graph* is a TOSA graph consisting of Baseline Inference Profile operators and *input_list* is a list of input tensors then the following test must pass.
160
161[source,c++]
162----
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000163bool tosa_test_compliance(tosa_graph_t graph, tosa_list_t input_list, tosa_level_t level) {
Dominic Symesca2a8542021-03-19 13:56:27 +0000164 shape_list_t output_list_spec = tosa_allocate_list(tosa_output_shape(graph));
165 shape_list_t output_list_test = tosa_allocate_list(tosa_output_shape(graph));
Dominic Symes7b0f1c92023-07-20 14:26:38 +0100166 tosa_graph_result = tosa_valid; // result starts as valid
167 tosa_nesting_depth = 0; // if/while nesting level
Dominic Symese4d6a1b2022-11-04 18:00:03 +0000168 tosa_execute_graph(graph, input_list, output_list_spec, level);
Dominic Symesca2a8542021-03-19 13:56:27 +0000169 if (tosa_graph_result == tosa_unpredictable) {
170 return true; // No requirement to match an unpredictable result
171 }
172 result_test = execute_implementation_under_test(graph, input_list, output_list_test);
173 if (tosa_graph_result == tosa_error) {
174 return result_test == tosa_error; // result must be an error
175 }
176 if (exact_tensor_match(output_list_spec, output_list_test)) {
177 // Predictable bit-exact value match required
178 return true;
179 }
180 return false;
181}
182----
183
Dominic Symes5b936a32023-03-01 11:34:40 +0000184==== Main Inference Profile Compliance
Dominic Symesca2a8542021-03-19 13:56:27 +0000185
Dominic Symesc386a052023-01-20 16:09:31 +0000186A Main Inference compliant implementation must satisfy the following:
187
188* The implementation must meet <<Base Inference Profile Compliance>> for all Base inference complaint graphs
189* The implementation must support all Main Inference operations using the datatype fp32_t
190** The operations must meet the precision requirements of <<Main Inference precision requirements>>
191* The implementation must support all Main Inference operations using the datatype fp16_t
192** The operations must meet the precision requirements of <<Main Inference precision requirements>>
193** Note: These requirements allow fp16_t operations to be implemented using the fp32_t datatype
194* The implementation must support all Main Inference operations using the datatype bf16_t
195** The operations must meet the precision requirements of <<Main Inference precision requirements>>
196** Note: These requirements allow bf16_t operations to be implemented using the fp32_t datatype
197
198As with <<Base Inference Profile Compliance>> the pseudo-code function tosa_execute_graph() can return one of three possible results.
199A compliant implementation must satisfy the following:
Dominic Symesca2a8542021-03-19 13:56:27 +0000200
201* For a graph returning tosa_error the implementation must also return an error
202* For a graph returning tosa_valid the implementation must execute the entire graph without error
203* For a graph returning tosa_valid and consisting only of integer operators the results must match exactly
Dominic Symesca2a8542021-03-19 13:56:27 +0000204
Dominic Symesc386a052023-01-20 16:09:31 +0000205===== Main Inference precision requirements
206
Dominic Symesc237b7e2023-09-20 15:08:53 +0100207In a compliant implementation, individual floating-point operations within the graph must meet the accuracy bounds listed in the table following.
208In the table _ulp_ means unit of the last place.
209The function tosa_reference_check_fp() defines the error range permitted by a given number of units of last place in this specification.
Dominic Symesc386a052023-01-20 16:09:31 +0000210
211NOTE: The error criteria in this section are at an early draft stage and are likely to change during conformance test development.
212
213The following criteria apply to all operations:
214
215* If any input is a NaN and the result is floating-point then the result must be a NaN
216* If any input is a NaN and the operation is a comparison (greater, greater-equal, equal) then the result must be false
217* if any input is a NaN and the operation is conversion to an integer or boolean then the result is unpredictable
218
219[cols="1,3"]
220|===
221| Operation | Accuracy bound
222
Eric Kunze0ae7fd62023-09-26 17:29:43 -0700223| <<ARGMAX>>, <<MAX_POOL2D>>, <<CLAMP>>, <<MAXIMUM>>, <<MINIMUM>>, <<ABS>>, <<NEGATE>>, <<SELECT>>, <<REDUCE_MAX>>, <<REDUCE_MIN>>, <<CONST>>, <<IDENTITY>>
Dominic Symes5b936a32023-03-01 11:34:40 +0000224| Non NaN results must be exact.
Dominic Symesc386a052023-01-20 16:09:31 +0000225
226| <<EQUAL>>, <<GREATER>>, <<GREATER_EQUAL>>
227| The result must be exact with: +
228(1) The sign of the zero is ignored +
229(2) Infinities of the same sign compare as equal
230
231| <<CONV2D>>, <<CONV3D>>, <<DEPTHWISE_CONV2D>>, <<FULLY_CONNECTED>>, <<MATMUL>>, <<TRANSPOSE_CONV2D>>
232| Each output can be expressed as a dot product of two input vectors. +
233The dot product must meet the <<Dot product accuracy requirements>>
234
235| <<FFT2D>>, <<RFFT2D>>
Dominic Symes5b936a32023-03-01 11:34:40 +0000236| Each output can be expressed as a dot product of an input vector with a constant coefficient vector. +
Dominic Symesc386a052023-01-20 16:09:31 +0000237The dot product must meet the <<Dot product accuracy requirements>>
238
Dominic Symes5b936a32023-03-01 11:34:40 +0000239| <<ADD>>, <<MUL>>, <<SUB>>, <<CEIL>>, <<FLOOR>>
Dominic Symesc386a052023-01-20 16:09:31 +0000240| Floating-point result overflows must be set to infinity of the correct sign. +
241Floating-point result underflows must be set to zero of the correct sign. +
Dominic Symesc386a052023-01-20 16:09:31 +0000242Addition of infinites of different signs must produce a NaN. +
243Subtraction of infinities of the same sign must produce a NaN. +
244Multiplication of an infinity by a zero must produce a NaN. +
Dominic Symesc237b7e2023-09-20 15:08:53 +0100245Otherwise the result must be within 0.5 ulp of the mathematical result.
Dominic Symesc386a052023-01-20 16:09:31 +0000246
Dominic Symes5b936a32023-03-01 11:34:40 +0000247| <<CAST>>
248| Floating-point result overflows must be set to infinity of the correct sign. +
249Floating-point result underflows must be set to zero of the correct sign. +
250Cast from floating-point to integer result overflows must be saturated. +
Dominic Symesc237b7e2023-09-20 15:08:53 +0100251Cast from floating-point to integer must be rounded using round to nearest, ties to even, rounding mode. +
252Otherwise cast to floating-point must be within 0.5 ulp of the mathematical result.
Dominic Symes5b936a32023-03-01 11:34:40 +0000253
Dominic Symesc386a052023-01-20 16:09:31 +0000254| <<RECIPROCAL>>
255| If the input is a zero or the result overlows the output must be an infinity of the same sign. +
256If the input is an infinty or the result underflows the output must be a zero of the same sign. +
257Otherwise:the result must be within 1 ulp of the mathematical result.
258
259| <<RSQRT>>
260| If the input is less than zero the result must be a NaN. +
261Otherwise if the input is a zero the output must be an infinity of the same sign. +
Dominic Symesa46cf1d2023-11-07 11:46:16 +0000262Otherwise the result must be within 2 ulp of the mathematical result.
Dominic Symesc386a052023-01-20 16:09:31 +0000263
Dominic Symes2bc6c572023-11-30 10:56:33 +0000264| <<LOG>>, <<ERF>>
Dominic Symesc386a052023-01-20 16:09:31 +0000265| If the input to LOG is less than zero then the result must be a NaN. +
Dominic Symesc386a052023-01-20 16:09:31 +0000266If the result overflows the output must be an infinity of the correct sign. +
267If the result underflows the output must be a zero of the correct sign. +
268Otherwise the result must be within 5 ulp of the mathematical result.
269
Dominic Symesf791b442023-10-30 14:26:11 +0000270| <<EXP>>
271| Let `x` be an input element and `out_imp` the implementation output of `exp(x)`. +
272Let `out_ref` be the result of the fp64_t reference implementation of `exp(x)`. +
Dominic Symesa46cf1d2023-11-07 11:46:16 +0000273Let `err_bnd = abs(out_ref) * exp2(-normal_frac<in_out_t>) * (1+abs(x))` +
274Then `tosa_reference_check_fp_bnd<in_out_t>(out_imp, out_ref, err_bnd)` must be true
Dominic Symesf791b442023-10-30 14:26:11 +0000275
276| <<POW>>
Eric Kunze18acfe32024-01-03 10:55:00 -0800277| Let `x`, `y` be input elements from `input1` and `input2` respectively. +
278Let `out_imp` be the implementation output of `pow(x,y)`. +
279If `x` is less than zero and `y` is non-integral then the result must be a NaN. +
Dominic Symesf791b442023-10-30 14:26:11 +0000280Let `out_ref` be the result of the fp64_t reference implementation of `pow(x,y)`. +
Dominic Symesa46cf1d2023-11-07 11:46:16 +0000281Let `err_bnd = abs(out_ref) * exp2(-normal_frac<in_out_t>) * (1+abs(log(abs(x))*y))` +
282Then `tosa_reference_check_fp_bnd<in_out_t>(out_imp, out_ref, err_bnd)` must be true
Dominic Symesf791b442023-10-30 14:26:11 +0000283
Dominic Symes8754ec22023-12-08 17:45:31 +0000284| <<SIGMOID>>
Dominic Symes2bc6c572023-11-30 10:56:33 +0000285| Let `x` be an input element and `out_imp` the implementation output. +
286Let `out_ref` be the result of the fp64_t reference implementation. +
287Let `err_bnd = abs(out_ref) * exp2(-normal_frac<in_out_t>) * (2 * (1+abs(x)))` +
288Then `tosa_reference_check_fp_bnd<in_out_t>(out_imp, out_ref, err_bnd)` must be true
289
Dominic Symes8754ec22023-12-08 17:45:31 +0000290| <<TANH>>
291| Let `x` be an input element and `out_imp` the implementation output. +
292Let `out_ref` be the result of the fp64_t reference implementation. +
293Let `err_bnd = exp2(-normal_frac<in_out_t>) * max(0.5, abs(out_ref) * (4 * (1+abs(x))))` +
294Then `tosa_reference_check_fp_bnd<in_out_t>(out_imp, out_ref, err_bnd)` must be true
295
Dominic Symesc386a052023-01-20 16:09:31 +0000296| <<REDUCE_SUM>>
297| Each output can be expressed as a dot product of an input vector with a vector of ones. +
298This dot product must meet the <<Dot product accuracy requirements>>
299
300| <<AVG_POOL2D>>
Dominic Symes5b936a32023-03-01 11:34:40 +0000301| Each output can be expressed as a dot product of an input vector with a vector with elements 1/KS where KS is the kernel size. +
Dominic Symesc386a052023-01-20 16:09:31 +0000302This dot product must meet the <<Dot product accuracy requirements>>
303
304| <<REDUCE_PRODUCT>>
305| Result overflows must be set to an infinity of the correct sign. +
306Result underflows must be set to a zero of the correct sign. +
Dominic Symes83e79b52024-01-08 10:45:47 +0000307Let n be number of elements in the product, out_imp the implementation result, and out_ref the result of the fp64_t reference implementation. +
308Let `err_bnd = abs(out_ref) * (pow(1 + pow(2, -normal_frac<in_out_t> - 1), n) - 1)` +
309Then `tosa_reference_check_fp_bnd<in_out_t>(out_imp, out_ref, err_bnd)` must be true
Dominic Symesc386a052023-01-20 16:09:31 +0000310
311|===
312
Dominic Symesf791b442023-10-30 14:26:11 +0000313===== Operator sequence precision requirement
314
315Precision criteria are specified for a single operator.
316
317An implementation M of a sequence of n TOSA operators, A[0] to A[n-1] is said to
318be compliant if M gives the same result as a sequence of implementations
319M[0] to M[n-1] such that:
320
321* Each M[k] implements A[k] with same or higher precision datatypes
322* Each M[k] meets the accuracy defined in this specification for A[k] where the M[k] output is converted to A[k] output precision using round to nearest
323
Dominic Symesc386a052023-01-20 16:09:31 +0000324===== Dot product accuracy requirements
325
Dominic Symesb5b06782023-07-27 11:50:57 +0100326This section assumes an operation acting on tensors named 'input', 'weight' and optionally 'bias'.
327Each output tensor element can be expressed as a dot product of elements between the 'input' and 'weight' tensors with optional bias addition.
Dominic Symes5b936a32023-03-01 11:34:40 +0000328The dot product has length KS, the kernel size.
Dominic Symesb5b06782023-07-27 11:50:57 +0100329If the operation does not specify a bias then 'bias' is taken to be zero in this section.
Dominic Symes5b936a32023-03-01 11:34:40 +0000330Note: KS is defined for each relevant operator in the appendix section <<Main Inference operator test data>>.
Dominic Symesc386a052023-01-20 16:09:31 +0000331
Dominic Symesb5b06782023-07-27 11:50:57 +0100332In other words, each output element `out` can be expressed as a dot product between input elements `in[k]`, weight elements `w[k]`, bias `b`:
Dominic Symesc386a052023-01-20 16:09:31 +0000333
Dominic Symesb5b06782023-07-27 11:50:57 +0100334`out = in[0] * w[0] + in[1] * w[1] + ... + in[KS-1] * w[KS-1] + b`
Dominic Symesc386a052023-01-20 16:09:31 +0000335
Dominic Symesb5b06782023-07-27 11:50:57 +0100336The positions of `in[k]`, `w[k]`, `b` in the input, weight and bias tensors depends on the operation being performed.
337This may be, for example, a convolution.
Dominic Symesc386a052023-01-20 16:09:31 +0000338
Dominic Symes5b936a32023-03-01 11:34:40 +0000339This section defines the accuracy required for these operations.
Dominic Symesb5b06782023-07-27 11:50:57 +0100340In this section:
Dominic Symesc386a052023-01-20 16:09:31 +0000341
Dominic Symesb5b06782023-07-27 11:50:57 +0100342* "fp64 arithmetic" refers to double-precision floating-point arithmetic defined by IEEE 754 (<<Other publications>>[1])
343* `operation_fp64()` is an fp64 reference implementation of the operation
344* `operation_imp()` is the implementation under test
345* `local_bound` is defined as follows:
346** For operations with a local_bound attribute it is the value of the optional attribute, with default value of false
347** For operations that do not have a local_bound attribute the value is true
Dominic Symes5b936a32023-03-01 11:34:40 +0000348
Dominic Symesb5b06782023-07-27 11:50:57 +0100349The checks described in the following code must pass for the following data sets:
Dominic Symes5b936a32023-03-01 11:34:40 +0000350
Dominic Symesb5b06782023-07-27 11:50:57 +0100351* Data sets defined for the operation in Appendix A <<Main Inference operator test data>>.
352* Data sets that have at least MIN_DOT_PRODUCT different output values. For these data sets we take S=-1.
Dominic Symes5b936a32023-03-01 11:34:40 +0000353
354[source,c++]
355----
Dominic Symesb5b06782023-07-27 11:50:57 +0100356output_ref = operation_fp64(input, weight, bias);
357output_imp = operation_imp (input, weight, bias);
358input_abs = abs(input); // Element-wise absolute
359weight_abs = abs(weight); // Element-wise absolute
360bias_abs = abs(bias); // Element-wise absolute
361if (!local_bound) {
362 input_abs_max = max_value(input_abs); // maximum over all elements
363 for_each(index in shape(input_abs) {
364 input_abs[index] = input_abs_max; // set all entries to global maximum
365 }
366}
367output_bnd = operation_fp64(input_abs, weight_abs, bias_abs);
368
Dominic Symes5b936a32023-03-01 11:34:40 +0000369size_t T = tensor_size(output_shape) // number dot product results
Dominic Symesb5b06782023-07-27 11:50:57 +0100370size_t ksb = (max_value(bias_abs) > 0) ? (KS + 1) : KS; // kernel size and bias
Dominic Symes5b936a32023-03-01 11:34:40 +0000371fp64_t out_err_sum = 0.0;
372fp64_t out_err_sumsq = 0.0;
Dominic Symes5b936a32023-03-01 11:34:40 +0000373for_each(index in output_shape) {
374 fp64_t out_bnd = tensor_read<fp64_t>(output_bnd, output_shape, index);
375 fp64_t out_ref = tensor_read<fp64_t>(output_ref, output_shape, index);
376 acc_t out_imp = tensor_read<acc_t> (output_imp, output_shape, index);
377 fp64_t out_err;
Dominic Symesb5b06782023-07-27 11:50:57 +0100378 if ((acc_t)out_bnd == infinity) {
379 // dot product can overflow and there is no accuracy limit
380 out_err = 0.0;
381 } else if (out_bnd == 0.0) {
Dominic Symes5b936a32023-03-01 11:34:40 +0000382 REQUIRE(out_ref == 0.0 && out_imp == 0.0);
383 out_err = 0.0;
Dominic Symesb5b06782023-07-27 11:50:57 +0100384 } else { // 0.0 < out_bnd < infinity
Dominic Symesc237b7e2023-09-20 15:08:53 +0100385 fp64_t out_err_bnd = max(out_bnd * exp2(-1-normal_frac<acc_t>()), normal_min<acc_t>());
Dominic Symesb2035122023-09-01 11:41:08 +0100386 out_err = (static_cast<fp64_t>(out_imp) - out_ref) / out_err_bnd;
Dominic Symesb5b06782023-07-27 11:50:57 +0100387 REQUIRE(abs(out_err) <= ksb);
Dominic Symes5b936a32023-03-01 11:34:40 +0000388 }
389 out_err_sum += out_err;
390 out_err_sumsq += out_err * out_err;
391}
Dominic Symesb5b06782023-07-27 11:50:57 +0100392if (input and weights are data set S with 3 <= S <= 5) {
Dominic Symes5b936a32023-03-01 11:34:40 +0000393 // check output error bias magnitude for data sets S which are not positive biased
Dominic Symesb5b06782023-07-27 11:50:57 +0100394 REQUIRE(abs(out_err_sum) <= 2*sqrt(ksb*T));
Dominic Symes5b936a32023-03-01 11:34:40 +0000395}
396// check output error variance magnitude
Dominic Symesb5b06782023-07-27 11:50:57 +0100397REQUIRE(out_err_sumsq <= 0.4*ksb*T)
Dominic Symes5b936a32023-03-01 11:34:40 +0000398----
Dominic Symesca2a8542021-03-19 13:56:27 +0000399
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700400=== Tensor Definitions
Eric Kunze3309a532020-10-01 18:50:46 -0700401
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700402==== Tensors
Eric Kunze3309a532020-10-01 18:50:46 -0700403
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700404Tensors are multidimensional arrays of data.
405Tensors have metadata associated with them that describe characteristics of the tensor, including:
Eric Kunze3309a532020-10-01 18:50:46 -0700406
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700407* Data Type
408* Shape
Eric Kunze3309a532020-10-01 18:50:46 -0700409
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700410The number of dimensions in a shape is called the rank.
411A tensor with rank equal to zero is permitted.
Dominic Symes830b43b2023-05-09 10:14:49 +0100412In that case, the tensor has a single entry and is also known as a scalar.
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700413A tensor shape is an array of integers of size equal to the rank of the tensor.
414Each element in the tensor shape describes the number of elements in the dimension.
415The tensor shape in each dimension must be greater than or equal to 1.
416For tensor access information, see <<Tensor Access Helpers>>.
Dominic Symes830b43b2023-05-09 10:14:49 +0100417
Eric Kunze526f6c72024-01-12 17:18:42 -0800418The shape of a tensor of non-zero rank is a special type shape_t.
419shape_t is a one-dimensional list with the size equal to the rank of the original tensor.
420The components of a shape_t are of type size_t.
Dominic Symes830b43b2023-05-09 10:14:49 +0100421
Dominic Symes830b43b2023-05-09 10:14:49 +0100422In this version of the specification, shape_t values must be resolvable to constants at backend compile time.
Eric Kunze3309a532020-10-01 18:50:46 -0700423
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700424==== Tensor size limit
Eric Kunze3309a532020-10-01 18:50:46 -0700425
Dominic Symesbc72ba82023-04-24 17:08:02 +0100426The tensor overall size is limited by the data type size_t.
Eric Kunze526f6c72024-01-12 17:18:42 -0800427This type must be able to hold integers in the range 0 to (1 << (MAX_LOG2_SIZE + 1)) - 1 where MAX_LOG2_SIZE is defined in <<Levels>>.
428For each tensor, the number of tensor elements multiplied by the element size in bytes (which is taken to be 1 for elements smaller than a 8-bit) must be less than or equal to (1 << (MAX_LOG2_SIZE + 1)) - 1.
Dominic Symesbc72ba82023-04-24 17:08:02 +0100429
Eric Kunze526f6c72024-01-12 17:18:42 -0800430The size of tensors along each of their dimensions is limited by the data type size_t.
431
432This means that the maximum size of a tensor along each dimension is (1 << MAX_LOG2_SIZE) - 1 and therefore the maximum coordinate value is (1 << MAX_LOG2_SIZE) - 2.
Dominic Symes0205d992022-10-07 15:03:01 +0100433Indices used to access tensors must be non-negative.
Eric Kunze3309a532020-10-01 18:50:46 -0700434
Dominic Symes830b43b2023-05-09 10:14:49 +0100435
Eric Kunze3309a532020-10-01 18:50:46 -0700436==== Data Layouts
437
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700438The following data layouts are supported in TOSA.
439TOSA operations are defined in terms of a linear packed tensor layout.
440In a linear packed layout a rank r tensor has elements of dimension (r-1) consecutive.
441The next to increment is dimension (r-2) and so on.
442For a specification of this layout see the tensor read and write functions in section <<Tensor Access Helpers>>.
443
444An implementation of TOSA can choose a different tensor memory layout provided that the operation behavior is maintained.
Eric Kunze3309a532020-10-01 18:50:46 -0700445
446.Data Layouts
447[cols="1,4,4"]
448|===
449|Name|Description of dimensions|Usage
450
451|NHWC|Batch, Height, Width, Channels|Feature maps
452|NDHWC|Batch, Depth, Height, Width, Channels|Feature maps for 3D convolution
453|OHWI|Output channels, Filter Height, Filter Width, Input channels|Weights
454|HWIM|Filter Height, Filter Width, Input channels, Channel Multiplier|Weights for depthwise convolutions
455|DOHWI|Depth, Output Channels, Filter Height, Filter Width, Input Channels|Weights for 3D convolution
456|===
457
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700458==== Broadcasting
Eric Kunze3309a532020-10-01 18:50:46 -0700459
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700460In operations where broadcasting is supported, an input shape dimension can be broadcast to an output shape dimension if the input shape dimension is 1.
461TOSA broadcast requires the rank of both tensors to be the same.
462A RESHAPE can be done to create a compatible tensor with appropriate dimensions of size 1.
463To map indexes in an output tensor to that of an input tensor, see <<Broadcast Helper>>.
Eric Kunze3309a532020-10-01 18:50:46 -0700464
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700465==== Supported Number Formats
Eric Kunze3309a532020-10-01 18:50:46 -0700466
Eric Kunze1e9ba652021-02-17 19:23:39 -0800467The following number formats are defined in TOSA.
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700468The number formats supported by a given operator are listed in its table of supported types.
Eric Kunze3309a532020-10-01 18:50:46 -0700469
470.Number formats
Eric Kunze1e9ba652021-02-17 19:23:39 -0800471[cols="1,1,1,5"]
Eric Kunze3309a532020-10-01 18:50:46 -0700472|===
473|Format|Minimum|Maximum|Description
474
Eric Kunze1e9ba652021-02-17 19:23:39 -0800475|bool_t
Eric Kunze3309a532020-10-01 18:50:46 -0700476| -
477| -
Kevin Petitf9fcb612024-01-23 19:09:29 +0000478|Boolean value that is either `true` or `false`. Size implementation defined. The TOSA reference model implements this as int8_t with 0 for `false` and 1 for `true`. All non-zero values are accepted on input as `true`.
Eric Kunze3309a532020-10-01 18:50:46 -0700479
Eric Kunzefb0284e2023-07-18 15:20:53 -0700480|i4_t
481| -
482| -
483|Signless 4-bit integer type. Will be interpreted as int4_t by all operators
484
Eric Kunze1e9ba652021-02-17 19:23:39 -0800485|int4_t
Eric Kunze3309a532020-10-01 18:50:46 -0700486| -7
487| +7
Eric Kunzeeef012e2022-05-13 14:54:06 -0700488|Signed 4-bit two's-complement value. Excludes -8 to maintain a symmetric about zero range for weights.
Eric Kunze3309a532020-10-01 18:50:46 -0700489
Eric Kunzefb0284e2023-07-18 15:20:53 -0700490|i8_t
491| -
492| -
493|Signless 8-bit integer value. Will be interpreted as int8_t unless otherwise specified by an operator.
494
Eric Kunze1e9ba652021-02-17 19:23:39 -0800495|int8_t
Eric Kunze3309a532020-10-01 18:50:46 -0700496| -128
497| +127
Eric Kunzeeef012e2022-05-13 14:54:06 -0700498|Signed 8-bit two's-complement value.
Eric Kunze3309a532020-10-01 18:50:46 -0700499
Eric Kunze1e9ba652021-02-17 19:23:39 -0800500|uint8_t
Eric Kunze3309a532020-10-01 18:50:46 -0700501| 0
502| 255
Eric Kunzefb0284e2023-07-18 15:20:53 -0700503|Unsigned 8-bit integer value.
504
505|i16_t
506| -
507| -
508|Signless 16-bit integer type. Will be interpreted as int16_t unless otherwise specified by an operator.
Eric Kunze3309a532020-10-01 18:50:46 -0700509
Eric Kunze1e9ba652021-02-17 19:23:39 -0800510|int16_t
Eric Kunze3309a532020-10-01 18:50:46 -0700511| -32768
Eric Kunze2dce0d02021-01-12 16:19:50 -0800512| +32767
Eric Kunzeeef012e2022-05-13 14:54:06 -0700513|Signed 16-bit two's-complement value.
514
515|uint16_t
516| 0
517| 65535
518|Unsigned 16-bit value.
Eric Kunze3309a532020-10-01 18:50:46 -0700519
Eric Kunzefb0284e2023-07-18 15:20:53 -0700520|i32_t
521| -
522| -
523|Signless 32-bit integer value. Will be interpreted as int32_t by all operators.
524
Eric Kunze1e9ba652021-02-17 19:23:39 -0800525|int32_t
Eric Kunze3309a532020-10-01 18:50:46 -0700526| -(1<<31)
Eric Kunze2dce0d02021-01-12 16:19:50 -0800527| (1<<31)-1
Eric Kunze173fc162021-08-17 14:57:46 -0700528|Signed 32-bit two's-complement value.
Eric Kunze3309a532020-10-01 18:50:46 -0700529
Eric Kunzefb0284e2023-07-18 15:20:53 -0700530|i48_t
531| -
532| -
Eric Kunze2f3f4a22024-01-08 14:22:11 -0800533|Signless 48-bit integer value. Will be interpreted as int48_t by all operators.
Eric Kunzefb0284e2023-07-18 15:20:53 -0700534
Eric Kunze1e9ba652021-02-17 19:23:39 -0800535|int48_t
Eric Kunze57e79c02020-11-03 11:23:09 -0800536| -(1<<47)
Eric Kunze2dce0d02021-01-12 16:19:50 -0800537| (1<<47)-1
Eric Kunze173fc162021-08-17 14:57:46 -0700538|Signed 48-bit two's-complement value.
Eric Kunze57e79c02020-11-03 11:23:09 -0800539
Eric Kunze42229d02022-04-07 16:54:46 -0700540|fp16_t
Eric Kunze3309a532020-10-01 18:50:46 -0700541| -infinity
542| +infinity
Dominic Symesc386a052023-01-20 16:09:31 +0000543| 16-bit half-precision floating-point defined by <<Other publications>>[1]. +
544Normal values must be supported. +
545Denormal values must either be supported or flushed to zero. +
546Positive and negative infinity must be supported. +
547At least one NaN encoding must be supported. +
548Signed zero must be supported.
Eric Kunze42229d02022-04-07 16:54:46 -0700549
550|bf16_t
551| -infinity
552| +infinity
Dominic Symesc386a052023-01-20 16:09:31 +0000553| 16-bit brain floating-point defined as bits [31:16] of the fp32_t format. +
554Normal values must be supported. +
555Denormal values must either be supported or flushed to zero. +
556Positive and negative infinity must be supported. +
557At least one NaN encoding must be supported. +
558Signed zero must be supported.
Eric Kunze42229d02022-04-07 16:54:46 -0700559
560|fp32_t
561| -infinity
562| +infinity
Eric Kunze277a4f12023-05-12 17:50:19 -0700563| 32-bit single-precision floating-point defined by <<Other publications>>[1]. +
564Normal values must be supported. +
565Denormal values must either be supported or flushed to zero. +
566Positive and negative infinity must be supported. +
567At least one NaN encoding must be supported. +
568Signed zero must be supported.
569
570|fp64_t
571| -infinity
572| + infinity
573| 64-bit double-precision floating-point defined by <<Other publications>>[1]. +
Dominic Symesc386a052023-01-20 16:09:31 +0000574Normal values must be supported. +
575Denormal values must either be supported or flushed to zero. +
576Positive and negative infinity must be supported. +
577At least one NaN encoding must be supported. +
578Signed zero must be supported.
Eric Kunze3309a532020-10-01 18:50:46 -0700579|===
580
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700581Note: In this specification minimum<type> and maximum<type> will denote the minimum and maximum values of the data as stored in memory (ignoring the zero point).
582The minimum and maximum values for each type is given in the preceeding table.
Eric Kunze3309a532020-10-01 18:50:46 -0700583
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700584Note: Integer number formats smaller than 8 bits may be used provided that the numerical result is the same as using a sequence of 8-bit TOSA operations.
585For example, a convolution with low precision data must equal that of running the convolution at 8 bits and then clipping the result to the peritted output range.
586This ensures that a Base Inference profile TOSA implementation can calculate the same result.
Eric Kunze3309a532020-10-01 18:50:46 -0700587
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700588=== Integer Behavior
Eric Kunze3309a532020-10-01 18:50:46 -0700589
Eric Kunzefb0284e2023-07-18 15:20:53 -0700590TOSA integer inputs and outputs are specified by signless values with the given number of bits.
591Unless otherwise specified, these values will be interpreted as signed twos-complement.
592The pseudocode will use int*_t to indicate use as a signed value and uint*_t to indicate use as an unsigned value.
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700593If overflow occurs doing integer calculation, the result is unpredictable, as indicated by the REQUIRE checks in the pseudocode for the operators.
Eric Kunze3309a532020-10-01 18:50:46 -0700594
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700595Unsigned 8 and 16-bit values are only allowed in the RESCALE operation, to allow for compatibility with networks which expect unsigned 8-bit or 16-bit tensors for input and output.
Eric Kunze3309a532020-10-01 18:50:46 -0700596
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700597==== Quantization
Eric Kunze3309a532020-10-01 18:50:46 -0700598
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700599Machine Learning frameworks may represent tensors with a quantized implementation, using integer values to represent the original floating-point numbers.
600TOSA integer operations do not perform any implicit scaling to represent quantized values.
601Required zero point values are passed to the operator as necessary, and will be processed according to the pseudocode for each operator.
Eric Kunzec949f8a2021-09-16 14:51:26 -0700602
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700603To convert a network containing quantized tensors to TOSA, generate explicit RESCALE operators for any change of quantization scaling.
604This reduces quantized operations to purely integer operations.
Eric Kunze839830a2021-03-11 15:38:22 -0800605
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700606As an example, an ADD between two quantized tensors requires the integer values represent the same range.
Kevin Petit5333c252023-05-16 09:08:48 +0100607The scale arguments for RESCALE can be calculated to ensure that the resulting tensors represent the same range.
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700608Then the ADD is performed, and a RESCALE can be used to ensure that the result is scaled properly.
Eric Kunze3309a532020-10-01 18:50:46 -0700609
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700610RESCALE provides support for per-tensor and per-channel scaling values to ensure compatibility with a range of possible quantization implementations.
Eric Kunze3309a532020-10-01 18:50:46 -0700611
Eric Kunzec949f8a2021-09-16 14:51:26 -0700612
Eric Kunze3309a532020-10-01 18:50:46 -0700613
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700614==== Precision scaling
Eric Kunze3309a532020-10-01 18:50:46 -0700615
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700616TOSA uses the RESCALE operation to scale between values with differing precision.
617The RESCALE operator is defined using an integer multiply, add, and shift.
618This guarantees that all TOSA implementations will return the same result for a RESCALE, including those with no support for floating-point numbers.
Eric Kunze3309a532020-10-01 18:50:46 -0700619
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700620This TOSA specification supports two precisions of multiplier: 16-bit and 32-bit.
621The 32-bit multiplier version supports two rounding modes to enable simpler lowering of existing frameworks that use two stage rounding.
622All arithmetic is designed so that it does not overflow a 64-bit accumulator and that the final result fits in 32 bits.
623In particular a 48-bit value can only be scaled with the 16-bit multiplier.
Eric Kunze3309a532020-10-01 18:50:46 -0700624
Dominic Symes3cb75352022-01-24 11:18:05 +0000625The apply_scale functions provide a scaling of approximately (multiplier * 2^-shift^).
626The shift and value range is limited to allow a variety of implementations.
627The limit of 62 on shift allows the shift to be decomposed as two right shifts of 31.
Eric Kunzece6e02c2022-03-11 15:12:38 -0800628The limit on value allows implementations that left shift the value before the multiply in the case of shifts of 32 or less.
Dominic Symes3cb75352022-01-24 11:18:05 +0000629For example, in the case shift=30 an implementation of the form ((value\<<2) * multiplier + round)>>32 can be used.
630A scaling range of 2^+12^ down to 2^-32^ is supported for both functions with a normalized multiplier.
631
632For example, in typical usage a scaling of m*2^-n^ where m is a fraction in the
633range 1.0 \<= m < 2.0 can be represented using multiplier=(1<<30)*m, shift=(30+n) for
634apply_scale_32() and multiplier=(1<<14)*m, shift=(14+n) for apply_scale_16().
635The values to achieve a scaling of 1.0 are shift=30, multiplier=1<<30 for apply_scale_32 and shift=14, multiplier=1<<14 for apply_scale_16.
Eric Kunze3309a532020-10-01 18:50:46 -0700636
Eric Kunze839830a2021-03-11 15:38:22 -0800637[source,c++]
638----
Kevin Petit98b3e332023-05-16 09:13:50 +0100639int32_t apply_scale_32(int32_t value, int32_t multiplier, int8_t shift, bool_t double_round=false) {
Eric Kunzea9101532021-06-17 18:01:09 -0700640 REQUIRE(multiplier >= 0);
641 REQUIRE(2 <= shift && shift <= 62);
Dominic Symes830b43b2023-05-09 10:14:49 +0100642 REQUIRE(value >= (-1 << (shift - 1)) && value < (1 << (shift - 1)));
Eric Kunze839830a2021-03-11 15:38:22 -0800643 int64_t round = 1 << (shift - 1);
644 if (double_round) {
645 if (shift > 31 && value >= 0) round += 1<<30;
646 if (shift > 31 && value < 0) round -= 1<<30;
647 }
Eric Kunzefb0284e2023-07-18 15:20:53 -0700648 int64_t result = static_cast<int64_t>(value) * multiplier + round;
Eric Kunze839830a2021-03-11 15:38:22 -0800649 result = result >> shift;
Dominic Symes3cb75352022-01-24 11:18:05 +0000650 // result will fit a 32-bit range due to the REQUIRE on value
Eric Kunzefb0284e2023-07-18 15:20:53 -0700651 return static_cast<int32_t>(result);
Eric Kunze3309a532020-10-01 18:50:46 -0700652}
653
Kevin Petit98b3e332023-05-16 09:13:50 +0100654int32_t apply_scale_16(int48_t value, int16_t multipler, int8_t shift) {
Eric Kunzea9101532021-06-17 18:01:09 -0700655 REQUIRE(multiplier >= 0);
656 REQUIRE(2 <= shift && shift <= 62);
Eric Kunze839830a2021-03-11 15:38:22 -0800657 int64_t round = (1 << (shift - 1));
Eric Kunzefb0284e2023-07-18 15:20:53 -0700658 int64_t result = static_cast<int64_t>(value) * multiplier + round;
Eric Kunze839830a2021-03-11 15:38:22 -0800659 result = result >> shift;
Eric Kunzea9101532021-06-17 18:01:09 -0700660 REQUIRE(result >= minimum<int32_t> && result <= maximum<int32_t>);
Eric Kunzefb0284e2023-07-18 15:20:53 -0700661 return static_cast<int32_t>(result);
Eric Kunze3309a532020-10-01 18:50:46 -0700662}
Eric Kunze839830a2021-03-11 15:38:22 -0800663----
Eric Kunze3309a532020-10-01 18:50:46 -0700664
665In some functions, the multiplier and shift are combined into a scale_t structure:
666
Eric Kunze839830a2021-03-11 15:38:22 -0800667[source,c++]
668----
Eric Kunze3309a532020-10-01 18:50:46 -0700669typedef struct {
Eric Kunze839830a2021-03-11 15:38:22 -0800670 int32_t multiplier;
Kevin Petit98b3e332023-05-16 09:13:50 +0100671 int8_t shift;
Eric Kunze3309a532020-10-01 18:50:46 -0700672} scale_t;
Eric Kunze839830a2021-03-11 15:38:22 -0800673----
Eric Kunze3309a532020-10-01 18:50:46 -0700674
675In places where a divide is required, we also use the function below to calculate an appropriate scaling value.
676
Eric Kunze839830a2021-03-11 15:38:22 -0800677[source,c++]
678----
Eric Kunze3309a532020-10-01 18:50:46 -0700679scale_t reciprocal_scale(uint32_t value) {
Eric Kunzea9101532021-06-17 18:01:09 -0700680 REQUIRE(value > 0);
Eric Kunze839830a2021-03-11 15:38:22 -0800681 scale_t scale;
Dominic Symescb6c6b32022-04-29 16:15:56 +0100682 int32_t k = 32 - count_leading_zeros(value - 1); // (1 << k) / 2 < value <= (1 << k)
Eric Kunze839830a2021-03-11 15:38:22 -0800683 int64_t numerator = ((1 << 30) + 1) << k;
684 scale.multiplier = numerator / value; // (1 << 30) <= multiplier < (1 << 31)
685 scale.shift = 30 + k;
686 return scale;
Eric Kunze3309a532020-10-01 18:50:46 -0700687}
Eric Kunze839830a2021-03-11 15:38:22 -0800688----
Eric Kunze3309a532020-10-01 18:50:46 -0700689
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700690==== Integer Convolutions
Eric Kunze1e9ba652021-02-17 19:23:39 -0800691
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700692For the convolution operators, the input is not required to be scaled.
693The integer versions of the convolution operators will subtract the zero point from the integer values as defined for each operator.
Eric Kunze1e9ba652021-02-17 19:23:39 -0800694The convolution produces an accumulator output of type int32_t or int48_t.
695This accumulator output is then scaled to the final output range using the RESCALE operator.
696The scale applied in the RESCALE operator should be set to multiplier and shift values such that: multiplier * 2^-shift^ = (input scale * weight scale) / output_scale.
697Here, input_scale, weight_scale and output_scale are the conversion factors from integer to floating-point for the input, weight and output tensor values respectively.
698If per-channel scaling is needed then the per-channel option of the RESCALE operation should be used.
699
Eric Kunzef9e5ba92022-05-26 16:38:40 -0700700==== Integer Elementwise Operators
Eric Kunze1e9ba652021-02-17 19:23:39 -0800701
702When two quantized tensors are used in an operation, they must represent the same numeric range for the result to be valid.
703In this case, TOSA expects that RESCALE operators will be used as necessary to generate 32-bit integer values in a common range.
704There are many valid choices for scale factors and options for the common range.
705TOSA does not impose a requirement on which scale factors and range should be used.
706Compilers generating TOSA sequences should choose a range that allows the operation to be computed without overflow, while allowing the highest possible accuracy of the output.
707
708==== General Unary Functions
709General unary functions such as sigmoid(), tanh(), exp() for integer inputs are expressed using a lookup table and interpolation to enable efficient implementation.
710This also allows for other operations with the addition of user-supplied tables (the TABLE operation).
711All table lookups are based on the following reference lookup function that takes as input a table of 513 entries of 16 bits each.
712
Eric Kunze839830a2021-03-11 15:38:22 -0800713[source,c++]
714----
Eric Kunzefb0284e2023-07-18 15:20:53 -0700715int32_t apply_lookup_s(int16_t *table, int32_t value)
Eric Kunze1e9ba652021-02-17 19:23:39 -0800716{
Eric Kunzefb0284e2023-07-18 15:20:53 -0700717 int16_t clipped_value = static_cast<int16_t>(apply_clip_s<int32_t>(value, -32768, +32767));
Eric Kunze1e9ba652021-02-17 19:23:39 -0800718 int32_t index = (clipped_value + 32768) >> 7;
719 int32_t fraction = clipped_value & 0x7f;
720 int16_t base = table[index];
721 int16_t next = table[index+1];
Dominic Symes2ff79fe2022-01-27 15:44:26 +0000722 int32_t slope = next - base;
723 REQUIRE(slope >= minimum<int16_t> && slope <= maximum<int16_t>)
724 int32_t return_value = (base << 7) + slope * fraction;
Eric Kunze1e9ba652021-02-17 19:23:39 -0800725 return return_value; // return interpolated value of 16 + 7 = 23 bits
726}
Eric Kunze839830a2021-03-11 15:38:22 -0800727----
Eric Kunze1e9ba652021-02-17 19:23:39 -0800728
729Note that although the table lookup defined here has 16-bit precision, for 8-bit only operations an 8-bit table can be derived by applying the reference function to each of the possible 256 input values.
730The following code constructs a 513-entry table based on a reference function.
731
Eric Kunze839830a2021-03-11 15:38:22 -0800732[source,c++]
733----
Eric Kunze1e9ba652021-02-17 19:23:39 -0800734void generate_lookup_table(int16_t *table, int32_t (*reference)(int32_t))
735{
736 for (int i = -256; i <= 256; i++) {
737 int32_t value = (*reference)(i);
Eric Kunze60858832024-01-22 16:54:29 -0800738 table[i + 256] = static_cast<int16_t>(apply_clip_s<int32_t>(value, -32768, +32767));
Eric Kunze1e9ba652021-02-17 19:23:39 -0800739 }
740}
Eric Kunze839830a2021-03-11 15:38:22 -0800741----
Eric Kunze1e9ba652021-02-17 19:23:39 -0800742
Dominic Symesc386a052023-01-20 16:09:31 +0000743=== Other publications
Eric Kunze1e9ba652021-02-17 19:23:39 -0800744
Dominic Symesc386a052023-01-20 16:09:31 +0000745The following publications are referred to in this specification, or provide more information:
Eric Kunze1e9ba652021-02-17 19:23:39 -0800746
Kevin Petit98b3e332023-05-16 09:13:50 +0100747. IEEE Std 754-2008, _IEEE Standard for Floating-point Arithmetic_, August 2008.