1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4
5 #include "fixed_point.hpp"
6 #include <type_traits>
7
8 #include "arm_math_types.h"
9
10 #if defined(ARM_FLOAT16_SUPPORTED)
11 #include "arm_math_types_f16.h"
12 #endif
13
14 #if defined(ARM_MATH_DSP)
15 #include "DSP/memory.hpp"
16 #endif
17
18 namespace arm_cmsis_dsp {
19
20 /** \addtogroup NUMBER Number datatypes
21 * \ingroup DSPPP
22 * Number datatypes expressing different properties of the numbers
23 * according to the architecture.
24 *
25 * Those definitions are used to write architecture independents
26 * algorithms.
27 * @{
28 */
29
maskFromShift(const uint32_t shift)30 constexpr uint32_t maskFromShift(const uint32_t shift)
31 {
32 return ((1<<shift)-1);
33 }
34
35
36
shiftFromValue(const uint32_t val)37 constexpr uint32_t shiftFromValue(const uint32_t val)
38 {
39 return (val == 1 ? 0 : 1 + shiftFromValue(val>>1));
40 }
41
42 /** @brief Properties of a scalar datatype
43 * @tparam T datatype
44 *
45 * Needs to contain two static bool : is_float and is_fixed
46 *
47 * Needs to contain a static function `one` returning the value
48 * 1 for this datatype (used to write some datatype generic
49 * algorithms)
50 */
51 template<typename T>
52 struct number_traits;
53
54
55 /*
56
57 When vector is true we have a vector datatype
58 A temporary accumulator datatype and an accumulator datatype.
59 For most types the temporary and accumulator are the same.
60 For float, vector instruction mac is doing a mac per lane.
61 So temporay is a vector and the final accumulator is a float.
62
63 */
64
65 /** @brief Properties of a vector datatype linked to a scalar datatype
66 * @tparam T Type of the scalar
67 * @tparam arch Architecture. It is defined by the
68 * architecture selection code and should never be
69 * set by the user.
70 */
71 template<typename T,typename arch = ARCH,typename = void>
72 struct vector_traits {
73 typedef T type; //!< Scalar datatype
74 typedef T storage_type; //!< Storage type (for instance for Q15 scalar the storage is int16_t)
75 static constexpr bool has_vector = false; //!< True if scalar type has a related vector type
76 static constexpr bool is_float = false; //!< True if scalar type is a float (half, float or double)
77 static constexpr bool is_fixed = false; //!< True if scalar type is fixed point
78 };
79
80 /** @brief Scalar properties of fixed point datatype
81 * @tparam M Mantissa bits (not including sign bit)
82 * @tparam F Fractional bits
83 * @tparam S Signed or unsigned
84 * @tparam T Storage datatype
85 */
86 template<int M, int F, bool S,typename T>
87 struct number_traits<Q<M,F,S,T>>
88 {
89 static constexpr bool is_float = false; //!< False because scalar is not a float datatype (half, float, double)
90 static constexpr bool is_fixed = true; //!< True because datatype is a fixed point arithmetic one
91
92 /** @brief Return 1 for this datatype
93 *
94 * Used for writing datatype generic algorithms
95 */
onearm_cmsis_dsp::number_traits96 static constexpr Q<M,F,S,T> one() {return Q<M,F,S,T>::one();};
97 };
98
99
100 namespace inner {
101
102 /** @brief Predicate (only defined for vector architectures)
103 * @tparam T scalar data type
104 * @param v Number of loops
105 * @return Predicate for the given architecture
106 */
107 template<typename T,typename = void>
108 struct vctpq {
109 static typename vector_traits<T>::predicate_t mk(uint32_t v);
110 };
111
112 };
113
114
115 /*
116
117 vconst
118 vconst_tail
119 vadd
120 vsub
121 vmul
122 vacc
123
124
125 vload1
126 vstore1
127
128 // When predicate
129 vctpq
130 vload1_z
131 vstore1_z
132
133 // When predicated loop
134 vadd_x
135 vsub_x
136 vmul_x
137 vmacc_p
138
139
140 */
141
142
143
144 // Common to all architectures
145 #include "num_features/double.hpp"
146 #include "num_features/float.hpp"
147 #include "num_features/half.hpp"
148 #include "num_features/q31.hpp"
149 #include "num_features/q15.hpp"
150 #include "num_features/q7.hpp"
151
152 // Specific for some architecture
153 //#include <Scalar/num_features>
154 #include "DSP/num_features.hpp"
155 #include "Helium/num_features.hpp"
156 //#include <Neon/num_features>
157
158
159 #include "num_features/group.hpp"
160
161 /*
162
163 If there is the need to tune the intrinsics depending on the
164 Helium variant of the architecture, somehting like that could be used.
165 In practice, selection is done at level of of algorithms more than
166 instructions where it may be simple to just use a #if to use the
167 right intrinsics when it is available.
168
169 */
170 #if 0
171 template<typename T>
172 __STATIC_FORCEINLINE mve_pred16_t _vctpq(uint32_t v,Helium * = nullptr);
173
174 template<>
175 __STATIC_FORCEINLINE mve_pred16_t _vctpq<float>(uint32_t v,Helium *)
176 {
177 return(vctp32q(v));
178 };
179
180 template<typename T>
181 __STATIC_FORCEINLINE mve_pred16_t vctpq(uint32_t v)
182 {
183 return(_vctpq<T>(v,CURRENT_ARCH));
184 }
185
186 #endif
187
188 /*! @} */
189
190 } // cmsis-dsp namespace