#include #include #include #include "inc/mob.h" #include "inc/benchmark.h" #include "inc/routines.h" #include "inc/genCode.h" /* global variables externally defined */ extern struct globalSystem sys; #define MIN_SET M_SIZE(M_2M) /* minimum block to read between gettimeofday() calls */ /* local function prototypes */ static int cacheShareRun( unsigned int level ); /* Determine if existing caches at same levels are shared. return - 0 if successful, non-zero if failed */ int cacheShare( void ) { int i,error=0; unsigned long maxCaches; struct cache * dupCache; /* Get the longer list */ maxCaches = maxVal( sys.numDataCaches, sys.numInstCaches ); /* Cleanup: "Delete"(duplicate) any existing cache that is marked shared */ for( i = 1; i <= maxCaches; i++ ) if( sys.dataCaches[i] && sys.dataCaches[i]->type == TYPE_SHARED ) { dupCache = (struct cache *)calloc( 1, sizeof(struct cache ) ); if( !dupCache ) return EnoMem; memcpy( dupCache, sys.dataCaches[i], sizeof(struct cache) ); sys.instCaches[i] = dupCache; sys.dataCaches[i]->type=TYPE_DATA; sys.instCaches[i]->type=TYPE_INST; } /* Go through the levels found and perform the shared test if at a particular level: - Both data and instruction caches exist - Both data and instruction caches have the same size */ for( i = 1; i <= maxCaches; i++ ) if( sys.dataCaches[i] && sys.instCaches[i] && sys.dataCaches[i]->size && sys.dataCaches[i]->size == sys.instCaches[i]->size ) error=cacheShareRun( i ); return error; } /* Perform a check to see if a particular level of the detected caches is shared between data and instructions. If shared, update the cache arrays by pointing to the same structure from data and instructions and marking the cache as type "shared". level - current cache level to test return - 0 if successful, non-zero otherwise */ static int cacheShareRun( unsigned int level ) { unsigned int trial, sets, size = sys.dataCaches[level]->size; double read, run, mixed, scale; char *code, *data; /* initialuze values arbitrarily high for use with minimums */ read = run = mixed = (double)LONG_MAX; /* compute scale to use between execution times and read times */ scale = (double)sizeof(int) / (double)nopBlockSize(); /* compute number of sets to perform between time calls */ sets = maxVal( MIN_SET / size, 1 ); /* setup code and data arrays the size of the current cache */ if( arrayPrepare( 2 * size ) ) handleError( "checking memory in cacheShare ", EnoMem ); data = sys.array; code = sys.array + size; /* take the minimum of a number of trials */ for( trial = 1; trial <= sys.args.trials; trial++ ) { /* 1 - calculate the optimal time value to read data */ read = min( read, dataRead( data, size, 0, sets )); /* 2 - calculate the normative time to execute the code, scale run time in terms of of ns. per word for comparison with mixed */ run = min( run, instExecute( code, size, 0, sets ) * scale ); /* 3 - calculate the time of read/execute interleaved */ mixed = min( mixed, shareCheck( data, code, size, 0, sets )); } show( VERB_INSPECT, "Level %d [%lu] ->Read: %.4f Run: %.4f (Read+Run: %.4f) Mixed: %.4f \n", level, cacheSize, read, run, read+run, mixed); /* 4 - compare 3 to 1+2, we're using a heuristic that assumes that the mixed set in a shared cache take "much longer" than separate caches: a third of the larger separate time is used to mean much longer. */ if( mixed > (read + run) + max( read, run ) / 3 ) { /* Delete one of them */ free( sys.instCaches[level] ); /* Make both entries point to the same cache */ sys.instCaches[level] = sys.dataCaches[level]; /* Mark it shared */ sys.dataCaches[level]->type = TYPE_SHARED; show( VERB_NORMAL, "Level %d cache is shared \n", level); } else show( VERB_NORMAL, "Level %d cache is not shared \n", level); return 0; } /* Determine whether we have already the information that the test provides. For now we'll return invalid always since we don't know if we're already run... return - 1 if valid, 0 otherwise */ int cacheShareValid( void ) { /* FIXME: maybe we should check for any shared cache, and if so we could assume that the test has been performed...*/ return 0; }