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

📄 cpu.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
               EXCEPTION(P, EXC_INT);            }         }      }#ifdef MIPSY_MXS      if (P->inMXS) {        mxs:         ms_cycle_once (P->st);         continue;      } else {         if (P->switchToMXS && (P->PC == P->nPC-4) && (P->stalledInst == 0)) {            P->inMXS = 1;            P->switchToMXS = 0;            CopyToMXS(P);            CPUWarning("MXS: Switching to MXS on CPU%d at 0x%x time %lld\n",                        cpuNum, P->PC, (uint64)MipsyReadTime(cpuNum));            goto mxs;         }      }#endif      /*        * Shortcut to keep from going through ReadInstruction again       * after an instruction caused a dcache miss and stalled. When       * the processor's data cache miss completes, we'll still have        * the instruction ready and waiting.        */      if (P->stalledInst) {         instr = P->stalledInst;         P->stalledInst = FALSE;      }  else {          Result ret;         VA vAddr = P->PC;         /*           * Anything we can do to avoid translating the virtual          * address is a good thing. This is a quick check to see if          * the current instruction is on the same page as the last          * one. If so, we don't have to translate it again. This           * cache entry is of course cleared whenever there is a          * chance that this translation is no longer correct.           */         if (PAGE_NUMBER(vAddr) == P->pcVPNcache) {            PA p = P->pcPaddrcache + PAGE_OFFSET(vAddr);            if (SKIP_CACHES(P)) {               instr = *(Inst *)HOST_DATA_ADDR(vAddr, p, cpuNum);            } else {               /*                 * Do a quick check if this was in the last line                 * checked. This cached address is set on a icache hit and                 * is invalidated whenever a line is flushed from the                 * icache. This could be changed to selectively delete the                 * line, but these are infrequent actions.                 */                              if (QUICK_ICACHE_CHECK(p, P)) {                  int lineIndex;                  /*                    * Quick cache hit! Be careful here - it won't work                    * with bypassing l1 caches right now. Don't need to                    * touch the lru bit since it will be set to this line.                    */                  MS_INSTRUCTION_SET(P->myNum, P->cachedSetIndex);                  MS_INSTRUCTION(cpuNum, p);                  lineIndex = p & (ICACHE_LINE_SIZE-1);                  instr = *(Inst *) (P->cachedILineData + lineIndex);               } else {                  /*                    * 2nd quickest route to the icache, no translation                    * needed, but we must check the cache.                    */                  ret = MemRefReadInst(cpuNum, vAddr, p, &instr);                  if (ret != SUCCESS) {                     if ((ret == STALL) || (ret == FAILURE)) {                        P->stalledInst = 0;                        STATS_SET(cpuNum, stallStart, MipsyReadTime(cpuNum));                        P->cpuStatus = cpu_stalled;                        continue;                     } else if (ret == BUSERROR) {                        RECORD_EXCEPTION(P, EXC_IBE, E_VEC, vAddr, P->CP0[C0_TLBHI],                                          P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);                     } else {                        CPUError("Bad return(%d) from ReadICache\n", ret);                     }                  }               }            }         } else {             /*              * This is the slow path to get an instruction. Full address              * translation and checking of the Icache is required.              */             ret = ReadInstruction(vAddr, &instr);            if (ret != SUCCESS) {               if (P->cpuStatus != cpu_running) {                  STATS_SET(cpuNum, stallStart, MipsyReadTime(cpuNum));               }               continue;            } else {               STATS_ADD_INTERVAL(cpuNum, stallTime, stallStart);            }         }         /*           * The stalledInstr is stored in HO. In all other cases, we          * instruction is fetched in BE and must be converted to HO.          */         instr = BE2HO_4(instr);         STATS_INC(cpuNum, iReads, 1);      };      if (mipsy_debug_mode) {         if ((cpuNum == mipsy_break_nexti)              || (mipsy_break_nexti == MIPSY_BREAKANYCPU)) {            /*              * MipsyDebug returns nonzero if the PC has changed              * or the contents of it have been overwritten, so it              * needs to be reloaded.              */            if (MipsyDebug(cpuNum, 1)) {               continue;            }         } else if (mipsy_sigusr) {            mipsy_debug_mode = 0;            mipsy_sigusr = 0;            AnnExec(AnnFind("simos", "sigusr"));         }      }      op = MAJOR_OP(instr);      if (mipsOpcodes[op].func(instr, P) == SUCCESS) {         /* CPUPrint("PC %llx - %s\n", P->PC, mipsOpcodes[op].opname);          */         /* Things to do after every successful instruction */         FIX_REG_ZERO;         INSTRUCTION_DONE_EVENT();         if (RunPCAnnotations(P->PC, P->nPC))             continue;         P->PC = P->nPC;         if (P->branchStatus == BranchStatus_taken) {            P->nPC = P->branchTarget;         } else {            P->nPC += INST_SIZE;         }         if (P->branchStatus == BranchStatus_taken              || P->branchStatus == BranchStatus_nottaken ) {             P->branchStatus = BranchStatus_bd;         } else {             P->branchStatus = BranchStatus_none;         }      }   }}/***************************************************************** * DoneRunning *****************************************************************/static voidDoneRunning(void) {   PrintRealTime("Simulation End");   MipsyExitFPU();   /*    * Mark as much true sharing as possible    */   FalseSharingCleanup();      if (SKIP_CACHES(P)) {      CPUWarning("DoneRunning and no caches being used\n");   } else {      if (mipsySyncWhenDone) {         Result allret, ret;         int timeout, i;         CPUPrint("Syncing all processors at time %lld\n", (uint64) MipsyReadTime(0));         for (timeout = 0; timeout < 1000*1000; timeout++) {             allret = SUCCESS;            for (i = 0; i < TOTAL_CPUS; i++) {               if (PE[i].cpuStatus == cpu_running) {                  ret = MemRefSync(i);                  if (ret == STALL) {                     allret = ret;                  }               } else {                  if (PE[i].cpuStatus != cpu_halted &&                      PE[i].cpuStatus != cpu_idle) {                     allret = STALL;                  }               }            }            if (allret == SUCCESS)                break;            MIPSY_ADD_TIME(0, 1);            EventPollSingleQueue(MipsyReadTime(0));         }          if (allret != SUCCESS)             CPUWarning("Sync failed!\n");       }   }}/***************************************************************** * Mipsy-specific annotation code *****************************************************************/voidMipsyInstallMemAnnotation(VA vAddr){   /* Think of a clever way to optimize this! */}/***************************************************************** * MipsyTclInit - mipsy-specific tcl/memstat initialization*****************************************************************/extern int memstatOption;#define MemStatNone 0#define MemStatGlobal 1void MipsyTclInit(Tcl_Interp *interp){   Tcl_CreateCommand(interp, "instDump", PrintInstTclCmd,                     (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);   Tcl_CreateCommand(interp, "printInsts", PrintInstTclCmd,                     (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);#ifdef DASH_PREFETCH   Tcl_CreateCommand(interp, "dashPrefetch", DashTclCmd,                     (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);#endif   Tcl_CreateCommand(interp, "verboseDebug", InterpretVerboseDebug,                     (char *)NULL, (Tcl_CmdDeleteProc*)NULL);#ifdef TRACING   Tcl_CreateCommand(interp, "traceDump", TraceDumpTclCmd,                     (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);#endif   Tcl_LinkVar(interp, SaveString("SIMOS(SOLO)"), (char*)&isSolo,               TCL_LINK_READ_ONLY | TCL_LINK_BOOLEAN);   ParamRegister("PARAM(CPU.Mipsy.MipsySampleCycles)", (char *)&mipsyRunInterval,                  PARAM_INT);   ParamRegister("PARAM(CPU.Mipsy.MXSSampleCycles)", (char *)&mxsRunInterval,                  PARAM_INT);#ifdef SOLO   memstatOption = MemStatNone;#else   memstatOption = MemStatGlobal;#endif#ifdef MIPSY_MXS   ms_events_init();#endif}/***************************************************************** * Tcl interface for controlling mipsy's vebose debugging *****************************************************************/int InterpretVerboseDebug(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){#ifndef DEBUG_DATA_VERBOSE   Tcl_AppendResult(interp,                     "verboseDebug not supported unless mipsy compiled -DDEBUG_DATA_VERBOSE",                    NULL);   return TCL_ERROR;#else #ifndef SOLO   if (simosCPUType != MIPSY) {      Tcl_AppendResult(interp, "verboseDebug not supported unless running in mipsy",                       NULL);      return TCL_ERROR;   }#endif   if (argc < 2) {      Tcl_AppendResult(interp,                        "Bad: should be: verboseDebug <on|off>",                        NULL);      return TCL_ERROR;   }   if (!strcmp(argv[1], "off")) {      CPUWarning("verboseDebug: Turning verbose cache debugging OFF\n");      verboseDebugEnabled = 0;   } else if (!strcmp(argv[1], "on")) {      CPUWarning("verboseDebug: Turning verbose cache debugging ON\n");      verboseDebugEnabled = 1;   } else {      Tcl_AppendResult(interp,                     "bad: should be: verboseDebug <on|off>", NULL);      return TCL_ERROR;   }   return TCL_OK;#endif}void MXSSwitch(int cpu, int enterMXS){#ifdef MIPSY_MXS   if ((PE[cpu].inMXS && enterMXS) || (!PE[cpu].inMXS && !enterMXS))      return;   if (enterMXS)      PE[cpu].switchToMXS = 1;   else      PE[cpu].switchToMIPSY = 1;   return;#else   CPUWarning("Trying to switch between mipsy and MXS, "              "but this simos was built without MXS\n");#endif}#ifdef MIPSY_MXS/* * DoUncachedRead - perform an uncached/bdoor read for MXS. */int DoUncachedRead(struct s_cpu_state *st, uint vAddr, uint pAddr,                int size, void *data){   RefSize refsize;   switch (size) {   case 1:       refsize = BYTE_SZ;       break;   case 2:       refsize = HALF_SZ;       break;   case 4:       refsize = WORD_SZ;       break;   case 8:       refsize = DOUBLE_SZ;       break;   default:       ASSERT(0);   }   return MipsyReadMem(vAddr, data, refsize, NO_FLAVOR);}/* * DoUncachedWrite - perform an uncached/bdoor write for MXS */int DoUncachedWrite(struct s_cpu_state *st,  uint vAddr, uint pAddr,                  int size, int accel, void *data){   RefSize refsize;   switch (size) {   case 1:       refsize = BYTE_SZ;       break;   case 2:       refsize = HALF_SZ;       break;   case 4:       refsize = WORD_SZ;       break;   case 8:       refsize = DOUBLE_SZ;       break;   default:       ASSERT(0);   }   return MipsyWriteMem(vAddr, data, refsize, NO_FLAVOR);}/* * GetLastException - Return the exception number of the last  *                    execption RECORDed by the RECORD_EXCEPTION macro. */intGetLastException(struct s_cpu_state *st){   CPUState *P = (CPUState *) (st->mipsyPtr);   return P->lastException;}voidRecordMxsMemsysStall(struct s_cpu_state *st, SimTime stallTime){  CPUState *P = (CPUState *) (st->mipsyPtr);  int cpuNum = P->myNum;  STATS_INC(cpuNum, stallTime, stallTime);}static void SwitchSimulators(int cpuNum,EventCallbackHdr *hdr, void *arg){   int i;   SimTime interval;   ASSERT( cpuNum ==  0 );   if (PE[0].inMXS) {      for (i = 0; i < TOTAL_CPUS; i++) {         MXSSwitch(i,FALSE);         /* WARNING - need switch simulators annotation */      }      interval = mipsyRunInterval;   } else {      for (i = 0; i < TOTAL_CPUS; i++) {         MXSSwitch(i,TRUE);         /* WARNING - need switch simulators annotation */             }      interval = mxsRunInterval;   }   EventDoCallback(cpuNum, SwitchSimulators, &switchSimHdr, 0, interval);}#endif  /* MIPSY_MXS */

⌨️ 快捷键说明

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