physical.cc

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

CC
557
字号
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * 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: Ronald G. Dreslinski Jr *          Ali G. Saidi */#include <sys/types.h>#include <sys/mman.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <zlib.h>#include <iostream>#include <string>#include "arch/isa_traits.hh"#include "base/misc.hh"#include "config/full_system.hh"#include "mem/packet_access.hh"#include "mem/physical.hh"#include "sim/eventq.hh"#include "sim/host.hh"using namespace std;using namespace TheISA;PhysicalMemory::PhysicalMemory(const Params *p)    : MemObject(p), pmemAddr(NULL), lat(p->latency){    if (params()->range.size() % TheISA::PageBytes != 0)        panic("Memory Size not divisible by page size\n");    int map_flags = MAP_ANON | MAP_PRIVATE;    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),                               PROT_READ | PROT_WRITE, map_flags, -1, 0);    if (pmemAddr == (void *)MAP_FAILED) {        perror("mmap");        fatal("Could not mmap!\n");    }    //If requested, initialize all the memory to 0    if (p->zero)        memset(pmemAddr, 0, p->range.size());    pagePtr = 0;    cachedSize = params()->range.size();    cachedStart = params()->range.start;}voidPhysicalMemory::init(){    if (ports.size() == 0) {        fatal("PhysicalMemory object %s is unconnected!", name());    }    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {        if (*pi)            (*pi)->sendStatusChange(Port::RangeChange);    }}PhysicalMemory::~PhysicalMemory(){    if (pmemAddr)        munmap((char*)pmemAddr, params()->range.size());    //Remove memPorts?}AddrPhysicalMemory::new_page(){    Addr return_addr = pagePtr << LogVMPageSize;    return_addr += start();    ++pagePtr;    return return_addr;}intPhysicalMemory::deviceBlockSize(){    //Can accept anysize request    return 0;}TickPhysicalMemory::calculateLatency(PacketPtr pkt){    return lat;}// Add load-locked to tracking list.  Should only be called if the// operation is a load and the LOCKED flag is set.voidPhysicalMemory::trackLoadLocked(PacketPtr pkt){    Request *req = pkt->req;    Addr paddr = LockedAddr::mask(req->getPaddr());    // first we check if we already have a locked addr for this    // xc.  Since each xc only gets one, we just update the    // existing record with the new address.    list<LockedAddr>::iterator i;    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {        if (i->matchesContext(req)) {            DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",                    req->getCpuNum(), req->getThreadNum(), paddr);            i->addr = paddr;            return;        }    }    // no record for this xc: need to allocate a new one    DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",            req->getCpuNum(), req->getThreadNum(), paddr);    lockedAddrList.push_front(LockedAddr(req));}// Called on *writes* only... both regular stores and// store-conditional operations.  Check for conventional stores which// conflict with locked addresses, and for success/failure of store// conditionals.boolPhysicalMemory::checkLockedAddrList(PacketPtr pkt){    Request *req = pkt->req;    Addr paddr = LockedAddr::mask(req->getPaddr());    bool isLocked = pkt->isLocked();    // Initialize return value.  Non-conditional stores always    // succeed.  Assume conditional stores will fail until proven    // otherwise.    bool success = !isLocked;    // Iterate over list.  Note that there could be multiple matching    // records, as more than one context could have done a load locked    // to this location.    list<LockedAddr>::iterator i = lockedAddrList.begin();    while (i != lockedAddrList.end()) {        if (i->addr == paddr) {            // we have a matching address            if (isLocked && i->matchesContext(req)) {                // it's a store conditional, and as far as the memory                // system can tell, the requesting context's lock is                // still valid.                DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",                        req->getCpuNum(), req->getThreadNum(), paddr);                success = true;            }            // Get rid of our record of this lock and advance to next            DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",                    i->cpuNum, i->threadNum, paddr);            i = lockedAddrList.erase(i);        }        else {            // no match: advance to next record            ++i;        }    }    if (isLocked) {        req->setExtraData(success ? 1 : 0);    }    return success;}#if TRACING_ON#define CASE(A, T)                                                      \  case sizeof(T):                                                       \    DPRINTF(MemoryAccess, A " of size %i on address 0x%x data 0x%x\n",  \            pkt->getSize(), pkt->getAddr(), pkt->get<T>());             \  break#define TRACE_PACKET(A)                                                 \    do {                                                                \        switch (pkt->getSize()) {                                       \          CASE(A, uint64_t);                                            \          CASE(A, uint32_t);                                            \          CASE(A, uint16_t);                                            \          CASE(A, uint8_t);                                             \          default:                                                      \            DPRINTF(MemoryAccess, A " of size %i on address 0x%x\n",    \                    pkt->getSize(), pkt->getAddr());                    \        }                                                               \    } while (0)#else#define TRACE_PACKET(A)#endifTickPhysicalMemory::doAtomicAccess(PacketPtr pkt){    assert(pkt->getAddr() >= start() &&           pkt->getAddr() + pkt->getSize() <= start() + size());    if (pkt->memInhibitAsserted()) {        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",                pkt->getAddr());        return 0;    }    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();    if (pkt->cmd == MemCmd::SwapReq) {        IntReg overwrite_val;        bool overwrite_mem;        uint64_t condition_val64;        uint32_t condition_val32;        assert(sizeof(IntReg) >= pkt->getSize());        overwrite_mem = true;        // keep a copy of our possible write value, and copy what is at the        // memory address into the packet        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());        if (pkt->req->isCondSwap()) {            if (pkt->getSize() == sizeof(uint64_t)) {                condition_val64 = pkt->req->getExtraData();                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,                                             sizeof(uint64_t));            } else if (pkt->getSize() == sizeof(uint32_t)) {                condition_val32 = (uint32_t)pkt->req->getExtraData();                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,                                             sizeof(uint32_t));            } else                panic("Invalid size for conditional read/write\n");        }        if (overwrite_mem)            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());        TRACE_PACKET("Read/Write");

⌨️ 快捷键说明

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