OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [coremark/] [core_main.c] - Blame information for rev 22

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
/*
2
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3
 
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7
 
8
    http://www.apache.org/licenses/LICENSE-2.0
9
 
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
 
16
Original Author: Shay Gal-on
17
*/
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
 
96
// -----------------------------------------------
97
// -----------------------------------------------
98
// Disable coremark compilation by default
99
#ifndef RUN_COREMARK
100 22 zero_gravi
  #warning COREMARK HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.
101 21 zero_gravi
 
102
  // inform the user if you are actually executing this
103
        portable_init(NULL, &argc, argv);
104 22 zero_gravi
  ee_printf("ERROR! CoreMark has not been compiled. Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.\n");
105 21 zero_gravi
 
106 2 zero_gravi
  return 0;
107
#endif
108
// -----------------------------------------------
109
// -----------------------------------------------
110
 
111
 
112
        ee_u16 i,j=0,num_algorithms=0;
113
        ee_s16 known_id=-1,total_errors=0;
114
        ee_u16 seedcrc=0;
115
        CORE_TICKS total_time;
116
        core_results results[MULTITHREAD];
117
#if (MEM_METHOD==MEM_STACK)
118
        ee_u8 stack_memblock[TOTAL_DATA_SIZE*MULTITHREAD];
119
#endif
120
        /* first call any initializations needed */
121
        portable_init(&(results[0].port), &argc, argv);
122
        /* First some checks to make sure benchmark will run ok */
123
        if (sizeof(struct list_head_s)>128) {
124
                ee_printf("list_head structure too big for comparable data!\n");
125
                return MAIN_RETURN_VAL;
126
        }
127
        results[0].seed1=get_seed(1);
128
        results[0].seed2=get_seed(2);
129
        results[0].seed3=get_seed(3);
130
        results[0].iterations=get_seed_32(4);
131
#if CORE_DEBUG
132
        results[0].iterations=1;
133
#endif
134
        results[0].execs=get_seed_32(5);
135
        if (results[0].execs==0) { /* if not supplied, execute all algorithms */
136
                results[0].execs=ALL_ALGORITHMS_MASK;
137
        }
138
                /* put in some default values based on one seed only for easy testing */
139
        if ((results[0].seed1==0) && (results[0].seed2==0) && (results[0].seed3==0)) { /* validation run */
140
                results[0].seed1=0;
141
                results[0].seed2=0;
142
                results[0].seed3=0x66;
143
        }
144
        if ((results[0].seed1==1) && (results[0].seed2==0) && (results[0].seed3==0)) { /* perfromance run */
145
                results[0].seed1=0x3415;
146
                results[0].seed2=0x3415;
147
                results[0].seed3=0x66;
148
        }
149
#if (MEM_METHOD==MEM_STATIC)
150
        results[0].memblock[0]=(void *)static_memblk;
151
        results[0].size=TOTAL_DATA_SIZE;
152
        results[0].err=0;
153
        #if (MULTITHREAD>1)
154
        #error "Cannot use a static data area with multiple contexts!"
155
        #endif
156
#elif (MEM_METHOD==MEM_MALLOC)
157
        for (i=0 ; i<MULTITHREAD; i++) {
158
                ee_s32 malloc_override=get_seed(7);
159
                if (malloc_override != 0)
160
                        results[i].size=malloc_override;
161
                else
162
                        results[i].size=TOTAL_DATA_SIZE;
163
                results[i].memblock[0]=portable_malloc(results[i].size);
164
                results[i].seed1=results[0].seed1;
165
                results[i].seed2=results[0].seed2;
166
                results[i].seed3=results[0].seed3;
167
                results[i].err=0;
168
                results[i].execs=results[0].execs;
169
        }
170
#elif (MEM_METHOD==MEM_STACK)
171
        for (i=0 ; i<MULTITHREAD; i++) {
172
                results[i].memblock[0]=stack_memblock+i*TOTAL_DATA_SIZE;
173
                results[i].size=TOTAL_DATA_SIZE;
174
                results[i].seed1=results[0].seed1;
175
                results[i].seed2=results[0].seed2;
176
                results[i].seed3=results[0].seed3;
177
                results[i].err=0;
178
                results[i].execs=results[0].execs;
179
        }
