📄 scache.c
字号:
#endif if (VERBOSE_DEBUG) { CPUPrint("%d: SCacheMiss: replacing PA: %8.8lx EX:%d\n",cpuNum, replacePaddr, writeback); } /* Writeback if dirty... retain == 0 =>remove the line */ PrimaryFlush(cpuNum, writeback, 0, replacePaddr, SCACHE_LINE_SIZE); { uint type; if (writeback) { type = E_L2 | E_WRITEBACK; } else { type = E_L2 | E_FLUSH_CLEAN; } L2_LINE_TRANS_EVENT(cpuNum, replacePaddr, type, vAddr, way, IS_KUSEG(CURRENT_PC(cpuNum))); } set->tags[way] = INVALID_TAG; if (writeback) { SCACHE[scacheNum].stats.Writebacks++; } else { SCACHE[scacheNum].stats.Replacements++; } } else { replacePaddr = MEMSYS_NOADDR; writeback = 0; } /* if not a NAK'ed reference */ (*missCntPtr)++;#ifdef DATA_HANDLING /* Store the cache line pointer in the SMHT */ /* for use later when the reply arrives */ SCACHE[scacheNum].SMHT[smhtind].lineData = set->data[way]; mret = memsysVec.MemsysCmd(cpuNum, SCACHE[scacheNum].SMHT[smhtind].memsyscmd, pAddr, smhtind, replacePaddr, writeback, set->data[way]);#else mret = memsysVec.MemsysCmd(cpuNum, SCACHE[scacheNum].SMHT[smhtind].memsyscmd, pAddr, smhtind, replacePaddr, writeback, NULL);#endif if (mret == STALL) { return SCSTALL; } /* magic memory system */ ASSERT(mret == SUCCESS);#ifndef BUFFER_WRITES ASSERT(!SCACHE[scacheNum].SMHT[smhtind].inuse); SCacheLRUTouch(&set->LRU, way); return SCSUCCESS;#endif}/***************************************************************** * *****************************************************************/PFResultSCachePrefetch(int cpuNum, VA vAddr, PA pAddr, MCMD mcmd){ int scacheNum = GET_SCACHE_NUM(cpuNum); PA replacePaddr; int writeback; int way; int replace; SMHTStatus ret; Result mret; int smhtind; struct SCacheSet *set = & SCACHE[scacheNum].set[SCACHE_INDEXOF(pAddr)]; if (interest(pAddr)) { LogEntry("l2-pf-issue",cpuNum,"pAddr=0x%x vAddr=0x%x foo=0x%x\n", pAddr,vAddr,set->tags[0]); } /* Quad-word align the address */ pAddr = QuadWordAlign(pAddr);#ifndef SOLO if (!IS_VALID_PA(M_FROM_CPU(cpuNum), pAddr)) { CPUWarning("%d: SCachePrefetch: VA: %8.8llx PA: %8.8lx FAIL out of range!\n", cpuNum, (Reg64)vAddr, pAddr); return PF_SUCCESS; /* Makes everyone above happy */ }#endif /* Check to see if line is already resident */ way = SCACHE_ASSOC; for(replace=0; replace<SCACHE_ASSOC; ++replace) { if ((set->tags[replace] & ~EXCLUSIVE_TAG) == SCACHE_TAG(pAddr)) { /* Line is resident in cache -- see if we need an upgrade */ if (((mcmd == MEMSYS_GETX) && (set->tags[replace] & EXCLUSIVE_TAG)) || (mcmd == MEMSYS_GET)) { return PF_RESIDENT; } else { mcmd = MEMSYS_UPGRADE; /* Need to upgrade here, a shared copy is present */ way = replace; break; } } else if (set->tags[replace] & INVALID_TAG) { way = replace; } } mcmd |= MEMSYS_PREFETCH; /* Allocate space in the SMHT for the prefetch */ if (way == SCACHE_ASSOC) { way = SCacheLRU(set->LRU); } ret = AllocSMHT(cpuNum, mcmd, pAddr, way, &smhtind); /* If SMHT is full, punt the prefetch */ if ((ret == SMHTCONFLICT) || (ret == SMHTFULL)) { if (VERBOSE_DEBUG) { CPUPrint("%d: SCachePrefetch: VA: %8.8lx PA: %8.8lx FAIL\n", cpuNum, vAddr, pAddr); } return PF_FAILURE; } if (ret == SMHTMERGE) { /* This line already has an outstanding miss of the right type -- punt */ if (VERBOSE_DEBUG) { CPUPrint("%d: SCachePrefetch: VA: %8.8lx PA: %8.8lx MERGE\n", cpuNum, vAddr, pAddr); } return PF_MERGE; } ASSERT(ret == SMHTSUCCESS); SCACHE[scacheNum].SMHT[smhtind].pfvAddr = vAddr; /* Now we need to allocate clear out space in the cache * for it. If the entry we choose is valid we flush * it from the primary cache(s). We pass the replaced * address to the memory system so it can simulated writebacks * and replacement hints, etc. */ if (VERBOSE_DEBUG) { CPUPrint("%d: SCachePrefetch: VA: %8.8lx PA: %8.8lx\n", cpuNum, vAddr, pAddr); } if (!((mcmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE) && !(set->tags[way] & INVALID_TAG)) { replacePaddr = STAG_TO_PA(set->tags[way],set-SCACHE[scacheNum].set); writeback = set->tags[way] & EXCLUSIVE_TAG; #ifndef SOLO ASSERT (IS_VALID_PA(M_FROM_CPU(cpuNum), replacePaddr));#endif if (VERBOSE_DEBUG) { CPUPrint("%d: SCachePrefetch: replacing PA: %8.8lx EX:%d\n",cpuNum, replacePaddr, writeback); } PrimaryFlush(cpuNum, writeback, 0, replacePaddr, SCACHE_LINE_SIZE); { uint type; if (writeback) { type = E_L2 | E_WRITEBACK; } else { type = E_L2 | E_FLUSH_CLEAN; } L2_LINE_TRANS_EVENT(cpuNum, replacePaddr, type, vAddr, way, IS_KUSEG(CURRENT_PC(cpuNum))); } set->tags[way] = INVALID_TAG; if (writeback) { SCACHE[scacheNum].stats.Writebacks++; } else { SCACHE[scacheNum].stats.Replacements++; } } else { replacePaddr = MEMSYS_NOADDR; writeback = 0; } SCACHE[scacheNum].stats.Prefetches++; PREFETCH_EVENT(CPUVec.CycleCount(cpuNum),cpuNum,CURRENT_PC(cpuNum),vAddr);#ifdef DATA_HANDLING /* Store the cache line pointer in the SMHT */ /* for use later when the reply arrives */ SCACHE[scacheNum].SMHT[smhtind].lineData = set->data[way]; mret = memsysVec.MemsysCmd(cpuNum, SCACHE[scacheNum].SMHT[smhtind].memsyscmd, pAddr, smhtind, replacePaddr, writeback, set->data[way]);#else mret = memsysVec.MemsysCmd(cpuNum, SCACHE[scacheNum].SMHT[smhtind].memsyscmd, pAddr, smhtind, replacePaddr, writeback, NULL);#endif if (mret == STALL) return (((mcmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE) ? PF_UPGRADE : PF_STALL); ASSERT(mret == SUCCESS); ASSERT(!SCACHE[scacheNum].SMHT[smhtind].inuse); SCacheLRUTouch(&set->LRU, way); return PF_SUCCESS;}SCResultSCacheUpgradeMiss(int cpuNum, VA vAddr, PA pAddr, SCacheCmd cmd, int mhtind, int way, struct SCacheSet *set, SimCounter *missCntPtr){ int cacheNum = GET_CACHE_NUM(cpuNum); int scacheNum = GET_SCACHE_NUM(cpuNum); MCMD mcmd = MEMSYS_UPGRADE; SMHTStatus ret; Result mret; int smhtind; if (cmd == SC_DSCUGETX) { mcmd |= MEMSYS_SCFLAVOR; } /* Quad-word align the miss */ pAddr = QuadWordAlign(pAddr);#ifndef SOLO ASSERT (IS_VALID_PA(M_FROM_CPU(cpuNum), pAddr));#endif ret = AllocSMHT(cpuNum, mcmd, pAddr, way, &smhtind); if ((ret == SMHTFULL) || (ret == SMHTCONFLICT)) { /* We've overrun or conflicted in the SMHT. Return * a retry so we will try again. */ SCACHE[scacheNum].stats.DUGetXMHTRetries++; if (VERBOSE_DEBUG) { CPUPrint("%d: SCacheUpgradeMiss: VA: %8.8lx PA: %8.8lx RETRY\n",cpuNum, vAddr, pAddr); } return SCRETRY; } ASSERT((ret == SMHTSUCCESS) || (ret == SMHTMERGE)); ASSERT(SCACHE[scacheNum].SMHT[smhtind].numMHTwait < MHT_SIZE); SCACHE[scacheNum].SMHT[smhtind].vAddr = vAddr; SCACHE[scacheNum].SMHT[smhtind].mhtInd[SCACHE[scacheNum].SMHT[smhtind].numMHTwait++] = mhtind; CACHE[cacheNum].MHT[mhtind].smhtEntry = smhtind; if (ret == SMHTMERGE) { /* This line already has an outstanding miss of the right * type. Merge into it. */ if (VERBOSE_DEBUG) { CPUPrint("%d: SCacheUpgradeMiss: VA: %8.8lx PA: %8.8lx MERGE\n",cpuNum, vAddr, pAddr); } return SCSTALL; } (*missCntPtr)++; if (VERBOSE_DEBUG) { CPUPrint("%d: SCacheUpgradeMiss: VA: %8.8lx PA: %8.8lx\n",cpuNum, vAddr, pAddr); } #ifdef DATA_HANDLING /* Store the cache line pointer in the SMHT */ /* for use later IN CASE DATA ARRIVES WITH */ /* the message */ SCACHE[scacheNum].SMHT[smhtind].lineData = set->data[way];#endif mret = memsysVec.MemsysCmd(cpuNum, SCACHE[scacheNum].SMHT[smhtind].memsyscmd, pAddr, smhtind, MEMSYS_NOADDR, 0, (byte *) 0); if (mret == SUCCESS) { /* magic memory system */#ifndef BUFFER_WRITES/* WARNING: --- this might be wrong: --- */ ASSERT(!SCACHE[scacheNum].SMHT[smhtind].inuse);#endif return SCSUCCESS; } else { return SCSTALL; }}#ifdef DATA_HANDLING/***************************************************************** * DumpCacheLine *****************************************************************/voidDumpCacheLine(byte *data,int length){ unsigned long *ld = (unsigned long *)data; int i; for (i=0; i< (length/sizeof(long)); i+=4) { CPUPrint("%8.8lx %8.8lx %8.8lx %8.8lx ",ld[i],ld[i+1], ld[i+2],ld[i+3]); if ((i+4)%8 == 0) { CPUPrint("\n"); } }}#endif/*************************************************************** * IsInSCache * * The data parameter is used to return a POINTER to the caller * indicating the line in the scache which is relevant. * * If the line is not in the cache, 0 is returned and the * data parameter is unchanged. * * ****************************************************************/intIsInSCache(int cpuNum, PA pAddr, int mode, char **data, int *way){ int scacheNum = GET_SCACHE_NUM(cpuNum); struct SCacheSet* set; PA tag; bool foundit = FALSE; uint w; if (skipCaches) { return foundit; } set = & SCACHE[scacheNum].set[SCACHE_INDEXOF(pAddr)]; if (mode == MEMSYS_EXCLUSIVE) { tag = SCACHE_TAG_EX(pAddr); for(w=0;w<SCACHE_ASSOC; ++w) { if (set->tags[w] == tag) { foundit=1;#ifdef DATA_HANDLING *data = set->data[w]; /* Return a pointer to the scache line */#endif break; /* if we found it, why not bail out!!!! */ } } } else { tag = SCACHE_TAG(pAddr); for(w=0;w<SCACHE_ASSOC;++w) { if ((set->tags[w] & ~EXCLUSIVE_TAG) == tag) { foundit=1;#ifdef DATA_HANDLING *data = set->data[w];#endif /* Return a pointer to the scache line */ break; /* if we found it, why not bail out!!!! */ } } } *way = w; return foundit;}/***************************************************************** * SCacheHitEvent * * Event callback for a first level miss that hits in the second level. * Basically, stuff the line into the cache if it is still in the second * level cache. *****************************************************************/static voidSCacheHitEvent(int cpuNum,EventCallbackHdr *event, void *arg){ MHT *mht = (MHT *) event; int result; int status; char *bogus; int way=0; result = IsInSCache(cpuNum, mht->pAddr, mht->mode, &bogus, &way); if (result) { status = MEMSYS_STATUS_SUCCESS; } else { status = MEMSYS_STATUS_NAK; } /* * Modify MHT and unstall processor with first data word as soon * as the bus is free (if bus utilization is on). */ if (mht->cmd & SC_IGET) { /* Sending to ICache */ if (status == MEMSYS_STATUS_NAK) { MHTReqDone(cpuNum, mht, mht->mode, status); return; } mht->status = status; MHTReqDone(cpuNum, mht, mht->mode, status); } else { /* Sending to DCache */ if ((status == MEMSYS_STATUS_NAK) || (mht->cmd == SC_DSCUGETX) || (mht->cmd == SC_DUGETX)) { MHTReqDone(cpuNum, mht, mht->mode, status); return; } mht->status = status; MHTReqDone(cpuNum, mht, mht->mode, status); }}/***************************************************************** * SCachePUT *****************************************************************/voidSCachePUT(int cpuNum, SMHT *smht, int mode, byte *fillData){ int scacheNum = GET_SCACHE_NUM(cpuNum); PA pAddr = smht->pAddr; uint ind = (pAddr/SCACHE_LINE_SIZE) % SCACHE_INDEX; PA tag = SCACHE_TAG(pAddr); int way = smht->scacheLRU; struct SCacheSet *set = &SCACHE[scacheNum].set[ind]; if (interest(pAddr)) { LogEntry("l2-PUT",cpuNum,"pAddr=0x%x tag=0x%x foo=0x%x\n", pAddr,tag,set->tags[0]); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -