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

📄 scache.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   QUICK_ICACHE_CLEAR(cpuNum);#ifndef SOLO   ASSERT (IS_VALID_PA(M_FROM_CPU(cpuNum), pAddr));/*   ASSERT( tag < SCACHE_TAG( MEM_SIZE(M_FROM_CPU(cpuNum))));*/#endif#ifdef DATA_HANDLING   ASSERT( SCACHE[scacheNum].set[ind].tags[way] == tag ||	   fillData);		/* We either have the data already, and */				/* this is an upgrade, or fillData is set */				/* so we can get the correct data*/#endif   if (mode & MEMSYS_EXCLUSIVE) {      tag |= EXCLUSIVE_TAG;   }   SCACHE[scacheNum].set[ind].tags[way] = tag;   SCacheLRUTouch(&SCACHE[scacheNum].set[ind].LRU, way);      /* WARNING: I think this was too restrictive:  ASSERT(fillData != 0); */   /* This parameter should never be zero when I get here */#ifdef DATA_HANDLING   if (fillData != 0) {      ASSERT(smht->lineData != (char *) 0xffffffff);      bcopy(fillData, smht->lineData, SCACHE_LINE_SIZE);      if (VERBOSE_DEBUG) {	 CPUPrint("%d: SCacheMiss: filling %8.8lx (from flashlite) ",cpuNum,		    smht->pAddr);	 CPUPrint("%d: bcopy %x -> %x (%d)  Data: ",cpuNum,		    fillData, smht->lineData, SCACHE_LINE_SIZE);      	 DumpCacheLine(smht->lineData, SCACHE_LINE_SIZE);		       }      smht->lineData = (char *) 0xffffffff;      /* Set lineData to be invalid to prevent erroneous reuse of this */      /* pointer, such as occured in our heinous bug of 3/28/95 */   }#endif   #ifdef CC_CHECKER   CacheChecker(pAddr, cpuNum, (tag & EXCLUSIVE_TAG)!=0); #endif}/**************************************************************** * SCacheFlush * * See DCacheFlush, the semantics is identical ****************************************************************/static FlushStatusSCacheFlush(int cpuNum, int writeback, int retain, PA paddr, int size,	    byte *data){   int scacheNum = GET_SCACHE_NUM(cpuNum);   PA a;     uint ind;   struct SCacheSet* set;   int way;   FlushStatus s = FLUSH_NOTFOUND;   if (interest(paddr)) {      LogEntry("flush",cpuNum,"%x state=%d\n",paddr, MSCacheState(cpuNum, paddr));   }   ASSERT(writeback || !retain);  /* One of these two should be set */      if (writeback && retain) {      SCACHE[scacheNum].stats.Downgrade++;   }   for (a = (paddr & ~(PA)(SCACHE_LINE_SIZE-1)); 	a < (paddr & ~(PA)(SCACHE_LINE_SIZE-1)) + size; 	a += SCACHE_LINE_SIZE) {      ind = SCACHE_INDEXOF(a);      set = & SCACHE[scacheNum].set[ind];      /*       * Direct-mapped caches. We do not rely on presence in the       * cache to determine the success of the SC, but rather       * on the LLbit.         */      if (SCACHE_ASSOC == 1  && CPUVec.GetLockAddr(cpuNum) == a) {          if (!retain) {             /* invalidated from the cache */	   CPUVec.ClearLockFlag(cpuNum);         }       }        for (way=0; way<SCACHE_ASSOC; ++way) {	 if (set->tags[way] == SCACHE_TAG_EX(a)) {	    goto ScFlush_Exclusive;	 }	 if ((set->tags[way] & ~EXCLUSIVE_TAG) == SCACHE_TAG(a))  {	    goto ScFlush_Shared;	 }      }      if (way==SCACHE_ASSOC) {         uint type;	 /* not found */         if (writeback & retain) {             type = E_L2 | E_WRITEBACK | E_FAKE_EXTERNAL;         } else {            type = E_L2 | E_FLUSH_CLEAN | E_FAKE_EXTERNAL;         }         L2_LINE_TRANS_EVENT(cpuNum, a, type, 0, 0,IS_KUSEG(CURRENT_PC(cpuNum)));         continue;      }            ASSERT(0);		/* Control should never reach this point */      return s;ScFlush_Exclusive:		/* Found an exclusive line in the flush */				/* region...handle it based on the flags*/      s = FLUSH_EXCLUSIVE;      PrimaryFlush(cpuNum, writeback, retain, a, SCACHE_LINE_SIZE);               SCACHE[scacheNum].stats.LinesWriteback++;      /* WARNING: I don't require the user to writeback the line if it's */      /* dirty since I want to support invalidations of dirty lines for */      /* memory copy, where I squash a line regardless of its state */            if (retain) {         /* Remove exclusive ownership */	 set->tags[way] &= SCACHE_TAG(a);#ifndef SOLO         ASSERT(IS_VALID_PA(M_FROM_CPU(cpuNum), STAG_TO_PA(set->tags[way],0)));/*         ASSERT( (set->tags[way]&~EXCLUSIVE_TAG) <                  SCACHE_TAG(MEM_SIZE(M_FROM_CPU(cpuNum))));*/#endif         L2_LINE_TRANS_EVENT(cpuNum, a, E_L2 | E_EXTERNAL | E_DOWNGRADE, 0, way,                             CURRENT_PC(cpuNum));      } else {	 set->tags[way] = INVALID_TAG;	 L2_LINE_TRANS_EVENT(cpuNum, a, E_L2 | E_EXTERNAL | E_WRITEBACK, 0, way,                             IS_KUSEG(CURRENT_PC(cpuNum)));      }#ifdef DATA_HANDLING      if (writeback) {	 ASSERT(data != NULL);	 if (data != NULL) {	/* If I want a data reply */            bcopy(set->data[way], data, SCACHE_LINE_SIZE);	 }         /* SAH: Why isn't there a writeback here? */	 if (VERBOSE_DEBUG) {	    CPUPrint("%d: bcopy %x -> %x (%d) (flashlite) Data:\n", cpuNum,		       set->data[way],(char *)data,SCACHE_LINE_SIZE);	    DumpCacheLine(set->data[way],SCACHE_LINE_SIZE);	 }      }#endif /* DATA_HANDLING */      continue;ScFlush_Shared:      if (!retain) {	 if (VERBOSE_DEBUG) {	    CPUPrint("%d: SCacheMiss:  spilling (shared) PA: %8.8lx \n",cpuNum,		       paddr);	 }	 PrimaryFlush(cpuNum, writeback, retain, a, SCACHE_LINE_SIZE);	 SCACHE[scacheNum].stats.LinesInval++;	 s = FLUSH_SHARED;	 set->tags[way] = INVALID_TAG;	 SCacheLRUMake(&set->LRU, way);         L2_LINE_TRANS_EVENT(cpuNum, a, (E_L2 | E_EXTERNAL | E_FLUSH_CLEAN),                              0, way,IS_KUSEG(CURRENT_PC(cpuNum)));      }      continue;   }   return s;}/**************************************************************** * SCacheFlushIndex * * Similar to SCacheFlush, but flushes one of the cached lines at * an index matching the one of the given paddr. Used to implement * the CACH_SD option to the CACHE instruction. ****************************************************************/static FlushStatusSCacheFlushIndex(int cpuNum, int writeback, int retain,		 PA paddr, PA *real_paddr, int size, byte *data){   int scacheNum = GET_SCACHE_NUM(cpuNum);   PA a, aa;     uint ind;   struct SCacheSet* set;   int way;   FlushStatus s = FLUSH_NOTFOUND;   if( interest(paddr))      LogEntry("flush index",cpuNum,"%x \n",paddr);   ASSERT(writeback || !retain);  /* One of these two should be set */      if (writeback && retain)      SCACHE[scacheNum].stats.Downgrade++;   for (a = (paddr & ~(PA)(SCACHE_LINE_SIZE-1)); 	a < (paddr & ~(PA)(SCACHE_LINE_SIZE-1)) + size; 	a += SCACHE_LINE_SIZE) {#ifndef SOLO      ASSERT (IS_VALID_PA(M_FROM_CPU(cpuNum), paddr));#endif      ind = SCACHE_INDEXOF(a);      set = & SCACHE[scacheNum].set[ind];      /*       * Direct-mapped caches. We do not rely on presence in the       * cache to determine the success of the SC, but rather       * on the LLbit.         */      if (SCACHE_ASSOC == 1  && CPUVec.GetLockAddr(cpuNum) == a) {          if (!retain) {             /* invalidated from the cache */	   CPUVec.ClearLockFlag(cpuNum);         }       }        for (way=0; way<SCACHE_ASSOC; ++way)	if (set->tags[way] != INVALID_TAG) {	  if ((set->tags[way] & EXCLUSIVE_TAG) != 0) {	    s = FLUSH_EXCLUSIVE;	    aa = STAG_TO_PA(set->tags[way], ind);	    if (real_paddr) *real_paddr = aa;	    #ifndef SOLO            ASSERT (IS_VALID_PA(M_FROM_CPU(cpuNum), aa));#endif	    PrimaryFlush(cpuNum, writeback, retain, aa, SCACHE_LINE_SIZE);	    	    SCACHE[scacheNum].stats.LinesWriteback++;	    	    /* WARNING: I don't require the user to writeback the line if it's */	    /* dirty since I want to support invalidations of dirty lines for */	    /* memory copy, where I squash a line regardless of its state */	    	    if (retain) {	      /* Remove exclusive ownership */	      set->tags[way] &= ~EXCLUSIVE_TAG;	      L2_LINE_TRANS_EVENT(cpuNum, aa, E_L2|E_EXTERNAL|E_DOWNGRADE, 0, way,                                  IS_KUSEG(CURRENT_PC(cpuNum)));	    } else {	      set->tags[way] = INVALID_TAG;	      L2_LINE_TRANS_EVENT(cpuNum, aa, E_L2|E_EXTERNAL|E_WRITEBACK, 0, way,                                  IS_KUSEG(CURRENT_PC(cpuNum)));	    }#ifdef DATA_HANDLING	    if (writeback) {	      ASSERT(data != NULL);	      if (data != NULL) {	/* If I want a data reply */		bcopy(set->data[way],data, SCACHE_LINE_SIZE);	      }	      if (VERBOSE_DEBUG) {		CPUPrint("%d: bcopy %x -> %x (%d) (flashlite) Data:\n", cpuNum,			   set->data[way],(char *)data,SCACHE_LINE_SIZE);		DumpCacheLine(set->data[way],SCACHE_LINE_SIZE);	      }	    }#endif /* DATA_HANDLING */	    return s; /* invalidate only one line */	  } else {	    aa = STAG_TO_PA(set->tags[way], ind);	    if (real_paddr) *real_paddr = aa;	    if (!retain) {	      if (VERBOSE_DEBUG) {		CPUPrint("%d: SCacheMiss: spilling (shared) PA: %8.8lx \n",                         cpuNum, paddr);	      }	      PrimaryFlush(cpuNum, writeback, retain, aa, SCACHE_LINE_SIZE);	      SCACHE[scacheNum].stats.LinesInval++;	      	      s = FLUSH_SHARED;	      set->tags[way] = INVALID_TAG;	      	      SCacheLRUMake(&set->LRU, way);	      	      L2_LINE_TRANS_EVENT(cpuNum, aa, (E_L2 | E_EXTERNAL | E_FLUSH_CLEAN), 				  0, way,IS_KUSEG(CURRENT_PC(cpuNum)));	    }	    return s; /* invalidate only one line */	  }	}   }   return s;}/***************************************************************** * CacheFakeInvalidate  * Called when a line has been invalidated by a cpu, and is known not * to be in the cache of cpuNum. This allows Memstat to maintain its * state machine. This is never called in perfectmem. * *****************************************************************/voidCacheFakeInvalidate(int cpuNum,PA paddr, int size){   int scacheNum = GET_SCACHE_NUM(cpuNum);   PA a;   uint ind;   struct SCacheSet* set;   int way;   for (a = paddr; a < paddr + size; a += SCACHE_LINE_SIZE) {      ind = SCACHE_INDEXOF(a);  /* (a/SCACHE_LINE_SIZE) % SCACHE_INDEX; */      set = & SCACHE[scacheNum].set[ind];            if( SCACHE_ASSOC == 1  &&           CPUVec.GetLockAddr(cpuNum) == (a &  ~(SCACHE_LINE_SIZE-1))  ) {           /* Direct-mapped cache. Invalidate it */	CPUVec.ClearLockFlag(cpuNum);      }      for(way=0;way<SCACHE_ASSOC;++way  ) {         if ((set->tags[way] & ~EXCLUSIVE_TAG) == SCACHE_TAG(a))             break;      }      if (way==SCACHE_ASSOC) {         /* not in the cache */	 L2_LINE_TRANS_EVENT(cpuNum, a, (E_L2 | E_FAKE_EXTERNAL), 0, 0,                             IS_KUSEG(CURRENT_PC(cpuNum)));         continue;      }      ASSERT( 0 );   }}/*************************************************************** * Cacheinvalidate * * This routine destructively invalidates a line from the cache. * In the case of shared data, the line is removed, and this * operation is equivalent to CacheExtract.   * * In the case of dirty data, this routine PERMANENTLY DISCARDS * the dirty copy and removes the line from the cache.  While * this violates most cache coherence protocols, for block * transfer this is a useful performance optimization. ***************************************************************/intCacheInvalidate(int cpuNum, PA paddr, int size, bool writeback,                 int *wasDirty) {   FlushStatus s;      if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheInvalidate for paddr %8.8lx\n",		 cpuNum, paddr);   }   if (writeback) {      /* writeback == TRUE  retain  == FALSE */            s = SCacheFlush(cpuNum, TRUE, FALSE, paddr, size, NULL);   } else {      /* writeback == FALSE  retain  == FALSE */      s = SCacheFlush(cpuNum, FALSE, FALSE, paddr, size, NULL);   }   *wasDirty = (s == FLUSH_EXCLUSIVE);   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;}/*************************************************************** * CacheinvalidateIndex * * Invoked through the "cache" op. Stalling the processor  * is a little messy here... I assume that if it was a writeback and * it was found, then I'll need to stall the processor..    ***************************************************************/intCacheInvalidateIndex(int cpuNum, PA paddr, int size, bool writeback, 		     int *wasDirty) {   FlushStatus s;      if (VERBOSE_DEBUG) {      CPUPrint("%d: CacheInvalidateIndex for paddr %8.8lx\n",		 cpuNum, paddr);   }   if (writeback) {      /* writeback == TRUE  retain  == FALSE */            s = SCacheFlushIndex(cpuNum, TRUE, FALSE, paddr, NULL, size, NULL);   } else {      /* writeback == FALSE  retain  == FALSE */      s = SCacheFlushIndex(cpuNum, FALSE, FALSE, paddr, NULL, size, NULL);   }   *wasDirty = (s == FLUSH_EXCLUSIVE);   if (s == FLUSH_NOTFOUND) {      return 0;   }   return 1;}/**************************************************************** * CacheWriteback * * This routine forces a line in the cache to be written back, * if it is dirty.  The line loses its ownership but remains in * the cache. (This is a GET operation) ****************************************************************/intCacheWriteback(int cpuNum, PA paddr, int size, byte *data)

⌨️ 快捷键说明

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