blob: 17013294e2d1ce53324f7324b262fb4fb8bef36e [file] [log] [blame]
Georgios Pinitase8291ac2020-02-26 09:58:13 +00001/*
Pablo Marquez Tellod208f4f2022-07-19 12:19:46 +01002 * Copyright (c) 2020-2022 Arm Limited.
Georgios Pinitase8291ac2020-02-26 09:58:13 +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#ifndef ARM_COMPUTE_BFLOAT16_H
25#define ARM_COMPUTE_BFLOAT16_H
26
27#include <cstdint>
Pablo Marquez Tellof73db972021-03-24 17:50:19 +000028#include <cstring>
Georgios Pinitase8291ac2020-02-26 09:58:13 +000029
30namespace arm_compute
31{
32namespace
33{
34/** Convert float to bfloat16
35 *
36 * @param[in] v Floating-point value to convert to bfloat
37 *
38 * @return Converted value
39 */
40inline uint16_t float_to_bf16(const float v)
41{
42 const uint32_t *fromptr = reinterpret_cast<const uint32_t *>(&v);
Pablo Marquez Tellod208f4f2022-07-19 12:19:46 +010043#if defined(ARM_COMPUTE_ENABLE_BF16)
Georgios Pinitase8291ac2020-02-26 09:58:13 +000044 uint16_t res;
45
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010046 __asm __volatile("ldr s0, [%[fromptr]]\n"
47 ".inst 0x1e634000\n" // BFCVT h0, s0
48 "str h0, [%[toptr]]\n"
49 :
50 : [fromptr] "r"(fromptr), [toptr] "r"(&res)
51 : "v0", "memory");
Pablo Marquez Tellod208f4f2022-07-19 12:19:46 +010052#else /* defined(ARM_COMPUTE_ENABLE_BF16) */
Georgios Pinitase8291ac2020-02-26 09:58:13 +000053 uint16_t res = (*fromptr >> 16);
54 const uint16_t error = (*fromptr & 0x0000ffff);
55 uint16_t bf_l = res & 0x0001;
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010056 if ((error > 0x8000) || ((error == 0x8000) && (bf_l != 0)))
Georgios Pinitase8291ac2020-02-26 09:58:13 +000057 {
58 res += 1;
59 }
Pablo Marquez Tellod208f4f2022-07-19 12:19:46 +010060#endif /* defined(ARM_COMPUTE_ENABLE_BF16) */
Georgios Pinitase8291ac2020-02-26 09:58:13 +000061 return res;
62}
63
64/** Convert bfloat16 to float
65 *
66 * @param[in] v Bfloat16 value to convert to float
67 *
68 * @return Converted value
69 */
70inline float bf16_to_float(const uint16_t &v)
71{
72 const uint32_t lv = (v << 16);
Pablo Marquez Tellof73db972021-03-24 17:50:19 +000073 float fp;
74 memcpy(&fp, &lv, sizeof(lv));
75 return fp;
Georgios Pinitase8291ac2020-02-26 09:58:13 +000076}
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010077} // namespace
Georgios Pinitase8291ac2020-02-26 09:58:13 +000078
79/** Brain floating point representation class */
Georgios Pinitasc7b183a2020-03-06 18:12:09 +000080class bfloat16 final
Georgios Pinitase8291ac2020-02-26 09:58:13 +000081{
82public:
83 /** Default Constructor */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010084 bfloat16() : value(0)
Georgios Pinitase8291ac2020-02-26 09:58:13 +000085 {
86 }
87 /** Constructor
88 *
89 * @param[in] v Floating-point value
90 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010091 bfloat16(float v) : value(float_to_bf16(v))
Georgios Pinitase8291ac2020-02-26 09:58:13 +000092 {
93 }
94 /** Assignment operator
95 *
96 * @param[in] v Floating point value to assign
97 *
98 * @return The updated object
99 */
100 bfloat16 &operator=(float v)
101 {
102 value = float_to_bf16(v);
103 return *this;
104 }
105 /** Floating point conversion operator
106 *
107 * @return Floating point representation of the value
108 */
109 operator float() const
110 {
111 return bf16_to_float(value);
112 }
113 /** Lowest representative value
114 *
115 * @return Returns the lowest finite value representable by bfloat16
116 */
117 static bfloat16 lowest()
118 {
119 bfloat16 val;
120 val.value = 0xFF7F;
121 return val;
122 }
123 /** Largest representative value
124 *
125 * @return Returns the largest finite value representable by bfloat16
126 */
127 static bfloat16 max()
128 {
129 bfloat16 val;
130 val.value = 0x7F7F;
131 return val;
132 }
133
134private:
135 uint16_t value;
136};
137} // namespace arm_compute
Pablo Marquez Tellof73db972021-03-24 17:50:19 +0000138#endif /* ARM_COMPUTE_BFLOAT16_H */