180
#else
181
#error "Please define a way to initialize a memory block."
182
#endif
183
        /* Data init */
184
        /* Find out how space much we have based on number of algorithms */
185
        for (i=0; i<NUM_ALGORITHMS; i++) {
186
                if ((1<<(ee_u32)i) & results[0].execs)
187
                        num_algorithms++;
188
        }
189
        for (i=0 ; i<MULTITHREAD; i++)
190
                results[i].size=results[i].size/num_algorithms;
191
        /* Assign pointers */
192
        for (i=0; i<NUM_ALGORITHMS; i++) {
193
                ee_u32 ctx;
194
                if ((1<<(ee_u32)i) & results[0].execs) {
195
                        for (ctx=0 ; ctx<MULTITHREAD; ctx++)
196
                                results[ctx].memblock[i+1]=(char *)(results[ctx].memblock[0])+results[0].size*j;
197
                        j++;
198
                }
199
        }
200
        /* call inits */
201
        for (i=0 ; i<MULTITHREAD; i++) {
202
                if (results[i].execs & ID_LIST) {
203
                        results[i].list=core_list_init(results[0].size,results[i].memblock[1],results[i].seed1);
204
                }
205
                if (results[i].execs & ID_MATRIX) {
206
                        core_init_matrix(results[0].size, results[i].memblock[2], (ee_s32)results[i].seed1 | (((ee_s32)results[i].seed2) << 16), &(results[i].mat) );
207
                }
208
                if (results[i].execs & ID_STATE) {
209
                        core_init_state(results[0].size,results[i].seed1,results[i].memblock[3]);
210
                }
211
        }
212
 
213
        /* automatically determine number of iterations if not set */
214
        if (results[0].iterations==0) {
215
                secs_ret secs_passed=0;
216
                ee_u32 divisor;
217
                results[0].iterations=1;
218
                while (secs_passed < (secs_ret)1) {
219
                        results[0].iterations*=10;
220
                        start_time();
221
                        iterate(&results[0]);
222
                        stop_time();
223
                        secs_passed=time_in_secs(get_time());
224
                }
225
                /* now we know it executes for at least 1 sec, set actual run time at about 10 secs */
226
                divisor=(ee_u32)secs_passed;
227
                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 */
228
                        divisor=1;
229
                results[0].iterations*=1+10/divisor;
230
        }
231
        /* perform actual benchmark */
232
        start_time();
233
#if (MULTITHREAD>1)
234
        if (default_num_contexts>MULTITHREAD) {
235
                default_num_contexts=MULTITHREAD;
236
        }
237
        for (i=0 ; i<default_num_contexts; i++) {
238
                results[i].iterations=results[0].iterations;
239
                results[i].execs=results[0].execs;
240
                core_start_parallel(&results[i]);
241
        }
242
        for (i=0 ; i<default_num_contexts; i++) {
243
                core_stop_parallel(&results[i]);
244
        }
245
#else
246
        iterate(&results[0]);
247
#endif
248
        stop_time();
249
        total_time=get_time();
250
        /* get a function of the input to report */
251
        seedcrc=crc16(results[0].seed1,seedcrc);
252
        seedcrc=crc16(results[0].seed2,seedcrc);
253
        seedcrc=crc16(results[0].seed3,seedcrc);
254
        seedcrc=crc16(results[0].size,seedcrc);
255
 
256
        switch (seedcrc) { /* test known output for common seeds */
257
                case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */
258
                        known_id=0;
259
                        ee_printf("6k performance run parameters for coremark.\n");
260
                        break;
261
                case 0x7b05: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per algorithm */
262
                        known_id=1;
263
                        ee_printf("6k validation run parameters for coremark.\n");
264
                        break;
265
                case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm */
266
                        known_id=2;
267
                        ee_printf("Profile generation run parameters for coremark.\n");
268
                        break;
269
                case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */
270
                        known_id=3;
271
                        ee_printf("2K performance run parameters for coremark.\n");
272
                        break;
273
                case 0x18f2: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per algorithm */
274
                        known_id=4;
275
                        ee_printf("2K validation run parameters for coremark.\n");
276
                        break;
277
                default:
278
                        total_errors=-1;
279
                        break;
280
        }
