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

📄 busuma.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
   default:      CPUError("Unknown memsys command (0x%x) in BusUma::BusArrive\n", mreq->cmd);   }   /* look for matching requests from other CPUS and merge if both CPUs issued a SHARED mode request,      otherwise add this one to delay queue */   requestTableFull = 1;   for (i = 0; i < REQUEST_TABLE_SIZE; i++) {      if (requestTable[mreq->machnum][i].used) {         if (requestTable[mreq->machnum][i].addr == mreq->addr) {            if ((requestTable[mreq->machnum][i].initiator->mode == MEMSYS_SHARED) &&                (mreq->mode == MEMSYS_SHARED)) {               RTMerge(mreq, i);            } else if (((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_UPGRADE) &&                       (requestTable[mreq->machnum][i].initiator->mode == MEMSYS_EXCLUSIVE)) {               /* by the time this upgrade gets to bus, cache will have been invalidated,                  so NAK this request */               NakRequest(mreq);            } else {               RTDelay(mreq, i);            }            return;         }      } else {         requestTableFull = 0;      }   }      /* if request table is full and this is a get or getx, this request will end up getting      nak'ed when it tries to insert itself in request table, so put it on queue */   if (requestTableFull && (((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GET) ||                            ((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_GETX))) {      mreq->state = RT_OVERFLOW;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&requestTableFullQ[mreq->machnum]));      return;   }   mreq->state = BUS_ARB_WAIT;   List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&highPri[mreq->machnum]));   Arbitrate(mreq->machnum);   return;}/***************************************************************** * MemsysCmd *  * Main interface from secondary cache into here * For DMA opeartions, the writeback parameter holds the * length of the DMA transfer and is NOT a boolean. *****************************************************************//*  xxxxx  things to do:    make uncached operations contend for bus    sync??    */ResultBusUmaCmd(int cpuNum, int cmd, PA addr, int transId,           PA replacedPaddr, int writeback, byte *data){   MemRequest *mreq;   List_Links *itemPtr;   int memnum, overhead;   int machine = M_FROM_CPU(cpuNum);#ifndef SOLO   addr = REMAP_PADDR(addr, cpuNum);   replacedPaddr = REMAP_PADDR(replacedPaddr, cpuNum);#endif    if (debugMem)      CPUPrint("DBGBSU %lld CPU %d 0x%x addr 0x%x 0x%x repl 0x%x %d PC 0x%x\n",               CPUVec.CycleCount(0), cpuNum, cmd, addr, transId, replacedPaddr, writeback,               CPUVec.CurrentPC(cpuNum));   if (cmd == MEMSYS_SYNC) {      return SUCCESS;   }    memnum = BusumaAddrToMemnum(machine, addr);      /* for a writeback, add it to writebuffer for this CPU.      If all the writebuffers are full, stall CPU until all the writes are flushed      This CPU will be removed from sharer list after the writeback has been issued      */   if (writeback && (replacedPaddr != MEMSYS_NOADDR)) {      int rmemnum = BusumaAddrToMemnum(machine, replacedPaddr);      ASSERT(!(cmd & MEMSYS_DMAFLAVOR));      if (IsInWBBuffer(cpuNum, replacedPaddr)) {         CPUError("DBGBSU %lld WB hit in wbBuffer (0x%x)\nThe GetX or upgrade in between should've removed the first wb.\n",                  CPUVec.CycleCount(0), replacedPaddr);      } else if (wbBuffers[cpuNum].numUsed == WB_BUFFER_SIZE) {         /* we just got a writeback and all writeback buffers are full,            so store the necessary parameters in overflow buffer,            and move one of the writebacks to high priority queue,            and stall until an entry is free */         List_Links *itemPtr, *nextPtr;         MemRequest *ovfReq;         ASSERT(List_IsEmpty(&wbBuffers[cpuNum].free));         ASSERT(wbBuffers[cpuNum].numOverflowUsed != maxOverflow);         itemPtr = List_First(&freeMemReqList);         ASSERT(itemPtr);         List_Remove(itemPtr);         ovfReq = LIST_TO_MREQ(itemPtr);         ovfReq->state = WB_OVERFLOW;         ovfReq->cmd = cmd;         ovfReq->addr = addr;         ovfReq->transId = transId;         /* i really shoulnd't put replacedPaddr in reqAddr, and writeback in len,            but MemRequest is already big enough, and those two fields are wasted in overflow MemRequest */         ovfReq->reqAddr = replacedPaddr;         ovfReq->len = writeback;         ovfReq->data = data;         List_Insert(itemPtr, LIST_ATREAR(&wbBuffers[cpuNum].overflow));         wbBuffers[cpuNum].numOverflowUsed++;    	 if (debugMem)            CPUPrint("DBGBSU %lld Writeback buffer full on CPU %d.\n",                     CPUVec.CycleCount(cpuNum), cpuNum);         /* stall => move the first entry from lowPri to highPri */         for (itemPtr = List_First(WB_QUEUE(machine)), nextPtr = NULL;              !List_IsAtEnd(WB_QUEUE(machine), itemPtr);              itemPtr = nextPtr) {            MemRequest *mreq = LIST_TO_MREQ(itemPtr);            nextPtr = List_Next(itemPtr);            if (mreq->cpunum == cpuNum) {               List_Remove(itemPtr);               List_Insert(itemPtr, LIST_ATREAR(&highPri[machine]));               break;            }         }         return STALL;      } else {         MemRequest *wbEntry;         List_Links *itemPtr;         ASSERT(!List_IsEmpty(&wbBuffers[cpuNum].free));         itemPtr = List_First(&wbBuffers[cpuNum].free);         List_Remove(itemPtr);         wbBuffers[cpuNum].numUsed++;         memState[rmemnum]->stats.counts[COUNT_WRITEBACKS]++;         wbEntry = LIST_TO_MREQ(itemPtr);         wbEntry->state = CPU_TO_BUS_OVERHEAD;         wbEntry->memnum = rmemnum;         wbEntry->machnum = machine;         wbEntry->cpunum = cpuNum;         wbEntry->starttime = CPUVec.CycleCount(cpuNum);#ifdef DATA_HANDLING         bcopy(data, wbEntry->data, SCACHE_LINE_SIZE);#endif         wbEntry->addr = replacedPaddr;         EventDoCallback(cpuNum, BusArrive, (EventCallbackHdr *)wbEntry, NULL, readOverhead);      }   }   /* Handle special case: a GET with transId -1 indicates    * a writeback or repl hint without the associated GET (due    * to a CACHE instruction executed in the processor)    */   if (((cmd & MEMSYS_CMDMASK) == MEMSYS_GET) && (transId == -1) &&       !(cmd & MEMSYS_DMAFLAVOR)) {      return SUCCESS;   }      /*    * Got a request. Fill allocate and fill in a memrequest and    * model the workload wait time for where it is going;    */   itemPtr = List_First(&freeMemReqList);   ASSERT(itemPtr);   List_Remove(itemPtr);   mreq = LIST_TO_MREQ(itemPtr);   mreq->cmd = cmd;   mreq->transId = transId;   mreq->reqAddr = addr;   mreq->addr =  addr & ~(SCACHE_LINE_SIZE-1);   mreq->memnum = memnum;   mreq->machnum = machine;   mreq->cpunum = cpuNum;   mreq->starttime = CPUVec.CycleCount(cpuNum);   mreq->rtIndex = -1;   if( cmd & MEMSYS_DMAFLAVOR ) {      ASSERT( transId < 0 );      ASSERT( data );      mreq->data = data;      mreq->len = writeback;   } else {      ASSERT( transId >= 0);      mreq->data = NULL;   }   switch (cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:      mreq->mode = MEMSYS_SHARED;      overhead = readOverhead;      if (cmd & MEMSYS_IFFLAVOR) {         memState[memnum]->stats.counts[COUNT_IGETS]++;      } else if (cmd & MEMSYS_LLFLAVOR) {         memState[memnum]->stats.counts[COUNT_LLGETS]++;      } else if (cmd & MEMSYS_DMAFLAVOR) {         memState[memnum]->stats.counts[COUNT_DMAGETS]++;      } else {                  memState[memnum]->stats.counts[COUNT_DGETS]++;      }      break;   case MEMSYS_GETX:      mreq->mode = MEMSYS_EXCLUSIVE;      overhead = readOverhead;      if (cmd & MEMSYS_DMAFLAVOR) {         memState[memnum]->stats.counts[COUNT_DMAGETXS]++;      } else {                  memState[memnum]->stats.counts[COUNT_GETXS]++;      }      break;   case MEMSYS_UPGRADE:      mreq->mode = MEMSYS_EXCLUSIVE;      overhead = upgradeOverhead;      if (cmd & MEMSYS_SCFLAVOR) {         memState[memnum]->stats.counts[COUNT_SCUPGRADES]++;      } else {         memState[memnum]->stats.counts[COUNT_UPGRADES]++;      }      break;   case MEMSYS_UNCWRITE:      memState[memnum]->stats.counts[COUNT_UNCACHEDWRITES]++;      BusUmaUncachedWrite(cpuNum, addr, data, writeback);      /* free mreq becuase it's not used */      mreq->state = REQ_FREE;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));      return SUCCESS;   case MEMSYS_UNCWRITE_ACCELERATED:      memState[memnum]->stats.counts[COUNT_UNCACHEDACCWRITES]++;      BusUmaUncachedWrite(cpuNum, addr, data, writeback);      /* free mreq becuase it's not used */      mreq->state = REQ_FREE;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));      return SUCCESS;   case MEMSYS_UNCREAD:      memState[memnum]->stats.counts[COUNT_UNCACHEDREADS]++;      BusUmaUncachedRead(cpuNum, addr, data, writeback);      /* free mreq becuase it's not used */      mreq->state = REQ_FREE;      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));      return SUCCESS;   default:      CPUError("Unknown memsys command (0x%x) in BusUmaCmd\n", cmd);      overhead = 0; /* Quite compiler warning message. */   }   /*    * compute a bunch of values to make future routines happier.    */   mreq->state = CPU_TO_BUS_OVERHEAD;   mreq->status = MEMSYS_STATUS_SUCCESS;   mreq->result = 0;   EventDoCallback(cpuNum, BusArrive, (EventCallbackHdr *)mreq, NULL, overhead);   return STALL;}void BusUmaStatus(void) {    char buf[1024];    char tmpBuf[32];    int i, memNum;    for (memNum = 0; memNum < TOTAL_MEMORIES; memNum++) {       sprintf(buf, "MEM %d ", memNum);       for (i = 0; i < COUNT_TOTAL; i++) {          sprintf(tmpBuf, LLD_SPACE, memState[memNum]->stats.counts[i]);          strcat(buf, tmpBuf);       }       CPUPrint("%s\n", buf);       sprintf(buf, "MEMBUSUMA %d ", memNum);       for (i = 0; i < BUC_TOTAL; i++) {          sprintf(tmpBuf, LLD_SPACE, memState[memNum]->stats.buCounts[i]);          strcat(buf, tmpBuf);       }       CPUPrint("%s\n", buf);    }}void BusUmaDone(void){   CPUPrint("Exiting the BusUma memory system\n");}voidBusUmaDumpStats(void){   BusUmaStatus();}static voidBusUmaUncachedWrite(int cpuNum, PA addr, byte *data, int len){#ifdef HWBCOPY   /* For now, if the given address is a valid physical address,    * assume that we are doing an access to the MSG space.    * These writes are only needed in Flashlite -- punt here    */   if (!IS_VALID_PA(M_FROM_CPU(cpuNum), addr))#endif      {#ifndef SOLO         /* should check firewall here because flashlite also          * checks it before calling doPio, and doPio can't          * check because cpuNum == dest node when called from          * flashlite.          *          * However things are complicated by the need to determine          * which node addr points at, perhaps firewall writes go          * through here (which means they should be allowed).          * Ignore for now.          */         Result ret;         ASSERT(CPUVec.UncachedPIO);         ret = CPUVec.UncachedPIO(cpuNum, addr, 0, len, data);         if (ret != SUCCESS) {             CPUError("SimMagic_DoPIO failed: cpu=%d addr=%#x pc=%#x \n",                     cpuNum,addr,CPUVec.CurrentPC(cpuNum));         }         ASSERT(ret == SUCCESS);#endif#ifdef SOLO         bcopy(data, (char *)addr, len); #endif#ifdef DEBUG_MEM         {            int foo;            bcopy(data, &foo, 4);            CPUPrint("Uncached write (%d bytes) to 0x%x of 0x%x\n",                      len, addr, foo);         }#endif /* DEBUG_MEM */      }}static voidBusUmaUncachedRead(int cpuNum, PA addr, byte *data, int len){#ifdef SOLO         bcopy(data, (char *)addr, len); #else         Result ret;         ASSERT(CPUVec.UncachedPIO);         ret = CPUVec.UncachedPIO(cpuNum, addr, 1, len, data);         if (ret != SUCCESS) {             CPUError("SimMagic_DoPIO failed: cpu=%d addr=%#x pc=%#x \n",                     cpuNum,addr,CPUVec.CurrentPC(cpuNum));         }         ASSERT(ret == SUCCESS);#endif#ifdef DEBUG_MEM   {        int foo;      bcopy(data, &foo, 4);      CPUPrint("Uncached read (%d bytes) to 0x%x of 0x%x\n", len, addr, foo);   }#endif /* DEBUG_MEM */}/* if running with data handling, need to drain writebacks */static voidBusUmaDrain(void){#ifdef DATA_HANDLING   int i, cpu;   MemRequest *mreq;   for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {      ASSERT(List_IsEmpty(&wbBuffers[cpu].overflow));      if (wbBuffers[cpu].numUsed != 0) {         for (i = 0; i < WB_BUFFER_SIZE; i++) {            mreq = &wbBuffers[cpu].entries[i];            switch (mreq->state) {            case REQ_FREE:               continue;               break;            case MEM_BUSY_WAIT:               List_Remove(MREQ_TO_LIST(mreq)); /* from memoryQueue */               /* fall through */            case CPU_TO_BUS_OVERHEAD:            case BUS_ARB_WAIT:            case BUS_TRANSFER_WAIT:               bcopy(mreq->data, DATA_ADDR(mreq->machnum, mreq->addr),                     SCACHE_LINE_SIZE);               FreeWBentry(mreq);               break;            default:               CPUError("State %d not handled.\n", mreq->state);            }         }      }   }#endif  /* DATA_HANDLING */}

⌨️ 快捷键说明

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