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

📄 busuma.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
         if (!List_IsEmpty(&requestTableFullQ[mreq->machnum])) {            itemPtr = List_First(&requestTableFullQ[mreq->machnum]);            List_Remove(itemPtr);            ASSERT(LIST_TO_MREQ(itemPtr)->state == RT_OVERFLOW);            LIST_TO_MREQ(itemPtr)->state = BUS_ARB_WAIT;            List_Insert(itemPtr, LIST_ATREAR(&highPri[mreq->machnum]));            if (debugMem)               CPUPrint("DBGBSU %lld %d issuing RTfullQ addr(0x%x)\n",                        CPUVec.CycleCount(mreq->cpunum), LIST_TO_MREQ(itemPtr)->cpunum,                        LIST_TO_MREQ(itemPtr)->addr);         }      }   }   /* sharing writeback also go to memory */   if (mreq->result & MEMSYS_RESULT_CACHE) {      mreq->state = MEM_BUSY_WAIT;      mreq->cmd = MEMSYS_SHARING_WRITEBACK;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&memState[mreq->memnum]->memoryQueue));      mreq->memQEnter = CPUVec.CycleCount(mreq->cpunum);      if (!memState[mreq->memnum]->busy)         MemoryArrive(mreq->memnum);         } else {      mreq->state = REQ_FREE;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));   }}static voidCacheTransferDone(int cpuNum, EventCallbackHdr *hdr, void *arg){   MemRequest *mreq = (MemRequest *)hdr;   ASSERT(M_FROM_CPU(cpuNum) == mreq->machnum);   if (mreq->cmd & MEMSYS_DMAFLAVOR) {      if ((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GET) {         bcopy(DATA_ADDR(mreq->machnum, mreq->reqAddr), mreq->data, mreq->len);      } else {         ASSERT((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GETX);         bcopy(mreq->data, DATA_ADDR(mreq->machnum, mreq->reqAddr), mreq->len);      }   } else {      mreq->data = (byte*)DATA_ADDR(mreq->machnum, mreq->addr);   }   mreq->state = REPLY_BUS_ARB_WAIT;   List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&highPri[mreq->machnum]));   Arbitrate(mreq->machnum);}/* Nak all pending upgrades to the same address */static voidNakUpgrades(MemRequest *mreq){   List_Links *queueHead, *itemPtr, *nextPtr;   if (mreq->rtIndex == -1) {      /* there cannot be a request table entry for this addr, so only check highPri queue */      queueHead = &highPri[mreq->machnum];   } else {      /* there cannot be upgrades in highPri queue, so only check requestTable delay queue */       queueHead = &requestTable[mreq->machnum][mreq->rtIndex].delay;   }   for (itemPtr = List_First(queueHead), nextPtr = NULL;        !List_IsAtEnd(queueHead, itemPtr);        itemPtr = nextPtr) {         MemRequest *req2 = LIST_TO_MREQ(itemPtr);      nextPtr = List_Next(itemPtr);      if ((req2->addr == mreq->addr) &&          ((req2->cmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE)) {         List_Remove(itemPtr);         NakRequest(req2);      }   }}/* Check caches and writeback buffers for coherency */static voidCacheSnoop(MemRequest *mreq){   MemRequest *wbReq;   int i, way=0, wasDirty, cacheToCache=0;   char *data;   int machine = M_FROM_CPU(mreq->cpunum);   ASSERT(mreq->state == BUS_TRANSFER_WAIT);   /* add gets without request table indexes to request table */   if ((mreq->rtIndex == -1) && (((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GET) ||                                 ((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GETX))) {      RTInsert(mreq);   }   switch (mreq->cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:      memState[mreq->memnum]->stats.buCounts[BUC_BUS_GETRQST] += arbitrationCycles + transferCycles;      /* do the sharing writeback if necessary */      for (i = FIRST_CPU(machine); i <= LAST_CPU(machine); i++) {         if ((i == mreq->cpunum) && !(mreq->cmd & MEMSYS_DMAFLAVOR)) continue;         if (IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_EXCLUSIVE, &data, &way)) {            CacheWriteback(i, BACKMAP_PADDR(mreq->addr,i), SCACHE_LINE_SIZE,                            (byte*)DATA_ADDR(mreq->machnum, mreq->addr));            cacheToCache=1;            mreq->result |= MEMSYS_RESULT_DOWNGRADE;            break;         }         wbReq = IsInWBBuffer(i, mreq->addr);         if (wbReq) {#ifdef DATA_HANDLING            bcopy(wbReq->data, DATA_ADDR(mreq->machnum, mreq->addr),                  SCACHE_LINE_SIZE);#endif            /* remove entry from writeback buffer */            FreeWBentry(wbReq);            cacheToCache=1;            mreq->result |= MEMSYS_RESULT_DOWNGRADE;            break;         }      }      break;   case MEMSYS_GETX:      memState[mreq->memnum]->stats.buCounts[BUC_BUS_GETRQST] += arbitrationCycles + transferCycles;      /* do the sharing writeback and invalidate if necessary */      for (i = FIRST_CPU(machine); i <= LAST_CPU(machine); i++) {         if ((i == mreq->cpunum) && !(mreq->cmd & MEMSYS_DMAFLAVOR)) continue;         if (IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_EXCLUSIVE, &data, &way)) {            CacheExtract(i, BACKMAP_PADDR(mreq->addr,i), SCACHE_LINE_SIZE, &wasDirty,                          (byte*)DATA_ADDR(mreq->machnum, mreq->addr));            cacheToCache=1;            mreq->result |= MEMSYS_RESULT_INVALIDATE;            break;         } else if (IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_SHARED, &data, &way)) {            CacheInvalidate(i, BACKMAP_PADDR(mreq->addr,i), SCACHE_LINE_SIZE, FALSE, &wasDirty);            mreq->result |= MEMSYS_RESULT_INVALIDATE;            memState[mreq->memnum]->stats.counts[COUNT_INVALORDNGRADESENT]++;            memState[mreq->memnum]->stats.counts[COUNT_EXCLUSIVEONSHARED]++;         } else {            CacheFakeInvalidate(i,BACKMAP_PADDR(mreq->addr,i),SCACHE_LINE_SIZE);         }                                wbReq = IsInWBBuffer(i, mreq->addr);         if (wbReq) {#ifdef DATA_HANDLING            bcopy(wbReq->data, DATA_ADDR(mreq->machnum, mreq->addr),                  SCACHE_LINE_SIZE);#endif            /* remove entry from writeback buffer */            FreeWBentry(wbReq);            cacheToCache=1;            mreq->result |= MEMSYS_RESULT_INVALIDATE;            break;         }      }      NakUpgrades(mreq);      break;   case MEMSYS_UPGRADE:      memState[mreq->memnum]->stats.buCounts[BUC_BUS_UPG] += arbitrationCycles + transferCycles;      /* send invalidate if necessary */      for (i = FIRST_CPU(machine); i <= LAST_CPU(machine); i++) {         if (i == mreq->cpunum) continue;         ASSERT(!IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_EXCLUSIVE, &data, &way));         if (IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_SHARED, &data, &way)) {            CacheInvalidate(i, BACKMAP_PADDR(mreq->addr,i), SCACHE_LINE_SIZE, FALSE, &wasDirty);            mreq->result |= MEMSYS_RESULT_INVALIDATE;            memState[mreq->memnum]->stats.counts[COUNT_INVALORDNGRADESENT]++;            memState[mreq->memnum]->stats.counts[COUNT_EXCLUSIVEONSHARED]++;         } else {             CacheFakeInvalidate(i,BACKMAP_PADDR(mreq->addr,i),SCACHE_LINE_SIZE);         }         ASSERT(!IsInWBBuffer(i, mreq->addr));      }      NakUpgrades(mreq);      break;   case MEMSYS_WRITEBACK:      memState[mreq->memnum]->stats.buCounts[BUC_BUS_WB] += arbitrationCycles + transferCycles;      /* just some sanity checks */      for (i = FIRST_CPU(machine); i < LAST_CPU(machine); i++) {         if (i == mreq->cpunum) continue;         ASSERT(!IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_EXCLUSIVE, &data, &way));         ASSERT(!IsInSCache(i, BACKMAP_PADDR(mreq->addr,i), MEMSYS_SHARED, &data, &way));         ASSERT(!IsInWBBuffer(i, mreq->addr));      }      break;   default:      CPUError("Bad mreq->cmd (0x%x)\n", mreq->cmd);   }   if (cacheToCache) {      if (debugMem)         CPUPrint("DBGBSU %lld %d cacheToCache addr(0x%x)\n",                  CPUVec.CycleCount(0), mreq->cpunum, mreq->addr);      mreq->state = CACHE_TRANSFER_WAIT;      mreq->result |= MEMSYS_RESULT_CACHE|MEMSYS_RESULT_DOWNGRADE;      memState[mreq->memnum]->stats.counts[COUNT_REMOTEDIRTY]++;      memState[mreq->memnum]->stats.counts[COUNT_INVALORDNGRADESENT]++;      EventDoCallback(FIRST_CPU(mreq->machnum), CacheTransferDone, (EventCallbackHdr *) mreq, NULL, memoryCycles + dirtyPenalty);   } else if ((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE) {      mreq->result |= MEMSYS_RESULT_MEMORY;	/* doesn't really make sense to set this for upgrades,                                                   but scache wants it set */      CPUArrive(mreq);   } else {      mreq->state = MEM_BUSY_WAIT;      mreq->result |= MEMSYS_RESULT_MEMORY;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&memState[mreq->memnum]->memoryQueue));      mreq->memQEnter = CPUVec.CycleCount(mreq->cpunum);      if (!memState[mreq->memnum]->busy)         MemoryArrive(mreq->memnum);   }}/* Bus transfer has finished, so send request to proper place (CPU or memory), * and setup the next arbitration if there's something in the queues */static voidBusFree(int cpuNum, EventCallbackHdr *hdr, void *arg){   MemRequest *mreq = (MemRequest *)hdr;   ASSERT(M_FROM_CPU(cpuNum) == mreq->machnum);      /* Send request to proper place */   if (mreq->state == BUS_TRANSFER_WAIT) {      CacheSnoop(mreq);   } else {      ASSERT(mreq->state == REPLY_BUS_TRANSFER_WAIT);      CPUArrive(mreq);   }   if (busIdleStart[mreq->machnum]) {      memState[FIRST_MEMORY(mreq->machnum)]->stats.buCounts[BUC_BUS_IDLE] +=          CPUVec.CycleCount(0) - busIdleStart[mreq->machnum] -          (arbitrationCycles + transferCycles);      busIdleStart[mreq->machnum] = 0;   }   /* Setup next arbitration */   if (!List_IsEmpty(&highPri[mreq->machnum]) ||       !List_IsEmpty(&lowPri[mreq->machnum])) {      EventDoCallback(FIRST_CPU(mreq->machnum), ArbitrateCallback, (EventCallbackHdr *) &arbitrate[mreq->machnum], NULL, arbitrationCycles);   } else {      busBusy[mreq->machnum] = 0;      busIdleStart[mreq->machnum] = CPUVec.CycleCount(0);   }}/* Arbitration cycles are finished, now decide the winner by first checking * the high priority queue, and then the low priority queue. */static voidArbitrateCallback(int cpuNum, EventCallbackHdr *hdr, void *arg){   List_Links *itemPtr;   MemRequest *mreq;   int machine = M_FROM_CPU(cpuNum);   if (!List_IsEmpty(&highPri[machine])) {      itemPtr = List_First(&highPri[machine]);   } else if (!List_IsEmpty(&lowPri[machine])) {      itemPtr = List_First(&lowPri[machine]);   } else {      /* this could happen if a CPU miss is satisfied from it's	 own writeback buffer */      /* Kinshuk, DT: BUT, this happens very often if you do a flush       * followed by a prefetch exclusive (as in the SIPS code).       * So this gets commented out for now.       */      /*	CPUWarning("ArbitrateCallback called with nothing to do (time: %lld)\n",	           CPUVec.CycleCount(cpuNum));       */      busBusy[machine] = 0;      return;   }   List_Remove(itemPtr);   /* now occupy the bus for the correct number of cycles */   mreq = LIST_TO_MREQ(itemPtr);   if (mreq->state == BUS_ARB_WAIT) {      mreq->state = BUS_TRANSFER_WAIT;   } else {      ASSERT(mreq->state == REPLY_BUS_ARB_WAIT);      mreq->state = REPLY_BUS_TRANSFER_WAIT;      memState[mreq->memnum]->stats.buCounts[BUC_BUS_GETREPLY] += arbitrationCycles + transferCycles;   }   memState[mreq->memnum]->stats.buCounts[BUC_BUS_BUSY] += arbitrationCycles + transferCycles;   EventDoCallback(FIRST_CPU(mreq->machnum), BusFree, (EventCallbackHdr *)mreq, NULL, transferCycles);}static voidArbitrate(int machine){   /* if arbitration callback is already set or will be once bus is free, just return */   if (busBusy[machine])      return;   busBusy[machine] = 1;   EventDoCallback(FIRST_CPU(machine), ArbitrateCallback, (EventCallbackHdr *) &arbitrate[machine], NULL, arbitrationCycles);}/* Request just arrived from CPU to Bus interface (time to go through caches, etc) */static voidBusArrive(int cpuNum, EventCallbackHdr *hdr, void *arg){   MemRequest *mreq = (MemRequest *)hdr;   MemRequest *wbReq;   char *data;   int i, way=0, requestTableFull;   ASSERT(M_FROM_CPU(cpuNum) == mreq->machnum);   ASSERT(mreq->state == CPU_TO_BUS_OVERHEAD);   /* if this request is for a bogus address, bus error it immediately */   if (!IS_VALID_PA(M_FROM_CPU(cpuNum), mreq->addr)) {      ErrorRequest(mreq);      return;   }#ifndef SOLO   /* if firewall is on and cpu is trying to write, check the firewall */   if (CPUVec.CheckFirewall) {      int c = mreq->cmd & MEMSYS_CMDMASK;      if ((c == MEMSYS_GETX) || (c == MEMSYS_UPGRADE)) {         if (!CPUVec.CheckFirewall(cpuNum, mreq->addr)) {            ErrorRequest(mreq);            return;         }      }   }#endif    /* check the writeback buffer first */   switch (mreq->cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:      wbReq = IsInWBBuffer(cpuNum, mreq->addr);      if (wbReq) {         memState[mreq->memnum]->stats.buCounts[BUC_GET_WBBUF]++;	 /*         CPUPrint("DBGBSU %lld GET hit in wbBuffer (0x%x)\n", CPUVec.CycleCount(0), mreq->addr);	 */#ifdef DATA_HANDLING         bcopy(wbReq->data, DATA_ADDR(mreq->machnum, mreq->addr),               SCACHE_LINE_SIZE);#endif	 CacheCmdDone(cpuNum, mreq->transId, mreq->mode, mreq->status,		      MEMSYS_RESULT_MEMORY|MEMSYS_RESULT_NOTRANSITION,		      (byte*)DATA_ADDR(mreq->machnum, mreq->addr));         /* free req */         mreq->state = REQ_FREE;         List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));         return;      }      break;   case MEMSYS_GETX:      wbReq = IsInWBBuffer(cpuNum, mreq->addr);      if (wbReq) {         memState[mreq->memnum]->stats.buCounts[BUC_GET_WBBUF]++;	 /*         CPUPrint("DBGBSU %lld GETX hit in wbBuffer (0x%x)\n", CPUVec.CycleCount(0), mreq->addr);	 */#ifdef DATA_HANDLING         bcopy(wbReq->data, DATA_ADDR(mreq->machnum, mreq->addr),               SCACHE_LINE_SIZE);#endif         /* remove writeback entry because cache now has the most-recent data */         FreeWBentry(wbReq);	 CacheCmdDone(cpuNum, mreq->transId, mreq->mode, mreq->status,		      MEMSYS_RESULT_MEMORY|MEMSYS_RESULT_NOTRANSITION,		      (byte*)DATA_ADDR(mreq->machnum, mreq->addr));         /* free req */         mreq->state = REQ_FREE;         List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));         return;      }      break;   case MEMSYS_UPGRADE:      wbReq = IsInWBBuffer(cpuNum, mreq->addr);      if (wbReq) {          memState[mreq->memnum]->stats.buCounts[BUC_UPG_WBBUF]++;         CPUPrint("DBGBSU %lld UPGRADE hit in wbBuffer (0x%x)\n", CPUVec.CycleCount(0), mreq->addr);         /* remove writeback entry because cache now has the most-recent data */         FreeWBentry(wbReq);	 CacheCmdDone(cpuNum, mreq->transId, mreq->mode, mreq->status,		      MEMSYS_RESULT_MEMORY|MEMSYS_RESULT_NOTRANSITION,		      (byte*)DATA_ADDR(mreq->machnum, mreq->addr));         /* free req */         mreq->state = REQ_FREE;         List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));         return;      }      /* Upgrades need to check wether that cache line is still in cache,         It could've been invalidated by now */      if (!IsInSCache(mreq->cpunum, BACKMAP_PADDR(mreq->addr, mreq->cpunum), MEMSYS_SHARED, &data, &way)) {         NakRequest(mreq);         return;      }      break;   case MEMSYS_WRITEBACK:      /* for writebacks, add to low priority queue */      mreq->state = BUS_ARB_WAIT;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(WB_QUEUE(mreq->machnum)));      Arbitrate(mreq->machnum);      return;

⌨️ 快捷键说明

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