281
        if (known_id>=0) {
282
                for (i=0 ; i<default_num_contexts; i++) {
283
                        results[i].err=0;
284
                        if ((results[i].execs & ID_LIST) &&
285
                                (results[i].crclist!=list_known_crc[known_id])) {
286
                                ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n",i,results[i].crclist,list_known_crc[known_id]);
287
                                results[i].err++;
288
                        }
289
                        if ((results[i].execs & ID_MATRIX) &&
290
                                (results[i].crcmatrix!=matrix_known_crc[known_id])) {
291
                                ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n",i,results[i].crcmatrix,matrix_known_crc[known_id]);
292
                                results[i].err++;
293
                        }
294
                        if ((results[i].execs & ID_STATE) &&
295
                                (results[i].crcstate!=state_known_crc[known_id])) {
296
                                ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n",i,results[i].crcstate,state_known_crc[known_id]);
297
                                results[i].err++;
298
                        }
299
                        total_errors+=results[i].err;
300
                }
301
        }
302
        total_errors+=check_data_types();
303
        /* and report results */
304
        ee_printf("CoreMark Size    : %lu\n", (long unsigned) results[0].size);
305
        ee_printf("Total ticks      : see NEORV32 output below\n", (long unsigned) total_time); /* NEORV32 modified due to overflow in %lu in ee_printf */
306
#if HAS_FLOAT
307
        ee_printf("Total time (secs): %f\n",time_in_secs(total_time));
308
        if (time_in_secs(total_time) > 0)
309
                ee_printf("Iterations/Sec   : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
310
#else 
311
        ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
312
        if (time_in_secs(total_time) > 0)
313
                ee_printf("Iterations/Sec   : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
314
#endif
315
        if (time_in_secs(total_time) < 10) {
316
                ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n");
317
                total_errors++;
318
        }
319
 
320
        ee_printf("Iterations       : %lu\n", (long unsigned) default_num_contexts*results[0].iterations);
321
        ee_printf("Compiler version : %s\n",COMPILER_VERSION);
322
        ee_printf("Compiler flags   : %s\n",COMPILER_FLAGS);
323
#if (MULTITHREAD>1)
324
        ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts);
325
#endif
326
        ee_printf("Memory location  : %s\n",MEM_LOCATION);
327
        /* output for verification */
328
        ee_printf("seedcrc          : 0x%04x\n",seedcrc);
329
        if (results[0].execs & ID_LIST)
330
                for (i=0 ; i<default_num_contexts; i++)
331
                        ee_printf("[%d]crclist       : 0x%04x\n",i,results[i].crclist);
332
        if (results[0].execs & ID_MATRIX)
333
                for (i=0 ; i<default_num_contexts; i++)
334
                        ee_printf("[%d]crcmatrix     : 0x%04x\n",i,results[i].crcmatrix);
335
        if (results[0].execs & ID_STATE)
336
                for (i=0 ; i<default_num_contexts; i++)
337
                        ee_printf("[%d]crcstate      : 0x%04x\n",i,results[i].crcstate);
338
        for (i=0 ; i<default_num_contexts; i++)
339
                ee_printf("[%d]crcfinal      : 0x%04x\n",i,results[i].crc);
340
        if (total_errors==0) {
341
                ee_printf("Correct operation validated. See README.md for run and reporting rules.\n");
342
#if HAS_FLOAT
343
                if (known_id==3) {
344
                        ee_printf("CoreMark 1.0 : %f / %s %s",default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS);
345
#if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC)
346
                        ee_printf(" / %s",MEM_LOCATION);
347
#else
348
                        ee_printf(" / %s",mem_name[MEM_METHOD]);
349
#endif
350
 
351
#if (MULTITHREAD>1)
352
                        ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD);
353
#endif
354
                        ee_printf("\n");
355
                }
356
#endif
357
        }
358
        if (total_errors>0)
359
                ee_printf("Errors detected\n");
360
        if (total_errors<0)
361
                ee_printf("Cannot validate operation for these seed values, please compare with results on a known platform.\n");
362
 
363
#if (MEM_METHOD==MEM_MALLOC)
364
        for (i=0 ; i<MULTITHREAD; i++)
365
                portable_free(results[i].memblock[0]);
366
#endif
367
        /* And last call any target specific code for finalizing */
368
        portable_fini(&(results[0].port));
369
 
370
        return MAIN_RETURN_VAL;
371
}
372
 
373
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.