📄 memstat.c
字号:
if (interest(pAddr)) { CPUWarning("%10lld L1 Ref cpu=%i pAddr=%08x type=%#x state=%#x\n", CPUVec.CycleCount(cpuNum), cpuNum, pAddr, missType, MSCacheState(cpuNum, pAddr)); }#endif } return -1; } if ((missType & E_L2) && (missType & E_UPGRADE)) { if (memStat.init && NO_RACE_CONDITION && MSCacheState(cpuNum,pAddr) != CACHE_INCACHE) { CPUError("MemStat: %10lld cpu=%i pAddr=0x%08x UPGRADE NOT IN CACHE \n", CPUVec.CycleCount(cpuNum), cpuNum, pAddr); } STAT_RECORD(dUpgrade,1); STAT_RECORD(dUpgradeStall, stallTime); if (!(missType & E_CAUSED_INVAL)) { STAT_RECORD(dUpgradeNoInval,1); } if (missType & E_SC_UPGRADE) { STAT_RECORD(dUpgradeSC, 1); } if (missType & E_REMOTE) { STAT_RECORD_I(dL2RemoteMiss,1); STAT_RECORD_I(dL2RemoteStall,stallTime); }#ifdef DEBUGGING if (interest(pAddr)) { CPUWarning("%10lld L2-upgrade cpu=%i pAddr=%08x type=%#x state=%#x\n", CPUVec.CycleCount(cpuNum), cpuNum, pAddr, missType, MSCacheState(cpuNum, pAddr)); }#endif return -1; } /* L2 cache Miss */ ASSERT(missType & E_L2); STAT_RECORD(dL2Miss, 1); STAT_RECORD(dL2Stall, stallTime); if (missType & E_FOUND_IN_CACHE) { STAT_RECORD(dL2DirtyMiss,1); STAT_RECORD(dL2DirtyStall,stallTime); } if (missType & E_REMOTE) { STAT_RECORD_I(dL2RemoteMiss,1); STAT_RECORD_I(dL2RemoteStall,stallTime); } if (memStat.trackL1) { /* * clear the capacity bits in the L1 cache */ for(i=0; i<SCACHE_LINE_SIZE; i+= DCACHE_LINE_SIZE) { uint L1pA = (pAddr & ~(SCACHE_LINE_SIZE-1)) + i; int l1Line = mcpu * MEM_L1D_LINE(MEM_SIZE(machine)) + MEM_L1D_LINE(L1pA); int l1Index = l1Line /32; int l1Pos = l1Line %32; memStat.l1DtrPtr[machine][l1Index] &= ~(1<<l1Pos); } } if (!memStat.init) return -1; ASSERT(categ >= 0); if (interest(pAddr)) { CPUWarning("%10lld CacheTrmiss : %i\n",CPUVec.CycleCount(cpuNum),categ); } if (missType & E_WRITE) { StatRecordEntry(cpuNum, pc, vAddr, memStatBucket.write[categ], 1); } else { StatRecordEntry(cpuNum, pc, vAddr, memStatBucket.read[categ], 1); } return missType;}void MemStatCacheTrans(int cpuNum, PA pAddr, int type, VA evictorAddr, int isUserMode){ unsigned int index,pos,state,off; int machine; int mcpu; if (!memStat.init) return; machine = M_FROM_CPU(cpuNum); mcpu = MCPU_FROM_CPU(cpuNum); /* debug */ if (interest(pAddr)) { char c[5]; c[0] = 't'; if ((type & E_L1) && (type & E_I)) { c[1] = 'i'; } else if ((type & E_L1) && (type & E_D)) { c[1] = 'd'; } else if (type & E_L2) { c[1] = '2'; } else ASSERT(0); if ((!(type & E_EXTERNAL)) && (!(type & E_FAKE_EXTERNAL))) { /* Line was replaced */ c[2] = 'r'; } else if (type & E_EXTERNAL) { c[2] = 'X'; } else if (type & E_FAKE_EXTERNAL) { c[2] = 'F'; } else ASSERT(0); if (type & E_WRITEBACK) { c[3] = 'W'; } else if (type & E_FLUSH_CLEAN) { c[3] = 'C'; } else if (type & E_DOWNGRADE) { c[3] = 'D'; } else c[3]='X'; c[4] = '\0'; ITRACE(c); } /* for now we only measure transitions in the L2 cache */ if (type & E_L1) return; ASSERT (type & E_L2); pAddr &= ~(SCACHE_LINE_SIZE-1); ASSERT(pAddr < MEM_SIZE(machine)); pos = memStat.bitsPerState *( memStat.trNumCPUs[machine] * MEM_LINE(pAddr) + mcpu); off = pos % 32; index = pos / 32; ASSERT(index*4<memStat.lastAddr[machine]); /* range check */ /* get current state */ state = ( memStat.trPtr[machine][index] >> off ) & memStat.cacheMask; /* * REPLACEMENT: * The line was in the cache and should be in the cache and is replaced. */ if ((!(type & E_EXTERNAL)) && (!(type & E_FAKE_EXTERNAL))) { /* evict your own line */ if (state != CACHE_INCACHE) { /* you better be in the cache! */ if (NO_RACE_CONDITION) { CPUError("MS 0x%08x %10lld MemStat: EVICT, cpu=%i state=%i type=%i\n", pAddr,CPUVec.CycleCount(cpuNum),cpuNum,state,type); } ++(memStat.trWarnings[machine]); } if (isUserMode) { type |= E_USER_REPLACED; } else { type |= E_KERN_REPLACED; } ASSERT(type & (E_KERN_REPLACED|E_USER_REPLACED)); if (type & E_USER_REPLACED) { uint newState; if (memStat.pidTable[machine][MS_pid(cpuNum)] == -1) { memStat.pidTable[machine][MS_pid(cpuNum)] = memStat.pidCount[machine]++; ASSERT(memStat.pidCount[machine] < MS_MAXPID); } if( memStat.trackPID ) { newState = (memStat.pidTable[machine] [MS_pid(cpuNum)]<<PIDOFFSET)|CACHE_REPLACED_U; } else { newState = CACHE_REPLACED_U; } if (interest(pAddr)) { LogEntry("newstate",cpuNum,"pAddr=%08x newstate=%i\n", pAddr,newState); } memStat.trPtr[machine][index] &= ~(memStat.cacheMask<<off); memStat.trPtr[machine][index] |=(newState<<off); } else { if (interest(pAddr)) { LogEntry("newstate",cpuNum,"pAddr=%08x newstate=%i\n", pAddr,CACHE_REPLACED_K); } memStat.trPtr[machine][index] &= ~(memStat.cacheMask<<off); memStat.trPtr[machine][index] |= CACHE_REPLACED_K<<off; } return ; } if (type & E_DOWNGRADE) { return; /* no transition on a writeback */ } if (type & E_EXTERNAL) { ASSERT(type & (E_WRITEBACK | E_FLUSH_CLEAN)); /* you better be in the cache! */ if (state != CACHE_INCACHE) { if (NO_RACE_CONDITION) { CPUError("MemStat 0x%08x %10lld EXTERNAL cpuNum=%i state=%i type=%i\n", pAddr,(uint64)CPUVec.CycleCount(cpuNum),cpuNum,state,type); } ++(memStat.trWarnings[machine]); } state = CACHE_INVALIDATED; } if (type & E_FAKE_EXTERNAL) { switch(state) { case CACHE_REPLACED_K: state = CACHE_REPL_INV; break; case CACHE_INCACHE: if (NO_RACE_CONDITION) { CPUError("MemStat %08x %10lld FAKE_EXTERNAL, cpuNum=%i\n", pAddr,CPUVec.CycleCount(cpuNum), cpuNum); } ++(memStat.trWarnings[machine]); break; case CACHE_COLD: break; default: if ((state&0xf)==CACHE_REPLACED_U) state=CACHE_REPL_INV; } } if (interest(pAddr)) { LogEntry("newstate",cpuNum,"pAddr=%08x newstate=%i\n", pAddr,state); } /* record new state */ memStat.trPtr[machine][index] &= ~(memStat.cacheMask<<off); memStat.trPtr[machine][index] |= (state <<off);}void MemStatPrefetchNoMiss (int cpuNum, PA pAddr, int way) { if (interest(pAddr)) { LogEntry("prefetch",cpuNum,"pAddr=0x%x, way=%i \n", pAddr,way); } if (memStat.init) { int categ = CacheTrMiss(cpuNum,pAddr); FalseSharingDefineOffset(cpuNum,pAddr,way,categ); }} /***************************************************************** * CacheTrMiss * * This is called when a line goes back into the cache * to maintain the correct state machine. *****************************************************************/static intCacheTrMiss(int cpuNum, PA pAddr){ int state,i; unsigned int pos,index,off; int retval = -1; int machine; int mcpu; if (!memStat.init) return 0; machine = M_FROM_CPU(cpuNum); mcpu = MCPU_FROM_CPU(cpuNum);#ifdef DEBUGGING if (interest(pAddr)) { CPUWarning("%10lld trMiss\n",CPUVec.CycleCount(cpuNum)); }#endif pAddr &=~(SCACHE_LINE_SIZE-1); ASSERT( memStat.trPtr[machine] ); if (pAddr >= MEM_SIZE(machine)) { CPUError("MemStat::CacheTrMiss. pAddr=0x%llx > MEM_SIZE=0x%llx\n", (uint64)pAddr, (uint64)MEM_SIZE(machine)); } pos = memStat.bitsPerState * (memStat.trNumCPUs[machine] * MEM_LINE(pAddr) + mcpu); off = pos% 32; index = pos / 32; ASSERT( index*4< memStat.lastAddr[machine] ); /* get old state */ state = (memStat.trPtr[machine][index] >> off ) & memStat.cacheMask; switch( state ) { case CACHE_COLD: retval= CATEG_ice; break; case CACHE_REPLACED_K: if (memStat.trackPID) { retval = CATEG_Kcap; } else { retval = CATEG_cap; } break; case CACHE_INVALIDATED: retval = CATEG_inv; break; case CACHE_REPL_INV: retval = CATEG_capinv; break; case CACHE_WARMED: retval = CATEG_cold; break; case CACHE_INCACHE: if( NO_RACE_CONDITION ) { CPUError("%10lld MemStat CacheTrMiss, state=%i pAddr=%08x\n", CPUVec.CycleCount(cpuNum), state, pAddr); } ++(memStat.trWarnings[machine]); break; default: ASSERT( (state&0xf)== CACHE_REPLACED_U ); if( memStat.trackPID) { if (memStat.pidTable[machine][MS_pid(cpuNum)] == -1) { memStat.pidTable[machine][MS_pid(cpuNum)] = memStat.pidCount[machine]++; ASSERT(memStat.pidCount[machine] < MS_MAXPID); } if (state>>PIDOFFSET == memStat.pidTable[machine][MS_pid(cpuNum)]) retval = CATEG_SelfCap; else retval = CATEG_OtherCap; } else { retval = CATEG_cap; } } memStat.trPtr[machine][index] &= ~(memStat.cacheMask <<off); memStat.trPtr[machine][index] |= CACHE_INCACHE<<off; /* it is back in the cache */ if (interest(pAddr)) { LogEntry("newstate",cpuNum,"pAddr=%08x newstate=IN_CACHE\n", pAddr); } if (state == CACHE_COLD) { pos = memStat.bitsPerState * (memStat.trNumCPUs[machine] * MEM_LINE(pAddr) ); off = pos % 32; index = pos / 32; for(i=0;i<memStat.trNumCPUs[machine];++i) { if( i != mcpu ) { memStat.trPtr[machine][index] &= ~(memStat.cacheMask <<off); memStat.trPtr[machine][index] |= (CACHE_WARMED<<off); } off += memStat.bitsPerState; if( off >= 32 ) { off -=32; index ++; } } } if (interest(pAddr)) { ITRACE("Cache"); } return retval;}int MemStatInitialized(void){ return( memStat.init );}/***************************************************************************** * Support routines for MemStat ****************************************************************************/void MemStatLog(FILE *f,char *tag, SimTime time, char *desc, char *text,...){ va_list ap; if (f) { if (time) { fprintf(f,"%-6s ",tag); va_start(ap,text); vfprintf(f,text,ap); va_end(ap); fprintf(f,"\n"); } else { fprintf(f,"DEF %-6s %s\n",tag,desc); } } }/***************************************************************** * Very useful debugging procedures *****************************************************************/intinterest( PA pAddr ) {#ifdef DEBUGGING#define INTERESTING_LINE 0x67460d80#define SET_PROBLEM 1 if( (pAddr & ~(SCACHE_LINE_SIZE-1))== ( INTERESTING_LINE &~(SCACHE_LINE_SIZE-1)) ) { CPU_nop(); return 1; } if( SET_PROBLEM ) { if( ((pAddr >> log2SCACHE_LINE_SIZE) & (SCACHE_INDEX-1)) == ((INTERESTING_LINE>>log2SCACHE_LINE_SIZE) & (SCACHE_INDEX-1)) ) { CPU_nop(); return 1; } }#endif return 0;} intMSCacheState(int cpu, PA pAddr) { int pos, off, index; int machine; int mcpu; if (!memStat.init) return -1; machine = M_FROM_CPU(cpu); mcpu = MCPU_FROM_CPU(cpu); pos = memStat.bitsPerState *( memStat.trNumCPUs[machine] * MEM_LINE(pAddr) + mcpu); off = pos % 32; index = pos / 32; ASSERT(index*4<memStat.lastAddr[machine]); /* range check */ /* get current state */ return ( memStat.trPtr[machine][index] >> off ) & memStat.cacheMask;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -