// the link information is bytes 8-16 of each page in mem (next/prev mem ptrs) void DiskPageCache::promotePage ( long poff , bool isNew ) { if ( isNew ) { here: long tmp = -1; writeToCache(poff, OFF_PREV, &tmp, sizeof(long)); // testing readFromCache ( &tmp, poff, OFF_PREV, sizeof(long) ); if ( tmp != -1 ){ char *xx=NULL; *xx=0;} //*(long *)(p + OFF_PREV) = -1 ;// our prev is -1 (none) writeToCache(poff, OFF_NEXT, &m_headOff, sizeof(long)); //*(long *)(p+OFF_NEXT) = m_headOff;// our next is the old head // the old head's prev is us if ( m_headOff >= 0 ) { writeToCache(m_headOff, OFF_PREV, &poff, sizeof(long)); //char *headPtr = getMemPtrFromOff ( m_headOff ) ; //*(long *)(headPtr + OFF_PREV) = poff; } // and we're the new head m_headOff = poff; // if no tail, we become that, too, we must be the first if ( m_tailOff < 0 ) m_tailOff = poff; return; } // otherwise, we have to excise excisePage ( poff ); // and add as new goto here; }
// add data from "page" (we just read it from disk or wrote to disk) // into "p" page in memory void DiskPageCache::enhancePage (long poff, char *page, long size, oldshort skip) { oldshort psize = 0; readFromCache( &psize, poff, OFF_SIZE, sizeof(oldshort)); //oldshort psize = *(oldshort *)(p+OFF_SIZE); oldshort pskip = 0; readFromCache( &pskip, poff, OFF_SKIP, sizeof(oldshort)); //oldshort pskip = *(oldshort *)(p+OFF_SKIP); // can we add to front of page? if ( skip < pskip ) { long diff = pskip - skip; // . we cored here because page[diff-1] was out of bounds. why? // . do not allow gap in between cached data, that is, we have // cached bytes at the end of the page, then we try to cache // some at the beginning, and it's not contiguous... we are // not built for that... this can happen when dumping a file, // if your first reads up to the file end (somewhere in the // middle of the page) and your second read starts somewhere // else.... mmmm... i dunno.... if ( skip + size < pskip || diff > size ) { log("db: Avoided cache gap in %s. diff=%li " "size=%li pskip=%li skip=%li.", m_dbname,diff,size,(long)pskip,(long)skip); return; } writeToCache(poff, HEADERSIZE + skip , page , diff); //memcpy ( p + HEADERSIZE + skip , page , diff ); psize += diff; pskip -= diff; writeToCache(poff, OFF_SIZE, &psize, sizeof(oldshort)); //*(oldshort *)(p+OFF_SIZE) = psize ; writeToCache(poff, OFF_SKIP, &pskip, sizeof(oldshort)); //*(oldshort *)(p+OFF_SKIP) = pskip ; } // can we add to end of page? long pend = pskip + psize; long end = skip + size; if ( end <= pend ) return; long diff = end - pend ; // if the read's starting point is beyond our ending point, bail, // we don't want any holes... if ( diff > size ) return; writeToCache(poff, HEADERSIZE + pend, page + size - diff, diff); //memcpy ( p + HEADERSIZE + pend , page + size - diff , diff ); oldshort tmp = psize+diff; writeToCache(poff, OFF_SIZE, &tmp, sizeof(oldshort)); //*(oldshort *)(p+OFF_SIZE) = (oldshort)psize + diff; }
int smsa_put_cache_line( SMSA_DRUM_ID drm, SMSA_BLOCK_ID blk, unsigned char *buf ) { uint32_t err = 0; //value to hold function return values logMessage ( LOG_INFO_LEVEL, "Writing Drum [%d], Block [%d] To the Cache...", drm, blk ); // Before we just put the block into the cache, we want // To check to make sure it doesn't already exist in the // cache, or else we could have duplicates in the cache. If // it is found, just change the line member of the struct, // and place in the newest spot of the cache ( highest index ) for ( int i = 0; i <= currentIndex; i++ ) { if ( cache[i].block == blk && cache[i].drum == drm ) { if ( DEBUG ) logMessage ( LOG_INFO_LEVEL, "Drum [%d], Block [%d], Exists in the Cache. Overwriting Now...", drm, blk ); cache[i].line = buf; //update the line member of the cache block // If the item exists in the highest index, then it does not // need to be upddated to the newest spot in the cache because it is // already there. Therefore only update the position in the cache, if // the item is not in the newest position already. if ( i == currentIndex ) { if ( currentIndex < maxIndex -1 ) currentIndex++; if ( DEBUG ) logMessage ( LOG_INFO_LEVEL, "Drum [%e], Block [%e], Is the Newest Item In the Cache. Updated Cache Index ( if the cache was not full ) Is Mow [%d]", drm, blk ); return 0; } //update the already existent line in the cache to the newest //postion in the cache, (currentIndex or currentIndex-1 ) err = justUsedAdjust ( drm, blk, cache[i].line, i ); return 0; } } logMessage ( LOG_INFO_LEVEL, "Drum [%d], Block [%d], Doesn't Exist In Cache, Must Eject and Vverwrite", drm, blk ); // Not found in the cache, so bring it into the cache err = writeToCache ( drm, blk, buf ); // Make return value recognizable by smsa_driver error handler if ( err > 0 ) err = 11; //printCache(0,0); return err; }
// remove a page from the linked list void DiskPageCache::excisePage ( long poff ) { // get our neighbors, NULL if none long prev = 0; readFromCache(&prev, poff, OFF_PREV, sizeof(long)); //long prev = *(long *)(p + OFF_PREV); long next = 0; readFromCache(&next, poff, OFF_NEXT, sizeof(long)); //long next = *(long *)(p + OFF_NEXT); // if we were the head or tail, then pass it off to our neighbor if ( poff == m_headOff ) m_headOff = next; if ( poff == m_tailOff ) m_tailOff = prev; // our prev's next becomes our old next if ( prev >= 0 ) { //char *prevPtr = getMemPtrFromOff ( prev ); writeToCache(prev, OFF_NEXT, &next, sizeof(long)); //*(long *)(prevPtr + OFF_NEXT ) = next; } // our next's prev becomes our old prev if ( next >= 0 ) { //char *nextPtr = getMemPtrFromOff ( next ); writeToCache(next, OFF_PREV, &prev, sizeof(long)); //long *)(nextPtr + OFF_PREV ) = prev; } }
void simulator(int C, int K, int L){ int setSize = calculateSetSize(C, K, L); int lineSize = calculateLineSize(C, K, L); //First set of arrays for data int LRUArray[lineSize*setSize], tagArray[lineSize*setSize], validBitArray[lineSize*setSize]; //First set of arrays for data int dataLRUArray[lineSize*setSize], dataTagArray[lineSize*setSize], dataValidBitArray[lineSize*setSize]; //Second set of arrays for instruction int instructionLRUArray[lineSize*setSize], instructionTagArray[lineSize*setSize], instructionValidBitArray[lineSize*setSize]; //Initializes all array entries to 0 int i,j; //Initializing every LRU of the cache to a value between 0 - (lineSize-1) for(i = 0; i<lineSize; i++ ){ for(j = 0; j<setSize; j++){ LRUArray[i+j*lineSize] = i; validBitArray[i+j*lineSize] = 0; tagArray[i+j*lineSize] = 0; dataLRUArray[i+j*lineSize] = i; dataValidBitArray[i+j*lineSize] = 0; dataTagArray[i+j*lineSize] = 0; instructionLRUArray[i+j*lineSize] = i; instructionValidBitArray[i+j*lineSize] = 0; instructionTagArray[i+j*lineSize] = 0; } } int instruction, address, tag, set, setLine; double missNumber, totalMemoryReferences, dataMiss, instructionMiss, dataReferences, instructionReferences; //miss will take care of maintaining track of how many misses the simulator has, toatlIteratiosn just counts how many total addresses the simulator has. missNumber = 0; dataMiss = 0; instructionMiss = 0; dataReferences = 0; instructionReferences = 0; totalMemoryReferences = 0; instruction = 1; address = 0; FILE *ifp; //Pointer to a file is declared ifp = fopen("trace.txt", "r"); // ifp points to file // trace.txt, opened for // reading while (!feof(ifp)) { // exit if end-of-file reached fscanf(ifp, "%d %x", &instruction, &address); // read next line switch (instruction){ // cases 0 -3 run the same thing case 0: case 1: tag = decodeTag(address, C, K, L, setSize); set = decodeSet(address, C, K, L, setSize); //Printing information //printf("Address: %x \n Tag: %d \n Set: %d \n\n", address, tag, set); if((setLine = tagHit(dataTagArray, set, tag, lineSize)) > -1){ if(dataValid(dataValidBitArray, set, setLine, lineSize)>0){ updateLRU(dataLRUArray, set, setLine, lineSize); }else{ writeToAddress(dataTagArray, set, tag, setLine, lineSize); validateData(dataValidBitArray, set, setLine, lineSize); updateLRU(dataLRUArray, set, setLine, lineSize); dataMiss++; missNumber++; } }else{ setLine = writeToCache(dataTagArray, dataLRUArray, set, tag, lineSize); validateData(dataValidBitArray, set, setLine, lineSize); updateLRU(dataLRUArray, set, setLine, lineSize); dataMiss++; missNumber++; } dataReferences++; totalMemoryReferences++; break; case 2: tag = decodeTag(address, C, K, L, setSize); set = decodeSet(address, C, K, L, setSize); //Printing information //printf("Address: %x \n Tag: %d \n Set: %d \n\n", address, tag, set); if((setLine = tagHit(instructionTagArray, set, tag, lineSize)) > -1){ if(dataValid(instructionValidBitArray, set, setLine, lineSize)>0){ updateLRU(instructionLRUArray, set, setLine, lineSize); }else{ writeToAddress(instructionTagArray, set, tag, setLine, lineSize); validateData(instructionValidBitArray, set, setLine, lineSize); updateLRU(instructionLRUArray, set, setLine, lineSize); instructionMiss++; missNumber++; } }else{ setLine = writeToCache(instructionTagArray, LRUArray, set, tag, lineSize); validateData(instructionValidBitArray, set, setLine, lineSize); updateLRU(instructionLRUArray, set, setLine, lineSize); instructionMiss++; missNumber++; } instructionReferences++; totalMemoryReferences++; break; //End iteration //address++; case 3:break; case 4: clearCache(dataValidBitArray, lineSize, setSize); clearCache(instructionValidBitArray, lineSize, setSize); break; } } fclose(ifp); // Close file double missRate = missNumber/totalMemoryReferences*100; //printCache(tagArray, validBitArray, LRUArray, setSize, lineSize); printf("%.0f misses, ", missNumber); printf("%.0f total memory references, ", totalMemoryReferences); printf("%2.4f miss rate, \n\n", missRate); }
// skip is offset of "page" into physical page void DiskPageCache::addPage(long vfd,long pageNum,char *page,long size, oldshort skip){ // . if pageNum is beyond the file size // . see the explanation for this same error msg above if ( pageNum >= m_maxPagesInFile[vfd] ) { // this has happened during a merge before!! (at startup) //log(LOG_LOGIC,"db: pagecache: addPage: Bad engineer. " // happens because rdbdump did not get a high enough // maxfilesize so we did not make enough pages! we endedup // dumping more than what was end the tree because stuff was // added to the tree while dumping! log("db: pagecache: Caught add breach. " "pageNum=%li max=%li db=%s", pageNum,m_maxPagesInFile[vfd],m_dbname); return; } // debug msg //log("addPage: pageNum=%li page[0]=%hhx size=%li skip=%li", // pageNum,page[0],size,(long)skip); long poff = m_memOff [ vfd ] [ pageNum ] ; // p will be NULL if page does not have any data in memory yet //char *p = getMemPtrFromOff ( poff ); // if page already exists in cache and needs data on the boundaries // we may be able to supply it if ( poff >= 0 ) { // debug msg //log("ENHANCING off=%li",poff); enhancePage ( poff , page , size , skip ); return; } // don't add any more if we're minimizing disk seeks and are full if ( m_minimizeDiskSeeks && m_numPagesPresentOfFile[vfd] >= m_maxPagesPerFile[vfd] ) return; // top: // try to get an available memory spot from list if ( m_numAvailMemOffs > 0 ) { poff = m_availMemOff [ --m_numAvailMemOffs ] ; // debug msg //log("RECYCLING off=%li",poff); } // can we grab a page from memory without having to grow? else if ( m_nextMemOff + m_pageSize + HEADERSIZE < m_upperMemOff ) { poff = m_nextMemOff; m_nextMemOff += m_pageSize + HEADERSIZE; // debug msg //log("CLAIMING off=%li",poff); } // . we now grow everything at start // . otherwise, try to grow the page cache by 200k //else if ( m_nextMemOff + m_pageSize + HEADERSIZE < m_maxMemOff ) { // // grow by 100k worth of pages each time // if ( ! growCache ( m_upperMemOff + 200*1024 ) ) return; // goto top; //} // this should never happen. Since in minimizeDiskSeek we have // an exact number of pages per file else if ( m_minimizeDiskSeeks ) { char *xx = NULL; *xx = 0; } // if no freebies left, take over the tail page in memory else { poff = m_tailOff; //char *p = getMemPtrFromOff ( poff ); excisePage ( poff ); // . the file no longer owns him // . this is a long ptr to &m_bufOffs[vfd][pageNum] // . if that vfd no longer exists it should have added all its // pages to m_avail list //long tmp = -1; long *memOffPtr = NULL; readFromCache(&memOffPtr, poff, OFF_PTR, sizeof(long*)); *memOffPtr = -1; //m_cacheBuf.writeToCache(poff, OFF_PTR, &tmp, sizeof(long)); // testing //m_cacheBuf.readFromCache ( &tmp, poff+OFF_PTR, sizeof(long) ); //if ( tmp != -1 ){ //char *xx=NULL; *xx=0;} //**(long **)(p+OFF_PTR) = -1; // debug msg //log("KICKINGTAIL off=%li",poff); } // sanity check if ( poff < 0 ) { char *xx = NULL; *xx = 0; } // get ptr to the page in memory from the memory offset //p = getMemPtrFromOff ( poff ); // store the size as first 2 bytes writeToCache(poff, OFF_SIZE, &size, sizeof(oldshort)); // oldshort tmp = 0; // m_cacheBuf.readFromCache ( &tmp, poff, OFF_SIZE, sizeof(long) ); // if ( tmp != size ){ // char *xx=NULL; *xx=0;} //*(oldshort *)(p+OFF_SIZE) = size; writeToCache( poff, OFF_SKIP, &skip, sizeof(oldshort) ); //*(oldshort *)(p+OFF_SKIP) = skip; // sanity check if ( size + skip > m_pageSize ) { char *xx = NULL; *xx = 0; } // store the link information in bytes 8-16 promotePage ( poff , true/*isNew?*/ ); // then store a ptr to m_memOff[vfd][pageNum] so we can set *ptr // to -1 if they page gets replaced by another long *memOffPtr = &m_memOff[ vfd ][ pageNum ]; writeToCache( poff, OFF_PTR, &memOffPtr, sizeof(long*)); //*(long **)(p+OFF_PTR) = &m_memOff [ vfd ] [ pageNum ] ; // then the data from disk (skip over link info) writeToCache( poff, HEADERSIZE + skip, page, size); //memcpy ( p + HEADERSIZE + skip , page , size ); // transform mem ptr to offset if ( !m_useRAMDisk && ! m_useSHM ) { long off = -1; char *p = getMemPtrFromOff ( poff ); for ( long i = 0 ; i < m_numPageSets ; i++ ) { if ( p < m_pageSet[i] ) continue; if ( p > m_pageSet[i] + m_pageSetSize[i] ) continue; off = p - m_pageSet[i] + i * m_maxPageSetSize ; break; } // update map m_memOff [ vfd ] [ pageNum ] = off; // sanity check if ( off != poff ) { char *xx=NULL; *xx=0; } } else m_memOff [ vfd ] [ pageNum ] = poff; // update the header of that page // we have added the page! if ( m_minimizeDiskSeeks ) m_numPagesPresentOfFile[vfd]++; }
int main(int argc, char *argv[]){ cache_params_t params; /* file handling stuff */ FILE *tracefile; char instruction_ptr[50]; char instruction; char mem_addr[50]; int count; char *traceData; Cache_t cache; int tagSize, setSize, offsetSize; if(argc == 2 && strcmp(argv[1], "-h") == 0){ printf("help menu\n"); return 1; } if(argc < 2 || argc > 6){ printf("ERROR: incorrect number of arguments\n"); return 1; } /* * TODO: * Check cachesize = numsets x setsize x blocksize */ /* Check if cachesize here and correct*/ /* should check that these are numbers as well */ if(isPowerOfTwo(atoi(argv[1]))){ params.cachesize = atoi(argv[1]); }else{ printf("ERROR: cachesize must be a power of 2\n"); return 1; } /* check if blocksize is here and correct */ if(isPowerOfTwo(atoi(argv[3]))){ params.blocksize = atoi(argv[3]); }else{ printf("ERROR: blocksize must be a power of 2\n"); return 1; } params.setsize = 1; /* check for associativit y */ if(strcmp("direct", argv[2]) == 0){ params.associativity = "direct"; }else if( strcmp("assoc", argv[2]) == 0){ params.associativity = "assoc"; }else{ int i = 0, digit = 0; char* str = argv[2]; char* test; while(str[i] != '\0'){ if(isdigit(str[i])){ digit = i; break; } i++; } /* * setsize = 1 for d-m caches */ params.setsize = 1; test = malloc(strlen(argv[2])); strncpy(test, argv[2], digit); if(strcmp("assoc:", test) == 0){ params.associativity = "n-way"; if(isPowerOfTwo( argv[2][digit] - '0')){ params.setsize = argv[2][digit] - '0'; }else{ printf("ERROR: n must be power of 2\n"); return 1; } }else{ printf("ERROR: invalid associativity format\n"); return 1; } } /* check for writepolicy*/ if(strcmp("wt", argv[4]) == 0){ params.writepolicy = "wt"; }else if(strcmp("wb", argv[4]) == 0){ params.writepolicy = "wb"; }else{ printf("ERROR: invalid writepolicy format\n"); return 1; } /* check for tracefile */ if(!(tracefile = fopen(argv[5], "r"))){ printf("ERROR: could not find tracefile: %s\n", argv[5]); return 1; }else{ traceData = readFile(argv[5]); } /* <<<<<<< HEAD * create the new cache, do initialization stuff ======= * create the new cache, do initializatino stuff >>>>>>> 59f4c294c92c026c0d9d15ccfd2984234f2a3158 */ cache = *newCache(params.cachesize, params.blocksize, params.setsize, params.associativity, params.writepolicy); /* * read each line of the tracefile * * DIRECT MAP ONLY RIGHT NOW */ count = 0; while(fscanf(tracefile, "%s %c %s", instruction_ptr, &instruction, mem_addr) == 3) { int tag_size; int lines; int offset_size; int set_size; int set_lines; unsigned int addr_int; char *addr_bin; char *formatted_bin; char *tag; char *setid; char *offset; formatted_bin = (char*) malloc(sizeof(char) * 35); addr_bin = (char*) malloc(sizeof(char) * 33); lines = (int)(params.cachesize / params.blocksize); set_lines = (int)(params.cachesize / (params.blocksize * params.setsize)); if(strcmp(params.associativity,"n-way") == 0){ set_size = (int) ceil((log10(set_lines)/log10(2.0))); }else{ set_size = (int) ceil((log10(lines)/log10(2.0))); } offset_size = ceil((log10(params.blocksize)/log10(2.0))); tag_size = (32 - (offset_size+set_size)); /* * just for output */ tagSize = tag_size; setSize = set_size; offsetSize = offset_size; tag = (char*) malloc(sizeof(char)*tag_size+1); setid = (char*) malloc(sizeof(char)*set_size+1); offset = (char*) malloc(sizeof(char)*offset_size+1); addr_int = htoi(mem_addr); addr_bin = itob(addr_int); memcpy(tag, &addr_bin[0], tag_size); tag[tag_size+1] = '\0'; memcpy(setid, &addr_bin[tag_size], set_size); setid[set_size+1] = '\0'; memcpy(offset, &addr_bin[(tag_size+set_size)], offset_size); offset[offset_size+1] = '\0'; if(DEBUG) { printf("------\n%s\n",mem_addr); printf("%s %s %s \n", tag, setid, offset); printf("tag: %i, set: %i, offset: %i\n", tagSize, setSize, offsetSize); } /* * Write to the cache */ if('W' == instruction){ if(DEBUG){ printf("Write instruction\n Cache State:\n"); printCache(&cache); if( isInCache(&cache, addr_bin, tag, setid, offset)){ printf("\ncache already contains %s\n",mem_addr); }else{ printf("\ncache does not contain %s\n",mem_addr); } if( isInCache(&cache, addr_bin, tag, setid, offset)){ printf("\ncache contains %s\n",mem_addr); } printf("\nCache State:\n"); printCache(&cache); } writeToCache(&cache, addr_bin, tag, setid, offset, lines); /* * Read from the cache */ }else if('R' == instruction ){ if(DEBUG) { printf("Read instruction\n Cache State:\n"); printCache(&cache); if( isInCache(&cache, addr_bin, tag, setid, offset)){ printf("\ncache already contains %s\n",mem_addr); }else{ printf("\ncache does not contain %s\n",mem_addr); } if( isInCache(&cache, addr_bin, tag, setid, offset)){ printf("\ncache contains %s\n",mem_addr); } printf("\nCache State:\n"); printCache(&cache); } readFromCache(&cache, addr_bin, tag, setid, offset, lines); } count++; } printCache(&cache); return 1; }
void simulator(int C, int K, int L){ int setSize = calculateSetSize(C, K, L); int lineSize = calculateLineSize(C, K, L); int LRUArray[lineSize*setSize], tagArray[lineSize*setSize], validBitArray[lineSize*setSize]; //Initializes all array entries to 0 int i,j; //Initializing every LRU of the cache to a value between 0 - (lineSize-1) for(i = 0; i<lineSize; i++ ){ for(j = 0; j<setSize; j++){ LRUArray[i+j*lineSize] = i; validBitArray[i+j*lineSize] = 0; tagArray[i+j*lineSize] = 0; } } int iter, instruction, address, tag, set, setLine; double missNumber, totalMemoryReferences; //miss will take care of maintaining track of how many misses the simulator has, toatlIteratiosn just counts how many total addresses the simulator has. missNumber = 0; totalMemoryReferences = 0; instruction = 1; iter = 0; srand(4342); while(iter < 100000){ address = rand(); //printf("%d\n", address); switch (instruction){ // cases 0 -3 run the same thing case 0: case 1: case 2: tag = decodeTag(address, C, K, L, setSize); set = decodeSet(address, C, K, L, setSize); //Printing information //printf("Address: %x \n Tag: %d \n Set: %d \n\n", address, tag, set); if((setLine = tagHit(tagArray, set, tag, lineSize)) > -1){ if(dataValid(validBitArray, set, setLine, lineSize)>0){ updateLRU(LRUArray, set, setLine, lineSize); }else{ writeToAddress(tagArray, set, tag, setLine, lineSize); validateData(validBitArray, set, setLine, lineSize); updateLRU(LRUArray, set, setLine, lineSize); missNumber++; } }else{ setLine = writeToCache(tagArray, LRUArray, set, tag, lineSize); validateData(validBitArray, set, setLine, lineSize); updateLRU(LRUArray, set, setLine, lineSize); missNumber++; } break; case 3:break; case 4: clearCache(validBitArray, lineSize, setSize); break; } iter++; totalMemoryReferences++; } double missRate = missNumber/totalMemoryReferences*100; //printCache(tagArray, validBitArray, LRUArray, setSize, lineSize); printf("%.0f misses, ", missNumber); printf("%.0f total memory references, ", totalMemoryReferences); printf("%2.4f miss rate, \n\n", missRate); }