physical.cc

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

CC
557
字号
    } else if (pkt->isRead()) {        assert(!pkt->isWrite());        if (pkt->isLocked()) {            trackLoadLocked(pkt);        }        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());        TRACE_PACKET("Read");    } else if (pkt->isWrite()) {        if (writeOK(pkt)) {            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());            TRACE_PACKET("Write");        }    } else if (pkt->isInvalidate()) {        //upgrade or invalidate        if (pkt->needsResponse()) {            pkt->makeAtomicResponse();        }    } else {        panic("unimplemented");    }    if (pkt->needsResponse()) {        pkt->makeAtomicResponse();    }    return calculateLatency(pkt);}voidPhysicalMemory::doFunctionalAccess(PacketPtr pkt){    assert(pkt->getAddr() >= start() &&           pkt->getAddr() + pkt->getSize() <= start() + size());    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();    if (pkt->isRead()) {        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());        TRACE_PACKET("Read");        pkt->makeAtomicResponse();    } else if (pkt->isWrite()) {        memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());        TRACE_PACKET("Write");        pkt->makeAtomicResponse();    } else if (pkt->isPrint()) {        Packet::PrintReqState *prs =            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);        // Need to call printLabels() explicitly since we're not going        // through printObj().        prs->printLabels();        // Right now we just print the single byte at the specified address.        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);    } else {        panic("PhysicalMemory: unimplemented functional command %s",              pkt->cmdString());    }}Port *PhysicalMemory::getPort(const std::string &if_name, int idx){    // Accept request for "functional" port for backwards compatibility    // with places where this function is called from C++.  I'd prefer    // to move all these into Python someday.    if (if_name == "functional") {        return new MemoryPort(csprintf("%s-functional", name()), this);    }    if (if_name != "port") {        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);    }    if (idx >= ports.size()) {        ports.resize(idx+1);    }    if (ports[idx] != NULL) {        panic("PhysicalMemory::getPort: port %d already assigned", idx);    }    MemoryPort *port =        new MemoryPort(csprintf("%s-port%d", name(), idx), this);    ports[idx] = port;    return port;}voidPhysicalMemory::recvStatusChange(Port::Status status){}PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,                                       PhysicalMemory *_memory)    : SimpleTimingPort(_name), memory(_memory){ }voidPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status){    memory->recvStatusChange(status);}voidPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,                                                   bool &snoop){    memory->getAddressRanges(resp, snoop);}voidPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop){    snoop = false;    resp.clear();    resp.push_back(RangeSize(start(), params()->range.size()));}intPhysicalMemory::MemoryPort::deviceBlockSize(){    return memory->deviceBlockSize();}TickPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt){    return memory->doAtomicAccess(pkt);}voidPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt){    pkt->pushLabel(memory->name());    if (!checkFunctional(pkt)) {        // Default implementation of SimpleTimingPort::recvFunctional()        // calls recvAtomic() and throws away the latency; we can save a        // little here by just not calculating the latency.        memory->doFunctionalAccess(pkt);    }    pkt->popLabel();}unsigned intPhysicalMemory::drain(Event *de){    int count = 0;    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {        count += (*pi)->drain(de);    }    if (count)        changeState(Draining);    else        changeState(Drained);    return count;}voidPhysicalMemory::serialize(ostream &os){    gzFile compressedMem;    string filename = name() + ".physmem";    SERIALIZE_SCALAR(filename);    // write memory file    string thefile = Checkpoint::dir() + "/" + filename.c_str();    int fd = creat(thefile.c_str(), 0664);    if (fd < 0) {        perror("creat");        fatal("Can't open physical memory checkpoint file '%s'\n", filename);    }    compressedMem = gzdopen(fd, "wb");    if (compressedMem == NULL)        fatal("Insufficient memory to allocate compression state for %s\n",                filename);    if (gzwrite(compressedMem, pmemAddr, params()->range.size()) !=        params()->range.size()) {        fatal("Write failed on physical memory checkpoint file '%s'\n",              filename);    }    if (gzclose(compressedMem))        fatal("Close failed on physical memory checkpoint file '%s'\n",              filename);}voidPhysicalMemory::unserialize(Checkpoint *cp, const string &section){    gzFile compressedMem;    long *tempPage;    long *pmem_current;    uint64_t curSize;    uint32_t bytesRead;    const int chunkSize = 16384;    string filename;    UNSERIALIZE_SCALAR(filename);    filename = cp->cptDir + "/" + filename;    // mmap memoryfile    int fd = open(filename.c_str(), O_RDONLY);    if (fd < 0) {        perror("open");        fatal("Can't open physical memory checkpoint file '%s'", filename);    }    compressedMem = gzdopen(fd, "rb");    if (compressedMem == NULL)        fatal("Insufficient memory to allocate compression state for %s\n",                filename);    // unmap file that was mmaped in the constructor    // This is done here to make sure that gzip and open don't muck with our    // nice large space of memory before we reallocate it    munmap((char*)pmemAddr, params()->range.size());    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);    if (pmemAddr == (void *)MAP_FAILED) {        perror("mmap");        fatal("Could not mmap physical memory!\n");    }    curSize = 0;    tempPage = (long*)malloc(chunkSize);    if (tempPage == NULL)        fatal("Unable to malloc memory to read file %s\n", filename);    /* Only copy bytes that are non-zero, so we don't give the VM system hell */    while (curSize < params()->range.size()) {        bytesRead = gzread(compressedMem, tempPage, chunkSize);        if (bytesRead != chunkSize &&            bytesRead != params()->range.size() - curSize)            fatal("Read failed on physical memory checkpoint file '%s'"                  " got %d bytes, expected %d or %d bytes\n",                  filename, bytesRead, chunkSize,                  params()->range.size() - curSize);        assert(bytesRead % sizeof(long) == 0);        for (int x = 0; x < bytesRead/sizeof(long); x++)        {             if (*(tempPage+x) != 0) {                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));                 *pmem_current = *(tempPage+x);             }        }        curSize += bytesRead;    }    free(tempPage);    if (gzclose(compressedMem))        fatal("Close failed on physical memory checkpoint file '%s'\n",              filename);}PhysicalMemory *PhysicalMemoryParams::create(){    return new PhysicalMemory(this);}

⌨️ 快捷键说明

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