abstract_mem.cc revision 8719
17513SN/A/* 27513SN/A * Copyright (c) 2010-2011 ARM Limited 37513SN/A * All rights reserved 410036SN/A * 58835SN/A * The license below extends only to copyright in the software and shall 610036SN/A * not be construed as granting a license to any other intellectual 77935SN/A * property including but not limited to intellectual property relating 87935SN/A * to a hardware implementation of the functionality of the software 97935SN/A * licensed hereunder. You may use the software subject to the license 107513SN/A * terms below provided that you ensure that this notice is replicated 117513SN/A * unmodified and in its entirety in all distributions of the software, 127513SN/A * modified or unmodified, in source code or in binary form. 1310315SN/A * 148835SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 159885SN/A * All rights reserved. 169885SN/A * 1711570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 1810036SN/A * modification, are permitted provided that the following conditions are 1911312Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 208835SN/A * notice, this list of conditions and the following disclaimer; 218835SN/A * redistributions in binary form must reproduce the above copyright 2210315SN/A * notice, this list of conditions and the following disclaimer in the 238835SN/A * documentation and/or other materials provided with the distribution; 2410038SN/A * neither the name of the copyright holders nor the names of its 259481SN/A * contributors may be used to endorse or promote products derived from 269481SN/A * this software without specific prior written permission. 278721SN/A * 2811066Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2911219Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 308721SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111570SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3211570SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3311570SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 358835SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368835SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711440SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811440SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397935SN/A * 407935SN/A * Authors: Ron Dreslinski 417935SN/A * Ali Saidi 427935SN/A */ 437935SN/A 447935SN/A#include <sys/mman.h> 457935SN/A#include <sys/types.h> 468893SN/A#include <sys/user.h> 477513SN/A#include <fcntl.h> 489885SN/A#include <unistd.h> 499885SN/A#include <zlib.h> 509885SN/A 5110315SN/A#include <cerrno> 5210036SN/A#include <cstdio> 5310315SN/A#include <iostream> 549885SN/A#include <string> 559885SN/A 567513SN/A#include "arch/isa_traits.hh" 577513SN/A#include "arch/registers.hh" 5810038SN/A#include "base/intmath.hh" 5910315SN/A#include "base/misc.hh" 607513SN/A#include "base/random.hh" 619885SN/A#include "base/types.hh" 627513SN/A#include "config/full_system.hh" 6311570SCurtis.Dunham@arm.com#include "config/the_isa.hh" 647513SN/A#include "debug/LLSC.hh" 658835SN/A#include "debug/MemoryAccess.hh" 667513SN/A#include "mem/packet_access.hh" 6710038SN/A#include "mem/physical.hh" 687513SN/A#include "sim/eventq.hh" 6910036SN/A 707513SN/Ausing namespace std; 717513SN/Ausing namespace TheISA; 728835SN/A 739481SN/APhysicalMemory::PhysicalMemory(const Params *p) 7410038SN/A : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 757513SN/A _size(params()->range.size()), _start(params()->range.start) 767513SN/A{ 777513SN/A if (size() % TheISA::PageBytes != 0) 787513SN/A panic("Memory Size not divisible by page size\n"); 797513SN/A 807513SN/A if (params()->null) 8111570SCurtis.Dunham@arm.com return; 8211570SCurtis.Dunham@arm.com 8311570SCurtis.Dunham@arm.com 8411570SCurtis.Dunham@arm.com if (params()->file == "") { 858835SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 867513SN/A pmemAddr = (uint8_t *)mmap(NULL, size(), 879885SN/A PROT_READ | PROT_WRITE, map_flags, -1, 0); 8810315SN/A } else { 899481SN/A int map_flags = MAP_PRIVATE; 9011960Sgabeblack@google.com int fd = open(params()->file.c_str(), O_RDONLY); 917513SN/A _size = lseek(fd, 0, SEEK_END); 927513SN/A lseek(fd, 0, SEEK_SET); 937513SN/A pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 947513SN/A PROT_READ | PROT_WRITE, map_flags, fd, 0); 957513SN/A } 967513SN/A 977513SN/A if (pmemAddr == (void *)MAP_FAILED) { 9811066Snilay@cs.wisc.edu perror("mmap"); 999885SN/A if (params()->file == "") 10011960Sgabeblack@google.com fatal("Could not mmap!\n"); 1017513SN/A else 1029885SN/A fatal("Could not find file: %s\n", params()->file); 10311219Snilay@cs.wisc.edu } 10411960Sgabeblack@google.com 10511570SCurtis.Dunham@arm.com //If requested, initialize all the memory to 0 10611066Snilay@cs.wisc.edu if (p->zero) 10710036SN/A memset(pmemAddr, 0, size()); 10811066Snilay@cs.wisc.edu} 1097513SN/A 1109481SN/Avoid 11111570SCurtis.Dunham@arm.comPhysicalMemory::init() 11211570SCurtis.Dunham@arm.com{ 11311570SCurtis.Dunham@arm.com if (ports.size() == 0) { 11411570SCurtis.Dunham@arm.com fatal("PhysicalMemory object %s is unconnected!", name()); 1157513SN/A } 1168835SN/A 1179481SN/A for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 11810036SN/A if (*pi) 1197513SN/A (*pi)->sendRangeChange(); 1208835SN/A } 12111960Sgabeblack@google.com} 1229885SN/A 1239481SN/APhysicalMemory::~PhysicalMemory() 1247513SN/A{ 12511219Snilay@cs.wisc.edu if (pmemAddr) 1267513SN/A munmap((char*)pmemAddr, size()); 1278893SN/A} 1287513SN/A 1299885SN/Avoid 1309885SN/APhysicalMemory::regStats() 1319885SN/A{ 1329885SN/A using namespace Stats; 1339885SN/A 13411960Sgabeblack@google.com bytesRead 13511570SCurtis.Dunham@arm.com .name(name() + ".bytes_read") 13610036SN/A .desc("Number of bytes read from this memory") 13711570SCurtis.Dunham@arm.com ; 13811570SCurtis.Dunham@arm.com bytesInstRead 13911570SCurtis.Dunham@arm.com .name(name() + ".bytes_inst_read") 14011570SCurtis.Dunham@arm.com .desc("Number of instructions bytes read from this memory") 14110036SN/A ; 1429885SN/A bytesWritten 14311960Sgabeblack@google.com .name(name() + ".bytes_written") 1449885SN/A .desc("Number of bytes written to this memory") 14510038SN/A ; 14610038SN/A numReads 14710038SN/A .name(name() + ".num_reads") 14810038SN/A .desc("Number of read requests responded to by this memory") 14910038SN/A ; 15011066Snilay@cs.wisc.edu numWrites 15110038SN/A .name(name() + ".num_writes") 15210038SN/A .desc("Number of write requests responded to by this memory") 15310038SN/A ; 15410038SN/A numOther 15510038SN/A .name(name() + ".num_other") 15610038SN/A .desc("Number of other requests responded to by this memory") 15710038SN/A ; 15810038SN/A bwRead 15910038SN/A .name(name() + ".bw_read") 16010038SN/A .desc("Total read bandwidth from this memory (bytes/s)") 16110038SN/A .precision(0) 16210038SN/A .prereq(bytesRead) 16310038SN/A ; 16411570SCurtis.Dunham@arm.com bwInstRead 16510038SN/A .name(name() + ".bw_inst_read") 16610038SN/A .desc("Instruction read bandwidth from this memory (bytes/s)") 16710038SN/A .precision(0) 16811570SCurtis.Dunham@arm.com .prereq(bytesInstRead) 16911570SCurtis.Dunham@arm.com ; 17011570SCurtis.Dunham@arm.com bwWrite 17111570SCurtis.Dunham@arm.com .name(name() + ".bw_write") 17210038SN/A .desc("Write bandwidth from this memory (bytes/s)") 17310038SN/A .precision(0) 1747513SN/A .prereq(bytesWritten) 1757513SN/A ; 1768835SN/A bwTotal 17710036SN/A .name(name() + ".bw_total") 17810038SN/A .desc("Total bandwidth to/from this memory (bytes/s)") 1797513SN/A .precision(0) 1808835SN/A .prereq(bwTotal) 1818835SN/A ; 1828835SN/A bwRead = bytesRead / simSeconds; 1838835SN/A bwInstRead = bytesInstRead / simSeconds; 1849885SN/A bwWrite = bytesWritten / simSeconds; 18511570SCurtis.Dunham@arm.com bwTotal = (bytesRead + bytesWritten) / simSeconds; 18610036SN/A} 18710038SN/A 1889265SN/Aunsigned 18911570SCurtis.Dunham@arm.comPhysicalMemory::deviceBlockSize() const 19011570SCurtis.Dunham@arm.com{ 19111570SCurtis.Dunham@arm.com //Can accept anysize request 19211570SCurtis.Dunham@arm.com return 0; 1938835SN/A} 1948893SN/A 1957513SN/ATick 1967513SN/APhysicalMemory::calculateLatency(PacketPtr pkt) 19711066Snilay@cs.wisc.edu{ 1989885SN/A Tick latency = lat; 19911960Sgabeblack@google.com if (lat_var != 0) 2007513SN/A latency += random_mt.random<Tick>(0, lat_var); 2019885SN/A return latency; 20211219Snilay@cs.wisc.edu} 20311960Sgabeblack@google.com 20411570SCurtis.Dunham@arm.com 20511066Snilay@cs.wisc.edu 20610036SN/A// Add load-locked to tracking list. Should only be called if the 20711066Snilay@cs.wisc.edu// operation is a load and the LLSC flag is set. 2087513SN/Avoid 2099481SN/APhysicalMemory::trackLoadLocked(PacketPtr pkt) 21011570SCurtis.Dunham@arm.com{ 21111570SCurtis.Dunham@arm.com Request *req = pkt->req; 21211570SCurtis.Dunham@arm.com Addr paddr = LockedAddr::mask(req->getPaddr()); 21311570SCurtis.Dunham@arm.com 2147513SN/A // first we check if we already have a locked addr for this 2158835SN/A // xc. Since each xc only gets one, we just update the 2169481SN/A // existing record with the new address. 21710036SN/A list<LockedAddr>::iterator i; 2187513SN/A 2198835SN/A for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 22011960Sgabeblack@google.com if (i->matchesContext(req)) { 2219885SN/A DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 2229481SN/A req->contextId(), paddr); 2237513SN/A i->addr = paddr; 22411219Snilay@cs.wisc.edu return; 2257513SN/A } 2268893SN/A } 2277513SN/A 2289885SN/A // no record for this xc: need to allocate a new one 2299885SN/A DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 2309885SN/A req->contextId(), paddr); 2319885SN/A lockedAddrList.push_front(LockedAddr(req)); 2329885SN/A} 23311960Sgabeblack@google.com 23411570SCurtis.Dunham@arm.com 23510036SN/A// Called on *writes* only... both regular stores and 23611570SCurtis.Dunham@arm.com// store-conditional operations. Check for conventional stores which 23711570SCurtis.Dunham@arm.com// conflict with locked addresses, and for success/failure of store 23811570SCurtis.Dunham@arm.com// conditionals. 23911570SCurtis.Dunham@arm.combool 24010036SN/APhysicalMemory::checkLockedAddrList(PacketPtr pkt) 2419885SN/A{ 24211960Sgabeblack@google.com Request *req = pkt->req; 2439885SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 2448835SN/A bool isLLSC = pkt->isLLSC(); 2458835SN/A 24610036SN/A // Initialize return value. Non-conditional stores always 2478835SN/A // succeed. Assume conditional stores will fail until proven 2489481SN/A // otherwise. 2499481SN/A bool success = !isLLSC; 25011219Snilay@cs.wisc.edu 25110036SN/A // Iterate over list. Note that there could be multiple matching 2529481SN/A // records, as more than one context could have done a load locked 25310038SN/A // to this location. 25410038SN/A list<LockedAddr>::iterator i = lockedAddrList.begin(); 25510038SN/A 25610038SN/A while (i != lockedAddrList.end()) { 25710038SN/A 25810038SN/A if (i->addr == paddr) { 25910038SN/A // we have a matching address 26010038SN/A 2619481SN/A if (isLLSC && i->matchesContext(req)) { 2629481SN/A // it's a store conditional, and as far as the memory 2639481SN/A // system can tell, the requesting context's lock is 2649481SN/A // still valid. 2659481SN/A DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 2669481SN/A req->contextId(), paddr); 26710038SN/A success = true; 2689481SN/A } 2699481SN/A 27010038SN/A // Get rid of our record of this lock and advance to next 27110038SN/A DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 27211066Snilay@cs.wisc.edu i->contextId, paddr); 27310038SN/A i = lockedAddrList.erase(i); 27410038SN/A } 27510038SN/A else { 27610038SN/A // no match: advance to next record 27710038SN/A ++i; 27810038SN/A } 27910038SN/A } 28011066Snilay@cs.wisc.edu 28110038SN/A if (isLLSC) { 28210038SN/A req->setExtraData(success ? 1 : 0); 28310038SN/A } 28410038SN/A 28510038SN/A return success; 28610038SN/A} 28710038SN/A 28810038SN/A 28910038SN/A#if TRACING_ON 29010038SN/A 29110038SN/A#define CASE(A, T) \ 29210038SN/A case sizeof(T): \ 29310038SN/A DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 29411570SCurtis.Dunham@arm.com A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 29510038SN/A break 29610038SN/A 29710038SN/A 29811570SCurtis.Dunham@arm.com#define TRACE_PACKET(A) \ 29911570SCurtis.Dunham@arm.com do { \ 30011570SCurtis.Dunham@arm.com switch (pkt->getSize()) { \ 30111570SCurtis.Dunham@arm.com CASE(A, uint64_t); \ 30210038SN/A CASE(A, uint32_t); \ 3039481SN/A CASE(A, uint16_t); \ 3047513SN/A CASE(A, uint8_t); \ 3057513SN/A default: \ 3068835SN/A DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 30710036SN/A A, pkt->getSize(), pkt->getAddr()); \ 30810038SN/A DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 3097513SN/A } \ 3108835SN/A } while (0) 3118835SN/A 3128835SN/A#else 3138835SN/A 3149885SN/A#define TRACE_PACKET(A) 31511570SCurtis.Dunham@arm.com 31610036SN/A#endif 31710038SN/A 3189265SN/ATick 31911570SCurtis.Dunham@arm.comPhysicalMemory::doAtomicAccess(PacketPtr pkt) 32011570SCurtis.Dunham@arm.com{ 32111570SCurtis.Dunham@arm.com assert(pkt->getAddr() >= start() && 32211570SCurtis.Dunham@arm.com pkt->getAddr() + pkt->getSize() <= start() + size()); 3238835SN/A 3248893SN/A if (pkt->memInhibitAsserted()) { 3257513SN/A DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 3267513SN/A pkt->getAddr()); 32711066Snilay@cs.wisc.edu return 0; 3289885SN/A } 32911960Sgabeblack@google.com 3309481SN/A uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3319885SN/A 33211219Snilay@cs.wisc.edu if (pkt->cmd == MemCmd::SwapReq) { 33311960Sgabeblack@google.com IntReg overwrite_val; 33411570SCurtis.Dunham@arm.com bool overwrite_mem; 33511066Snilay@cs.wisc.edu uint64_t condition_val64; 33610036SN/A uint32_t condition_val32; 33711066Snilay@cs.wisc.edu 3387513SN/A if (!pmemAddr) 3399481SN/A panic("Swap only works if there is real memory (i.e. null=False)"); 34011570SCurtis.Dunham@arm.com assert(sizeof(IntReg) >= pkt->getSize()); 34111570SCurtis.Dunham@arm.com 34211570SCurtis.Dunham@arm.com overwrite_mem = true; 34311570SCurtis.Dunham@arm.com // keep a copy of our possible write value, and copy what is at the 3447513SN/A // memory address into the packet 3458835SN/A std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 3469481SN/A std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 34710036SN/A 3487513SN/A if (pkt->req->isCondSwap()) { 3498835SN/A if (pkt->getSize() == sizeof(uint64_t)) { 35011960Sgabeblack@google.com condition_val64 = pkt->req->getExtraData(); 3519885SN/A overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 3529481SN/A sizeof(uint64_t)); 3537513SN/A } else if (pkt->getSize() == sizeof(uint32_t)) { 35411219Snilay@cs.wisc.edu condition_val32 = (uint32_t)pkt->req->getExtraData(); 3558893SN/A overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 3568893SN/A sizeof(uint32_t)); 3577513SN/A } else 3589885SN/A panic("Invalid size for conditional read/write\n"); 3599885SN/A } 3609885SN/A 3619885SN/A if (overwrite_mem) 3629885SN/A std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 36311960Sgabeblack@google.com 36411570SCurtis.Dunham@arm.com assert(!pkt->req->isInstFetch()); 36510036SN/A TRACE_PACKET("Read/Write"); 36611570SCurtis.Dunham@arm.com numOther++; 36711570SCurtis.Dunham@arm.com } else if (pkt->isRead()) { 36811570SCurtis.Dunham@arm.com assert(!pkt->isWrite()); 36911570SCurtis.Dunham@arm.com if (pkt->isLLSC()) { 37010036SN/A trackLoadLocked(pkt); 3719885SN/A } 37211960Sgabeblack@google.com if (pmemAddr) 3739885SN/A memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3747513SN/A TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 37510451SN/A numReads++; 37611219Snilay@cs.wisc.edu bytesRead += pkt->getSize(); 3779885SN/A if (pkt->req->isInstFetch()) 37811570SCurtis.Dunham@arm.com bytesInstRead += pkt->getSize(); 37910036SN/A } else if (pkt->isWrite()) { 38011066Snilay@cs.wisc.edu if (writeOK(pkt)) { 38111066Snilay@cs.wisc.edu if (pmemAddr) 38211570SCurtis.Dunham@arm.com memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 38311570SCurtis.Dunham@arm.com assert(!pkt->req->isInstFetch()); 38411570SCurtis.Dunham@arm.com TRACE_PACKET("Write"); 38511440SCurtis.Dunham@arm.com numWrites++; 38611570SCurtis.Dunham@arm.com bytesWritten += pkt->getSize(); 38711066Snilay@cs.wisc.edu } 38811219Snilay@cs.wisc.edu } else if (pkt->isInvalidate()) { 38911066Snilay@cs.wisc.edu //upgrade or invalidate 3909885SN/A if (pkt->needsResponse()) { 3917524SN/A pkt->makeAtomicResponse(); 3929481SN/A } 3938893SN/A } else { 39411066Snilay@cs.wisc.edu panic("unimplemented"); 3957513SN/A } 39611219Snilay@cs.wisc.edu 39711219Snilay@cs.wisc.edu if (pkt->needsResponse()) { 39811219Snilay@cs.wisc.edu pkt->makeAtomicResponse(); 39911219Snilay@cs.wisc.edu } 40011219Snilay@cs.wisc.edu return calculateLatency(pkt); 40111219Snilay@cs.wisc.edu} 40211219Snilay@cs.wisc.edu 4037513SN/A 4047513SN/Avoid 40510036SN/APhysicalMemory::doFunctionalAccess(PacketPtr pkt) 4067513SN/A{ 4077513SN/A assert(pkt->getAddr() >= start() && 40811960Sgabeblack@google.com pkt->getAddr() + pkt->getSize() <= start() + size()); 4097513SN/A 41011066Snilay@cs.wisc.edu 41111066Snilay@cs.wisc.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 4127513SN/A 4137513SN/A if (pkt->isRead()) { 4147513SN/A if (pmemAddr) 4157513SN/A memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 41610036SN/A TRACE_PACKET("Read"); 41711960Sgabeblack@google.com pkt->makeAtomicResponse(); 4187513SN/A } else if (pkt->isWrite()) { 41911960Sgabeblack@google.com if (pmemAddr) 42011066Snilay@cs.wisc.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 42111960Sgabeblack@google.com TRACE_PACKET("Write"); 4227513SN/A pkt->makeAtomicResponse(); 42311960Sgabeblack@google.com } else if (pkt->isPrint()) { 4247513SN/A Packet::PrintReqState *prs = 42511960Sgabeblack@google.com dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 4267513SN/A // Need to call printLabels() explicitly since we're not going 4277513SN/A // through printObj(). 4287513SN/A prs->printLabels(); 42910451SN/A // Right now we just print the single byte at the specified address. 4307513SN/A ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 4319885SN/A } else { 4329885SN/A panic("PhysicalMemory: unimplemented functional command %s", 4339885SN/A pkt->cmdString()); 43410315SN/A } 43510036SN/A} 43610315SN/A 4379885SN/A 4389885SN/APort * 43910315SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 44010315SN/A{ 44110315SN/A if (if_name != "port") { 44210315SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 44310315SN/A } 44410315SN/A 44510315SN/A if (idx >= (int)ports.size()) { 44610315SN/A ports.resize(idx + 1); 4477513SN/A } 44810451SN/A 44911960Sgabeblack@google.com if (ports[idx] != NULL) { 4509885SN/A panic("PhysicalMemory::getPort: port %d already assigned", idx); 45111570SCurtis.Dunham@arm.com } 45210036SN/A 45311066Snilay@cs.wisc.edu MemoryPort *port = 45411066Snilay@cs.wisc.edu new MemoryPort(csprintf("%s-port%d", name(), idx), this); 45511570SCurtis.Dunham@arm.com 45611570SCurtis.Dunham@arm.com ports[idx] = port; 45711570SCurtis.Dunham@arm.com return port; 45811440SCurtis.Dunham@arm.com} 45911570SCurtis.Dunham@arm.com 46011066Snilay@cs.wisc.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 46111960Sgabeblack@google.com PhysicalMemory *_memory) 46211066Snilay@cs.wisc.edu : SimpleTimingPort(_name, _memory), memory(_memory) 4639885SN/A{ } 4647524SN/A 46511066Snilay@cs.wisc.eduvoid 4669265SN/APhysicalMemory::MemoryPort::recvRangeChange() 4678893SN/A{ 4687513SN/A // memory is a slave and thus should never have to worry about its 46911960Sgabeblack@google.com // neighbours address ranges 47011960Sgabeblack@google.com} 47111960Sgabeblack@google.com 47211960Sgabeblack@google.comAddrRangeList 47311960Sgabeblack@google.comPhysicalMemory::MemoryPort::getAddrRanges() 47411960Sgabeblack@google.com{ 47511960Sgabeblack@google.com return memory->getAddrRanges(); 4767513SN/A} 4778983SN/A 4789265SN/AAddrRangeList 4799885SN/APhysicalMemory::getAddrRanges() 4809885SN/A{ 48111570SCurtis.Dunham@arm.com AddrRangeList ranges; 48210036SN/A ranges.push_back(RangeSize(start(), size())); 4838983SN/A return ranges; 48411960Sgabeblack@google.com} 4857513SN/A 4867513SN/Aunsigned 4877513SN/APhysicalMemory::MemoryPort::deviceBlockSize() const 48811570SCurtis.Dunham@arm.com{ 48911570SCurtis.Dunham@arm.com return memory->deviceBlockSize(); 49011570SCurtis.Dunham@arm.com} 49111570SCurtis.Dunham@arm.com 49211960Sgabeblack@google.comTick 4938893SN/APhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4947513SN/A{ 4959885SN/A return memory->doAtomicAccess(pkt); 4969885SN/A} 49710036SN/A 4989885SN/Avoid 4999885SN/APhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 500{ 501 pkt->pushLabel(memory->name()); 502 503 if (!checkFunctional(pkt)) { 504 // Default implementation of SimpleTimingPort::recvFunctional() 505 // calls recvAtomic() and throws away the latency; we can save a 506 // little here by just not calculating the latency. 507 memory->doFunctionalAccess(pkt); 508 } 509 510 pkt->popLabel(); 511} 512 513unsigned int 514PhysicalMemory::drain(Event *de) 515{ 516 int count = 0; 517 for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 518 count += (*pi)->drain(de); 519 } 520 521 if (count) 522 changeState(Draining); 523 else 524 changeState(Drained); 525 return count; 526} 527 528void 529PhysicalMemory::serialize(ostream &os) 530{ 531 if (!pmemAddr) 532 return; 533 534 gzFile compressedMem; 535 string filename = name() + ".physmem"; 536 537 SERIALIZE_SCALAR(filename); 538 SERIALIZE_SCALAR(_size); 539 540 // write memory file 541 string thefile = Checkpoint::dir() + "/" + filename.c_str(); 542 int fd = creat(thefile.c_str(), 0664); 543 if (fd < 0) { 544 perror("creat"); 545 fatal("Can't open physical memory checkpoint file '%s'\n", filename); 546 } 547 548 compressedMem = gzdopen(fd, "wb"); 549 if (compressedMem == NULL) 550 fatal("Insufficient memory to allocate compression state for %s\n", 551 filename); 552 553 if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 554 fatal("Write failed on physical memory checkpoint file '%s'\n", 555 filename); 556 } 557 558 if (gzclose(compressedMem)) 559 fatal("Close failed on physical memory checkpoint file '%s'\n", 560 filename); 561 562 list<LockedAddr>::iterator i = lockedAddrList.begin(); 563 564 vector<Addr> lal_addr; 565 vector<int> lal_cid; 566 while (i != lockedAddrList.end()) { 567 lal_addr.push_back(i->addr); 568 lal_cid.push_back(i->contextId); 569 i++; 570 } 571 arrayParamOut(os, "lal_addr", lal_addr); 572 arrayParamOut(os, "lal_cid", lal_cid); 573} 574 575void 576PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 577{ 578 if (!pmemAddr) 579 return; 580 581 gzFile compressedMem; 582 long *tempPage; 583 long *pmem_current; 584 uint64_t curSize; 585 uint32_t bytesRead; 586 const uint32_t chunkSize = 16384; 587 588 string filename; 589 590 UNSERIALIZE_SCALAR(filename); 591 592 filename = cp->cptDir + "/" + filename; 593 594 // mmap memoryfile 595 int fd = open(filename.c_str(), O_RDONLY); 596 if (fd < 0) { 597 perror("open"); 598 fatal("Can't open physical memory checkpoint file '%s'", filename); 599 } 600 601 compressedMem = gzdopen(fd, "rb"); 602 if (compressedMem == NULL) 603 fatal("Insufficient memory to allocate compression state for %s\n", 604 filename); 605 606 // unmap file that was mmapped in the constructor 607 // This is done here to make sure that gzip and open don't muck with our 608 // nice large space of memory before we reallocate it 609 munmap((char*)pmemAddr, size()); 610 611 UNSERIALIZE_SCALAR(_size); 612 if (size() > params()->range.size()) 613 fatal("Memory size has changed! size %lld, param size %lld\n", 614 size(), params()->range.size()); 615 616 pmemAddr = (uint8_t *)mmap(NULL, size(), 617 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 618 619 if (pmemAddr == (void *)MAP_FAILED) { 620 perror("mmap"); 621 fatal("Could not mmap physical memory!\n"); 622 } 623 624 curSize = 0; 625 tempPage = (long*)malloc(chunkSize); 626 if (tempPage == NULL) 627 fatal("Unable to malloc memory to read file %s\n", filename); 628 629 /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 630 while (curSize < size()) { 631 bytesRead = gzread(compressedMem, tempPage, chunkSize); 632 if (bytesRead == 0) 633 break; 634 635 assert(bytesRead % sizeof(long) == 0); 636 637 for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 638 { 639 if (*(tempPage+x) != 0) { 640 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 641 *pmem_current = *(tempPage+x); 642 } 643 } 644 curSize += bytesRead; 645 } 646 647 free(tempPage); 648 649 if (gzclose(compressedMem)) 650 fatal("Close failed on physical memory checkpoint file '%s'\n", 651 filename); 652 653 vector<Addr> lal_addr; 654 vector<int> lal_cid; 655 arrayParamIn(cp, section, "lal_addr", lal_addr); 656 arrayParamIn(cp, section, "lal_cid", lal_cid); 657 for(int i = 0; i < lal_addr.size(); i++) 658 lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 659} 660 661PhysicalMemory * 662PhysicalMemoryParams::create() 663{ 664 return new PhysicalMemory(this); 665} 666