📄 pcache.c
字号:
goto foundit; }#endif#if DCACHE_ASSOC > 2 if (set->tags[2] == tag) { way = 2; goto foundit; }#endif#if DCACHE_ASSOC > 3 if (set->tags[3] == tag) { way = 3; goto foundit; }#endif } if (set->tags[0] == DCACHE_TAG(pAddr)) { way = 0; upgrade = TRUE; goto miss_or_upgrade; }#if DCACHE_ASSOC > 1 if (set->tags[1] == DCACHE_TAG(pAddr)) { way = 1; upgrade = TRUE; goto miss_or_upgrade; }#endif#if DCACHE_ASSOC > 2 if (set->tags[2] == DCACHE_TAG(pAddr)) { way = 2; upgrade = TRUE; goto miss_or_upgrade; }#endif#if DCACHE_ASSOC > 3 if (set->tags[3] == DCACHE_TAG(pAddr)) { way = 3; upgrade = TRUE; goto miss_or_upgrade; }#endif /****** a true miss (not an upgrade) ********/ upgrade = FALSE; way = DCACHE_LRU(set->LRU); if (set->tags[0] == DCACHE_TAG(pAddr)) { way = 0; upgrade = TRUE; goto miss_or_upgrade; }#if DCACHE_ASSOC > 1 if (set->tags[1] == DCACHE_TAG(pAddr)) { way = 1; upgrade = TRUE; goto miss_or_upgrade; }#endif#if DCACHE_ASSOC > 2 if (set->tags[2] == DCACHE_TAG(pAddr)) { way = 2; upgrade = TRUE; goto miss_or_upgrade; }#endifmiss_or_upgrade: { Result ret;#ifdef DEBUG_BUFFER CPUPrint("%d: Write D$ MISS VA: 0x%8.8lx PA: 0x%8.8lx\n", cpuNum, vAddr, pAddr);#endif ret = DCacheWriteMiss(cpuNum, vAddr, pAddr, size, flavor, set, way, upgrade, &mhtind); if (ret == FAILURE) { if (flavor == SC_FLAVOR) { /* SAH: Satisfies problem with write buffer where an SC was being merged with a regular store in the MHT. */ return SCFAILURE; } else { STATS_INC(cpuNum, writeBufferStats.writeMHTStall, 1); STATS_SET(cpuNum, writeMHTStallStart, CPUVec.CycleCount(cpuNum)); return STALL; } } if (ret == SCFAILURE || ret == BUSERROR) { return ret; } if (ret == STALL) { /* Check to see if a write buffer can avoid stalling otherwise * stall. SC don't every get bufferred. */ if (useWriteBuffer && !(flavor & SC_FLAVOR)) { if(AddToWriteBuffer(cpuNum, pAddr, data, size, mhtind)) return SUCCESS; else { STATS_INC(cpuNum, writeBufferStats.writeMHTStall, 1); STATS_SET(cpuNum, writeMHTStallStart, CPUVec.CycleCount(cpuNum)); return STALL; } } else { return STALL; } } ASSERT(ret == SUCCESS); } /* after satisfying the miss (either if it merged with another write in the * write buffer, or if running on a magic memory system), rejoin * the hit case and finish processing the access. */foundit: DCACHE_TOUCH(set->LRU, way); DATA_WRITE_EVENT(); lineindex = vAddr & (DCACHE_LINE_SIZE-1); FALSE_SHARING_ACCESS(cpuNum,set->fSharing[way],pAddr); FALSE_SHARING_MODIFY(cpuNum,pAddr); switch (size) { case WORD_SZ: if (VERBOSE_DEBUG) { CPUPrint("%d: WRITE D$ hit VA: 0x%8.8lx PA: 0x%8.8lx writing WORD: 0x%8.8lx \n", cpuNum, vAddr, pAddr, (uint) data); } *(uint *) (set->data[way] + lineindex) = (uint)data; break; case BYTE_SZ: if (VERBOSE_DEBUG) { CPUPrint("%d: WRITE D$ hit VA: 0x%8.8lx PA: 0x%8.8lx writing BYTE: 0x%2.2x \n", cpuNum, vAddr, pAddr, (char) data); } *(char *) (set->data[way] + lineindex) = (char)data; break; case HALF_SZ: if (VERBOSE_DEBUG) { CPUPrint("%d: WRITE D$ hit VA: 0x%8.8lx PA: 0x%8.8lx writing HALF: 0x%8.8lx \n", cpuNum, vAddr, pAddr, (short) data); } *(short *) (set->data[way] + lineindex) = (short)data; break; case DOUBLE_SZ: if (VERBOSE_DEBUG) {#ifdef __alpha CPUPrint("%d: WRITE D$ hit VA: 0x%8.8lx PA: 0x%8.8lx write DBLE: 0x%16.16lx\n", cpuNum, vAddr, pAddr, (uint64) data);#else CPUPrint("%d: WRITE D$ hit VA: 0x%8.8lx PA: 0x%8.8lx write DBLE: 0x%16.16llx\n", cpuNum, vAddr, pAddr, (uint64) data);#endif } *(uint64 *) (set->data[way] + lineindex) = (uint64)data; break; default: CPUError("Bad size request to ReadDCache"); break; } return SUCCESS;}/********************************************************************* * DCacheWriteMiss *********************************************************************/static ResultDCacheWriteMiss(int cpuNum, VA vAddr, PA pAddr, RefSize size, RefFlavor flavor, struct DCacheSet* set, int way, bool upgrade, int* mergemhtp){ int cacheNum = GET_CACHE_NUM(cpuNum); SCResult sret; MHTStatus mhtret; int mhtind; SCacheCmd cmd = SC_NO_CMD; if (flavor != SC_FLAVOR) { if (upgrade) cmd = SC_DUGETX; else cmd = SC_DGETX; } else { /* Handling of the SC instruction */ if (upgrade) { cmd = SC_DSCUGETX; } else { /* actual write miss on an SC */ if ((DCACHE_MISS_ALWAYS || SCACHE_ASSOC == 1) && CPUVec.GetLockFlag(cpuNum)) { /* Direct-maped L2-cache. * We do not rely on the presence in the cache, but rather * on the LLbit. Issue a GETX in this case. * Same thing if we bypass the L1-cache. */ PA instrLine, dataLine; cmd = SC_DGETX; STATS_INC(cpuNum, syncStats.llscConflictSuccess, 1); instrLine = (CURRENT_PC(cpuNum) & ~(SCACHE_LINE_SIZE-1)) & (SCACHE_SIZE-1); dataLine = (pAddr & ~(SCACHE_LINE_SIZE-1)) & (SCACHE_SIZE-1); if ((!DCACHE_MISS_ALWAYS) && (instrLine != dataLine) && (IS_KSEG0(instrLine))) { CPUError("Direct-map LL/SC conflict, cpu=%i PC=0x%x pAddr=0x%x\n", cpuNum, CURRENT_PC(cpuNum), pAddr); } } else { /* SC instructions fail if the line is not in the cache. */ return SCFAILURE; } } } if (cmd == SC_NO_CMD) CPUError("cmd unset"); /* --- pAddr gets cache-line aligned in call to AllocMHT --- */ mhtret = AllocMHT(cpuNum, cmd, vAddr, pAddr, DCACHE_LINE_SIZE, way, &mhtind); *mergemhtp = mhtind; if (mhtret == MHTFULL || mhtret == MHTCONFLICT) return FAILURE; if (mhtret == MHTMERGE) { return STALL; } ASSERT(mhtret == MHTSUCCESS); if (VERBOSE_DEBUG) { CPUPrint("%d: DCacheWriteMiss: VA: %8.8lx PA: %8.8lx\n",cpuNum, vAddr, pAddr); } /* Write back the current dcache line to make space for the fill!! */ if (set->tags[way] & EXCLUSIVE_TAG) { CACHE[cacheNum].stats.DCache.Writebacks++;#ifdef DATA_HANDLING { char *scacheData; int cacheindex; PA writebackAddr; int myWay=0; cacheindex = CACHE[cacheNum].MHT[mhtind].ind; writebackAddr = DTAG_TO_PA(set->tags[way],cacheindex); if (VERBOSE_DEBUG) { CPUPrint("%d: Spilling %8.8lx to make way\n",cpuNum,writebackAddr); } if (!(IsInSCache(cpuNum, writebackAddr, MEMSYS_EXCLUSIVE, &scacheData, &myWay))) { CPUError("DCacheWriteMiss didn't find exc. line in SCache for WB"); } }#endif } if (!upgrade) { /* replacing the previous line in this way */#ifdef MIPSY_MXS if (!(set->tags[way] & INVALID_TAG)) { PA paddr = DTAG_TO_PA(set->tags[way], (set - CACHE[cacheNum].DCache.set)); DoMxsIntervention(PE[cpuNum].st, paddr, DCACHE_LINE_SIZE, 0); }#endif#ifdef DATA_HANDLING if (!(set->tags[way] & INVALID_TAG)) { PA flushAddr = DTAG_TO_PA(set->tags[way], (set - CACHE[cacheNum].DCache.set)); if (VERBOSE_DEBUG) { CPUPrint("%d: dcache discarding line %8.8lx\n", cpuNum,flushAddr); } }#endif set->tags[way] = INVALID_TAG; } sret = SCacheFetch(cpuNum, vAddr, pAddr, cmd, mhtind); if (sret == SCRETRY) { /* * We must of conflicted with another miss. Clean MHT and stall. * XXX Is this right? */ FreeMHT(cpuNum, mhtind); return FAILURE; } else if (sret == SCBUSERROR) { FreeMHT(cpuNum, mhtind); return BUSERROR; } if (!upgrade) { CACHE[cacheNum].stats.DCache.WriteMisses++; } else { CACHE[cacheNum].stats.DCache.UpgradeMisses++; } if (sret == SCSUCCESS) { /* *SCacheFetch may return SUCCESS if zero latency misses are configured. */ return SUCCESS; } ASSERT(sret == SCSTALL); if (flavor == SC_FLAVOR) { /* Store conditionals are always blocking. This should be just * return STALL except somebody added the following... why? */ *mergemhtp = mhtind; if (CACHE[cacheNum].MHT[mhtind].inuse) return STALL; else return SCFAILURE; } *mergemhtp = mhtind; return STALL;}voidMemRefRemoveReq(int cpuNum, PA pAddr, int size){ MHTRemoveReq(cpuNum, pAddr, SCACHE_LINE_SIZE);}#ifdef MIPSY_MXS/* * MxsClassifyMiss - Return the memstat classification for the specified * miss. */intMxsClassifyMiss(int cpuNum, VA vaddr, PA pAddr, bool isICache){ int cacheNum = GET_CACHE_NUM(cpuNum); int entry; int paddrMask = ~((isICache ? ICACHE_LINE_SIZE : DCACHE_LINE_SIZE)-1); int stallType; for (entry = 0; entry < MHT_SIZE; entry++) { if (!CACHE[cacheNum].MHT[entry].inuse) continue; if ((CACHE[cacheNum].MHT[entry].pAddr & paddrMask) != (pAddr & paddrMask)) continue; stallType = isICache ? E_I : E_D; if (CACHE[cacheNum].MHT[entry].smhtEntry == SECOND_LEVEL_HIT_ENTRY) { stallType |= E_L1; } else { if ((CACHE[cacheNum].MHT[entry].cmd == SC_DUGETX) || (CACHE[cacheNum].MHT[entry].cmd == SC_DSCUGETX)) { stallType |= E_L2 | E_UPGRADE; } else { stallType |= E_L2; } } return stallType; } CPUError("MxsClassifyMiss failed!\n"); return 0;}#endif /* MIPSY_MXS */ /***************************************************************** * Routines for dealing with the miss handling table MHT that * supports lockup free caches. *****************************************************************//***************************************************************** * SyncCaches * *****************************************************************/extern Result MemRefSync(int cpuNum){ /* * First make sure the MHT in the caches are empty then send a sync * to the memory system. */ if (CACHE[cpuNum].MHTnumInuse != 0) { return STALL; } if (memsysVec.MemsysCmd != NULL) { return memsysVec.MemsysCmd(cpuNum, MEMSYS_SYNC, 0LL, 0, 0LL, 0, 0); } else { return SUCCESS; }}/***************************************************************** * MHTRemoveReq * Blindly remove any entries corresponding to this address and size * that are in the MHT. *****************************************************************/#define SMALLEST_LINE_SIZE ((ICACHE_LINE_SIZE < DCACHE_LINE_SIZE) \ ? ICACHE_LINE_SIZE : DCACHE_LINE_SIZE)voidMHTRemoveReq(int cpuNum, PA pAddr, int size)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -