1 | /* |
---|
2 | Author : Shay Gal-On, EEMBC |
---|
3 | |
---|
4 | This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 |
---|
5 | All rights reserved. |
---|
6 | |
---|
7 | EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the |
---|
8 | CoreMark License that is distributed with the official EEMBC COREMARK Software release. |
---|
9 | If you received this EEMBC CoreMark Software without the accompanying CoreMark License, |
---|
10 | you must discontinue use and download the official release from www.coremark.org. |
---|
11 | |
---|
12 | Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, |
---|
13 | make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file. |
---|
14 | |
---|
15 | EEMBC |
---|
16 | 4354 Town Center Blvd. Suite 114-200 |
---|
17 | El Dorado Hills, CA, 95762 |
---|
18 | */ |
---|
19 | /* File: core_main.c |
---|
20 | This file contains the framework to acquire a block of memory, seed initial parameters, tun t he benchmark and report the results. |
---|
21 | */ |
---|
22 | #include "coremark.h" |
---|
23 | |
---|
24 | /* Function: iterate |
---|
25 | Run the benchmark for a specified number of iterations. |
---|
26 | |
---|
27 | Operation: |
---|
28 | For each type of benchmarked algorithm: |
---|
29 | a - Initialize the data block for the algorithm. |
---|
30 | b - Execute the algorithm N times. |
---|
31 | |
---|
32 | Returns: |
---|
33 | NULL. |
---|
34 | */ |
---|
35 | static ee_u16 list_known_crc[] = {(ee_u16)0xd4b0,(ee_u16)0x3340,(ee_u16)0x6a79,(ee_u16)0xe714,(ee_u16)0xe3c1}; |
---|
36 | static ee_u16 matrix_known_crc[] = {(ee_u16)0xbe52,(ee_u16)0x1199,(ee_u16)0x5608,(ee_u16)0x1fd7,(ee_u16)0x0747}; |
---|
37 | static ee_u16 state_known_crc[] = {(ee_u16)0x5e47,(ee_u16)0x39bf,(ee_u16)0xe5a4,(ee_u16)0x8e3a,(ee_u16)0x8d84}; |
---|
38 | void *iterate(void *pres) { |
---|
39 | ee_u32 i; |
---|
40 | ee_u16 crc; |
---|
41 | core_results *res=(core_results *)pres; |
---|
42 | ee_u32 iterations=res->iterations; |
---|
43 | res->crc=0; |
---|
44 | res->crclist=0; |
---|
45 | res->crcmatrix=0; |
---|
46 | res->crcstate=0; |
---|
47 | |
---|
48 | for (i=0; i<iterations; i++) { |
---|
49 | crc=core_bench_list(res,1); |
---|
50 | res->crc=crcu16(crc,res->crc); |
---|
51 | crc=core_bench_list(res,-1); |
---|
52 | res->crc=crcu16(crc,res->crc); |
---|
53 | if (i==0) res->crclist=res->crc; |
---|
54 | } |
---|
55 | return NULL; |
---|
56 | } |
---|
57 | |
---|
58 | #if (SEED_METHOD==SEED_ARG) |
---|
59 | ee_s32 get_seed_args(int i, int argc, char *argv[]); |
---|
60 | #define get_seed(x) (ee_s16)get_seed_args(x,argc,argv) |
---|
61 | #define get_seed_32(x) get_seed_args(x,argc,argv) |
---|
62 | #else /* via function or volatile */ |
---|
63 | ee_s32 get_seed_32(int i); |
---|
64 | #define get_seed(x) (ee_s16)get_seed_32(x) |
---|
65 | #endif |
---|
66 | |
---|
67 | #if (MEM_METHOD==MEM_STATIC) |
---|
68 | ee_u8 static_memblk[TOTAL_DATA_SIZE]; |
---|
69 | #endif |
---|
70 | char *mem_name[3] = {"Static","Heap","Stack"}; |
---|
71 | /* Function: main |
---|
72 | Main entry routine for the benchmark. |
---|
73 | This function is responsible for the following steps: |
---|
74 | |
---|
75 | 1 - Initialize input seeds from a source that cannot be determined at compile time. |
---|
76 | 2 - Initialize memory block for use. |
---|
77 | 3 - Run and time the benchmark. |
---|
78 | 4 - Report results, testing the validity of the output if the seeds are known. |
---|
79 | |
---|
80 | Arguments: |
---|
81 | 1 - first seed : Any value |
---|
82 | 2 - second seed : Must be identical to first for iterations to be identical |
---|
83 | 3 - third seed : Any value, should be at least an order of magnitude less then the input size, but bigger then 32. |
---|
84 | 4 - Iterations : Special, if set to 0, iterations will be automatically determined such that the benchmark will run between 10 to 100 secs |
---|
85 | |
---|
86 | */ |
---|
87 | |
---|
88 | #if MAIN_HAS_NOARGC |
---|
89 | MAIN_RETURN_TYPE main(void) { |
---|
90 | int argc=0; |
---|
91 | char *argv[1]; |
---|
92 | #else |
---|
93 | MAIN_RETURN_TYPE main(int argc, char *argv[]) { |
---|
94 | #endif |
---|
95 | ee_u16 i,j=0,num_algorithms=0; |
---|
96 | ee_s16 known_id=-1,total_errors=0; |
---|
97 | ee_u16 seedcrc=0; |
---|
98 | CORE_TICKS total_time; |
---|
99 | core_results results[MULTITHREAD]; |
---|
100 | #if (MEM_METHOD==MEM_STACK) |
---|
101 | ee_u8 stack_memblock[TOTAL_DATA_SIZE*MULTITHREAD]; |
---|
102 | #endif |
---|
103 | /* first call any initializations needed */ |
---|
104 | portable_init(&(results[0].port), &argc, argv); |
---|
105 | /* First some checks to make sure benchmark will run ok */ |
---|
106 | if (sizeof(struct list_head_s)>128) { |
---|
107 | ee_printf("list_head structure too big for comparable data!\n"); |
---|
108 | return MAIN_RETURN_VAL; |
---|
109 | } |
---|
110 | results[0].seed1=get_seed(1); |
---|
111 | results[0].seed2=get_seed(2); |
---|
112 | results[0].seed3=get_seed(3); |
---|
113 | results[0].iterations=get_seed_32(4); |
---|
114 | #if CORE_DEBUG |
---|
115 | results[0].iterations=1; |
---|
116 | #endif |
---|
117 | results[0].execs=get_seed_32(5); |
---|
118 | if (results[0].execs==0) { /* if not supplied, execute all algorithms */ |
---|
119 | results[0].execs=ALL_ALGORITHMS_MASK; |
---|
120 | } |
---|
121 | /* put in some default values based on one seed only for easy testing */ |
---|
122 | if ((results[0].seed1==0) && (results[0].seed2==0) && (results[0].seed3==0)) { /* validation run */ |
---|
123 | results[0].seed1=0; |
---|
124 | results[0].seed2=0; |
---|
125 | results[0].seed3=0x66; |
---|
126 | } |
---|
127 | if ((results[0].seed1==1) && (results[0].seed2==0) && (results[0].seed3==0)) { /* perfromance run */ |
---|
128 | results[0].seed1=0x3415; |
---|
129 | results[0].seed2=0x3415; |
---|
130 | results[0].seed3=0x66; |
---|
131 | } |
---|
132 | #if (MEM_METHOD==MEM_STATIC) |
---|
133 | results[0].memblock[0]=(void *)static_memblk; |
---|
134 | results[0].size=TOTAL_DATA_SIZE; |
---|
135 | results[0].err=0; |
---|
136 | #if (MULTITHREAD>1) |
---|
137 | #error "Cannot use a static data area with multiple contexts!" |
---|
138 | #endif |
---|
139 | #elif (MEM_METHOD==MEM_MALLOC) |
---|
140 | for (i=0 ; i<MULTITHREAD; i++) { |
---|
141 | ee_s32 malloc_override=get_seed(7); |
---|
142 | if (malloc_override != 0) |
---|
143 | results[i].size=malloc_override; |
---|
144 | else |
---|
145 | results[i].size=TOTAL_DATA_SIZE; |
---|
146 | results[i].memblock[0]=portable_malloc(results[i].size); |
---|
147 | results[i].seed1=results[0].seed1; |
---|
148 | results[i].seed2=results[0].seed2; |
---|
149 | results[i].seed3=results[0].seed3; |
---|
150 | results[i].err=0; |
---|
151 | results[i].execs=results[0].execs; |
---|
152 | } |
---|
153 | #elif (MEM_METHOD==MEM_STACK) |
---|
154 | for (i=0 ; i<MULTITHREAD; i++) { |
---|
155 | results[i].memblock[0]=stack_memblock+i*TOTAL_DATA_SIZE; |
---|
156 | results[i].size=TOTAL_DATA_SIZE; |
---|
157 | results[i].seed1=results[0].seed1; |
---|
158 | results[i].seed2=results[0].seed2; |
---|
159 | results[i].seed3=results[0].seed3; |
---|
160 | results[i].err=0; |
---|
161 | results[i].execs=results[0].execs; |
---|
162 | } |
---|
163 | #else |
---|
164 | #error "Please define a way to initialize a memory block." |
---|
165 | #endif |
---|
166 | /* Data init */ |
---|
167 | /* Find out how space much we have based on number of algorithms */ |
---|
168 | for (i=0; i<NUM_ALGORITHMS; i++) { |
---|
169 | if ((1<<(ee_u32)i) & results[0].execs) |
---|
170 | num_algorithms++; |
---|
171 | } |
---|
172 | for (i=0 ; i<MULTITHREAD; i++) |
---|
173 | results[i].size=results[i].size/num_algorithms; |
---|
174 | /* Assign pointers */ |
---|
175 | for (i=0; i<NUM_ALGORITHMS; i++) { |
---|
176 | ee_u32 ctx; |
---|
177 | if ((1<<(ee_u32)i) & results[0].execs) { |
---|
178 | for (ctx=0 ; ctx<MULTITHREAD; ctx++) |
---|
179 | results[ctx].memblock[i+1]=(char *)(results[ctx].memblock[0])+results[0].size*j; |
---|
180 | j++; |
---|
181 | } |
---|
182 | } |
---|
183 | /* call inits */ |
---|
184 | for (i=0 ; i<MULTITHREAD; i++) { |
---|
185 | if (results[i].execs & ID_LIST) { |
---|
186 | results[i].list=core_list_init(results[0].size,results[i].memblock[1],results[i].seed1); |
---|
187 | } |
---|
188 | if (results[i].execs & ID_MATRIX) { |
---|
189 | core_init_matrix(results[0].size, results[i].memblock[2], (ee_s32)results[i].seed1 | (((ee_s32)results[i].seed2) << 16), &(results[i].mat) ); |
---|
190 | } |
---|
191 | if (results[i].execs & ID_STATE) { |
---|
192 | core_init_state(results[0].size,results[i].seed1,results[i].memblock[3]); |
---|
193 | } |
---|
194 | } |
---|
195 | |
---|
196 | /* automatically determine number of iterations if not set */ |
---|
197 | if (results[0].iterations==0) { |
---|
198 | secs_ret secs_passed=0; |
---|
199 | ee_u32 divisor; |
---|
200 | results[0].iterations=1; |
---|
201 | while (secs_passed < (secs_ret)1) { |
---|
202 | results[0].iterations*=10; |
---|
203 | start_time(); |
---|
204 | iterate(&results[0]); |
---|
205 | stop_time(); |
---|
206 | secs_passed=time_in_secs(get_time()); |
---|
207 | } |
---|
208 | /* now we know it executes for at least 1 sec, set actual run time at about 10 secs */ |
---|
209 | divisor=(ee_u32)secs_passed; |
---|
210 | if (divisor==0) /* some machines cast float to int as 0 since this conversion is not defined by ANSI, but we know at least one second passed */ |
---|
211 | divisor=1; |
---|
212 | results[0].iterations*=1+10/divisor; |
---|
213 | } |
---|
214 | /* perform actual benchmark */ |
---|
215 | start_time(); |
---|
216 | #if (MULTITHREAD>1) |
---|
217 | if (default_num_contexts>MULTITHREAD) { |
---|
218 | default_num_contexts=MULTITHREAD; |
---|
219 | } |
---|
220 | for (i=0 ; i<default_num_contexts; i++) { |
---|
221 | results[i].iterations=results[0].iterations; |
---|
222 | results[i].execs=results[0].execs; |
---|
223 | core_start_parallel(&results[i]); |
---|
224 | } |
---|
225 | for (i=0 ; i<default_num_contexts; i++) { |
---|
226 | core_stop_parallel(&results[i]); |
---|
227 | } |
---|
228 | #else |
---|
229 | iterate(&results[0]); |
---|
230 | #endif |
---|
231 | stop_time(); |
---|
232 | total_time=get_time(); |
---|
233 | /* get a function of the input to report */ |
---|
234 | seedcrc=crc16(results[0].seed1,seedcrc); |
---|
235 | seedcrc=crc16(results[0].seed2,seedcrc); |
---|
236 | seedcrc=crc16(results[0].seed3,seedcrc); |
---|
237 | seedcrc=crc16(results[0].size,seedcrc); |
---|
238 | |
---|
239 | switch (seedcrc) { /* test known output for common seeds */ |
---|
240 | case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */ |
---|
241 | known_id=0; |
---|
242 | ee_printf("6k performance run parameters for coremark.\n"); |
---|
243 | break; |
---|
244 | case 0x7b05: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per algorithm */ |
---|
245 | known_id=1; |
---|
246 | ee_printf("6k validation run parameters for coremark.\n"); |
---|
247 | break; |
---|
248 | case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm */ |
---|
249 | known_id=2; |
---|
250 | ee_printf("Profile generation run parameters for coremark.\n"); |
---|
251 | break; |
---|
252 | case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */ |
---|
253 | known_id=3; |
---|
254 | ee_printf("2K performance run parameters for coremark.\n"); |
---|
255 | break; |
---|
256 | case 0x18f2: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per algorithm */ |
---|
257 | known_id=4; |
---|
258 | ee_printf("2K validation run parameters for coremark.\n"); |
---|
259 | break; |
---|
260 | default: |
---|
261 | total_errors=-1; |
---|
262 | break; |
---|
263 | } |
---|
264 | if (known_id>=0) { |
---|
265 | for (i=0 ; i<default_num_contexts; i++) { |
---|
266 | results[i].err=0; |
---|
267 | if ((results[i].execs & ID_LIST) && |
---|
268 | (results[i].crclist!=list_known_crc[known_id])) { |
---|
269 | ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n",i,results[i].crclist,list_known_crc[known_id]); |
---|
270 | results[i].err++; |
---|
271 | } |
---|
272 | if ((results[i].execs & ID_MATRIX) && |
---|
273 | (results[i].crcmatrix!=matrix_known_crc[known_id])) { |
---|
274 | ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n",i,results[i].crcmatrix,matrix_known_crc[known_id]); |
---|
275 | results[i].err++; |
---|
276 | } |
---|
277 | if ((results[i].execs & ID_STATE) && |
---|
278 | (results[i].crcstate!=state_known_crc[known_id])) { |
---|
279 | ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n",i,results[i].crcstate,state_known_crc[known_id]); |
---|
280 | results[i].err++; |
---|
281 | } |
---|
282 | total_errors+=results[i].err; |
---|
283 | } |
---|
284 | } |
---|
285 | total_errors+=check_data_types(); |
---|
286 | /* and report results */ |
---|
287 | ee_printf("CoreMark Size : %lu\n",(ee_u32)results[0].size); |
---|
288 | ee_printf("Total ticks : %lu\n",(ee_u32)total_time); |
---|
289 | #if HAS_FLOAT |
---|
290 | ee_printf("Total time (secs): %f\n",time_in_secs(total_time)); |
---|
291 | if (time_in_secs(total_time) > 0) |
---|
292 | ee_printf("Iterations/Sec : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time)); |
---|
293 | #else |
---|
294 | ee_printf("Total time (secs): %d\n",time_in_secs(total_time)); |
---|
295 | if (time_in_secs(total_time) > 0) |
---|
296 | ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time)); |
---|
297 | #endif |
---|
298 | if (time_in_secs(total_time) < 10) { |
---|
299 | ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n"); |
---|
300 | total_errors++; |
---|
301 | } |
---|
302 | |
---|
303 | ee_printf("Iterations : %lu\n",(ee_u32)default_num_contexts*results[0].iterations); |
---|
304 | ee_printf("Compiler version : %s\n",COMPILER_VERSION); |
---|
305 | ee_printf("Compiler flags : %s\n",COMPILER_FLAGS); |
---|
306 | #if (MULTITHREAD>1) |
---|
307 | ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts); |
---|
308 | #endif |
---|
309 | ee_printf("Memory location : %s\n",MEM_LOCATION); |
---|
310 | /* output for verification */ |
---|
311 | ee_printf("seedcrc : 0x%04x\n",seedcrc); |
---|
312 | if (results[0].execs & ID_LIST) |
---|
313 | for (i=0 ; i<default_num_contexts; i++) |
---|
314 | ee_printf("[%d]crclist : 0x%04x\n",i,results[i].crclist); |
---|
315 | if (results[0].execs & ID_MATRIX) |
---|
316 | for (i=0 ; i<default_num_contexts; i++) |
---|
317 | ee_printf("[%d]crcmatrix : 0x%04x\n",i,results[i].crcmatrix); |
---|
318 | if (results[0].execs & ID_STATE) |
---|
319 | for (i=0 ; i<default_num_contexts; i++) |
---|
320 | ee_printf("[%d]crcstate : 0x%04x\n",i,results[i].crcstate); |
---|
321 | for (i=0 ; i<default_num_contexts; i++) |
---|
322 | ee_printf("[%d]crcfinal : 0x%04x\n",i,results[i].crc); |
---|
323 | if (total_errors==0) { |
---|
324 | ee_printf("Correct operation validated. See readme.txt for run and reporting rules.\n"); |
---|
325 | #if HAS_FLOAT |
---|
326 | if (known_id==3) { |
---|
327 | ee_printf("CoreMark 1.0 : %f / %s %s",default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS); |
---|
328 | #if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC) |
---|
329 | ee_printf(" / %s",MEM_LOCATION); |
---|
330 | #else |
---|
331 | ee_printf(" / %s",mem_name[MEM_METHOD]); |
---|
332 | #endif |
---|
333 | |
---|
334 | #if (MULTITHREAD>1) |
---|
335 | ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD); |
---|
336 | #endif |
---|
337 | ee_printf("\n"); |
---|
338 | } |
---|
339 | #endif |
---|
340 | } |
---|
341 | if (total_errors>0) |
---|
342 | ee_printf("Errors detected\n"); |
---|
343 | if (total_errors<0) |
---|
344 | ee_printf("Cannot validate operation for these seed values, please compare with results on a known platform.\n"); |
---|
345 | |
---|
346 | #if (MEM_METHOD==MEM_MALLOC) |
---|
347 | for (i=0 ; i<MULTITHREAD; i++) |
---|
348 | portable_free(results[i].memblock[0]); |
---|
349 | #endif |
---|
350 | /* And last call any target specific code for finalizing */ |
---|
351 | portable_fini(&(results[0].port)); |
---|
352 | |
---|
353 | return MAIN_RETURN_VAL; |
---|
354 | } |
---|
355 | |
---|
356 | |
---|