# Copyright (c) 2021-2022 Huawei Device Co., 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. definitions: [] tests: - file-name: "fp_calc" isa: title: Two address floating-point binary operation on accumulator description: > Perform specified floating-point binary operation on accumulator and register and store result into accumulator. The results of instructions correspond IEEE-754 arithmetic rules. exceptions: - x_none commands: - file-name: "sin_cheb7" isa: instructions: - sig: fadd2.64 v:in:f64 acc: inout:f64 format: [op_v_8] - sig: fmul2.64 v:in:f64 acc: inout:f64 format: [op_v_8] check-type: empty tags: ['tsan', 'irtoc_ignore'] code-template: | # fmovi.64 v0, %s call.short get_approx, v0 sta.64 v0 fldai.64 %s fcmpg.64 v0 return } .function f64 pow (i32 a0, f64 a1) { mov.64 v2, a1 # v2 - value for calculation fmovi.64 v1, 1.0 # v1 - initial value mov v3, a0 # v3 - iteration counter pow_iter: ldai 0 jeq v3, exit lda.64 v1 fmul2.64 v2 sta.64 v1 inci v3, -1 jmp pow_iter exit: lda.64 v1 return.64 } .function f64 get_approx(f64 a0) { # sin(PI * x / 2) approximation using polynom A1*x + A3*x^3 + A5*x^5 + A7*x^7 # Where A[i] is coefficients of Chebyshev polynomial approximation of sin(PI * x / 2) on [-1; 1] fmovi.64 v0, 0.0 # Results mov.64 v1, a0 # v1 = x lda.64 a0 # x fmovi.64 v2, 1.5707909877360093 # A1 coefficient fmul2.64 v2 # x*A1 sta.64 v0 # v0 = A1 * x movi v2, 3 call.short pow, v2, v1 # acc = x^3 fmovi.64 v2, -0.6458926627154391 # A3 fmul2.64 v2 # acc = A3 * x^3 fadd2.64 v0 sta.64 v0 # v0 = A1*x + A3*x^3 movi v2,5 call.short pow, v2, v1 # acc = x^5 fmovi.64 v2, 0.07943397081887174 fmul2.64 v2 # A5 * x^5 fadd2.64 v0 sta.64 v0 # v0 = A1*x + A3*x^3 + A5*x^5 movi v2,7 call.short pow, v2, v1 # acc = x^7 fmovi.64 v2, -0.0043328816450923634 fmul2.64 v2 fadd2.64 v0 # acc = A1*x + A3*x^3 + A5*x^5 + A7*x^7 return.64 } cases: - values: - "0.0" - "0.0" - values: - "0.01" - "0.015707263992640733" - values: - "0.1" - "0.1564340000173055" - values: - "0.123456789" - "0.19271172682380572" - values: - "0.14" - "0.21814267639869997" - values: - "0.4" - "0.5877855695485135" - values: - "0.7" - "0.8910061441444742" - values: - "0.9" - "0.9876886994127743" - values: - "0.99" - "0.9998764601533426" - values: - "1.0" - "0.9999994141943497" - values: - "-0.0" - "0.0" - values: - "-0.01" - "-0.015707263992640733" - values: - "-0.1" - "-0.1564340000173055" - values: - "-0.123456789" - "-0.19271172682380572" - values: - "-0.14" - "-0.21814267639869997" - values: - "-0.4" - "-0.5877855695485135" - values: - "-0.7" - "-0.8910061441444742" - values: - "-0.9" - "-0.9876886994127743" - values: - "-0.99" - "-0.9998764601533426" - values: - "-1.0" - "-0.9999994141943497" - file-name: "cheb3" isa: instructions: - sig: fadd2.64 v:in:f64 acc: inout:f64 format: [op_v_8] - sig: fmul2.64 v:in:f64 acc: inout:f64 format: [op_v_8] tags: ['tsan', 'irtoc_ignore'] check-type: empty code-template: | # fmovi.64 v0, %s call.short get_value, v0 sta.64 v0 fldai.64 %s fcmpg.64 v0 return } .function f64 get_value(f64 a0) { # Calculate Chebyshev polynom value iteratively # Since on [-1; 1] result value is limited by [-1; 1] iteration is possible movi v0, 100 mov.64 v1, a0 loop: ldai 0 jeq v0, exit lda.64 v1 fmul2.64 v1 fmul2.64 v1 fmovi.64 v2, 4.0 fmul2.64 v2 # 4 * x^3 sta.64 v3 lda.64 v1 fmovi.64 v2, -3.0 fmul2.64 v2 fadd2.64 v3 sta.64 v1 # 4*x*x*x - 3*x inci v0, -1 jmp loop exit: lda.64 v1 return.64 } cases: - values: - "0.0" - "0.0" - values: - "0.3333333333333333" - "0.9711499729865962" - values: - "0.9" - "0.6562849760306007" - values: - "0.12" - "0.7565938935844838" - values: - "0.55" - "-0.6575967480875675" - values: - "0.5" - "-1.0" - values: - "0.66666" - "0.9388838883478421" - values: - "0.87654321" - "0.02200409867255329" - values: - "1.0" - "1.0" - values: - "-0.0" - "0.0" - values: - "-0.3333333333333333" - "-0.9711499729865962" - values: - "-0.9" - "-0.6562849760306007" - values: - "-0.12" - "-0.7565938935844838" - values: - "-0.55" - "0.6575967480875675" - values: - "-0.5" - "1.0" - values: - "-0.66666" - "-0.9388838883478421" - values: - "-0.87654321" - "-0.02200409867255329" - values: - "-1.0" - "-1.0" - file-name: "cheb11" isa: instructions: - sig: fadd2.64 v:in:f64 acc: inout:f64 format: [op_v_8] - sig: fmul2.64 v:in:f64 acc: inout:f64 format: [op_v_8] tags: ['tsan', 'irtoc_ignore'] check-type: empty code-template: | # fmovi.64 v0, %s call.short get_value, v0 sta.64 v0 fldai.64 %s fcmpg.64 v0 return } .function f64 pow_mul(i32 a0, f64 a1, f64 a2) { mov v0, a0 mov.64 v1, a1 mov.64 v2, a2 call.short pow, v0, v1 fmul2.64 v2 return.64 } .function f64 pow (i32 a0, f64 a1) { mov.64 v2, a1 # v2 - value for calculation fmovi.64 v1, 1.0 # v1 - initial value mov v3, a0 # v3 - iteration counter pow_iter: ldai 0 jeq v3, exit lda.64 v1 fmul2.64 v2 sta.64 v1 inci v3, -1 jmp pow_iter exit: lda.64 v1 return.64 } .function f64 get_value(f64 a0) { # Calculate Chebyshev polynom value iteratively # x = 1024 * Math.pow(x, 11) - 2816 * Math.pow(x,9) + 2816 * Math.pow(x,7) - 1232 * Math.pow(x,5) + 220*Math.pow(x,3) - 11 *x; # Since on [-1; 1] result value is limited by [-1; 1] iteration is possible # Repeat 100 times movi v0, 100 mov.64 v4, a0 loop: mov.64 v1, v4 ldai 0 jeq v0, exit movi v2, 11 fmovi.64 v3, 1024.0 call pow_mul, v2, v1, v3 # acc = v1^11*1024 sta.64 v4 movi v2, 9 fmovi.64 v3, -2816.0 call pow_mul, v2, v1, v3 # acc = -v1^9*2816 fadd2.64 v4 sta.64 v4 movi v2, 7 fmovi.64 v3, 2816.0 call pow_mul, v2, v1, v3 # acc = v1^7*2816 fadd2.64 v4 sta.64 v4 movi v2, 5 fmovi.64 v3, -1232.0 call pow_mul, v2, v1, v3 # acc = -v1^5*1232 fadd2.64 v4 sta.64 v4 movi v2, 3 fmovi.64 v3, 220.0 call pow_mul, v2, v1, v3 # acc = v1^3*220 fadd2.64 v4 sta.64 v4 movi v2, 1 fmovi.64 v3, -11.0 call pow_mul, v2, v1, v3 # acc = -v1^1*11 fadd2.64 v4 sta.64 v4 inci v0, -1 jmp loop exit: lda.64 v4 return.64 } cases: - values: - "0.0" - "0.0" - values: - "0.3333333333333333" - "0.7868241150060133" - values: - "0.9" - "-0.22919667772362332" - values: - "0.12" - "0.05719322440846497" - values: - "0.55" - "-0.7222928963047401" - values: - "0.5" - "0.5" - values: - "0.66666" - "-0.9376142114702866" - values: - "0.87654321" - "-0.2508041890501467" - values: - "1.0" - "1.0" - values: - "-0.0" - "0.0" - values: - "-0.3333333333333333" - "-0.7868241150060133" - values: - "-0.9" - "0.22919667772362332" - values: - "-0.12" - "-0.05719322440846497" - values: - "-0.55" - "0.7222928963047401" - values: - "-0.5" - "-0.5" - values: - "-0.66666" - "0.9376142114702866" - values: - "-0.87654321" - "0.2508041890501467" - values: - "-1.0" - "-1.0" - file-name: "sin_taylor" isa: instructions: - sig: fadd2.64 v:in:f64 acc: inout:f64 format: [op_v_8] - sig: fmul2.64 v:in:f64 acc: inout:f64 format: [op_v_8] - sig: fdiv2.64 v:in:f64 acc: inout:f64 format: [op_v_8] tags: ['tsan', 'irtoc_ignore'] check-type: empty code-template: | # Calculate sin(x) using Taylor series for small x # Check relative deviation fmovi.64 v0, %s call.short get_value, v0 sta.64 v0 fldai.64 %s fsub2.64 v0 fdiv2.64 v0 sta.64 v0 fldai.64 0.0 fcmpg.64 v0 jeqz l1 lda.64 v0 fneg.64 sta.64 v0 l1: fldai.64 0.0001 fcmpg.64 v0 jltz err ldai 0 return err: ldai 1 return } .function f64 fact(i32 a0) { mov v0, a0 fmovi.64 v1, 1.0 loop: ldai 1 jeq v0, exit lda v0 i32tof64 fmul2.64 v1 sta.64 v1 inci v0, -1 jmp loop exit: lda.64 v1 return.64 } .function f64 pow_div(i32 a0, f64 a1, f64 a2) { mov v0, a0 mov.64 v1, a1 mov.64 v2, a2 call.short pow, v0, v1 fdiv2.64 v2 return.64 } .function f64 pow (i32 a0, f64 a1) { mov.64 v2, a1 # v2 - value for calculation fmovi.64 v1, 1.0 # v1 - initial value mov v3, a0 # v3 - iteration counter pow_iter: ldai 0 jeq v3, exit lda.64 v1 fmul2.64 v2 sta.64 v1 inci v3, -1 jmp pow_iter exit: lda.64 v1 return.64 } .function f64 get_value(f64 a0) { # Taylor series for sin(x) movi v0, 1 # n fmovi.64 v1, 1.0 # sign fmovi.64 v2, 0.0 # result mov.64 v3, a0 loop: ldai 20 jlt v0, exit call fact, v0 # acc = v0! sta.64 v4 # v4 = n! call pow_div, v0, v3, v4 # x^n/n! fmul2.64 v1 # *sign fadd2.64 v2 sta.64 v2 # result fldai.64 -1.0 fmul2.64 v1 # flip sign sta.64 v1 inci v0, 2 jmp loop exit: lda.64 v2 return.64 } cases: - values: - "1.0e-4" - "9.999999950000001e-5" - values: - "0.001" - "9.999995000000417e-4" - values: - "0.0015" - "0.0014999983125003164" - values: - "0.005" - "0.004999937500130208" - values: - "0.01" - "0.009999500004166653" - values: - "0.0123456789" - "0.012344738073763926" - values: - "0.015" - "0.014998312531640386" - values: - "-1.0e-4" - "-9.999999950000001e-5" - values: - "-0.001" - "-9.999995000000417e-4" - values: - "-0.0015" - "-0.0014999983125003164" - values: - "-0.005" - "-0.004999937500130208" - values: - "-0.01" - "-0.009999500004166653" - values: - "-0.0123456789" - "-0.012344738073763926" - values: - "-0.015" - "-0.014998312531640386"