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