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

📄 pcache.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   if ( !ICACHE_MISS_ALWAYS ) {       if (set->tags[0] == tag) {         ICACHE_TOUCH(set->LRU, 0);         setindex=0;         MS_INSTRUCTION_SET(cpuNum,0);         QUICK_ICACHE_SET(cpuNum, pAddr, set, setindex);         goto hit;      }#if ICACHE_ASSOC > 1      if (set->tags[1] == tag) {         ICACHE_TOUCH(set->LRU, 1);         setindex=1;         MS_INSTRUCTION_SET(cpuNum,1);         QUICK_ICACHE_SET(cpuNum, pAddr, set, setindex);         goto hit;      }#endif#if ICACHE_ASSOC > 2      if (set->tags[2] == tag) {         ICACHE_TOUCH(set->LRU, 2);         setindex=2;         MS_INSTRUCTION_SET(cpuNum,2);         QUICK_ICACHE_SET(cpuNum, pAddr, set, setindex);         goto hit;      }#endif#if ICACHE_ASSOC > 3      if (set->tags[3] == tag) {         ICACHE_TOUCH(set->LRU, 3);         setindex=3;         MS_INSTRUCTION_SET(cpuNum,3);         QUICK_ICACHE_SET(cpuNum, pAddr, set, setindex);         goto hit;      }#endif   }   ret = ICacheMiss(cpuNum, vAddr, pAddr, &setindex);   if (ret != SUCCESS) {      return ret;   } else {       goto hit;   }hit:   MS_INSTRUCTION(cpuNum, pAddr);   lineindex = pAddr & (ICACHE_LINE_SIZE-1);   *inst =  *(Inst *) (set->data[setindex] + lineindex);   return SUCCESS;}/***************************************************************** * ICacheMiss * * XXX - Should make this virtually index, physically tagged. *****************************************************************/Result ICacheMiss(int cpuNum, VA vAddr, PA pAddr, int *setindex){   int cacheNum = GET_CACHE_NUM(cpuNum);   int       mhtind;   int       ind = ICACHE_INDEXOF(pAddr);   int       lru;   MHTStatus mhtret;   SCResult  sret;   if (VERBOSE_DEBUG) {      CPUPrint("%d: ICacheMiss: VA: %8.8lx  PA: %8.8lx\n",cpuNum, vAddr, pAddr);   }#ifdef MIPSY_MXS   if (!MxsApproveImiss(PE[cpuNum].st, pAddr)) {       /* This means that the current Imiss could cause a previous load or        * store to be aborted due to a coherency exception.  We stall the        * miss until the condition clears.  This is a performance optimization        * that becomes necessary if we speculate through SC instructions.        */       return FAILURE;   }#endif /* MIPSY_MXS */   /*    * Check the second level cache for the line. Before we     * record the miss in the ICache MHT entry make sure    * this isn't a re-issued ICache miss from a CONFLICT case.    */   lru = ICACHE_LRU(CACHE[cacheNum].ICache.set[ind].LRU);   mhtret = AllocMHT(cpuNum, SC_IGET, vAddr,                      pAddr,                     ICACHE_LINE_SIZE, lru, &mhtind);   switch (mhtret) {   case MHTFULL:      return FAILURE;   case MHTCONFLICT:      return FAILURE;   case MHTMERGE:      /*        * This can occur if someone does a data acces to a line       * and then jumps to it.        */      return STALL;   default:      ASSERT(mhtret == MHTSUCCESS);      break;   }   if (CACHE[cacheNum].ICache.set[ind].tags[lru] != INVALID_TAG) {      uint type = E_L1 | E_I | E_READ | E_FLUSH_CLEAN;      PA replPA = ITAG_TO_PA(CACHE[cacheNum].ICache.set[ind].tags[lru], ind);            L1_LINE_TRANS_EVENT(cpuNum, replPA, type, lru,                          IS_KUSEG(CURRENT_PC(cpuNum)));   }   CACHE[cacheNum].ICache.set[ind].tags[lru] = INVALID_TAG;   /*    * Forward the request on to the secondary cache.    */   sret = SCacheFetch(cpuNum, vAddr, pAddr, SC_IGET, mhtind);   if (sret == SCRETRY) {      /*       * We must of conflicted with a data miss. Deallocate       * MHT entry and stall waiting for the SMHT to clear up.       * XXX - Should me reissue this ourselves?       */      FreeMHT(cpuNum, mhtind);      return FAILURE;   } else {      if (sret == SCBUSERROR) {         FreeMHT(cpuNum, mhtind);         return BUSERROR;      }    }   /* Due to the MHT and the fact that the scache will call ICachePUT      and will fill in the pcache, this routine will only be called on      once on the miss to the icache line. */   CACHE[cacheNum].stats.ICache.ReadMisses++;   if (sret == SCSTALL) {      return STALL;   }   /* SCacheFetch may return SCSUCCESS if zero latency misses    * are configured. Record this as a miss but don't stall.     */   (*setindex) = lru;   ASSERT(sret == SCSUCCESS);   return SUCCESS;} /***************************************************************** * ICacheFlush *****************************************************************/void ICacheFlush(int cpuNum, PA paddr, int size){   int cacheNum = GET_CACHE_NUM(cpuNum);   PA a;   int ind;   int  set;   QUICK_ICACHE_CLEAR(cpuNum);   CACHE[cacheNum].stats.ICache.Inval++;   for (a = paddr; a < paddr + size; a += ICACHE_LINE_SIZE) {      ind = ICACHE_INDEXOF(a);      if (CACHE[cacheNum].ICache.set[ind].tags[0] == ICACHE_TAG(a)) {         set = 0;         goto foundit;      }#if ICACHE_ASSOC > 1      if (CACHE[cacheNum].ICache.set[ind].tags[1] == ICACHE_TAG(a)) {         set = 1;         goto foundit;      }#endif#if ICACHE_ASSOC > 2      if (CACHE[cacheNum].ICache.set[ind].tags[2] == ICACHE_TAG(a)) {         set = 2;         goto foundit;      }#endif#if ICACHE_ASSOC > 3      if (CACHE[cacheNum].ICache.set[ind].tags[3] == ICACHE_TAG(a)) {         set = 3;         goto foundit;      }#endif      continue;  /* not found, go around loop */ foundit:      CACHE[cacheNum].stats.ICache.LinesInval++;      CACHE[cacheNum].ICache.set[ind].tags[set] = INVALID_TAG;      ICACHE_MAKE_LRU(CACHE[cacheNum].ICache.set[ind].LRU, set);      L1_LINE_TRANS_EVENT(cpuNum, a,                           (E_L1 | E_I | E_READ | E_EXTERNAL | E_FLUSH_CLEAN), 0,                          IS_KUSEG(CURRENT_PC(cpuNum)));   }}/***************************************************************** * AllocMHT   * * Allocate an entry in the miss handling table for the  * specified first level miss. This routine is responsible for  * checking for conflict and merge miss as well.  *****************************************************************/static MHTStatusAllocMHT(int cpuNum, SCacheCmd cmd, VA vAddr, PA pAddr, int size,          int lru, int *mhtind){   int cacheNum = GET_CACHE_NUM(cpuNum);   int entry;   int ind,cacheLineSize;   if (cmd == SC_IGET) {       ind = ICACHE_INDEXOF(pAddr);      cacheLineSize = ICACHE_LINE_SIZE;   } else {       ind = DCACHE_INDEXOF(pAddr);      cacheLineSize = DCACHE_LINE_SIZE;   }   ASSERT( size == cacheLineSize );   if (CACHE[cacheNum].MHTnumInuse == 0) {       entry = 0;  /* Special case for speed: allocate when MHT is empty */   } else {       int numChecked = CACHE[cacheNum].MHTnumInuse;      int i;      entry = -1;      for (i = 0; (i < MHT_SIZE) && numChecked; i++) {         if (!CACHE[cacheNum].MHT[i].inuse) {            entry = i;         } else {            numChecked--;            if (CACHE[cacheNum].MHT[i].ind == ind) {               if ( (cmd==SC_IGET && CACHE[cacheNum].MHT[i].cmd==SC_IGET) ||                   (cmd!=SC_IGET && CACHE[cacheNum].MHT[i].cmd!=SC_IGET) ) {                  *mhtind = i;                  if (!SameCacheLine(CACHE[cacheNum].MHT[i].pAddr, pAddr,                                      cacheLineSize)) {                     /* Currently we only support one miss per cache index */                     return MHTCONFLICT;                  }                  /* Except we call them merges if two misses happen to the same                   * line */                  if (CACHE[cacheNum].MHT[i].cmd != cmd) {                     /* Call it a conflict if we need a GETX and only a                      * GET is outstanding.                       */                     return MHTCONFLICT;                  }                   return MHTMERGE;               }            }         }      }      if (entry == -1) {         if (i == MHT_SIZE) {             /* MHT is full */            return MHTFULL;         } else {            entry = i;            }      }   }      CACHE[cacheNum].MHTnumInuse++;   CACHE[cacheNum].MHT[entry].inuse = TRUE;   CACHE[cacheNum].MHT[entry].startTime = CPUVec.CycleCount(cpuNum);   CACHE[cacheNum].MHT[entry].cmd = cmd;   CACHE[cacheNum].MHT[entry].vAddr = vAddr;   CACHE[cacheNum].MHT[entry].pAddr = pAddr;   CACHE[cacheNum].MHT[entry].PC = CURRENT_PC(cpuNum);   CACHE[cacheNum].MHT[entry].ind = ind;   CACHE[cacheNum].MHT[entry].lru = lru;   CACHE[cacheNum].MHT[entry].writeBuffer->active = FALSE;   *mhtind = entry;#ifdef MIPSY_MXS   CACHE[cacheNum].MHT[entry].cpu_action = GetMxsAction (PE[cpuNum].st);#endif      return MHTSUCCESS;}   /***************************************************************** * FreeMHT - Delete a MHT entry * *****************************************************************/static voidFreeMHT(int cpuNum, int entryNum){   int cacheNum = GET_CACHE_NUM(cpuNum);   ASSERT(CACHE[cacheNum].MHT[entryNum].inuse);   CACHE[cacheNum].MHT[entryNum].inuse = 0;   CACHE[cacheNum].MHTnumInuse--;   ASSERT(CACHE[cacheNum].MHTnumInuse >= 0);   ASSERT(CACHE[cacheNum].MHT[entryNum].writeBuffer->active == FALSE);}/***************************************************************** * ICachePUT * Since this is the ICache, no real writing. *****************************************************************/static voidICachePUT(int cpuNum, MHT *mht, int mode){   int result;   int cacheNum = GET_CACHE_NUM(cpuNum);   PA paddr = mht->pAddr;   int ind  = ICACHE_INDEXOF(paddr);   PA tag = ICACHE_TAG(paddr);   int lru  = mht->lru;   char *data;   int way =0;   ASSERT(mht->cmd & SC_IGET);   ASSERT(CACHE[cacheNum].ICache.set[ind].tags[lru] == INVALID_TAG);   /* 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 */   result = IsInSCache(cpuNum, paddr, MEMSYS_SHARED, &data, &way);   if (!result) {      CPUError("ICachePUT didn't find line in SCache (with IsInSCache())");   }   CACHE[cacheNum].ICache.set[ind].tags[lru] = tag; #ifdef DATA_HANDLING   CACHE[cacheNum].ICache.set[ind].data[lru] =      data+((paddr&(SCACHE_LINE_SIZE-1)&~(PA)(ICACHE_LINE_SIZE-1)));   /* Point L1 to data location in L2 */#else   CACHE[cacheNum].ICache.set[ind].data[lru] =      (byte*)CPUVec.PAToHostAddr(cpuNum, (paddr&~(PA)(ICACHE_LINE_SIZE-1)), 0);#endif}/***************************************************************** * MemRefReadData * Return values: *          SUCCESS - Request hit in the cache, data returned. *          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.  * * Main entry into 1st level data cache from CPU. *****************************************************************/Result MemRefReadData(int cpuNum, VA vAddr, PA pAddr, void *data,                RefSize size, RefFlavor flavor){   int cacheNum = GET_CACHE_NUM(cpuNum);   PA  tag = DCACHE_TAG(pAddr);   int ind = DCACHE_INDEXOF(pAddr);   struct DCache *dcache = &CACHE[cacheNum].DCache;   struct DCacheSet *set = &(dcache->set[ind]);   Result ret;   int lineindex;   int setindex;   if ( DCACHE_HIT_ALWAYS ) {       setindex = 0;      set->data[setindex] =         (byte*)CPUVec.PAToHostAddr(cpuNum, pAddr&~(PA)(DCACHE_LINE_SIZE-1), vAddr);      goto hit;   }         if ( !DCACHE_MISS_ALWAYS ) {       if (((~EXCLUSIVE_TAG) & (set->tags[0])) == tag) {         DCACHE_TOUCH(set->LRU, 0);         setindex=0;         goto hit;      }#if DCACHE_ASSOC > 1      if (((~EXCLUSIVE_TAG) & (set->tags[1])) == tag) {         DCACHE_TOUCH(set->LRU, 1);         setindex=1;         goto hit;      }#endif#if DCACHE_ASSOC > 2      if (((~EXCLUSIVE_TAG) & (set->tags[2])) == tag) {         DCACHE_TOUCH(set->LRU, 2);         setindex=2;         goto hit;      }#endif#if DCACHE_ASSOC > 3      if (((~EXCLUSIVE_TAG) & (set->tags[3])) == tag) {         DCACHE_TOUCH(set->LRU, 3);         setindex=3;         goto hit;      }#endif   }   /* Cache misses go here */      if (VERBOSE_DEBUG) {      CPUPrint("%d: Read  D$ MISS VA: 0x%8.8lx  PA: 0x%8.8lx\n",               cpuNum, vAddr, pAddr);   }   ret = DCacheReadMiss(cpuNum, vAddr, pAddr, data, size, flavor, &setindex);

⌨️ 快捷键说明

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