3251ef9843e67aeb1a97134079572f03cf234195
[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 void exit();
57 #endif
58
59
60 //--------------------------------------------------------------------------
61 // Complex Value Structs
62
63 struct Complex
64 {
65 float real;
66 float imag;
67 };
68
69
70 //--------------------------------------------------------------------------
71 // Input/Reference Data
72
73 //#include "dataset_test.h"
74 #include "dataset.h"
75
76
77 //--------------------------------------------------------------------------
78 // Helper functions
79
80 float absolute( float in)
81 {
82 if (in > 0)
83 return in;
84 else
85 return -in;
86 }
87
88
89 // are two floating point numbers "close enough"?
90 // this is pretty loose, because Perl is giving me pretty terrible answers
91 int close_enough(float a, float b)
92 {
93 int close_enough = 1;
94
95 if ( absolute(a) > 1.10*absolute(b)
96 || absolute(a) < 0.90*absolute(b)
97 || absolute(a) > 1.10*absolute(b)
98 || absolute(a) < 0.90*absolute(b))
99 {
100 if (absolute(absolute(a) - absolute(b)) > 0.1)
101 {
102 close_enough = 0;
103 }
104 }
105
106 return close_enough;
107 }
108
109 int verify( int n, struct Complex test[], struct Complex correct[] )
110 {
111 int i;
112 for ( i = 0; i < n; i++ ) {
113 if ( !close_enough(test[i].real, correct[i].real)
114 || !close_enough(test[i].imag, correct[i].imag))
115 {
116 #if HOST_DEBUG
117 printf(" test[%d] : {%3.2f, %3.2f}\n", i, test[i].real, test[i].imag);
118 printf(" corr[%d] : {%3.2f, %3.2f}\n", i, correct[i].real, correct[i].imag);
119 #endif
120 // tell us which index fails + 10
121 // (so that if i==0,i==1 fails, we don't
122 // think it was a 'not-finished yet' or pass)
123 // return i+10;
124 return 2;
125 }
126 }
127 return 1;
128 }
129
130 //#if HOST_DEBUG
131 void printComplexArray( char name[], int n, struct Complex arr[] )
132 {
133 #if HOST_DEBUG
134 int i;
135 printf( " %10s :", name );
136 for ( i = 0; i < n; i++ )
137 printf( " {%03.2f,%03.2f} ", arr[i].real, arr[i].imag );
138 printf( "\n" );
139 #else
140 int i;
141 printstr( name );
142 for ( i = 0; i < n; i++ )
143 {
144 printstr(" {");
145 printhex((int) arr[i].real);
146 printstr(",");
147 printhex((int) arr[i].imag);
148 printstr("}");
149 }
150 printstr( "\n" );
151 #endif
152 }
153 //#endif
154
155
156
157 void finishTest( int correct, long long num_cycles, long long num_retired )
158 {
159 int toHostValue = correct;
160 #if HOST_DEBUG
161 if ( toHostValue == 1 )
162 printf( "*** PASSED ***\n" );
163 else
164 printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
165 exit(0);
166 #else
167 // we no longer run in -testrun mode, which means we can't use
168 // the tohost register to communicate "test is done" and "test results"
169 // so instead we will communicate through print* functions!
170 if ( correct == 1 )
171 {
172 printstr( "*** PASSED *** (num_cycles = 0x" );
173 printhex(num_cycles);
174 printstr( ", num_inst_retired = 0x");
175 printhex(num_retired);
176 printstr( ")\n" );
177 }
178 else
179 {
180 printstr( "*** FAILED *** (num_cycles = 0x");
181 printhex(num_cycles);
182 printstr( ", num_inst_retired = 0x");
183 printhex(num_retired);
184 printstr( ")\n" );
185 }
186 exit();
187 #endif
188 }
189
190
191
192
193 // deprecated - cr10/stats-enable register no longer exists
194 void setStats( int enable )
195 {
196 #if ( !HOST_DEBUG && SET_STATS )
197 asm( "mtpcr %0, cr10" : : "r" (enable) );
198 #endif
199 }
200
201 long long getCycles()
202 {
203 long long cycles = 1337;
204 #if ( !HOST_DEBUG && SET_STATS )
205 __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) );
206 #endif
207 return cycles;
208 }
209
210 long long getInstRetired()
211 {
212 long long inst_retired = 1338;
213 #if ( !HOST_DEBUG && SET_STATS )
214 __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) );
215 #endif
216 return inst_retired;
217 }
218
219 //--------------------------------------------------------------------------
220 // complex multiply function
221
222 // scalar C implementation
223 void cmplxmult( int n, struct Complex a[], struct Complex b[], struct Complex c[] )
224 {
225 int i;
226 for ( i = 0; i < n; i++ )
227 {
228 c[i].real = (a[i].real * b[i].real) - (a[i].imag * b[i].imag);
229 c[i].imag = (a[i].imag * b[i].real) + (a[i].real * b[i].imag);
230 }
231 }
232
233 // assembly implementations can be found in *_asm.S
234
235 //--------------------------------------------------------------------------
236 // Main
237
238 int main( int argc, char* argv[] )
239 {
240 struct Complex results_data[DATA_SIZE];
241 long long start_cycles = 0;
242 long long stop_cycles = 0;
243 long long num_cycles;
244 long long start_retired = 0;
245 long long stop_retired = 0;
246 long long num_retired;
247
248 // Output the input array
249
250 #if HOST_DEBUG
251 printComplexArray( "input1", DATA_SIZE, input1_data );
252 printComplexArray( "input2", DATA_SIZE, input2_data );
253 printComplexArray( "verify", DATA_SIZE, verify_data );
254 #endif
255
256 // --------------------------------------------------
257 // If needed we preallocate everything in the caches
258
259 #if PREALLOCATE
260
261 #ifdef SCALAR_C
262 cmplxmult( DATA_SIZE, input1_data, input2_data, results_data );
263 #else
264 #ifdef SCALAR_ASM
265 scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
266 #else
267 #ifdef VT_ASM
268 vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
269 #endif
270 #endif
271 #endif
272
273 #endif
274
275 // --------------------------------------------------
276 // Do the cmplxmult
277
278 start_cycles = getCycles();
279 start_retired = getInstRetired();
280
281 #ifdef SCALAR_C
282 cmplxmult( DATA_SIZE, input1_data, input2_data, results_data );
283 #else
284 #ifdef SCALAR_ASM
285 #if HOST_DEBUG==0
286 scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
287 #endif
288 #else
289 #ifdef VT_ASM
290 #if HOST_DEBUG==0
291 vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data );
292 #endif
293 #endif
294 #endif
295 #endif
296
297 stop_cycles = getCycles();
298 stop_retired = getInstRetired();
299 num_cycles = stop_cycles - start_cycles;
300 num_retired = stop_retired - start_retired;
301
302 // --------------------------------------------------
303 // Print out the results
304
305 #if HOST_DEBUG
306 printComplexArray( "results", DATA_SIZE, results_data );
307 printComplexArray( "verify ", DATA_SIZE, verify_data );
308 #endif
309
310
311 // --------------------------------------------------
312 // Check the results
313 int correct = verify( DATA_SIZE, results_data, verify_data );
314 finishTest(correct, num_cycles, num_retired);
315
316 }