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

📄 pcache.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   if (ret != SUCCESS) {      return ret;   } else {      ASSERT(setindex >=0 && setindex < DCACHE_ASSOC);      goto hit;   }hit:   if ( !DCACHE_HIT_ALWAYS ) {       if (useWriteBuffer && AddrIsInWriteBuffer(cpuNum, pAddr, size)) {         /*           * We currently don't implement any kind of load bypassing so           * we stall when a load hits a buffered write word.           */         return STALL;      }   }   DATA_READ_EVENT();   FALSE_SHARING_ACCESS(cpuNum,set->fSharing[setindex],pAddr);   lineindex = pAddr & (DCACHE_LINE_SIZE-1);   switch (size) {   case WORD_SZ:       *(int *) data =  *(int *) (set->data[setindex] + lineindex);      if (VERBOSE_DEBUG) {         CPUPrint("%d: Read  D$ hit  VA: 0x%8.8lx  PA: 0x%8.8lx  WORD data: 0x%8.8lx lineindex=%d\n",                  cpuNum, vAddr, pAddr, *(int *) (set->data[setindex] + lineindex), lineindex);      }      break;   case BYTE_SZ:       *(byte *) data =  *(byte *) (set->data[setindex] + lineindex);      if (VERBOSE_DEBUG) {         CPUPrint("%d: Read  D$ hit  VA: 0x%8.8lx  PA: 0x%8.8lx  BYTE data: 0x%2.2x lineindex=%d\n",                  cpuNum, vAddr, pAddr, *(char *) (set->data[setindex] + lineindex), lineindex);      }      break;   case HALF_SZ:       *(short *) data =  *(short *) (set->data[setindex] + lineindex);      if (VERBOSE_DEBUG) {         CPUPrint("%d: Read  D$ hit  VA: 0x%8.8lx  PA: 0x%8.8lx  HALF data: 0x%8.8lx lineindex=%d\n",                  cpuNum, vAddr, pAddr, *(short *) (set->data[setindex] + lineindex), lineindex);      }      break;   case DOUBLE_SZ:       *(uint64 *) data =  *(uint64 *) (set->data[setindex] + lineindex);      if (VERBOSE_DEBUG) {#ifdef __alpha          CPUPrint("%d: Read D$ hit VA: 0x%8.8lx PA: 0x%8.8lx DOUBLE data: 0x%16.16lx lineindex=%d\n",                   cpuNum, vAddr, pAddr, *(uint64 *) (set->data[setindex] + lineindex), lineindex);#else          CPUPrint("%d: Read D$ hit VA: 0x%8.8lx PA: 0x%8.8lx DOUBLE data: 0x%16.16llx\n",                   cpuNum, vAddr, pAddr, *(uint64 *) (set->data[setindex] + lineindex));#endif      }      break;   default:       CPUError("Bad size %d passed to ReadDCache\n", size);      break;    }   return SUCCESS;}/***************************************************************** * DCacheReadMiss *  *****************************************************************/static Result DCacheReadMiss(int cpuNum, VA vAddr, PA pAddr, void *data,                RefSize size, RefFlavor flavor, int *indPtr){   PA writebackAddr;   int cacheNum = GET_CACHE_NUM(cpuNum);   int  ind = (pAddr/DCACHE_LINE_SIZE) % DCACHE_INDEX;   int mhtind;   int lru;   SCacheCmd cmd;   MHTStatus mhtret;   SCResult sret;   if (noUpgrades) {      cmd = (flavor == LL_FLAVOR ? SC_DLLGETX : SC_DGETX);   } else {      cmd = (flavor == LL_FLAVOR ? SC_DLLGET : SC_DGET);   }   lru  = DCACHE_LRU(CACHE[cacheNum].DCache.set[ind].LRU);   mhtret = AllocMHT(cpuNum, cmd, vAddr,                      pAddr, DCACHE_LINE_SIZE, lru, &mhtind);   switch (mhtret) {   case MHTFULL:      return FAILURE;   case MHTCONFLICT:      return FAILURE;   case MHTMERGE:      (*indPtr) = mhtind;      return STALL;   default:      ASSERT(mhtret == MHTSUCCESS);      break;   }   if (VERBOSE_DEBUG) {      CPUPrint("%d: DCacheReadMiss: VA: %8.8lx  PA: %8.8lx\n",cpuNum, vAddr,               pAddr);   }   if (CACHE[cacheNum].DCache.set[ind].tags[lru] & EXCLUSIVE_TAG) {      CACHE[cacheNum].stats.DCache.Writebacks++;#ifdef DATA_HANDLING      {         int way;         char *scacheData;         /* Generate writeback address */         writebackAddr = DTAG_TO_PA(CACHE[cacheNum].DCache.set[ind].tags[lru],                                    ind);         if (!(IsInSCache(cacheNum, writebackAddr, MEMSYS_EXCLUSIVE,                           &scacheData, &way))) {            CPUError("DCacheReadMiss didn't find excl. line in SCache for WB");         }       }#endif               {         uint type = E_L1 | E_D | E_READ | E_WRITEBACK;         PA replPA = DTAG_TO_PA(CACHE[cacheNum].DCache.set[ind].tags[lru], ind);               L1_LINE_TRANS_EVENT(cpuNum, replPA, type, lru,                             IS_KUSEG(CURRENT_PC(cpuNum)));      }   } else {      if (!(CACHE[cacheNum].DCache.set[ind].tags[lru] & INVALID_TAG)) {         /* Generate "replacement" address */         writebackAddr = DTAG_TO_PA(CACHE[cacheNum].DCache.set[ind].tags[lru],                                    ind);         if (VERBOSE_DEBUG) {            CPUPrint("%d: dcache discarding clean line %8.8lx\n",                     cpuNum,writebackAddr);         }      }      if (!(CACHE[cacheNum].DCache.set[ind].tags[lru] & INVALID_TAG)) {         uint type = E_L1 | E_D | E_READ | E_FLUSH_CLEAN;         PA replPA = DTAG_TO_PA(CACHE[cacheNum].DCache.set[ind].tags[lru], ind);               L1_LINE_TRANS_EVENT(cpuNum, replPA, type, lru,                             IS_KUSEG(CURRENT_PC(cpuNum)));      }   }   CACHE[cacheNum].DCache.set[ind].tags[lru] = INVALID_TAG;   sret = SCacheFetch(cpuNum, vAddr, pAddr, cmd, mhtind);   if (sret == SCRETRY) {      /*       * We must of conflicted with a data miss. Clean MHT and       * stall.         * XXX should we reissue this ourselves?       */      FreeMHT(cpuNum, mhtind);      return FAILURE;   } else if (sret == SCBUSERROR) {      FreeMHT(cpuNum, mhtind);      return BUSERROR;   }   CACHE[cacheNum].stats.DCache.ReadMisses++;   if (sret == SCSTALL) {       (*indPtr) = mhtind;      return STALL;   }   /*    * SCacheFetch may return SUCCESS if zero latency misses    * are configured. Record this as a miss but don't stall.     */   (*indPtr) = lru;      return SUCCESS;}/***************************************************************** * DCachePUT *****************************************************************/static voidDCachePUT(int cpuNum, MHT *mht, int mode){   int cacheNum = GET_CACHE_NUM(cpuNum);   PA pAddr = mht->pAddr;   int ind  = DCACHE_INDEXOF(pAddr);   int lru  = mht->lru;   int way  = 0;   PA tag   = DCACHE_TAG(pAddr);   char *data;   /* NOTE: This call is no longer optional! We use it to find       the SCache line that will be used to satisfy the data part of      the miss */   if (!(IsInSCache(cpuNum, pAddr, mode, &data, &way))) {      CPUError("DCachePUT didn't find line in SCache (with IsInSCache())");   }   if (mode & MEMSYS_EXCLUSIVE)      tag |= EXCLUSIVE_TAG;      if (mht->cmd == SC_DSCUGETX        && (CACHE[cacheNum].DCache.set[ind].tags[lru] & INVALID_TAG)) {      CPUVec.ClearLockFlag(cpuNum);   /* SC fails due to a race */   }   /* We don't want to copy data if it is already in the DCache    * exclusive.      */   if (!((CACHE[cacheNum].DCache.set[ind].tags[lru] & EXCLUSIVE_TAG) &&         ((CACHE[cacheNum].DCache.set[ind].tags[lru] & ~EXCLUSIVE_TAG) ==          (tag & ~EXCLUSIVE_TAG)))) {            CACHE[cacheNum].DCache.set[ind].tags[lru] = tag;   #ifdef DATA_HANDLING      CACHE[cacheNum].DCache.set[ind].data[lru] =         data+((pAddr&(SCACHE_LINE_SIZE-1)&~(PA)(DCACHE_LINE_SIZE-1)));      /* Point L1 to data location in L2 */#else      CACHE[cacheNum].DCache.set[ind].data[lru] =         (byte*)CPUVec.PAToHostAddr(cpuNum, pAddr&~(PA)(DCACHE_LINE_SIZE-1), mht->vAddr);#endif      CACHE[cacheNum].DCache.set[ind].fSharing[lru] =          SCacheLineToFalseSharing(cacheNum,pAddr,way);         }   if (mht->writeBuffer->active) {       ASSERT(CACHE[cacheNum].DCache.set[ind].tags[lru] & EXCLUSIVE_TAG);       RetireWriteBuffer(cpuNum, mht, CACHE[cacheNum].DCache.set[ind].data[lru]);   }   DCACHE_TOUCH(CACHE[cacheNum].DCache.set[ind].LRU, lru);   }/*************************************************************** * DCacheFlush * * This routine now takes two parameters: writeback and discard. * Writeback: Should I write the line back to the scache if *            it is dirty? * Retain:   After this call, should the line be retained in  my *            cache?  (If the line was exclusive and writeback *            is set, the line is downgraded to Shared). * * NOTE: writeback==0 && retain==1 is effectively a NOP.  We'll * support that, but I don't see why it should ever be used. ****************************************************************//* FIXTHIS: These statistics are mimimally correct, but not much more */static void DCacheFlush(int cpuNum, int writeback, int retain, PA paddr, int size){   int cacheNum = GET_CACHE_NUM(cpuNum);   PA a;     int ind, set;   ASSERT (writeback || !retain);   /* One of these two should be set */   /* ASSERT for now */   ASSERT((paddr & (DCACHE_LINE_SIZE-1)) == 0);   if (writeback && retain) {      CACHE[cacheNum].stats.DCache.Downgrade++;   } else if (!writeback && !retain) {      CACHE[cacheNum].stats.DCache.Inval++;   }   for (a = paddr; a < paddr + size; a += DCACHE_LINE_SIZE) {      ind = DCACHE_INDEXOF(a);            if ((CACHE[cacheNum].DCache.set[ind].tags[0] & (~EXCLUSIVE_TAG))           == DCACHE_TAG(a)) {         set = 0;         goto foundit;      }      #if DCACHE_ASSOC > 1      if ((CACHE[cacheNum].DCache.set[ind].tags[1] & (~EXCLUSIVE_TAG)) == DCACHE_TAG(a)) {         set = 1;         goto foundit;      }#endif#if DCACHE_ASSOC > 2      if ((CACHE[cacheNum].DCache.set[ind].tags[2] & (~EXCLUSIVE_TAG)) == DCACHE_TAG(a)) {         set = 2;         goto foundit;      }#endif#if DCACHE_ASSOC > 3      if ((CACHE[cacheNum].DCache.set[ind].tags[3] & (~EXCLUSIVE_TAG)) == DCACHE_TAG(a)) {         set = 3;         goto foundit;      }#endif      continue;   /* not present, go around the loop */       foundit:      if ((CACHE[cacheNum].DCache.set[ind].tags[set] & EXCLUSIVE_TAG) != 0) {         /* Line is exclusive */         if (writeback) {            CACHE[cacheNum].stats.DCache.LinesWriteback++;            CACHE[cacheNum].DCache.set[ind].tags[set] = DCACHE_TAG(a);#ifdef DATA_HANDLING            {               char *data;               int way;                              /* NOTE: This call is not optional for                  DATA_HANDLING..we use it to find the scache line                  that will be used to receive the writeback */               if (!(IsInSCache(cpuNum, a, 0, &data, &way))) {                  CPUError("DCacheFlush didn't find line in SCache");               }                /* Write the line back to the scache */            }#endif            L1_LINE_TRANS_EVENT(cpuNum, a,                                 (E_L1 | E_D | E_EXTERNAL | E_DOWNGRADE), 0,                                IS_KUSEG(CURRENT_PC(cpuNum)));         }       }         if (!writeback && !retain) {         uint type;         CACHE[cacheNum].stats.DCache.LinesInval++;         if (CACHE[cacheNum].DCache.set[ind].tags[set] & EXCLUSIVE_TAG) {            type = E_L1 | E_D | E_EXTERNAL | E_WRITEBACK;         } else {            type = E_L1 | E_D | E_EXTERNAL | E_FLUSH_CLEAN;         }         L1_LINE_TRANS_EVENT(cpuNum, a, type, 0,                             IS_KUSEG(CURRENT_PC(cpuNum)));      }            if (retain) {         CACHE[cacheNum].DCache.set[ind].tags[set] &= ~EXCLUSIVE_TAG;         /* Take away exclusive ownership */      } else {         CACHE[cacheNum].DCache.set[ind].tags[set] = INVALID_TAG;      }      DCACHE_MAKE_LRU(CACHE[cacheNum].DCache.set[ind].LRU, set);   }}/**************************************************************** * MemRefWriteData * Return values: *          SUCCESS - Request hit in the cache, data written. *          STALL   - Request missed in the cache, sent to the 2nd-level or memsys. *          FAILURE - Request missed but couldn't be issued to 2nd-level or *                    memory system. Caller must retry. *          BUSERROR - Request suffered a bus error.  *          SCFAILURE - Was an SC and it failed. * * Main entry into 1st level data cache writing from the CPU *****************************************************************/ResultMemRefWriteData(int cpuNum, VA vAddr, PA pAddr, uint64 data,                 RefSize size, RefFlavor flavor){   int cacheNum = GET_CACHE_NUM(cpuNum);   PA     tag =  DCACHE_TAG_EX(pAddr);   struct DCacheSet* set;    bool   upgrade;   int    way;   int    mhtind = -1;   int    lineindex;   int    ind = DCACHE_INDEXOF(pAddr);   set = & CACHE[cacheNum].DCache.set[ind];   /* See if weve been stalled on the MHT, update stats if so */   if (useWriteBuffer) {      STATS_ADD_INTERVAL(cpuNum, writeBufferStats.writeMHTStallTime,                          writeMHTStallStart);   }   if ( DCACHE_HIT_ALWAYS ) {       way = 0;      set->data[way] =         (byte*)CPUVec.PAToHostAddr(cpuNum, pAddr&~(PA)(DCACHE_LINE_SIZE-1), vAddr);      goto foundit;   }   if (!DCACHE_MISS_ALWAYS ) {       if (set->tags[0] == tag) {         way = 0;         goto foundit;      }#if DCACHE_ASSOC > 1      if (set->tags[1] == tag) {         way = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -