timing.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 880 行 · 第 1/2 页
CC
880 行
TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, int size, unsigned flags){ Request *req = new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0); if (traceData) { traceData->setAddr(vaddr); } Fault fault = thread->translateDataWriteReq(req); if (fault == NoFault) paddr = req->getPaddr(); delete req; return fault;}#ifndef DOXYGEN_SHOULD_SKIP_THIStemplateFaultTimingSimpleCPU::write(Twin32_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultTimingSimpleCPU::write(Twin64_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultTimingSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultTimingSimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultTimingSimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultTimingSimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);#endif //DOXYGEN_SHOULD_SKIP_THIStemplate<>FaultTimingSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res){ return write(*(uint64_t*)&data, addr, flags, res);}template<>FaultTimingSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res){ return write(*(uint32_t*)&data, addr, flags, res);}template<>FaultTimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res){ return write((uint32_t)data, addr, flags, res);}voidTimingSimpleCPU::fetch(){ DPRINTF(SimpleCPU, "Fetch\n"); if (!curStaticInst || !curStaticInst->isDelayedCommit()) checkForInterrupts(); checkPcEventQueue(); Request *ifetch_req = new Request(); ifetch_req->setThreadContext(cpuId, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); if (fault == NoFault) { if (!icachePort.sendTiming(ifetch_pkt)) { // Need to wait for retry _status = IcacheRetry; } else { // Need to wait for cache to respond _status = IcacheWaitResponse; // ownership of packet transferred to memory system ifetch_pkt = NULL; } } else { delete ifetch_req; delete ifetch_pkt; // fetch fault: advance directly to next instruction (fault handler) advanceInst(fault); } numCycles += tickToCycles(curTick - previousTick); previousTick = curTick;}voidTimingSimpleCPU::advanceInst(Fault fault){ advancePC(fault); if (_status == Running) { // kick off fetch of next instruction... callback from icache // response will cause that instruction to be executed, // keeping the CPU running. fetch(); }}voidTimingSimpleCPU::completeIfetch(PacketPtr pkt){ DPRINTF(SimpleCPU, "Complete ICache Fetch\n"); // received a response from the icache: execute the received // instruction assert(!pkt->isError()); assert(_status == IcacheWaitResponse); _status = Running; numCycles += tickToCycles(curTick - previousTick); previousTick = curTick; if (getState() == SimObject::Draining) { delete pkt->req; delete pkt; completeDrain(); return; } preExecute(); if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { // load or store: just send to dcache Fault fault = curStaticInst->initiateAcc(this, traceData); if (_status != Running) { // instruction will complete in dcache response callback assert(_status == DcacheWaitResponse || _status == DcacheRetry); assert(fault == NoFault); } else { if (fault == NoFault) { // Note that ARM can have NULL packets if the instruction gets // squashed due to predication // early fail on store conditional: complete now assert(dcache_pkt != NULL || THE_ISA == ARM_ISA); fault = curStaticInst->completeAcc(dcache_pkt, this, traceData); if (dcache_pkt != NULL) { delete dcache_pkt->req; delete dcache_pkt; dcache_pkt = NULL; } // keep an instruction count if (fault == NoFault) countInst(); } else if (traceData) { // If there was a fault, we shouldn't trace this instruction. delete traceData; traceData = NULL; } postExecute(); // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroop() || curStaticInst->isFirstMicroop())) instCnt++; advanceInst(fault); } } else { // non-memory instruction: execute completely now Fault fault = curStaticInst->execute(this, traceData); // keep an instruction count if (fault == NoFault) countInst(); else if (traceData) { // If there was a fault, we shouldn't trace this instruction. delete traceData; traceData = NULL; } postExecute(); // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroop() || curStaticInst->isFirstMicroop())) instCnt++; advanceInst(fault); } delete pkt->req; delete pkt;}voidTimingSimpleCPU::IcachePort::ITickEvent::process(){ cpu->completeIfetch(pkt);}boolTimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt){ if (pkt->isResponse() && !pkt->wasNacked()) { // delay processing of returned data until next CPU clock edge Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeIfetch(pkt); else tickEvent.schedule(pkt, next_tick); return true; } else if (pkt->wasNacked()) { assert(cpu->_status == IcacheWaitResponse); pkt->reinitNacked(); if (!sendTiming(pkt)) { cpu->_status = IcacheRetry; cpu->ifetch_pkt = pkt; } } //Snooping a Coherence Request, do nothing return true;}voidTimingSimpleCPU::IcachePort::recvRetry(){ // we shouldn't get a retry unless we have a packet that we're // waiting to transmit assert(cpu->ifetch_pkt != NULL); assert(cpu->_status == IcacheRetry); PacketPtr tmp = cpu->ifetch_pkt; if (sendTiming(tmp)) { cpu->_status = IcacheWaitResponse; cpu->ifetch_pkt = NULL; }}voidTimingSimpleCPU::completeDataAccess(PacketPtr pkt){ // received a response from the dcache: complete the load or store // instruction assert(!pkt->isError()); assert(_status == DcacheWaitResponse); _status = Running; numCycles += tickToCycles(curTick - previousTick); previousTick = curTick; Fault fault = curStaticInst->completeAcc(pkt, this, traceData); // keep an instruction count if (fault == NoFault) countInst(); else if (traceData) { // If there was a fault, we shouldn't trace this instruction. delete traceData; traceData = NULL; } if (pkt->isRead() && pkt->isLocked()) { TheISA::handleLockedRead(thread, pkt->req); } delete pkt->req; delete pkt; postExecute(); if (getState() == SimObject::Draining) { advancePC(fault); completeDrain(); return; } advanceInst(fault);}voidTimingSimpleCPU::completeDrain(){ DPRINTF(Config, "Done draining\n"); changeState(SimObject::Drained); drainEvent->process();}voidTimingSimpleCPU::DcachePort::setPeer(Port *port){ Port::setPeer(port);#if FULL_SYSTEM // Update the ThreadContext's memory ports (Functional/Virtual // Ports) cpu->tcBase()->connectMemPorts();#endif}boolTimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt){ if (pkt->isResponse() && !pkt->wasNacked()) { // delay processing of returned data until next CPU clock edge Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeDataAccess(pkt); else tickEvent.schedule(pkt, next_tick); return true; } else if (pkt->wasNacked()) { assert(cpu->_status == DcacheWaitResponse); pkt->reinitNacked(); if (!sendTiming(pkt)) { cpu->_status = DcacheRetry; cpu->dcache_pkt = pkt; } } //Snooping a Coherence Request, do nothing return true;}voidTimingSimpleCPU::DcachePort::DTickEvent::process(){ cpu->completeDataAccess(pkt);}voidTimingSimpleCPU::DcachePort::recvRetry(){ // we shouldn't get a retry unless we have a packet that we're // waiting to transmit assert(cpu->dcache_pkt != NULL); assert(cpu->_status == DcacheRetry); PacketPtr tmp = cpu->dcache_pkt; if (sendTiming(tmp)) { cpu->_status = DcacheWaitResponse; // memory system takes ownership of packet cpu->dcache_pkt = NULL; }}TimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t) : Event(&mainEventQueue), pkt(_pkt), cpu(_cpu){ schedule(t);}voidTimingSimpleCPU::IprEvent::process(){ cpu->completeDataAccess(pkt);}const char *TimingSimpleCPU::IprEvent::description() const{ return "Timing Simple CPU Delay IPR event";}voidTimingSimpleCPU::printAddr(Addr a){ dcachePort.printAddr(a);}//////////////////////////////////////////////////////////////////////////// TimingSimpleCPU Simulation Object//TimingSimpleCPU *TimingSimpleCPUParams::create(){ TimingSimpleCPU::Params *params = new TimingSimpleCPU::Params(); params->name = name; 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->progress_interval = progress_interval; params->deferRegistration = defer_registration; params->clock = clock; params->phase = phase; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; params->system = system; params->cpu_id = cpu_id; params->tracer = tracer; params->itb = itb; params->dtb = dtb;#if FULL_SYSTEM params->profile = profile; params->do_quiesce = do_quiesce; params->do_checkpoint_insts = do_checkpoint_insts; params->do_statistics_insts = do_statistics_insts;#else if (workload.size() != 1) panic("only one workload allowed"); params->process = workload[0];#endif TimingSimpleCPU *cpu = new TimingSimpleCPU(params); return cpu;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?