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

📄 cpu.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
            ASSERT(tlbFlavor == TLB_BDOOR_FUNC);      switch (size) {      case BYTE_SZ:         returnFlag = ((Result (*)(int, uint, uint, unsigned char*))bdoorAddr)            (P->myNum, vAddr, BDOOR_STORE_BYTE, (byte *)data);         break;      case HALF_SZ:         returnFlag = ((Result (*)(int, uint, uint, short*))bdoorAddr)            (P->myNum, vAddr, BDOOR_STORE_HALF, (short *)data);         break;      case WORD_SZ:         returnFlag = ((Result (*)(int, uint, uint, uint*))bdoorAddr)            (P->myNum, vAddr, BDOOR_STORE_WORD, (uint *)data);         break;      case DOUBLE_SZ:         returnFlag = ((Result (*)(int, uint, uint, uint64*))bdoorAddr)            (P->myNum, vAddr, BDOOR_STORE_DOUBLE, (uint64 *)data);         break;      default:         ASSERT(0);      }      if (returnFlag == SUCCESS) {         return SUCCESS;      } else if (returnFlag == BUSERROR) {         ASSERT(0);         RECORD_EXCEPTION(P, EXC_DBE, E_VEC, vAddr,                           P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);         return BUSERROR;      } else {         CPUError("Unknown result type: 0x%x\n", returnFlag);      }   }   return SUCCESS;}ResultSoloWriteByte(int cpuNum, VA vAddr, char data){   return MipsyWriteMem(vAddr, &data, BYTE_SZ, NO_FLAVOR);}/***************************************************************** * UncachedWrite.  *****************************************************************/static ResultUncachedWrite(VA vAddr, PA pAddr, void *data, RefSize size, bool accelerated){   Result ret;#ifdef FLASHPOINT   uint flavor;   FLASHAddress addr;   LL storeData;#endif   ASSERT ((size == BYTE_SZ) || (size == HALF_SZ)            || (size == WORD_SZ) || (size == DOUBLE_SZ));   /* need to temporarily set cpu_stalled_uncached before MemRefWrite      because it might block */   P->cpuStatus = cpu_stalled_uncached;   ret = MemRefWriteUncached(P->myNum, vAddr, pAddr, data, size, accelerated);   if (ret != SUCCESS) {      P->cpuStatus = cpu_stalled_uncached;   } else {      P->cpuStatus = cpu_running;#ifdef FLASHPOINT      flavor = TLB_UNCACHED;      addr.ll = SoloV_to_P(P->myNum, vAddr, P->myNum, 0, &flavor);       storeData = *((LL *) data);            CPUPrint("Mipsy: cpu %d, Uncached store to 0x%llx, data is %lld\n",                P->myNum, addr.ll, storeData);            if(addr.fa.space == PERF) {         CPUPrint("Mipsy: Perf store!\n");         if((addr.fa.offset & PERF_FP_MASK) == PERF_FP_ENTER_PROC) {            Memspy_ProcedureNum newProcedure =               Memspy_Sim_GetProcedureNum(GetSimulatorMemspyGlobals(),                                          P->myNum);            newProcedure += storeData;            CPUPrint("Mispy: Enter proc, delta = %lld\n", storeData);            Memspy_Sim_SetProcedureNum(GetSimulatorMemspyGlobals(),                                       P->myNum,                                        newProcedure);            FP_BinStatsProcedureDelta(P->myNum, storeData);         }         if((addr.fa.offset & PERF_FP_MASK) == PERF_FP_NEW_BIN) {            Memspy_VA app_addr = (Memspy_VA)                SoloGetMemoryAddr(storeData & 0xffffffffffLL);            unsigned length = (unsigned) (storeData >> 52);            Memspy_Sim_MapPage(GetSimulatorMemspyGlobals(),                               app_addr, length);            CPUPrint("Mipsy: Perf Mapping page containing vaddr %lx, paddr %llx to bin %lld, length %u\n", app_addr,                     storeData & 0xffffffffffLL,                     (storeData>>40)&0xfff, length);         }      }      #endif   }   CHECK_ST_ANN(vAddr,pAddr);   STATS_INC(P->myNum, dWrites, 1);   TraceUncachedDataRef(P, vAddr, pAddr);   return ret;}/**************************************************************** * UncachedRead *****************************************************************/static ResultUncachedRead(VA vAddr, PA pAddr, void *data, RefSize size){   Result ret;   ASSERT ((size == BYTE_SZ) || (size == HALF_SZ)            || (size == WORD_SZ) || (size == DOUBLE_SZ));   /* need to temporarily set cpu_stalled_uncached before MemRefRead      because it might block */   P->cpuStatus = cpu_stalled_uncached;   ret = MemRefReadUncached(P->myNum, vAddr, pAddr, data, size);   if (ret != SUCCESS) {      P->cpuStatus = cpu_stalled_uncached;   } else {      P->cpuStatus = cpu_running;   }   CHECK_LD_ANN(vAddr,pAddr);   STATS_INC(P->myNum, dReads, 1);   TraceUncachedDataRef(P, vAddr, pAddr);   return ret;}/***************************************************************** * ****************************************************************/voidMipsyNakUncachedOp(int cpuNum){   CPUState *P = &PE[cpuNum];   StatusReg statusReg;   MipsyUnstall(cpuNum);   statusReg.ts_data = P->CP0[C0_SR];   if (statusReg.s32.ts_erl) {      if (P->nPC == CACHE_ERR_VEC_BEV0) {      /* HACK         assume CPU was waiting for this uncached op to finish before         starting the cache error handler, so make it take the error now.         Undo effects of previous call to MipsyCacheError and call it again         (this time with cpu_running) */         CPUWarning("Uncached op nak'd on cpu %d while waiting for cache error\n",                    cpuNum);         P->nPC = P->CP0[C0_ERROR_EPC];         MipsyCacheError(cpuNum, 1);      }   }}/***************************************************************** * *****************************************************************/voidMipsyErrUncachedOp(int cpuNum, uint addr){   CPUState *P = &PE[cpuNum];   StatusReg statusReg;   MipsyTakeBusError(cpuNum, FALSE, addr);   /* dont need MipsyUnstall(cpuNum) because TakeBusError already does that */   statusReg.ts_data = P->CP0[C0_SR];   if (statusReg.s32.ts_erl) {      if (P->nPC == CACHE_ERR_VEC_BEV0) {      /* HACK         assume CPU was waiting for this uncached op to finish before         starting the cache error handler, so make it take the error now.         Undo effects of previous call to MipsyCacheError and call it again         (this time with cpu_running) */         CPUWarning("Uncached op err'd on cpu %d while waiting for cache error\n",                    cpuNum);         P->nPC = P->CP0[C0_ERROR_EPC];         MipsyCacheError(cpuNum, 1);      }   }}voidMipsyReissueUncachedOp(int cpuNum){   MipsyUnstall(cpuNum);}void MipsyTurnOnCaches(void){   mipsySkipCaches = FALSE;}voidMipsyTurnOffCaches(void){   CPUWarning("MIPSY: Turning off caches without flushing.\n");   mipsySkipCaches = TRUE;}boolMipsyCachesAreOn(void){   return !mipsySkipCaches;}/***************************************************************** * Bus errors that aren't determined until you are in the memory  * system will come back through this path *****************************************************************/voidMipsyTakeBusError(int cpuNum, bool isIRef, VA vAddr){   CPUState *P = &PE[cpuNum];   PA pAddr;   ASSERT((P->cpuStatus == cpu_stalled) || (P->cpuStatus == cpu_stalled_uncached));   P->cpuStatus = cpu_running;   if (TranslateVirtualNoSideeffect(P, vAddr, &pAddr) != SUCCESS) {      CPUWarning("Couldn't translate virtual in MipsyTakeBusError\n");      ASSERT(0);   }   MemRefRemoveReq(cpuNum, pAddr, SCACHE_LINE_SIZE);   if (isIRef) {      RECORD_EXCEPTION(P, EXC_IBE, E_VEC, vAddr,                        P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);   } else {      RECORD_EXCEPTION(P, EXC_DBE, E_VEC, vAddr,                        P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);   }}/***************************************************************** * MipsyRun *  * This is the interface into starting the fetch-decode-execute * loop.  *****************************************************************/void MipsyRun(int swtch){   int i;   PrintRealTime("Simulation Start");   MipsyInitFPU();#ifdef MIPSY_MXS   if ((mxsRunInterval > 0) && (mipsyRunInterval > 0)) {       /* Run first in mipsy and then switch */      EventDoCallback(0,SwitchSimulators, &switchSimHdr, 0, mipsyRunInterval);   } else {      int cpu;       /* If we aren't going to switch back and forth, start in MXS */      for (cpu=0; cpu < TOTAL_CPUS; cpu++)         PE[cpu].inMXS = 1;   }#endif #ifdef T5_MODEL   {      int usingT5 = 0;      ParamLookup(&usingT5, "MEMSYS.FLASH.UseNewtT5", PARAM_INT);      if (usingT5) {        ParamLookup(&T5NodeNum, "MEMSYS.FLASH.VerilogNodeNum", PARAM_INT);      } else {         T5NodeNum = -1;         /* Won't match any node numbers */      }   }#endif         for (i=0; i < TOTAL_CPUS; i++) {      /* Optimization to avoid directly indexing the PE array */      pePtr[i] = &PE[i];   }   AnnFMInit(128);   if (!swtch) {      /* this is not a switch from another simulator */      AnnCommonSetup();      for (i=0; i < TOTAL_CPUS; i++) {         P = &PE[i];         AnnExec(AnnFind("simos", "enter"));      }   }   /* Now jump into the main loop.When it is time for mipsy to quit */   /* simulating, a longjmp will switch control here and then to */   /* DoneRunning(). */    if (setjmp(jmpEnv) != 0) {      DoneRunning();   } else {      TraceInit();      CPURun(NULL);   }#ifdef MIPSY_MXS   if ((mxsRunInterval > 0) && (mipsyRunInterval > 0)) {       EventCallbackRemove(&switchSimHdr);     }#endif /* MIPSY_MXS */   MemRefExit();#ifdef DATA_HANDLING#ifndef SOLO   /* flush cache. This is inappropriate for SOLO, not to mention it crashes*/   {      int cpu;      for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {         FlushEntireCache(cpu, 0);      }   }#endif#endif}/**************************************************************** * CPURun * * This is the fetch-decode-execute loop. Loop exit points include * exceptions and calls to the memory system to fetch instructions and * data. The premise behind exceptions is that the PC will not be  * incremented so that the exception handler can set the correct PC. * It takes the void * parameter to match the function type that * sproc() expects. ****************************************************************/static void CPURun(void *Nada){   register  CPUState *lastP;    register  CPUState *firstP;   int i;   firstP = &PE[0];   lastP  = &PE[TOTAL_CPUS-1];   P      = lastP;   for (i=0; i < TOTAL_CPUS; i++) {      P = &PE[i];      pePtr[i] = &PE[i];   }   while (1) {      Inst instr;      register uint cpuNum;      register uint op;       P++;      if (P > lastP) {         P = firstP;         mipsyCurrentTime++;          EventPollSingleQueue(MipsyReadTime(0));      }             if (P->cpuStatus != cpu_running) {         /*           * A cpu can be halted or stalled. In solo mipsy, all but the           * first cpu is halted until the CREATE macro is encountered.           */          continue;      }#ifdef USE_FLASHLITE#ifdef SOLO      if (sys_place_range_StallCPUS) {         continue;      }#endif#ifdef T5_MODEL      /*        * If we're using the T5 model on this node to model the processor,       * we'll need to make sure this node just idles        */      if (T5NodeNum == P->myNum) {         if (T5NodeNum == 0) {            /*              * Special case for verilog on node 0: need to make sure              * Flashlite's threads can run as needed              */            (void)  FlashAdvanceTime(MipsyReadTime(cpuNum));           }         continue;      }#endif#endif      cpuNum = P->myNum;      if (P->takeInterrupt) {         if (P->stalledInst) {         /*           * If we've reached this point, it means that we have just          * unstalled the processor and are immediately supposed to          * take an interrupt. In the past, this would smash the          * current instruction and have it reissued when the          * interrupt handling finished. Now we will first let the          * unstall complete. This is especially useful in the          * uncached cases where we don't want to reissue the ops.          */         } else {            P->takeInterrupt = FALSE;            if (!IN_MXS(P)) {

⌨️ 快捷键说明

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