⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcache.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
         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 + -