Make qsort input size more reasonable
[riscv-tests.git] / benchmarks / vec-cmplxmult / vec_cmplxmult_main.c
1 //**************************************************************************
2 // Vector-Thread Complex Multiply benchmark
3 //--------------------------------------------------------------------------
4 //
5 // This benchmark multiplies two complex numbers together. The input data (and
6 // reference data) should be generated using the cmplxmult_gendata.pl perl
7 // script and dumped to a file named dataset.h. The riscv-gcc toolchain does
8 // not support system calls so printf's can only be used on a host system, not
9 // on the riscv-v processor simulator itself.
10 //
11 // HOWEVER: printstr() and printhex() are provided, for a primitive form of
12 // printing strings and hexadecimal values to stdout.
13
14
15 // Choose which implementation you wish to test... but leave only one on!
16 // (only the first one will be executed).
17 //#define SCALAR_C
18 //#define SCALAR_ASM
19 #define VT_ASM
20
21 //--------------------------------------------------------------------------
22 // Macros
23
24 // Set HOST_DEBUG to 1 if you are going to compile this for a host
25 // machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
26 // to 0 if you are compiling with the smips-gcc toolchain.
27
28 #ifndef HOST_DEBUG
29 #define HOST_DEBUG 0
30 #endif
31
32 // Set PREALLOCATE to 1 if you want to preallocate the benchmark
33 // function before starting stats. If you have instruction/data
34 // caches and you don't want to count the overhead of misses, then
35 // you will need to use preallocation.
36
37 #ifndef PREALLOCATE
38 #define PREALLOCATE 0
39 #endif
40
41 // Set SET_STATS to 1 if you want to carve out the piece that actually
42 // does the computation.
43
44 #ifndef SET_STATS
45 #define SET_STATS 0
46 #endif
47
48 //--------------------------------------------------------------------------
49 // Host Platform Includes
50
51 #if HOST_DEBUG
52 #include <stdio.h>
53 #include <stdlib.h>
54 #else
55 void printstr(const char*);
56 #endif
57
58 #include "util.h"
59
60
61 //--------------------------------------------------------------------------
62 // Complex Value Structs
63
64 struct Complex
65 {
66 float real;
67 float imag;
68 };
69
70
71 //--------------------------------------------------------------------------
72 // Input/Reference Data
73
74 //#include "dataset_test.h"
75 #include "dataset.h"
76
77
78 //--------------------------------------------------------------------------
79 // Helper functions
80
81 float absolute( float in)
82 {
83 if (in > 0)
84 return in;
85 else
86 return -in;
87 }
88
89
90 // are two floating point numbers "close enough"?
91 // this is pretty loose, because Perl is giving me pretty terrible answers
92 int close_enough(float a, float b)
93 {
94 int close_enough = 1;
95
96 if ( absolute(a) > 1.10*absolute(b)
97 || absolute(a) < 0.90*absolute(b)
98 || absolute(a) > 1.10*absolute(b)
99 || absolute(a) < 0.90*absolute(b))
100 {
101 if (absolute(absolute(a) - absolute(b)) > 0.1)
102 {
103 close_enough = 0;
104 }
105 }
106
107 return close_enough;
108 }
109
110 int verify( int n, struct Complex test[], struct Complex correct[] )
111 {
112 int i;
113 for ( i = 0; i < n; i++ ) {
114 if ( !close_enough(test[i].real, correct[i].real)
115 || !close_enough(test[i].imag, correct[i].imag))
116 {
117 #if HOST_DEBUG
118 printf(" test[%d] : {%3.2f, %3.2f}\n", i, test[i].real, test[i].imag);
119 printf(" corr[%d] : {%3.2f, %3.2f}\n", i, correct[i].real, correct[i].imag);
120 #endif
121 // tell us which index fails + 10
122 // (so that if i==0,i==1 fails, we don't
123 // think it was a 'not-finished yet' or pass)
124 // return i+10;
125 return 2;
126 }
127 }
128 return 1;
129 }
130
131 //#if HOST_DEBUG
132 void printComplexArray( char name[], int n, struct Complex arr[] )
133 {
134 #if HOST_DEBUG
135 int i;
136 printf( " %10s :", name );
137 for ( i = 0; i < n; i++ )
138 printf( " {%03.2f,%03.2f} ", arr[i].real, arr[i].imag );
139 printf( "\n" );
140 #else
141 int i;
142 printstr( name );
143 for ( i = 0; i < n; i++ )
144 {
145 printstr(" {");
146 printhex((int) arr[i].real);
147 printstr(",");
148 printhex((int) arr[i].imag);
149 printstr("}");
150 }
151 printstr( "\n" );
152 #endif
153 }
154 //#endif
155
156
157
158 void finishTest( int correct, long long num_cycles, long long num_retired )
159 {
160 int toHostValue = correct;
161 #if HOST_DEBUG
162 if ( toHostValue == 1 )
163 printf( "*** PASSED ***\n" );
164 else
165 printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
166 exit(0);
167 #else
168 // we no longer run in -testrun mode, which means we can't use
169 // the tohost register to communicate "test is done" and "test results"
170 // so instead we will communicate through print* functions!
171 if ( correct == 1 )
172 {
173 printstr( "*** PASSED *** (num_cycles = 0x" );
174 printhex(num_cycles);
175 printstr( ", num_inst_retired = 0x");
176 printhex(num_retired);
177 printstr( ")\n" );
178 }
179 else
180 {
181 printstr( "*** FAILED *** (num_cycles = 0x");
182 printhex(num_cycles);
183 printstr( ", num_inst_retired = 0x");
184 printhex(num_retired);
185 printstr( ")\n" );
186 }
187 exit();
188 #endif
189 }
190
191
192
193
194 // deprecated - cr10/stats-enable register no longer exists
195 void setStats( int enable )
196 {
197 #if ( !HOST_DEBUG && SET_STATS )
198 asm( "mtpcr %0, cr10" : : "r" (enable) );
199 #endif
200 }
201
202 long long getCycles()
203 {
204 long long cycles = 1337;
205 #if ( !HOST_DEBUG && SET_STATS )
206 __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) );
207 #endif
208 return cycles;
209 }
210
211 long long getInstRetired()
212 {
213 long long inst_retired = 1338;
214 #if ( !HOST_DEBUG && SET_STATS )
215 __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) );
216 #endif
217 return inst_retired;
218 }
219
220 //--------------------------------------------------------------------------
221 // complex multiply function
222
223 // scalar C implementation
224 void cmplxmult( int n, struct Complex a[], struct Complex b[], struct Complex c[] )
225 {
226 int i;
227 for ( i = 0; i < n; i++ )
228 {
229 c[i].real = (a[i].real * b[i].real) - (a[i].imag * b[i].imag);
230 c[i].imag = (a[i].imag * b[i].real) + (a[i].real * b[i].imag);
231 }
232 }
233
234 // assembly implementations can be found in *_asm.S
235
236 //--------------------------------------------------------------------------
237 // Main
238
239 int main( int argc, char* argv[] )
240 {
241 struct Complex results_data[DATA_SIZE];
242 long long start_cycles = 0;
243 long long stop_cycles = 0;
244 long long num_cycles;
245 long long start_retired = 0;
246 long long stop_retired = 0;
247 long long num_retired;
248
249 // Output the input array
250
251 #if HOST_DEBUG
252 printComplexArray( "input1", DATA_SIZE, input1_data );
253 printComplexArray( "input2", DATA_SIZE, input2_data );
254 printComplexArray( "verify", DATA_SIZE, verify_data );
255 #endif
256
257 // --------------------------------------------------
258 // If needed we preallocate everything in the caches
259
260 #if PREALLOCATE
261
262 #ifdef SCALAR_C
263 cmplxmult( DATA_SIZE, input1_data, input2_data, results_data );
264 #else
265 #ifdef SCALAR_ASM
266 scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
267 #else
268 #ifdef VT_ASM
269 vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
270 #endif
271 #endif
272 #endif
273
274 #endif
275
276 // --------------------------------------------------
277 // Do the cmplxmult
278
279 start_cycles = getCycles();
280 start_retired = getInstRetired();
281
282 #ifdef SCALAR_C
283 cmplxmult( DATA_SIZE, input1_data, input2_data, results_data );
284 #else
285 #ifdef SCALAR_ASM
286 #if HOST_DEBUG==0
287 scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
288 #endif
289 #else
290 #ifdef VT_ASM
291 #if HOST_DEBUG==0
292 vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
293 #endif
294 #endif
295 #endif
296 #endif
297
298 stop_cycles = getCycles();
299 stop_retired = getInstRetired();
300 num_cycles = stop_cycles - start_cycles;
301 num_retired = stop_retired - start_retired;
302
303 // --------------------------------------------------
304 // Print out the results
305
306 #if HOST_DEBUG
307 printComplexArray( "results", DATA_SIZE, results_data );
308 printComplexArray( "verify ", DATA_SIZE, verify_data );
309 #endif
310
311
312 // --------------------------------------------------
313 // Check the results
314 int correct = verify( DATA_SIZE, results_data, verify_data );
315 finishTest(correct, num_cycles, num_retired);
316
317 }