📄 cpu.cc
字号:
templateFaultSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);#endif //DOXYGEN_SHOULD_SKIP_THIStemplate<>FaultSimpleCPU::read(Addr addr, double &data, unsigned flags){ return read(addr, *(uint64_t*)&data, flags);}template<>FaultSimpleCPU::read(Addr addr, float &data, unsigned flags){ return read(addr, *(uint32_t*)&data, flags);}template<>FaultSimpleCPU::read(Addr addr, int32_t &data, unsigned flags){ return read(addr, (uint32_t&)data, flags);}template <class T>FaultSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res){ memReq->reset(addr, sizeof(T), flags); // translate to physical address Fault fault = xc->translateDataWriteReq(memReq); // do functional access if (fault == No_Fault) fault = xc->write(memReq, data); if (fault == No_Fault && dcacheInterface) { memReq->cmd = Write; memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; memReq->time = curTick; MemAccessResult result = dcacheInterface->access(memReq); // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. if (result != MA_HIT && dcacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; unscheduleTickEvent(); _status = DcacheMissStall; } } if (res && (fault == No_Fault)) *res = memReq->result; if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) recordEvent("Uncached Write"); return fault;}#ifndef DOXYGEN_SHOULD_SKIP_THIStemplateFaultSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultSimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultSimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultSimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);#endif //DOXYGEN_SHOULD_SKIP_THIStemplate<>FaultSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res){ return write(*(uint64_t*)&data, addr, flags, res);}template<>FaultSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res){ return write(*(uint32_t*)&data, addr, flags, res);}template<>FaultSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res){ return write((uint32_t)data, addr, flags, res);}#if FULL_SYSTEMAddrSimpleCPU::dbg_vtophys(Addr addr){ return vtophys(xc, addr);}#endif // FULL_SYSTEMvoidSimpleCPU::processCacheCompletion(){ switch (status()) { case IcacheMissStall: icacheStallCycles += curTick - lastIcacheStall; _status = IcacheMissComplete; scheduleTickEvent(1); break; case DcacheMissStall: if (memReq->cmd.isRead()) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } dcacheStallCycles += curTick - lastDcacheStall; _status = Running; scheduleTickEvent(1); break; case DcacheMissSwitch: if (memReq->cmd.isRead()) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } _status = SwitchedOut; sampler->signalSwitched(); case SwitchedOut: // If this CPU has been switched out due to sampling/warm-up, // ignore any further status changes (e.g., due to cache // misses outstanding at the time of the switch). return; default: panic("SimpleCPU::processCacheCompletion: bad state"); break; }}#if FULL_SYSTEMvoidSimpleCPU::post_interrupt(int int_num, int index){ BaseCPU::post_interrupt(int_num, index); if (xc->status() == ExecContext::Suspended) { DPRINTF(IPI,"Suspended Processor awoke\n"); xc->activate(); }}#endif // FULL_SYSTEM/* start simulation, program loaded, processor precise state initialized */voidSimpleCPU::tick(){ numCycles++; traceData = NULL; Fault fault = No_Fault;#if FULL_SYSTEM if (checkInterrupts && check_interrupts() && !xc->inPalMode() && status() != IcacheMissComplete) { int ipl = 0; int summary = 0; checkInterrupts = false; IntReg *ipr = xc->regs.ipr; if (xc->regs.ipr[TheISA::IPR_SIRR]) { for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); } } } uint64_t interrupts = xc->cpu->intr_status(); for (int i = TheISA::INTLEVEL_EXTERNAL_MIN; i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { if (interrupts & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = i; summary |= (ULL(1) << i); } } if (ipr[TheISA::IPR_ASTRR]) panic("asynchronous traps not implemented\n"); if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { ipr[TheISA::IPR_ISR] = summary; ipr[TheISA::IPR_INTID] = ipl; xc->ev5_trap(Interrupt_Fault); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", ipr[TheISA::IPR_IPLR], ipl, summary); } }#endif // maintain $r0 semantics xc->regs.intRegFile[ZeroReg] = 0;#ifdef TARGET_ALPHA xc->regs.floatRegFile.d[ZeroReg] = 0.0;#endif // TARGET_ALPHA if (status() == IcacheMissComplete) { // We've already fetched an instruction and were stalled on an // I-cache miss. No need to fetch it again. // Set status to running; tick event will get rescheduled if // necessary at end of tick() function. _status = Running; } else { // Try to fetch an instruction // set up memory request for instruction fetch#if FULL_SYSTEM#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0#else#define IFETCH_FLAGS(pc) 0#endif memReq->cmd = Read; memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), IFETCH_FLAGS(xc->regs.pc)); fault = xc->translateInstReq(memReq); if (fault == No_Fault) fault = xc->mem->read(memReq, inst); if (icacheInterface && fault == No_Fault) { memReq->completionEvent = NULL; memReq->time = curTick; MemAccessResult result = icacheInterface->access(memReq); // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. if (result != MA_HIT && icacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastIcacheStall = curTick; unscheduleTickEvent(); _status = IcacheMissStall; return; } } } // If we've got a valid instruction (i.e., no fault on instruction // fetch), then execute it. if (fault == No_Fault) { // keep an instruction count numInst++; numInsts++; // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); // decode the instruction inst = gtoh(inst); curStaticInst = StaticInst<TheISA>::decode(inst); traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst, xc->regs.pc);#if FULL_SYSTEM xc->setInst(inst);#endif // FULL_SYSTEM xc->func_exe_inst++; fault = curStaticInst->execute(this, traceData);#if FULL_SYSTEM if (xc->fnbin) xc->execute(curStaticInst.get());#endif if (curStaticInst->isMemRef()) { numMemRefs++; } if (curStaticInst->isLoad()) { ++numLoad; comLoadEventQueue[0]->serviceEvents(numLoad); } // If we have a dcache miss, then we can't finialize the instruction // trace yet because we want to populate it with the data later if (traceData && !(status() == DcacheMissStall && memReq->cmd.isRead())) { traceData->finalize(); } traceFunctions(xc->regs.pc); } // if (fault == No_Fault) if (fault != No_Fault) {#if FULL_SYSTEM xc->ev5_trap(fault);#else // !FULL_SYSTEM fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc);#endif // FULL_SYSTEM } else { // go to the next instruction xc->regs.pc = xc->regs.npc; xc->regs.npc += sizeof(MachInst); }#if FULL_SYSTEM Addr oldpc; do { oldpc = xc->regs.pc; system->pcEventQueue.service(xc); } while (oldpc != xc->regs.pc);#endif assert(status() == Running || status() == Idle || status() == DcacheMissStall); if (status() == Running && !tickEvent.scheduled()) tickEvent.schedule(curTick + cycles(1));}//////////////////////////////////////////////////////////////////////////// SimpleCPU Simulation Object//BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) Param<Counter> max_insts_any_thread; Param<Counter> max_insts_all_threads; Param<Counter> max_loads_any_thread; Param<Counter> max_loads_all_threads;#if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; Param<int> cpu_id;#else SimObjectParam<Process *> workload;#endif // FULL_SYSTEM Param<int> clock; SimObjectParam<BaseMem *> icache; SimObjectParam<BaseMem *> dcache; Param<bool> defer_registration; Param<int> width; Param<bool> function_trace; Param<Tick> function_trace_start;END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) INIT_PARAM(max_insts_any_thread, "terminate when any thread reaches this inst count"), INIT_PARAM(max_insts_all_threads, "terminate when all threads have reached this inst count"), INIT_PARAM(max_loads_any_thread, "terminate when any thread reaches this load count"), INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"),#if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"),#else INIT_PARAM(workload, "processes to run"),#endif // FULL_SYSTEM INIT_PARAM(clock, "clock speed"), INIT_PARAM(icache, "L1 instruction cache object"), INIT_PARAM(dcache, "L1 data cache object"), INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(width, "cpu width"), INIT_PARAM(function_trace, "Enable function trace"), INIT_PARAM(function_trace_start, "Cycle to start function trace")END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)CREATE_SIM_OBJECT(SimpleCPU){ SimpleCPU::Params *params = new SimpleCPU::Params(); params->name = getInstanceName(); params->numberOfThreads = 1; params->max_insts_any_thread = max_insts_any_thread; params->max_insts_all_threads = max_insts_all_threads; params->max_loads_any_thread = max_loads_any_thread; params->max_loads_all_threads = max_loads_all_threads; params->deferRegistration = defer_registration; params->clock = clock; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; params->icache_interface = (icache) ? icache->getInterface() : NULL; params->dcache_interface = (dcache) ? dcache->getInterface() : NULL; params->width = width;#if FULL_SYSTEM params->itb = itb; params->dtb = dtb; params->mem = mem; params->system = system; params->cpu_id = cpu_id;#else params->process = workload;#endif SimpleCPU *cpu = new SimpleCPU(params); return cpu;}REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -