📄 cache.cpp
字号:
/*************************************************************************** Cache.cpp - Cache ------------------- begin : Mon Apr 30 2001 copyright : (C) 2001 Universite Paris Sud and CEA author : Gilles Mouchard email : gilles.mouchard@lri.fr, gilles.mouchard@.cea.fr ***************************************************************************/#include <Cache.h>#if defined(ICACHE) || defined(DCACHE)#ifdef ICACHE#define CLASSNAME ICache#define CPU2CACHE fetch2icache#define CACHE2MEM icache2biu#else#define CLASSNAME DCache#define CPU2CACHE lsu2dcache#define CACHE2MEM dcache2biu#endifvoid CLASSNAME::DecodeAddress(UInt32 addr, UInt32& tag, UInt32& index, UInt32& offset){ offset = addr & offsetMask; index = (addr >> indexShift) & indexMask; tag = addr >> tagShift;#ifdef DEBUG if(Debug(DebugCache)) { cout << name() << ": Decoding address "; WriteHex(cout, addr); cout << " (tag = " << tag << ", index = " << index << ", offset = " << offset << ")" << endl; } if(offset >= linesize) { cout << name() << ": Error while decoding address : offset is out of range" << endl; ABORT(); } if(index >= nlines) { cout << name() << ": Error while decoding address : index is out of range" << endl; ABORT(); }#endif}int CLASSNAME::Search(UInt32 index, UInt32 tag){ int bank; #ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Searching for tag " << tag << " at index " << index << endl;#endif for(bank = 0; bank < associativity; bank++) { if(directory[bank][index].valid && directory[bank][index].tag == tag) {#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": tag found in bank " << bank << endl;#endif return bank; } }#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": tag not found" << endl;#endif return -1;}const int B0 = 1 << 0;const int B1 = 1 << 1;const int B2 = 1 << 2;const int B3 = 1 << 3;const int B4 = 1 << 4;const int B5 = 1 << 5;const int B6 = 1 << 6;void CLASSNAME::UpdatePLRUBits(UInt32 bank, UInt32 index){ switch(associativity) { case 4: switch(bank) { case 0: plrubits[index] |= B0 + B1; break; case 1: plrubits[index] |= B0; plrubits[index] &= B1; break; case 2: plrubits[index] |= B2; plrubits[index] &= B0; break; case 3: plrubits[index] &= B0 + B2; break; } break; case 8: switch(bank) { case 0: plrubits[index] |= B0 + B1 + B3; break; case 1: plrubits[index] |= B0 + B1; plrubits[index] &= ~B3; break; case 2: plrubits[index] |= B0 + B4; plrubits[index] &= ~B1; break; case 3: plrubits[index] |= B0; plrubits[index] &= ~(B1 + B4); break; case 4: plrubits[index] |= B2 + B5; plrubits[index] &= ~B0; break; case 5: plrubits[index] |= B2; plrubits[index] &= ~(B0 + B5); break; case 6: plrubits[index] |=B6; plrubits[index] &=~(B0 + B2); break; case 7: plrubits[index] &= ~(B0 + B2 + B6); break; } break; }}void CLASSNAME::Read(UInt32 bank, UInt32 index, UInt32 offset, UInt8 *data, int size){ memcpy(data, &storage[bank][index][offset], size); UpdatePLRUBits(bank, index);}UInt32 CLASSNAME::MakeAddr(UInt32 bank, UInt32 index, UInt32 offset){ return (directory[bank][index].tag << tagShift) | (index << indexShift) | offset;}#ifndef ICACHEvoid CLASSNAME::Write(UInt32 bank, UInt32 index, UInt32 offset, const UInt8 *data, int size){ memcpy(&storage[bank][index][offset], data, size); UpdatePLRUBits(bank, index); directory[bank][index].dirty = true;}void CLASSNAME::Zero(UInt32 bank, UInt32 index){ memset(&storage[bank][index], 0, linesize); UpdatePLRUBits(bank, index); directory[bank][index].dirty = true;}#endifint CLASSNAME::Choose(UInt32 index){ /* See figure 3-5. PLRU Replacement Algorithm */ /* table 3-2. PLRU Bit Update Rules */ /* of MPC750 RISC Microprocessor User's Manual */ int bank; for(bank = 0; bank < associativity; bank++) { if(!directory[bank][index].valid) { return bank; } } switch(associativity) { case 4: if(plrubits[index] & B0) { if(plrubits[index] & B2) return 3; else return 2; } else { if(plrubits[index] & B1) return 1; else return 0; } break; case 8: if(plrubits[index] & B0) { if(plrubits[index] & B2) { if(plrubits[index] & B5) return 5; else return 4; } else { if(plrubits[index] & B6) return 7; else return 6; } } else { if(plrubits[index] & B1) { if(plrubits[index] & B4) return 3; else return 2; } else { if(plrubits[index] & B3) return 1; else return 0; } } } return -1;}bool CLASSNAME::IsValid(UInt32 bank, UInt32 index){ return directory[bank][index].valid;}#ifndef ICACHEbool CLASSNAME::IsDirty(UInt32 bank, UInt32 index){ return directory[bank][index].dirty;}#endifUInt32 CLASSNAME::GetLineAddr(UInt32 bank, UInt32 index){ return (directory[bank][index].tag << tagShift) | (index << indexShift);}UInt32 CLASSNAME::AlignToLineBoundary(UInt32 addr){ return addr - (addr % linesize);}UInt32 CLASSNAME::AlignToMemoryWord(UInt32 addr){ return addr - (addr % memoryWord);}UInt8 *CLASSNAME::GetLineStorage(UInt32 bank, UInt32 index){ return &storage[bank][index][0];}void CLASSNAME::ReplaceLine(UInt32 bank, UInt32 index, UInt32 tag){ directory[bank][index].tag = tag; directory[bank][index].valid = true;#ifndef ICACHE directory[bank][index].dirty = false;#endif}void CLASSNAME::GetRequest(){ bool ack = false; if(inReq) { // CPU has made a request UInt32 /*curInstructionTag,*/ curTag, curIndex, curOffset, curSize, curAddr;#ifndef ICACHE bool curZeroBlock;#endif int curBank; curAddr = inAddr;// curInstructionTag = inTag; curSize = inSize;#ifndef ICACHE curZeroBlock = inZeroBlock;#endif #ifdef DEBUG if(Debug(DebugCache)) { cout << name() << ": Getting a CPU request at "; WriteHex(cout, curAddr); cout << " for " << curSize << " bytes " << endl; }#endif DecodeAddress(curAddr, curTag, curIndex, curOffset); curBank = Search(curIndex, curTag); hit = curBank >= 0; if(hit) { hits++; // Hit ack = true;// outTag = curInstructionTag; #ifndef ICACHE if(!inWrite) {#endif // Read DataArray<CPU2CACHE> data; Read(curBank, curIndex, curOffset, data.buffer, curSize);#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Reading " << curSize << " bytes (" << data << ")" << endl;#endif outData = data;#ifndef ICACHE } else { writeBank = curBank; writeIndex = curIndex; writeOffset = curOffset; writeZeroBlock = curZeroBlock; }#endif } else { misses++;#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Miss" << endl;#endif // Miss if(!busy) { busy = true; tag = curTag; offset = curOffset; index = curIndex; addr = curAddr; size = curSize;#ifndef ICACHE zeroBlock = curZeroBlock;#endif// instructionTag = curInstructionTag; bankToReplace = Choose(index);#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Choosing bank " << bankToReplace << endl;#endif #ifndef ICACHE if(inWrite) {// ack = true; // Miss on write if(IsValid(bankToReplace, index) && IsDirty(bankToReplace, index)) { // Cache line eject state = 1; } else { if(zeroBlock) { // Cache line fill with zeros state = 5; } else { // Cache line fill state = 3; } } } else#endif { // Miss on read#ifndef ICACHE if(IsValid(bankToReplace, index) && IsDirty(bankToReplace, index)) { // Cache line eject state = 6; } else#endif { // Cache line fill#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Filling line" << endl;#endif state = 8; } } } } }#ifdef DEBUG if(Debug(DebugCache)) if(ack) cout << name() << ": Sending an ack" << endl;#endif outAck = ack;}void CLASSNAME::Async(){ if(state == 0) GetRequest();}void CLASSNAME::OnFrontEdge(){ hit = false; #ifdef ICACHE if((state == 6 || state == 8) && inCancel) {#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": canceling previous request" << endl;#endif busy = false; state = 0; }#endif#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": state " << state << endl;#endif switch(state) { case 0: GetRequest(); break;#ifndef ICACHE case 1: // Write request to eject the cache line before a write {#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Memory write request for ejecting a cache line before a write" << endl;#endif DataArray<CACHE2MEM> data; line = GetLineStorage(bankToReplace, index); lineOffset = 0; length = 0; memcpy(data.buffer, &line[lineOffset], CACHE2MEM); lineOffset = (lineOffset + CACHE2MEM) % linesize; length += CACHE2MEM; if(length == linesize) { if(zeroBlock) state = 5; else state = 3; } else { state = 2; } outMemReq = true; outMemAddr = GetLineAddr(bankToReplace, index); outMemWrite = true; outMemData = data; waitingForAck = true; } break; case 2: // Cache line eject before a write if(!waitingForAck) {#ifdef DEBUG if(Debug(DebugCache)) cout << name() << ": Ejecting a cache line before a write" << endl;#endif DataArray<CACHE2MEM> data; memcpy(data.buffer, &line[lineOffset], CACHE2MEM); lineOffset = (lineOffset + CACHE2MEM) % linesize; length += CACHE2MEM; if(length == linesize) { if(zeroBlock) state = 5; else state = 3; } outMemReq = false; outMemData = data; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -