cpu.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 399 行

CC
399
字号
/* * Copyright (c) 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Kevin T. Lim */#include <list>#include <string>#include "cpu/base.hh"#include "cpu/checker/cpu.hh"#include "cpu/simple_thread.hh"#include "cpu/static_inst.hh"#include "cpu/thread_context.hh"#if FULL_SYSTEM#include "arch/kernel_stats.hh"#include "arch/vtophys.hh"#endif // FULL_SYSTEMusing namespace std;//The CheckerCPU does alpha onlyusing namespace AlphaISA;voidCheckerCPU::init(){}CheckerCPU::CheckerCPU(Params *p)    : BaseCPU(p), thread(NULL), tc(NULL){    memReq = NULL;    numInst = 0;    startNumInst = 0;    numLoad = 0;    startNumLoad = 0;    youngestSN = 0;    changedPC = willChangePC = changedNextPC = false;    exitOnError = p->exitOnError;    warnOnlyOnLoadError = p->warnOnlyOnLoadError;#if FULL_SYSTEM    itb = p->itb;    dtb = p->dtb;    systemPtr = NULL;#else    process = p->process;    thread = new SimpleThread(this, /* thread_num */ 0, process,                              /* asid */ 0);    thread->setStatus(ThreadContext::Suspended);    tc = thread->getTC();    threadContexts.push_back(tc);#endif    result.integer = 0;}CheckerCPU::~CheckerCPU(){}voidCheckerCPU::setSystem(System *system){#if FULL_SYSTEM    systemPtr = system;    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);    thread->setStatus(ThreadContext::Suspended);    tc = thread->getTC();    threadContexts.push_back(tc);    delete thread->kernelStats;    thread->kernelStats = NULL;#endif}voidCheckerCPU::setIcachePort(Port *icache_port){    icachePort = icache_port;}voidCheckerCPU::setDcachePort(Port *dcache_port){    dcachePort = dcache_port;}voidCheckerCPU::serialize(ostream &os){/*    BaseCPU::serialize(os);    SERIALIZE_SCALAR(inst);    nameOut(os, csprintf("%s.xc", name()));    thread->serialize(os);    cacheCompletionEvent.serialize(os);*/}voidCheckerCPU::unserialize(Checkpoint *cp, const string &section){/*    BaseCPU::unserialize(cp, section);    UNSERIALIZE_SCALAR(inst);    thread->unserialize(cp, csprintf("%s.xc", section));*/}FaultCheckerCPU::copySrcTranslate(Addr src){    panic("Unimplemented!");}FaultCheckerCPU::copy(Addr dest){    panic("Unimplemented!");}template <class T>FaultCheckerCPU::read(Addr addr, T &data, unsigned flags){    // need to fill in CPU & thread IDs here    memReq = new Request();    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());    // translate to physical address    translateDataReadReq(memReq);    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);    pkt->dataStatic(&data);    if (!(memReq->isUncacheable())) {        // Access memory to see if we have the same data        dcachePort->sendFunctional(pkt);    } else {        // Assume the data is correct if it's an uncached access        memcpy(&data, &unverifiedResult.integer, sizeof(T));    }    delete pkt;    return NoFault;}#ifndef DOXYGEN_SHOULD_SKIP_THIStemplateFaultCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);templateFaultCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);templateFaultCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);templateFaultCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);#endif //DOXYGEN_SHOULD_SKIP_THIStemplate<>FaultCheckerCPU::read(Addr addr, double &data, unsigned flags){    return read(addr, *(uint64_t*)&data, flags);}template<>FaultCheckerCPU::read(Addr addr, float &data, unsigned flags){    return read(addr, *(uint32_t*)&data, flags);}template<>FaultCheckerCPU::read(Addr addr, int32_t &data, unsigned flags){    return read(addr, (uint32_t&)data, flags);}template <class T>FaultCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res){    // need to fill in CPU & thread IDs here    memReq = new Request();    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());    // translate to physical address    thread->translateDataWriteReq(memReq);    // Can compare the write data and result only if it's cacheable,    // not a store conditional, or is a store conditional that    // succeeded.    // @todo: Verify that actual memory matches up with these values.    // Right now it only verifies that the instruction data is the    // same as what was in the request that got sent to memory; there    // is no verification that it is the same as what is in memory.    // This is because the LSQ would have to be snooped in the CPU to    // verify this data.    if (unverifiedReq &&        !(unverifiedReq->isUncacheable()) &&        (!(unverifiedReq->isLocked()) ||         ((unverifiedReq->isLocked()) &&          unverifiedReq->getExtraData() == 1))) {        T inst_data;/*        // This code would work if the LSQ allowed for snooping.        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);        pkt.dataStatic(&inst_data);        dcachePort->sendFunctional(pkt);        delete pkt;*/        memcpy(&inst_data, unverifiedMemData, sizeof(T));        if (data != inst_data) {            warn("%lli: Store value does not match value in memory! "                 "Instruction: %#x, memory: %#x",                 curTick, inst_data, data);            handleError();        }    }    // Assume the result was the same as the one passed in.  This checker    // doesn't check if the SC should succeed or fail, it just checks the    // value.    if (res && unverifiedReq->scResultValid())        *res = unverifiedReq->getExtraData();    return NoFault;}#ifndef DOXYGEN_SHOULD_SKIP_THIStemplateFaultCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);templateFaultCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);#endif //DOXYGEN_SHOULD_SKIP_THIStemplate<>FaultCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res){    return write(*(uint64_t*)&data, addr, flags, res);}template<>FaultCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res){    return write(*(uint32_t*)&data, addr, flags, res);}template<>FaultCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res){    return write((uint32_t)data, addr, flags, res);}#if FULL_SYSTEMAddrCheckerCPU::dbg_vtophys(Addr addr){    return vtophys(tc, addr);}#endif // FULL_SYSTEMboolCheckerCPU::translateInstReq(Request *req){#if FULL_SYSTEM    return (thread->translateInstReq(req) == NoFault);#else    thread->translateInstReq(req);    return true;#endif}voidCheckerCPU::translateDataReadReq(Request *req){    thread->translateDataReadReq(req);    if (req->getVaddr() != unverifiedReq->getVaddr()) {        warn("%lli: Request virtual addresses do not match! Inst: %#x, "             "checker: %#x",             curTick, unverifiedReq->getVaddr(), req->getVaddr());        handleError();    }    req->setPaddr(unverifiedReq->getPaddr());    if (checkFlags(req)) {        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",             curTick, unverifiedReq->getFlags(), req->getFlags());        handleError();    }}voidCheckerCPU::translateDataWriteReq(Request *req){    thread->translateDataWriteReq(req);    if (req->getVaddr() != unverifiedReq->getVaddr()) {        warn("%lli: Request virtual addresses do not match! Inst: %#x, "             "checker: %#x",             curTick, unverifiedReq->getVaddr(), req->getVaddr());        handleError();    }    req->setPaddr(unverifiedReq->getPaddr());    if (checkFlags(req)) {        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",             curTick, unverifiedReq->getFlags(), req->getFlags());        handleError();    }}boolCheckerCPU::checkFlags(Request *req){    // Remove any dynamic flags that don't have to do with the request itself.    unsigned flags = unverifiedReq->getFlags();    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;    flags = flags & (mask);    if (flags == req->getFlags()) {        return false;    } else {        return true;    }}voidCheckerCPU::dumpAndExit(){    warn("%lli: Checker PC:%#x, next PC:%#x",         curTick, thread->readPC(), thread->readNextPC());    panic("Checker found an error!");}

⌨️ 快捷键说明

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