see http://mbed.org/users/no2chem/notebook/mbed-clock-control--benchmarks/

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers core_main.c Source File

core_main.c

00001 /*
00002 Author : Shay Gal-On, EEMBC
00003 
00004 This file is part of  EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 
00005 All rights reserved.                            
00006 
00007 EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the
00008 CoreMark License that is distributed with the official EEMBC COREMARK Software release. 
00009 If you received this EEMBC CoreMark Software without the accompanying CoreMark License, 
00010 you must discontinue use and download the official release from www.coremark.org.  
00011 
00012 Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, 
00013 make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file.
00014 
00015 EEMBC 
00016 4354 Town Center Blvd. Suite 114-200
00017 El Dorado Hills, CA, 95762 
00018 */ 
00019 /* File: core_main.c
00020     This file contains the framework to acquire a block of memory, seed initial parameters, tun t he benchmark and report the results.
00021 */
00022 #include "coremark.h"
00023 
00024 /* Function: iterate
00025     Run the benchmark for a specified number of iterations.
00026 
00027     Operation:
00028     For each type of benchmarked algorithm:
00029         a - Initialize the data block for the algorithm.
00030         b - Execute the algorithm N times.
00031 
00032     Returns:
00033     NULL.
00034 */
00035 static ee_u16 list_known_crc[]   =      {(ee_u16)0xd4b0,(ee_u16)0x3340,(ee_u16)0x6a79,(ee_u16)0xe714,(ee_u16)0xe3c1};
00036 static ee_u16 matrix_known_crc[] =      {(ee_u16)0xbe52,(ee_u16)0x1199,(ee_u16)0x5608,(ee_u16)0x1fd7,(ee_u16)0x0747};
00037 static ee_u16 state_known_crc[]  =      {(ee_u16)0x5e47,(ee_u16)0x39bf,(ee_u16)0xe5a4,(ee_u16)0x8e3a,(ee_u16)0x8d84};
00038 void *iterate(void *pres) {
00039     ee_u32 i;
00040     ee_u16 crc;
00041     core_results *res=(core_results *)pres;
00042     ee_u32 iterations=res->iterations;
00043     res->crc=0;
00044     res->crclist=0;
00045     res->crcmatrix=0;
00046     res->crcstate=0;
00047 
00048     for (i=0; i<iterations; i++) {
00049         crc=core_bench_list(res,1);
00050         res->crc=crcu16(crc,res->crc);
00051         crc=core_bench_list(res,-1);
00052         res->crc=crcu16(crc,res->crc);
00053         if (i==0) res->crclist=res->crc;
00054     }
00055     return NULL;
00056 }
00057 
00058 #if (SEED_METHOD==SEED_ARG)
00059 ee_s32 get_seed_args(int i, int argc, char *argv[]);
00060 #define get_seed(x) (ee_s16)get_seed_args(x,argc,argv)
00061 #define get_seed_32(x) get_seed_args(x,argc,argv)
00062 #else /* via function or volatile */
00063 ee_s32 get_seed_32(int i);
00064 #define get_seed(x) (ee_s16)get_seed_32(x)
00065 #endif
00066 
00067 #if (MEM_METHOD==MEM_STATIC)
00068 ee_u8 static_memblk[TOTAL_DATA_SIZE];
00069 #endif
00070 char *mem_name[3] = {"Static","Heap","Stack"};
00071 /* Function: main
00072     Main entry routine for the benchmark.
00073     This function is responsible for the following steps:
00074 
00075     1 - Initialize input seeds from a source that cannot be determined at compile time.
00076     2 - Initialize memory block for use.
00077     3 - Run and time the benchmark.
00078     4 - Report results, testing the validity of the output if the seeds are known.
00079 
00080     Arguments:
00081     1 - first seed  : Any value
00082     2 - second seed : Must be identical to first for iterations to be identical
00083     3 - third seed  : Any value, should be at least an order of magnitude less then the input size, but bigger then 32.
00084     4 - Iterations  : Special, if set to 0, iterations will be automatically determined such that the benchmark will run between 10 to 100 secs
00085 
00086 */
00087 
00088 #if MAIN_HAS_NOARGC
00089 MAIN_RETURN_TYPE mainCoreMark(void) {
00090     int argc=0;
00091     char *argv[1];
00092 #else
00093 MAIN_RETURN_TYPE mainCoreMark(int argc, char *argv[]) {
00094 #endif
00095     ee_u16 i,j=0,num_algorithms=0;
00096     ee_s16 known_id=-1,total_errors=0;
00097     ee_u16 seedcrc=0;
00098     CORE_TICKS total_time;
00099     core_results results[MULTITHREAD];
00100 #if (MEM_METHOD==MEM_STACK)
00101     ee_u8 stack_memblock[TOTAL_DATA_SIZE*MULTITHREAD];
00102 #endif
00103     /* first call any initializations needed */
00104     portable_init(&(results[0].port), &argc, argv);
00105     /* First some checks to make sure benchmark will run ok */
00106     if (sizeof(struct list_head_s)>128) {
00107         ee_printf("list_head structure too big for comparable data!\n");
00108         return MAIN_RETURN_VAL;
00109     }
00110     results[0].seed1=get_seed(1);
00111     results[0].seed2=get_seed(2);
00112     results[0].seed3=get_seed(3);
00113     results[0].iterations=get_seed_32(4);
00114 #if CORE_DEBUG
00115     results[0].iterations=1;
00116 #endif
00117     results[0].execs=get_seed_32(5);
00118     if (results[0].execs==0) { /* if not supplied, execute all algorithms */
00119         results[0].execs=ALL_ALGORITHMS_MASK;
00120     }
00121         /* put in some default values based on one seed only for easy testing */
00122     if ((results[0].seed1==0) && (results[0].seed2==0) && (results[0].seed3==0)) { /* validation run */
00123         results[0].seed1=0;
00124         results[0].seed2=0;
00125         results[0].seed3=0x66;
00126     }
00127     if ((results[0].seed1==1) && (results[0].seed2==0) && (results[0].seed3==0)) { /* perfromance run */
00128         results[0].seed1=0x3415;
00129         results[0].seed2=0x3415;
00130         results[0].seed3=0x66;
00131     }
00132 #if (MEM_METHOD==MEM_STATIC)
00133     results[0].memblock[0]=(void *)static_memblk;
00134     results[0].size=TOTAL_DATA_SIZE;
00135     results[0].err=0;
00136     #if (MULTITHREAD>1)
00137     #error "Cannot use a static data area with multiple contexts!"
00138     #endif
00139 #elif (MEM_METHOD==MEM_MALLOC)
00140     for (i=0 ; i<MULTITHREAD; i++) {
00141         ee_s32 malloc_override=get_seed(7);
00142         if (malloc_override != 0) 
00143             results[i].size=malloc_override;
00144         else
00145             results[i].size=TOTAL_DATA_SIZE;
00146         results[i].memblock[0]=portable_malloc(results[i].size);
00147         results[i].seed1=results[0].seed1;
00148         results[i].seed2=results[0].seed2;
00149         results[i].seed3=results[0].seed3;
00150         results[i].err=0;
00151         results[i].execs=results[0].execs;
00152     }
00153 #elif (MEM_METHOD==MEM_STACK)
00154     for (i=0 ; i<MULTITHREAD; i++) {
00155         results[i].memblock[0]=stack_memblock+i*TOTAL_DATA_SIZE;
00156         results[i].size=TOTAL_DATA_SIZE;
00157         results[i].seed1=results[0].seed1;
00158         results[i].seed2=results[0].seed2;
00159         results[i].seed3=results[0].seed3;
00160         results[i].err=0;
00161         results[i].execs=results[0].execs;
00162     }
00163 #else
00164 #error "Please define a way to initialize a memory block."
00165 #endif
00166     /* Data init */ 
00167     /* Find out how space much we have based on number of algorithms */
00168     for (i=0; i<NUM_ALGORITHMS; i++) {
00169         if ((1<<(ee_u32)i) & results[0].execs)
00170             num_algorithms++;
00171     }
00172     for (i=0 ; i<MULTITHREAD; i++) 
00173         results[i].size=results[i].size/num_algorithms;
00174     /* Assign pointers */
00175     for (i=0; i<NUM_ALGORITHMS; i++) {
00176         ee_u32 ctx;
00177         if ((1<<(ee_u32)i) & results[0].execs) {
00178             for (ctx=0 ; ctx<MULTITHREAD; ctx++)
00179                 results[ctx].memblock[i+1]=(char *)(results[ctx].memblock[0])+results[0].size*j;
00180             j++;
00181         }
00182     }
00183     /* call inits */
00184     for (i=0 ; i<MULTITHREAD; i++) {
00185         if (results[i].execs & ID_LIST) {
00186             results[i].list=core_list_init(results[0].size, (list_head*) results[i].memblock[1],results[i].seed1);
00187         }
00188         if (results[i].execs & ID_MATRIX) {
00189             core_init_matrix(results[0].size, results[i].memblock[2], (ee_s32)results[i].seed1 | (((ee_s32)results[i].seed2) << 16), &(results[i].mat) );
00190         }
00191         if (results[i].execs & ID_STATE) {
00192             core_init_state(results[0].size,results[i].seed1, (ee_u8*) results[i].memblock[3]);
00193         }
00194     }
00195     
00196     /* automatically determine number of iterations if not set */
00197     if (results[0].iterations==0) { 
00198         secs_ret secs_passed=0;
00199         ee_u32 divisor;
00200         results[0].iterations=1;
00201         while (secs_passed < (secs_ret)1) {
00202             results[0].iterations*=10;
00203             start_time();
00204             iterate(&results[0]);
00205             stop_time();
00206             secs_passed=time_in_secs(get_time());
00207         }
00208         /* now we know it executes for at least 1 sec, set actual run time at about 10 secs */
00209         divisor=(ee_u32)secs_passed;
00210         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 */
00211             divisor=1;
00212         results[0].iterations*=1+10/divisor;
00213     }
00214     /* perform actual benchmark */
00215     start_time();
00216 #if (MULTITHREAD>1)
00217     if (default_num_contexts>MULTITHREAD) {
00218         default_num_contexts=MULTITHREAD;
00219     }
00220     for (i=0 ; i<default_num_contexts; i++) {
00221         results[i].iterations=results[0].iterations;
00222         results[i].execs=results[0].execs;
00223         core_start_parallel(&results[i]);
00224     }
00225     for (i=0 ; i<default_num_contexts; i++) {
00226         core_stop_parallel(&results[i]);
00227     }
00228 #else
00229     iterate(&results[0]);
00230 #endif
00231     stop_time();
00232     total_time=get_time();
00233     /* get a function of the input to report */
00234     seedcrc=crc16(results[0].seed1,seedcrc);
00235     seedcrc=crc16(results[0].seed2,seedcrc);
00236     seedcrc=crc16(results[0].seed3,seedcrc);
00237     seedcrc=crc16(results[0].size,seedcrc);
00238     
00239     switch (seedcrc) { /* test known output for common seeds */
00240         case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */
00241             known_id=0;
00242             ee_printf("6k performance run parameters for coremark.\n");
00243             break;
00244         case 0x7b05: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per algorithm */
00245             known_id=1;
00246             ee_printf("6k validation run parameters for coremark.\n");
00247             break;
00248         case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm */
00249             known_id=2;
00250             ee_printf("Profile generation run parameters for coremark.\n");
00251             break;
00252         case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */
00253             known_id=3;
00254             ee_printf("2K performance run parameters for coremark.\n");
00255             break;
00256         case 0x18f2: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per algorithm */
00257             known_id=4;
00258             ee_printf("2K validation run parameters for coremark.\n");
00259             break;
00260         default:
00261             total_errors=-1;
00262             break;
00263     }
00264     if (known_id>=0) {
00265         for (i=0 ; i<default_num_contexts; i++) {
00266             results[i].err=0;
00267             if ((results[i].execs & ID_LIST) && 
00268                 (results[i].crclist!=list_known_crc[known_id])) {
00269                 ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n",i,results[i].crclist,list_known_crc[known_id]);
00270                 results[i].err++;
00271             }
00272             if ((results[i].execs & ID_MATRIX) &&
00273                 (results[i].crcmatrix!=matrix_known_crc[known_id])) {
00274                 ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n",i,results[i].crcmatrix,matrix_known_crc[known_id]);
00275                 results[i].err++;
00276             }
00277             if ((results[i].execs & ID_STATE) &&
00278                 (results[i].crcstate!=state_known_crc[known_id])) {
00279                 ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n",i,results[i].crcstate,state_known_crc[known_id]);
00280                 results[i].err++;
00281             }
00282             total_errors+=results[i].err;
00283         }
00284     }
00285     total_errors+=check_data_types();
00286     /* and report results */
00287     ee_printf("CoreMark Size    : %lu\n",(ee_u32)results[0].size);
00288     ee_printf("Total ticks      : %lu\n",(ee_u32)total_time);
00289 #if HAS_FLOAT
00290     ee_printf("Total time (secs): %f\n",time_in_secs(total_time));
00291     if (time_in_secs(total_time) > 0)
00292         ee_printf("Iterations/Sec   : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
00293 #else 
00294     ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
00295     if (time_in_secs(total_time) > 0)
00296         ee_printf("Iterations/Sec   : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
00297 #endif
00298     if (time_in_secs(total_time) < 10) {
00299         ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n");
00300         total_errors++;
00301     }
00302 
00303     ee_printf("Iterations       : %lu\n",(ee_u32)default_num_contexts*results[0].iterations);
00304     ee_printf("Compiler version : %s\n",COMPILER_VERSION);
00305     ee_printf("Compiler flags   : %s\n",COMPILER_FLAGS);
00306 #if (MULTITHREAD>1)
00307     ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts);
00308 #endif
00309     ee_printf("Memory location  : %s\n",MEM_LOCATION);
00310     /* output for verification */
00311     ee_printf("seedcrc          : 0x%04x\n",seedcrc);
00312     if (results[0].execs & ID_LIST)
00313         for (i=0 ; i<default_num_contexts; i++) 
00314             ee_printf("[%d]crclist       : 0x%04x\n",i,results[i].crclist);
00315     if (results[0].execs & ID_MATRIX) 
00316         for (i=0 ; i<default_num_contexts; i++) 
00317             ee_printf("[%d]crcmatrix     : 0x%04x\n",i,results[i].crcmatrix);
00318     if (results[0].execs & ID_STATE)
00319         for (i=0 ; i<default_num_contexts; i++) 
00320             ee_printf("[%d]crcstate      : 0x%04x\n",i,results[i].crcstate);
00321     for (i=0 ; i<default_num_contexts; i++) 
00322         ee_printf("[%d]crcfinal      : 0x%04x\n",i,results[i].crc);
00323     if (total_errors==0) {
00324         ee_printf("Correct operation validated. See readme.txt for run and reporting rules.\n");
00325 #if HAS_FLOAT
00326         if (known_id==3) {
00327             ee_printf("CoreMark 1.0 : %f / %s %s",default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS);
00328 #if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC)
00329             ee_printf(" / %s",MEM_LOCATION);
00330 #else
00331             ee_printf(" / %s",mem_name[MEM_METHOD]);
00332 #endif
00333 
00334 #if (MULTITHREAD>1)
00335             ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD);
00336 #endif
00337             ee_printf("\n");
00338         }
00339 #endif
00340     }
00341     if (total_errors>0)
00342         ee_printf("Errors detected\n");
00343     if (total_errors<0)
00344         ee_printf("Cannot validate operation for these seed values, please compare with results on a known platform.\n");
00345 
00346 #if (MEM_METHOD==MEM_MALLOC)
00347     for (i=0 ; i<MULTITHREAD; i++) 
00348         portable_free(results[i].memblock[0]);
00349 #endif
00350     /* And last call any target specific code for finalizing */
00351     portable_fini(&(results[0].port));
00352 
00353     return MAIN_RETURN_VAL; 
00354 }
00355 
00356