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 + -
显示快捷键?