#include "precomp.h" #define DELAY #ifdef DELAY #define L1delay Sleep(0); #define L2delay Sleep(0); #define L3delay Sleep(0); #else #define L1delay ; #define L2delay ; #define L3delay ; #endif CacheStats profilestats; CacheStats profilecopy; CacheStats* ProfileTick() { profilecopy.L1Hits = profilestats.L1Hits; profilecopy.L2Misses = profilestats.L2Misses; profilecopy.L3Misses = profilestats.L3Misses; profilecopy.TotalReads = profilestats.TotalReads; profilecopy.L1Misses = profilestats.L1Misses; profilecopy.RAMReads = profilestats.RAMReads; profilestats.L1Hits = 0; profilestats.L2Misses = 0; profilestats.L3Misses = 0; profilestats.TotalReads = 0; profilestats.L1Misses = 0; profilestats.RAMReads = 0; return &profilecopy; } const int LineSize = 64; const int Offset = (int)log2((double)LineSize); int rngarray[1000]; int rngcounter; long hit1, hit2, hit3; uint datatypebitshift = 2; struct CacheAddress { uint tag; uint offset; uint valid; uint dirty; uint linenummer; int* nooffset; }; struct CacheLine { CacheAddress address; union dataline{ char dc[LineSize]; short ds[LineSize >> 1]; int di[LineSize >> 2]; long long dll[LineSize >> 3]; }data; }; //L1 const uint L1CacheSize = 8; const uint L1Associative = 4; const uint L1CacheRows = L1CacheSize * 1024 / ((LineSize)*L1Associative); const uint L1Index = (uint)ceil(log2((double)L1CacheRows)); //L2 const uint L2CacheSize = 8; const uint L2Associative = 4; const uint L2CacheRows = L2CacheSize * 1024 / ((LineSize)*L2Associative); const uint L2Index = (uint)ceil(log2((double)L2CacheRows)); //L3 const uint L3CacheSize = 8; //2048 KB = 2 MB const uint L3Associative = 4; const uint L3CacheRows = L3CacheSize * 1024 / ((LineSize)*L3Associative); const uint L3Index = (uint)ceil(log2((double)L3CacheRows)); CacheLine L1[L1CacheRows][L1Associative]; CacheLine L2[L2CacheRows][L2Associative]; CacheLine L3[L3CacheRows][L3Associative]; void CleanCache() { for (uint i = 0; i < L1CacheRows; i++) { for (uint j = 0; j < L1Associative; j++) { L1[i][j].address.valid = 0; L1[i][j].address.dirty = 0; } } for (uint i = 0; i < L2CacheRows; i++) { for (uint j = 0; j < L2Associative; j++) { L2[i][j].address.valid = 0; L2[i][j].address.dirty = 0; } } for (uint i = 0; i < L3CacheRows; i++) { for (uint j = 0; j < L3Associative; j++) { L3[i][j].address.valid = 0; L3[i][j].address.dirty = 0; } } } void InitializeCache() { srand(0);// create an array filled with random numbers rngcounter = 0; uint rgnmax = max(max(L1Associative, L2Associative), L3Associative); for (uint i = 0; i < 1000; i++) { rngarray[i] = rand() % rgnmax; } CleanCache(); } CacheAddress ConvertToCacheAddress(int* address, uint Lindex) { uint castaddress = (uint)address; CacheAddress cacheline; cacheline.tag = castaddress >> (Offset + Lindex); cacheline.valid = castaddress << (31) >> (31); cacheline.dirty = castaddress >> 1 << (31) >> (31); cacheline.offset = castaddress << (32 - Offset) >> (32 - Offset); cacheline.linenummer = castaddress << (32 - Offset - Lindex) >> (32 - Lindex); cacheline.nooffset = (int*)(castaddress >> Offset << Offset); return cacheline; } int ReadL1(int* address) { CacheAddress workaddress = ConvertToCacheAddress(address, L1Index); int value = 0; for (uint i = 0; i < L1Associative; i++) //finding address in cache to update { if (L1[workaddress.linenummer][i].address.valid) { if (L1[workaddress.linenummer][i].address.tag == workaddress.tag) { // HIT! profilestats.L1Hits++; value = L1[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift]; //datatype dependency return value; } } } profilestats.L1Misses++; value = ReadL2(address); WriteL1(address, value); L1delay; return value; } int ReadL2(int* address) { CacheAddress workaddress = ConvertToCacheAddress(address, L2Index); int value = 0; for (uint i = 0; i < L2Associative; i++) //finding address in cache to update { if (L2[workaddress.linenummer][i].address.valid) { if (L2[workaddress.linenummer][i].address.tag == workaddress.tag) { // HIT! value = L2[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift]; //datatype dependency return value; } } } profilestats.L2Misses++; value = ReadL3(address); WriteL2(address, value); L2delay; return value; } int ReadL3(int* address) { CacheAddress workaddress = ConvertToCacheAddress(address, L3Index); int value = 0; for (uint i = 0; i < L3Associative; i++) //finding address in cache to update { if (L3[workaddress.linenummer][i].address.valid) { if (L3[workaddress.linenummer][i].address.tag == workaddress.tag) { // HIT! value = L3[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift]; //datatype dependency return value; } } } profilestats.RAMReads++; profilestats.L3Misses++; value = ReadFromRAM(address); WriteL3(address, value); L3delay; return value; } int READ( int* address ) { int value = ReadL1(address); profilestats.TotalReads++; return value; // prevent ReadFromRAM using caching //return ReadFromRAM( address ); } uint EvictionPolicyCache() { uint value = rngarray[rngcounter]; rngcounter = (rngcounter + 1) % 1000; return value; } void WriteL1(int* address, int value) { L1delay; CacheAddress workaddress = ConvertToCacheAddress(address, L1Index); for (uint i = 0; i < L1Associative; i++) //finding address in cache to update { if (L1[workaddress.linenummer][i].address.valid) { if (L1[workaddress.linenummer][i].address.tag == workaddress.tag) { L1[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L1[workaddress.linenummer][i].address.dirty = 1; return; } } } for (uint i = 0; i < L1Associative; i++) // finding empty spot to store value { if (!L1[workaddress.linenummer][i].address.valid) { L1[workaddress.linenummer][i].address.tag = workaddress.tag; L1[workaddress.linenummer][i].address.offset = workaddress.offset; L1[workaddress.linenummer][i].address.linenummer = workaddress.linenummer; L1[workaddress.linenummer][i].address.nooffset = workaddress.nooffset; int* tempaddress = (int*) workaddress.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint j = 0; j < LineSize >> 2; j++) { L1[workaddress.linenummer][i].data.di[j] = ReadL2(tempaddress); tempaddress++; } L1[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L1[workaddress.linenummer][i].address.dirty = 1; L1[workaddress.linenummer][i].address.valid = 1; return; } } uint slot = EvictionPolicyCache() % L1Associative; //copy to RAM if dirty if (L1[workaddress.linenummer][slot].address.dirty) { int* tempaddress = (int*) L1[workaddress.linenummer][slot].address.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint i = 0; i < LineSize >> 2; i++) { WriteL2(tempaddress, L1[workaddress.linenummer][slot].data.di[i]); tempaddress++; } L1[workaddress.linenummer][slot].address.dirty = 0; L1[workaddress.linenummer][slot].address.valid = 0; } WriteL1(address, value); } void WriteL2(int* address, int value) { L2delay; CacheAddress workaddress = ConvertToCacheAddress(address, L2Index); for (uint i = 0; i < L2Associative; i++) //finding address in cache to update { if (L2[workaddress.linenummer][i].address.valid) { if (L2[workaddress.linenummer][i].address.tag == workaddress.tag) { L2[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L2[workaddress.linenummer][i].address.dirty = 1; return; } } } for (uint i = 0; i < L2Associative; i++) // finding empty spot to store value { if (!L2[workaddress.linenummer][i].address.valid) { L2[workaddress.linenummer][i].address.tag = workaddress.tag; L2[workaddress.linenummer][i].address.offset = workaddress.offset; L2[workaddress.linenummer][i].address.linenummer = workaddress.linenummer; L2[workaddress.linenummer][i].address.nooffset = workaddress.nooffset; int* tempaddress = (int*) workaddress.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint j = 0; j < LineSize >> 2; j++) { L2[workaddress.linenummer][i].data.di[j] = ReadL3(tempaddress); tempaddress++; } L2[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L2[workaddress.linenummer][i].address.dirty = 1; L2[workaddress.linenummer][i].address.valid = 1; return; } } uint slot = EvictionPolicyCache() % L2Associative; //copy to RAM if dirty if (L2[workaddress.linenummer][slot].address.dirty) { int* tempaddress = (int*) L2[workaddress.linenummer][slot].address.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint i = 0; i < LineSize >> 2; i++) { WriteL3(tempaddress, L2[workaddress.linenummer][slot].data.di[i]); tempaddress++; } L2[workaddress.linenummer][slot].address.dirty = 0; L2[workaddress.linenummer][slot].address.valid = 0; } WriteL2(address, value); } void WriteL3(int* address, int value) { L3delay; CacheAddress workaddress = ConvertToCacheAddress(address, L3Index); for (uint i = 0; i < L3Associative; i++) //finding address in cache to update { if (L3[workaddress.linenummer][i].address.valid) { if (L3[workaddress.linenummer][i].address.tag == workaddress.tag) { L3[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L3[workaddress.linenummer][i].address.dirty = 1; return; } } } for (uint i = 0; i < L3Associative; i++) // finding empty spot to store value { if (!L3[workaddress.linenummer][i].address.valid) { L3[workaddress.linenummer][i].address.tag = workaddress.tag; L3[workaddress.linenummer][i].address.offset = workaddress.offset; L3[workaddress.linenummer][i].address.linenummer = workaddress.linenummer; L3[workaddress.linenummer][i].address.nooffset = workaddress.nooffset; int* tempaddress = (int*) workaddress.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint j = 0; j < LineSize >> 2; j++) { L3[workaddress.linenummer][i].data.di[j] = ReadFromRAM(tempaddress); tempaddress++; profilestats.RAMReads++; } L3[workaddress.linenummer][i].data.di[workaddress.offset >> datatypebitshift] = value; //datatype dependency L3[workaddress.linenummer][i].address.dirty = 1; L3[workaddress.linenummer][i].address.valid = 1; return; } } uint slot = EvictionPolicyCache() % L3Associative; //copy to RAM if dirty if (L3[workaddress.linenummer][slot].address.dirty) { int* tempaddress = (int*) L3[workaddress.linenummer][slot].address.nooffset; // by adding the (int*) cast this part becomes datatype independent for (uint i = 0; i < LineSize >> 2; i++) { WriteToRAM(tempaddress, L3[workaddress.linenummer][slot].data.di[i]); tempaddress++; } L3[workaddress.linenummer][slot].address.dirty = 0; L3[workaddress.linenummer][slot].address.valid = 0; } WriteL3(address, value); } void WRITE( int* address, int value ) { WriteL1(address, value); // prevent WriteToRAM using caching // WriteToRAM( address, value ); }