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

📄 scache.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
{   FlushStatus s;   if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheWriteback for paddr %8.8lx\n",		 cpuNum, paddr);   }   s = SCacheFlush(cpuNum, TRUE, TRUE, paddr, size, data);				/* writeback == TRUE */				/* retain  == TRUE */   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;} /**************************************************************** * CacheFlush * * This routine forces a line in the cache to be written back, * if it is dirty.  The line is flushed out of the cache. ****************************************************************/intCacheFlush(int cpuNum, PA paddr, int size, byte *data){   FlushStatus s;   if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheFlush for paddr %8.8lx\n",		 cpuNum, paddr);   }   s = SCacheFlush(cpuNum, TRUE, FALSE, paddr, size, data);				/* writeback == TRUE */				/* retain  == FALSE */   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;} /*************************************************************** * CacheExtract * * This operation requests a line from the cache, and removes it * from the cache.  The line is written back, if dirty. * (This is a GETX operation) * * After this operation, the line is no longer present in the * cache. ***************************************************************/intCacheExtract(int cpuNum, PA paddr, int size, int *writeback, byte *data){   FlushStatus s;   if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheExtract for paddr %8.8lx\n",		 cpuNum, paddr);   }   s = SCacheFlush(cpuNum, TRUE, FALSE, paddr, size, data);				/* writeback == TRUE */				/* retain  == FALSE */   *writeback = (s == FLUSH_EXCLUSIVE);   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;} /*************************************************************** * CacheExtractIndex * * This operation requests a line from the cache, and removes it * from the cache.  The line is written back, if dirty. * (This is a GETX operation) * * After this operation, the line is no longer present in the * cache. ***************************************************************/intCacheExtractIndex(int cpuNum, PA paddr, int size,		  int *writeback, PA *real_paddr,		  byte *data) {   FlushStatus s;   if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheExtract for paddr %8.8lx\n",		 cpuNum, paddr);   }   s = SCacheFlushIndex(cpuNum, TRUE, FALSE, paddr, real_paddr, size, data);				/* writeback == TRUE */				/* retain  == FALSE */   *writeback = (s == FLUSH_EXCLUSIVE);   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;} /***************************************************************** * CacheCmdDone *****************************************************************/struct {  int stalled;          /* stalled OSPC access on this CPU? */  int transId;          /* data for completing stalled access */  int mode;  int status;  int result;  EventCallbackHdr hdr; /* callback header for t/o */} ospcs[SIM_MAXCPUS];/* called in the event of an OSPC timeout. * Must complete the access and conclude the transaction. */#if defined(SIM_MIPS32) || defined(SIM_MIPS64)static voidOSPCCallback(int cpuNum, EventCallbackHdr *hdr, void *arg){  int          scacheNum = GET_SCACHE_NUM(cpuNum);  SMHT*        smht      = SCACHE[scacheNum].SMHT + ospcs[cpuNum].transId;  static byte* data      = 0;  int          delay;  ASSERT(ospcs[cpuNum].stalled);  if (!data) {     data = (byte *)malloc(SCACHE_LINE_SIZE);     bzero((char*)data,SCACHE_LINE_SIZE);     ASSERT(data);  }#ifndef SOLO  /* let MAGIC know the access has timed out, so it should   * generate an int when the data finally makes it here.   */  sim_magic_OSPC_stalled(cpuNum, smht->pAddr+K0BASE, 0);  /* get the real OSPC data from MAGIC */  delay = sim_magic_OSPC_access(cpuNum, smht->pAddr+K0BASE, data);  ASSERT(delay == 0);#endif  /* complete the pending transaction */  SCacheUpdate(cpuNum, smht,	       ospcs[cpuNum].mode, ospcs[cpuNum].status, ospcs[cpuNum].result,	       data);#ifdef DEBUG_OSPC_STALL  LogEntry("OSPC access",cpuNum,"pA=0%08x TIMED OUT\n",smht->pAddr);#endif  /* mark that all done */  ospcs[cpuNum].stalled = 0;}#endif voidCacheCmdDone(int cpuNum, int transId, int mode, int status, int result,	     byte *data){   int   scacheNum = GET_SCACHE_NUM(cpuNum);   SMHT *smht      = SCACHE[scacheNum].SMHT + transId;   int   delay;#if !defined(SOLO) &&  !defined(SIM_X86)   if (transId < 0) {      DMAStatus res;      if (status == MEMSYS_STATUS_SUCCESS) {         res = DMA_OK;      } else if (status == MEMSYS_STATUS_NAK) {         res = DMA_NAK;      } else {         res = DMA_BAD;      }      DMACmdDone(transId, res);      return;   }#else   ASSERT (transId >= 0);#endif   if ((status == MEMSYS_STATUS_NAK) ||       ((smht->memsyscmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE)) {      SCacheUpdate(cpuNum, smht, mode, status, result, data);      return;   }#if !defined(SOLO) && !defined(SIM_ALPHA) && !defined(SIM_X86)   /* Support for OSPC's.    *    * For references to the OSPC area (enabled only when the remap is),    * we let the reference go as usual through the memory system. When    * the ref completes, we just substitute the OSPC data for the data    * provided by the memory system.    *    * This is a nasty hack and should eventually be replaced by having    * all memory accesses go through MAGIC (simmagic.c).    */   if ( IS_REMAPPED_PADDR(0, cpuNum)                                  &&        (smht->memsyscmd & MEMSYS_CMDMASK) == MEMSYS_GET              &&	status == MEMSYS_STATUS_SUCCESS                               &&	(delay = sim_magic_OSPC_access(cpuNum,smht->pAddr+K0BASE,data)) != 0 ) {#ifndef DATA_HANDLING     ASSERT(0);#endif     /* must block on this access */     ASSERT(!ospcs[cpuNum].stalled);     ospcs[cpuNum].stalled = 1;     ospcs[cpuNum].transId = transId;     ospcs[cpuNum].mode    = mode;     ospcs[cpuNum].status  = status;     ospcs[cpuNum].result  = result;#ifndef SOLO     /* let MAGIC know the access has stalled, so it shouldn't      * generate an int when the SIPS arrives.      */     sim_magic_OSPC_stalled(cpuNum, smht->pAddr+K0BASE, 1);#endif     /* set timeout */     EventDoCallback(cpuNum, OSPCCallback, &ospcs[cpuNum].hdr, NULL, delay);#ifdef DEBUG_OSPC_STALL     LogEntry("OSPC access",cpuNum,"pA=0%08x STALLED\n",smht->pAddr);#endif     /* will get a call to CacheCmdUnstall when SIPS arrives, or will      * time out, call OSPCCallback, and complete the access.      */     return;   }#endif   SCacheUpdate(cpuNum, smht, mode, status, result, data);}voidCacheCmdUnstall(int cpuNum, VA vAddr){  int          scacheNum = GET_SCACHE_NUM(cpuNum);  SMHT*        smht      = SCACHE[scacheNum].SMHT + ospcs[cpuNum].transId;  static byte* data      = 0;  int          delay;  #if defined(SIM_MIPS32) || defined(SIM_MIPS64)  if (ospcs[cpuNum].stalled && smht->pAddr+K0BASE == vAddr) {    if (!data) {       data = (byte*)malloc(SCACHE_LINE_SIZE);       bzero(data,SCACHE_LINE_SIZE);       ASSERT(data);    }#ifndef SOLO    sim_magic_OSPC_stalled(cpuNum, smht->pAddr+K0BASE, 0);    /* get the real OSPC data from MAGIC */    delay = sim_magic_OSPC_access(cpuNum, vAddr, data);    ASSERT(delay == 0);#endif        /* complete the pending transaction */    SCacheUpdate(cpuNum, smht,		 ospcs[cpuNum].mode, ospcs[cpuNum].status, ospcs[cpuNum].result,		 data);    /* mark that all done and kill timeout */    ospcs[cpuNum].stalled = 0;    EventCallbackRemove(&ospcs[cpuNum].hdr);#ifdef DEBUG_OSPC_STALL    LogEntry("OSPC access",cpuNum,"pA=0%08x GOT DATA\n",smht->pAddr);#endif  } /* else: must be other OSPC priority */  #endif  }  VA   CacheGetVaddr(int cpuNum, int transId){   int   scacheNum = GET_SCACHE_NUM(cpuNum);   SMHT *smht      = SCACHE[scacheNum].SMHT + transId;   ASSERT(transId >=0);   return smht->vAddr;}  /***************************************************************** * SCacheUpdate *****************************************************************/static voidSCacheUpdate(int cpuNum, SMHT *smht, int mode, int status, int result,	     byte *data){   int cacheNum = GET_CACHE_NUM(cpuNum);   int scacheNum = GET_SCACHE_NUM(cpuNum);   int i;   int reported = 0;      QUICK_ICACHE_CLEAR(cpuNum);   if (status == MEMSYS_STATUS_ERROR) {      for (i = 0; i < smht->numMHTwait; i++) {         bool isIRef = FALSE;         int mhtind  = smht->mhtInd[i];         MHT *mht    = &(CACHE[cacheNum].MHT[mhtind]);            ASSERT (mhtind < MHT_SIZE);         CPUPrint("MEMSYS ERROR: CPU %d at PC %#x Addr %#x\n",                   cpuNum, smht->PC, smht->vAddr);         if (mht->cmd & SC_IGET) {            isIRef = TRUE;         }         CPUVec.TakeBusError(cpuNum, isIRef, smht->vAddr);         break;      }      FreeSMHT(cpuNum, smht - SCACHE[scacheNum].SMHT);      return;   }   if (status == MEMSYS_STATUS_NAK) {      if (smht->numMHTwait == 0) {        SCACHE[scacheNum].stats.Prefetches--;      }      for (i = 0; i < smht->numMHTwait; i++) {         int mhtind = smht->mhtInd[i];         MHT *mht = &(CACHE[cacheNum].MHT[mhtind]);            ASSERT( mhtind < MHT_SIZE );         MHTReqDone(cpuNum, mht, 0, MEMSYS_STATUS_NAK);         /* We don't want nak'ed requests to count towards the            number of misses... the number of read misses should just            equal the number of read replies. */         /* RPB: When there are multiple MHT entries waiting, only one of             them is counted as a miss by the stats; the rest are merges.            In order to make the stats come out right, only the counter             for the first miss should be decremented. */         /* If there is a prefetch in this entry, then the other requests             must have merged with it (since we would just punt the prefetch            otherwise), so don't need to decrement the counter in that case            either. */         if ((i > 0) || (smht->pfvAddr > 0)) continue;         if (mht->cmd & SC_IGET) {            SCACHE[scacheNum].stats.IgetMisses--;         } else {             switch (mht->cmd & (SC_DGET|SC_DGETX|SC_DUGETX|SC_DSCUGETX|SC_DLLGET|SC_DLLGETX)) {            case SC_DGET:            case SC_DLLGET:               SCACHE[scacheNum].stats.DgetMisses--;               break;            case SC_DGETX:            case SC_DLLGETX:               SCACHE[scacheNum].stats.DgetXMisses--;               break;            case SC_DUGETX:            case SC_DSCUGETX:               SCACHE[scacheNum].stats.DupgradeMisses--;               break;            default:               ASSERT(0);            }         }      }      SCACHE[scacheNum].stats.NAKs++;      FreeSMHT(cpuNum, smht - SCACHE[scacheNum].SMHT);      /* --- WARNING: This was put in because SYNCs mean that a request ---       * --- arrival does not necessarily wake up the processor --- */      CPUVec.Unstall(cpuNum);      return;   }   ASSERT(status == MEMSYS_STATUS_SUCCESS);   SCachePUT(cpuNum, smht, mode, data);      if (smht->numMHTwait == 0) {      uint type = E_L2 | E_D;      int stall = 0;      if (mode == MEMSYS_EXCLUSIVE) {          if (result & MEMSYS_RESULT_INVALIDATE) {            type |= E_WRITE | E_CAUSED_INVAL;         } else {            type |= E_WRITE;         }      } else {         type |= E_READ;      }            if ((smht->memsyscmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE) {         type |= E_UPGRADE;      }            ASSERT((result & MEMSYS_RESULT_CACHE)              || (result & MEMSYS_RESULT_MEMORY));      ASSERT(!((result & MEMSYS_RESULT_CACHE)                && (result &MEMSYS_RESULT_MEMORY)));            if (result & MEMSYS_RESULT_CACHE) {         type |= E_FOUND_IN_CACHE;      }                  /*       * Record the prefetch that did not incur a miss       */      if (interest(smht->pAddr)) {         LogEntry("pfupdate",cpuNum,"vAddr=0x%x pAddr=0x%x type=%x\n",                  smht->pfvAddr,smht->pAddr, type);      }      if (CPUVec.CPUstatus(cpuNum) != cpu_running) { 

⌨️ 快捷键说明

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