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

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [sw/] [example/] [coremark/] [core_main.c] - Blame information for rev 198

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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