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

Subversion Repositories steelcore

[/] [coremark/] [core_main.c] - Blame information for rev 11

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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