1 #include "FIRF32.h"
2 #include <stdio.h>
3 #include "Error.h"
4
5 #define SNR_THRESHOLD 120
6
7 /*
8
9 Reference patterns are generated with
10 a double precision computation.
11
12 */
13 #define REL_ERROR (3.0e-5)
14
15 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
16 static __ALIGNED(8) float32_t coeffArray[32];
17 #endif
18
checkInnerTail(float32_t * b)19 static void checkInnerTail(float32_t *b)
20 {
21 ASSERT_TRUE(b[0] == 0.0f);
22 ASSERT_TRUE(b[1] == 0.0f);
23 ASSERT_TRUE(b[2] == 0.0f);
24 ASSERT_TRUE(b[3] == 0.0f);
25 }
26
27 // Coef must be padded to a multiple of 4
28 #define FIRCOEFPADDING 2
29
test_fir_f32()30 void FIRF32::test_fir_f32()
31 {
32
33
34 const int16_t *configp = configs.ptr();
35 float32_t *statep = state.ptr();
36 const float32_t *orgcoefsp = coefs.ptr();
37
38 const float32_t *coefsp;
39 const float32_t *inputp = inputs.ptr();
40
41 float32_t *outp = output.ptr();
42
43 unsigned long i;
44 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
45 int j;
46 #endif
47 int blockSize;
48 int numTaps;
49 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
50 int round;
51 #endif
52
53
54 /*
55
56 Python script is generating different tests with
57 different blockSize and numTaps.
58
59 We loop on those configs.
60
61 */
62 for(i=0; i < configs.nbSamples() ; i += 2)
63 {
64 blockSize = configp[0];
65 numTaps = configp[1];
66
67 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
68 /* Copy coefficients and pad to zero
69 */
70 memset(coeffArray,127,32*sizeof(float32_t));
71 round = numTaps >> FIRCOEFPADDING;
72 if ((round << FIRCOEFPADDING) < numTaps)
73 {
74 round ++;
75 }
76 round = round<<FIRCOEFPADDING;
77 memset(coeffArray,0,round*sizeof(float32_t));
78
79 //printf("blockSize=%d, numTaps=%d, round=%d (%d)\n",blockSize,numTaps,round,round - numTaps);
80
81
82 for(j=0;j < numTaps; j++)
83 {
84 coeffArray[j] = orgcoefsp[j];
85 }
86
87 coefsp = coeffArray;
88 #else
89 coefsp = orgcoefsp;
90 #endif
91
92 /*
93
94 The filter is initialized with the coefs, blockSize and numTaps.
95
96 */
97 arm_fir_init_f32(&this->S,numTaps,coefsp,statep,blockSize);
98
99 /*
100
101 Input pointer is reset since the same input pattern is used
102
103 */
104 inputp = inputs.ptr();
105
106
107 /*
108
109 Python script is filtering a 2*blockSize number of samples.
110 We do the same filtering in two pass to check (indirectly that
111 the state management of the fir is working.)
112
113 */
114
115
116 arm_fir_f32(&this->S,inputp,outp,blockSize);
117
118 outp += blockSize;
119 checkInnerTail(outp);
120
121 inputp += blockSize;
122 arm_fir_f32(&this->S,inputp,outp,blockSize);
123 outp += blockSize;
124 checkInnerTail(outp);
125
126 configp += 2;
127 orgcoefsp += numTaps;
128
129 }
130
131
132 ASSERT_EMPTY_TAIL(output);
133
134 ASSERT_SNR(output,ref,(float32_t)SNR_THRESHOLD);
135
136 ASSERT_REL_ERROR(output,ref,REL_ERROR);
137
138 }
139
140
setUp(Testing::testID_t id,std::vector<Testing::param_t> & params,Client::PatternMgr * mgr)141 void FIRF32::setUp(Testing::testID_t id,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr)
142 {
143
144 (void)params;
145
146 switch(id)
147 {
148 case FIRF32::TEST_FIR_F32_1:
149 break;
150
151 }
152
153
154 inputs.reload(FIRF32::FIRINPUTS_F32_ID,mgr);
155 coefs.reload(FIRF32::FIRCOEFS_F32_ID,mgr);
156 configs.reload(FIRF32::FIRCONFIGS_S16_ID,mgr);
157 ref.reload(FIRF32::FIRREFS_F32_ID,mgr);
158
159 output.create(ref.nbSamples(),FIRF32::OUT_F32_ID,mgr);
160 /* Max 2*blockSize + numTaps - 1 as generated by Python script
161 A temp buffer blockSize is used by Helium implementation.
162 It is at beginning of state buffer and is NOT the state
163 of the FIR which is in the following part.
164 */
165 state.create(47+47,FIRF32::OUT_F32_ID,mgr);
166
167
168
169 }
170
tearDown(Testing::testID_t id,Client::PatternMgr * mgr)171 void FIRF32::tearDown(Testing::testID_t id,Client::PatternMgr *mgr)
172 {
173 (void)id;
174 output.dump(mgr);
175 }
176