benchmarks initial commit
[riscv-tests.git] / benchmarks / vec-vvadd / vec_vvadd_main.c
1 //**************************************************************************
2 // Vector-Thread Vector-vector add benchmark
3 //--------------------------------------------------------------------------
4 //
5 // This benchmark uses adds to vectors and writes the results to a third
6 // vector. The input data (and reference data) should be generated using the
7 // vvadd_gendata.pl perl script and dumped to a file named dataset.h. The
8 // riscv-gcc toolchain does not support system calls so printf's can only be
9 // used on a host system, not 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 // Platform Specific 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 // Input/Reference Data
62
63 //#include "dataset_test.h"
64 #include "dataset.h"
65
66 //--------------------------------------------------------------------------
67 // Helper functions
68
69 int verify( int n, float test[], float correct[] )
70 {
71 int i;
72 for ( i = 0; i < n; i++ ) {
73 // if ( test[i] != correct[i] ) {
74 if ( test[i] > 1.02*correct[i]
75 || test[i] < 0.98*correct[i]) {
76 #if HOST_DEBUG
77 printf(" test[%d] : %3.2f\n", i, test[i]);
78 printf(" corr[%d] : %3.2f\n", i, correct[i]);
79 #endif
80 // tell us which index fails + 2
81 // (so that if i==0,i==1 fails, we don't
82 // think it was a 'not-finished yet' or pass)
83 // return i+10;
84 return 2;
85 }
86 }
87 return 1;
88 }
89
90 #if HOST_DEBUG
91 void printArray( char name[], int n, float arr[] )
92 {
93 int i;
94 printf( " %10s :", name );
95 for ( i = 0; i < n; i++ )
96 printf( " %03.2f ", arr[i] );
97 printf( "\n" );
98 }
99 #endif
100
101
102 void finishTest( int correct, long long num_cycles, long long num_retired )
103 {
104 int toHostValue = correct;
105 #if HOST_DEBUG
106 if ( toHostValue == 1 )
107 printf( "*** PASSED ***\n" );
108 else
109 printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
110 exit(0);
111 #else
112 // we no longer run in -testrun mode, which means we can't use
113 // the tohost register to communicate "test is done" and "test results"
114 // so instead we will communicate through print* functions!
115 if ( correct == 1 )
116 {
117 printstr( "*** PASSED *** (num_cycles = 0x" );
118 printhex(num_cycles);
119 printstr( ", num_inst_retired = 0x");
120 printhex(num_retired);
121 printstr( ")\n" );
122 }
123 else
124 {
125 printstr( "*** FAILED *** (num_cycles = 0x");
126 printhex(num_cycles);
127 printstr( ", num_inst_retired = 0x");
128 printhex(num_retired);
129 printstr( ")\n" );
130 }
131 exit();
132 #endif
133 }
134
135
136 // deprecated - cr10/stats-enable register no longer exists
137 void setStats( int enable )
138 {
139 #if ( !HOST_DEBUG && SET_STATS )
140 asm( "mtpcr %0, cr10" : : "r" (enable) );
141 #endif
142 }
143
144 long long getCycles()
145 {
146 long long cycles = 1337;
147 #if ( !HOST_DEBUG && SET_STATS )
148 __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) );
149 #endif
150 return cycles;
151 }
152
153 long long getInstRetired()
154 {
155 long long inst_retired = 1338;
156 #if ( !HOST_DEBUG && SET_STATS )
157 __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) );
158 #endif
159 return inst_retired;
160 }
161
162 //--------------------------------------------------------------------------
163 // vvadd function
164
165 // scalar C implementation
166 void vvadd( int n, float a[], float b[], float c[] )
167 {
168 int i;
169 for ( i = 0; i < n; i++ )
170 c[i] = a[i] + b[i];
171 }
172
173 // assembly implementations can be found in *_asm.S
174
175 //--------------------------------------------------------------------------
176 // Main
177
178 int main( int argc, char* argv[] )
179 {
180 float results_data[DATA_SIZE];
181 long long start_cycles = 0;
182 long long stop_cycles = 0;
183 long long num_cycles;
184 long long start_retired = 0;
185 long long stop_retired = 0;
186 long long num_retired;
187
188 // Output the input array
189
190 #if HOST_DEBUG
191 printArray( "input1", DATA_SIZE, input1_data );
192 printArray( "input2", DATA_SIZE, input2_data );
193 printArray( "verify", DATA_SIZE, verify_data );
194 #endif
195
196 // --------------------------------------------------
197 // If needed we preallocate everything in the caches
198
199 #if PREALLOCATE
200
201 #ifdef SCALAR_C
202 vvadd( DATA_SIZE, input1_data, input2_data, results_data );
203 #else
204 #ifdef SCALAR_ASM
205 scalar_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data );
206 #else
207 #ifdef VT_ASM
208 vt_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data );
209 #endif
210 #endif
211 #endif
212
213 #endif
214
215 // --------------------------------------------------
216 // Do the vvadd
217 start_cycles = getCycles();
218 start_retired = getInstRetired();
219
220 #ifdef SCALAR_C
221 vvadd( DATA_SIZE, input1_data, input2_data, results_data );
222 #else
223 #ifdef SCALAR_ASM
224 #if HOST_DEBUG==0
225 scalar_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data );
226 #endif
227 #else
228 #ifdef VT_ASM
229 #if HOST_DEBUG==0
230 vt_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data );
231 #endif
232 #endif
233 #endif
234 #endif
235
236 stop_cycles = getCycles();
237 stop_retired = getInstRetired();
238 num_cycles = stop_cycles - start_cycles;
239 num_retired = stop_retired - start_retired;
240
241 // printstr("stop_cycles: "); printhex(stop_cycles); printstr("\n");
242 // printstr("star_cycles: "); printhex(start_cycles); printstr("\n");
243
244 // --------------------------------------------------
245 // Print out the results
246
247 #if HOST_DEBUG
248 printArray( "results", DATA_SIZE, results_data );
249 #endif
250
251 // --------------------------------------------------
252 // Check the results
253 int correct = verify( DATA_SIZE, results_data, verify_data );
254 finishTest(correct, num_cycles, num_retired);
255 }