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