abstract_mem.cc revision 8636
12623SN/A/* 22623SN/A * Copyright (c) 2010 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 152623SN/A * All rights reserved. 162623SN/A * 172623SN/A * Redistribution and use in source and binary forms, with or without 182623SN/A * modification, are permitted provided that the following conditions are 192623SN/A * met: redistributions of source code must retain the above copyright 202623SN/A * notice, this list of conditions and the following disclaimer; 212623SN/A * redistributions in binary form must reproduce the above copyright 222623SN/A * notice, this list of conditions and the following disclaimer in the 232623SN/A * documentation and/or other materials provided with the distribution; 242623SN/A * neither the name of the copyright holders nor the names of its 252623SN/A * contributors may be used to endorse or promote products derived from 262623SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313170Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323806Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344040Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373348Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383348Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394762Snate@binkert.org * 402901Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 412623SN/A * Ali Saidi 422623SN/A */ 432623SN/A 442623SN/A#include <sys/mman.h> 452623SN/A#include <sys/types.h> 465606Snate@binkert.org#include <sys/user.h> 472623SN/A#include <fcntl.h> 482623SN/A#include <unistd.h> 492623SN/A#include <zlib.h> 502623SN/A 512623SN/A#include <cerrno> 522623SN/A#include <cstdio> 532623SN/A#include <iostream> 542623SN/A#include <string> 552623SN/A 562623SN/A#include "arch/isa_traits.hh" 572623SN/A#include "arch/registers.hh" 585336Shines@cs.fsu.edu#include "base/intmath.hh" 592623SN/A#include "base/misc.hh" 604873Sstever@eecs.umich.edu#include "base/random.hh" 612623SN/A#include "base/types.hh" 622623SN/A#include "config/full_system.hh" 632856Srdreslin@umich.edu#include "config/the_isa.hh" 642856Srdreslin@umich.edu#include "debug/LLSC.hh" 652856Srdreslin@umich.edu#include "debug/MemoryAccess.hh" 662856Srdreslin@umich.edu#include "mem/packet_access.hh" 672856Srdreslin@umich.edu#include "mem/physical.hh" 682856Srdreslin@umich.edu#include "sim/eventq.hh" 692856Srdreslin@umich.edu 704968Sacolyte@umich.eduusing namespace std; 714968Sacolyte@umich.eduusing namespace TheISA; 724968Sacolyte@umich.edu 734968Sacolyte@umich.eduPhysicalMemory::PhysicalMemory(const Params *p) 742856Srdreslin@umich.edu : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 752856Srdreslin@umich.edu _size(params()->range.size()), _start(params()->range.start) 762856Srdreslin@umich.edu{ 772623SN/A if (size() % TheISA::PageBytes != 0) 782623SN/A panic("Memory Size not divisible by page size\n"); 792623SN/A 802623SN/A if (params()->null) 812623SN/A return; 825310Ssaidi@eecs.umich.edu 832623SN/A 842680Sktlim@umich.edu if (params()->file == "") { 852680Sktlim@umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 862623SN/A pmemAddr = (uint8_t *)mmap(NULL, size(), 872623SN/A PROT_READ | PROT_WRITE, map_flags, -1, 0); 885310Ssaidi@eecs.umich.edu } else { 892623SN/A int map_flags = MAP_PRIVATE; 902623SN/A int fd = open(params()->file.c_str(), O_RDONLY); 914968Sacolyte@umich.edu _size = lseek(fd, 0, SEEK_END); 924968Sacolyte@umich.edu lseek(fd, 0, SEEK_SET); 934968Sacolyte@umich.edu pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 944968Sacolyte@umich.edu PROT_READ | PROT_WRITE, map_flags, fd, 0); 954968Sacolyte@umich.edu } 964968Sacolyte@umich.edu 975310Ssaidi@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 985310Ssaidi@eecs.umich.edu perror("mmap"); 995310Ssaidi@eecs.umich.edu if (params()->file == "") 1002623SN/A fatal("Could not mmap!\n"); 1012623SN/A else 1022623SN/A fatal("Could not find file: %s\n", params()->file); 1033349Sbinkertn@umich.edu } 1042623SN/A 1053184Srdreslin@umich.edu //If requested, initialize all the memory to 0 1062623SN/A if (p->zero) 1072623SN/A memset(pmemAddr, 0, size()); 1082623SN/A} 1092623SN/A 1103349Sbinkertn@umich.eduvoid 1112623SN/APhysicalMemory::init() 1123310Srdreslin@umich.edu{ 1133649Srdreslin@umich.edu if (ports.size() == 0) { 1142623SN/A fatal("PhysicalMemory object %s is unconnected!", name()); 1152623SN/A } 1162623SN/A 1173349Sbinkertn@umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 1182623SN/A if (*pi) 1193184Srdreslin@umich.edu (*pi)->sendStatusChange(Port::RangeChange); 1203184Srdreslin@umich.edu } 1212623SN/A} 1222623SN/A 1232623SN/APhysicalMemory::~PhysicalMemory() 1242623SN/A{ 1252623SN/A if (pmemAddr) 1263647Srdreslin@umich.edu munmap((char*)pmemAddr, size()); 1273647Srdreslin@umich.edu} 1283647Srdreslin@umich.edu 1293647Srdreslin@umich.eduunsigned 1303647Srdreslin@umich.eduPhysicalMemory::deviceBlockSize() const 1312626SN/A{ 1323647Srdreslin@umich.edu //Can accept anysize request 1332626SN/A return 0; 1342623SN/A} 1352623SN/A 1362623SN/ATick 1372657Ssaidi@eecs.umich.eduPhysicalMemory::calculateLatency(PacketPtr pkt) 1382623SN/A{ 1392623SN/A Tick latency = lat; 1402623SN/A if (lat_var != 0) 1412623SN/A latency += random_mt.random<Tick>(0, lat_var); 1422623SN/A return latency; 1434192Sktlim@umich.edu} 1444192Sktlim@umich.edu 1454192Sktlim@umich.edu 1464192Sktlim@umich.edu 1474192Sktlim@umich.edu// Add load-locked to tracking list. Should only be called if the 1484192Sktlim@umich.edu// operation is a load and the LLSC flag is set. 1494192Sktlim@umich.eduvoid 1504192Sktlim@umich.eduPhysicalMemory::trackLoadLocked(PacketPtr pkt) 1515497Ssaidi@eecs.umich.edu{ 1524192Sktlim@umich.edu Request *req = pkt->req; 1534192Sktlim@umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1542623SN/A 1555529Snate@binkert.org // first we check if we already have a locked addr for this 1565487Snate@binkert.org // xc. Since each xc only gets one, we just update the 1575487Snate@binkert.org // existing record with the new address. 1585487Snate@binkert.org list<LockedAddr>::iterator i; 1594968Sacolyte@umich.edu 1604968Sacolyte@umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1612623SN/A if (i->matchesContext(req)) { 1622623SN/A DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 1632623SN/A req->contextId(), paddr); 1643647Srdreslin@umich.edu i->addr = paddr; 1653647Srdreslin@umich.edu return; 1663647Srdreslin@umich.edu } 1672623SN/A } 1682623SN/A 1692623SN/A // no record for this xc: need to allocate a new one 1702623SN/A DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 1712623SN/A req->contextId(), paddr); 1722623SN/A lockedAddrList.push_front(LockedAddr(req)); 1732623SN/A} 1742623SN/A 1752623SN/A 1762623SN/A// Called on *writes* only... both regular stores and 1772915Sktlim@umich.edu// store-conditional operations. Check for conventional stores which 1782915Sktlim@umich.edu// conflict with locked addresses, and for success/failure of store 1793145Shsul@eecs.umich.edu// conditionals. 1802623SN/Abool 1812623SN/APhysicalMemory::checkLockedAddrList(PacketPtr pkt) 1822623SN/A{ 1832623SN/A Request *req = pkt->req; 1842623SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1852623SN/A bool isLLSC = pkt->isLLSC(); 1862623SN/A 1872915Sktlim@umich.edu // Initialize return value. Non-conditional stores always 1882915Sktlim@umich.edu // succeed. Assume conditional stores will fail until proven 1893145Shsul@eecs.umich.edu // otherwise. 1902915Sktlim@umich.edu bool success = !isLLSC; 1912915Sktlim@umich.edu 1922915Sktlim@umich.edu // Iterate over list. Note that there could be multiple matching 1932915Sktlim@umich.edu // records, as more than one context could have done a load locked 1942915Sktlim@umich.edu // to this location. 1952915Sktlim@umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 1965220Ssaidi@eecs.umich.edu 1975220Ssaidi@eecs.umich.edu while (i != lockedAddrList.end()) { 1985220Ssaidi@eecs.umich.edu 1994940Snate@binkert.org if (i->addr == paddr) { 2005220Ssaidi@eecs.umich.edu // we have a matching address 2013324Shsul@eecs.umich.edu 2025220Ssaidi@eecs.umich.edu if (isLLSC && i->matchesContext(req)) { 2035220Ssaidi@eecs.umich.edu // it's a store conditional, and as far as the memory 2045606Snate@binkert.org // system can tell, the requesting context's lock is 2055606Snate@binkert.org // still valid. 2062915Sktlim@umich.edu DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 2072623SN/A req->contextId(), paddr); 2082623SN/A success = true; 2092623SN/A } 2102798Sktlim@umich.edu 2112623SN/A // Get rid of our record of this lock and advance to next 2125496Ssaidi@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 2132798Sktlim@umich.edu i->contextId, paddr); 2142623SN/A i = lockedAddrList.erase(i); 2152798Sktlim@umich.edu } 2162623SN/A else { 2172623SN/A // no match: advance to next record 2182623SN/A ++i; 2192623SN/A } 2202623SN/A } 2212623SN/A 2224192Sktlim@umich.edu if (isLLSC) { 2232623SN/A req->setExtraData(success ? 1 : 0); 2242623SN/A } 2252623SN/A 2262680Sktlim@umich.edu return success; 2272623SN/A} 2282680Sktlim@umich.edu 2292680Sktlim@umich.edu 2302680Sktlim@umich.edu#if TRACING_ON 2312623SN/A 2325606Snate@binkert.org#define CASE(A, T) \ 2332623SN/A case sizeof(T): \ 2342623SN/A DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 2352623SN/A A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2363512Sktlim@umich.edu break 2373512Sktlim@umich.edu 2383512Sktlim@umich.edu 2395169Ssaidi@eecs.umich.edu#define TRACE_PACKET(A) \ 2405169Ssaidi@eecs.umich.edu do { \ 2415310Ssaidi@eecs.umich.edu switch (pkt->getSize()) { \ 2425310Ssaidi@eecs.umich.edu CASE(A, uint64_t); \ 2435310Ssaidi@eecs.umich.edu CASE(A, uint32_t); \ 2442623SN/A CASE(A, uint16_t); \ 2452623SN/A CASE(A, uint8_t); \ 2462623SN/A default: \ 2472623SN/A DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 2482623SN/A A, pkt->getSize(), pkt->getAddr()); \ 2492623SN/A DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 2504940Snate@binkert.org } \ 2514940Snate@binkert.org } while (0) 2522623SN/A 2532683Sktlim@umich.edu#else 2542623SN/A 2552623SN/A#define TRACE_PACKET(A) 2562623SN/A 2572623SN/A#endif 2582623SN/A 2595101Ssaidi@eecs.umich.eduTick 2603686Sktlim@umich.eduPhysicalMemory::doAtomicAccess(PacketPtr pkt) 2613430Sgblack@eecs.umich.edu{ 2625606Snate@binkert.org assert(pkt->getAddr() >= start() && 2632623SN/A pkt->getAddr() + pkt->getSize() <= start() + size()); 2642623SN/A 2652623SN/A if (pkt->memInhibitAsserted()) { 2662623SN/A DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 2672623SN/A pkt->getAddr()); 2682623SN/A return 0; 2692623SN/A } 2704940Snate@binkert.org 2714940Snate@binkert.org uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 2722623SN/A 2732683Sktlim@umich.edu if (pkt->cmd == MemCmd::SwapReq) { 2742623SN/A IntReg overwrite_val; 2752623SN/A bool overwrite_mem; 2762626SN/A uint64_t condition_val64; 2772626SN/A uint32_t condition_val32; 2782626SN/A 2792626SN/A if (!pmemAddr) 2805606Snate@binkert.org panic("Swap only works if there is real memory (i.e. null=False)"); 2812623SN/A assert(sizeof(IntReg) >= pkt->getSize()); 2822623SN/A 2832623SN/A overwrite_mem = true; 2842623SN/A // keep a copy of our possible write value, and copy what is at the 2852623SN/A // memory address into the packet 2862623SN/A std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2872623SN/A std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2882623SN/A 2892623SN/A if (pkt->req->isCondSwap()) { 2902623SN/A if (pkt->getSize() == sizeof(uint64_t)) { 2913169Sstever@eecs.umich.edu condition_val64 = pkt->req->getExtraData(); 2924870Sstever@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 2932623SN/A sizeof(uint64_t)); 2942623SN/A } else if (pkt->getSize() == sizeof(uint32_t)) { 2952623SN/A condition_val32 = (uint32_t)pkt->req->getExtraData(); 2962623SN/A overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 2972623SN/A sizeof(uint32_t)); 2984999Sgblack@eecs.umich.edu } else 2994999Sgblack@eecs.umich.edu panic("Invalid size for conditional read/write\n"); 3004999Sgblack@eecs.umich.edu } 3014999Sgblack@eecs.umich.edu 3022623SN/A if (overwrite_mem) 3034999Sgblack@eecs.umich.edu std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 3042623SN/A 3054999Sgblack@eecs.umich.edu assert(!pkt->req->isInstFetch()); 3064999Sgblack@eecs.umich.edu TRACE_PACKET("Read/Write"); 3074999Sgblack@eecs.umich.edu } else if (pkt->isRead()) { 3084999Sgblack@eecs.umich.edu assert(!pkt->isWrite()); 3094999Sgblack@eecs.umich.edu if (pkt->isLLSC()) { 3104999Sgblack@eecs.umich.edu trackLoadLocked(pkt); 3114999Sgblack@eecs.umich.edu } 3124999Sgblack@eecs.umich.edu if (pmemAddr) 3134999Sgblack@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3144999Sgblack@eecs.umich.edu TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 3154999Sgblack@eecs.umich.edu } else if (pkt->isWrite()) { 3164999Sgblack@eecs.umich.edu if (writeOK(pkt)) { 3174999Sgblack@eecs.umich.edu if (pmemAddr) 3184999Sgblack@eecs.umich.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3194999Sgblack@eecs.umich.edu assert(!pkt->req->isInstFetch()); 3204999Sgblack@eecs.umich.edu TRACE_PACKET("Write"); 3214999Sgblack@eecs.umich.edu } 3224999Sgblack@eecs.umich.edu } else if (pkt->isInvalidate()) { 3234999Sgblack@eecs.umich.edu //upgrade or invalidate 3244999Sgblack@eecs.umich.edu if (pkt->needsResponse()) { 3254999Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3264999Sgblack@eecs.umich.edu } 3274999Sgblack@eecs.umich.edu } else { 3284999Sgblack@eecs.umich.edu panic("unimplemented"); 3294999Sgblack@eecs.umich.edu } 3304999Sgblack@eecs.umich.edu 3314999Sgblack@eecs.umich.edu if (pkt->needsResponse()) { 3324999Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3334999Sgblack@eecs.umich.edu } 3344999Sgblack@eecs.umich.edu return calculateLatency(pkt); 3354999Sgblack@eecs.umich.edu} 3365012Sgblack@eecs.umich.edu 3374999Sgblack@eecs.umich.edu 3384999Sgblack@eecs.umich.eduvoid 3394999Sgblack@eecs.umich.eduPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 3404999Sgblack@eecs.umich.edu{ 3414999Sgblack@eecs.umich.edu assert(pkt->getAddr() >= start() && 3424968Sacolyte@umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 3434986Ssaidi@eecs.umich.edu 3444999Sgblack@eecs.umich.edu 3454999Sgblack@eecs.umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3464999Sgblack@eecs.umich.edu 3474762Snate@binkert.org if (pkt->isRead()) { 3484999Sgblack@eecs.umich.edu if (pmemAddr) 3494999Sgblack@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3504999Sgblack@eecs.umich.edu TRACE_PACKET("Read"); 3514999Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3524999Sgblack@eecs.umich.edu } else if (pkt->isWrite()) { 3534999Sgblack@eecs.umich.edu if (pmemAddr) 3544999Sgblack@eecs.umich.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3555408Sgblack@eecs.umich.edu TRACE_PACKET("Write"); 3565408Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3575408Sgblack@eecs.umich.edu } else if (pkt->isPrint()) { 3584999Sgblack@eecs.umich.edu Packet::PrintReqState *prs = 3594968Sacolyte@umich.edu dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 3603170Sstever@eecs.umich.edu // Need to call printLabels() explicitly since we're not going 3614999Sgblack@eecs.umich.edu // through printObj(). 3624999Sgblack@eecs.umich.edu prs->printLabels(); 3634999Sgblack@eecs.umich.edu // Right now we just print the single byte at the specified address. 3644999Sgblack@eecs.umich.edu ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 3654999Sgblack@eecs.umich.edu } else { 3664999Sgblack@eecs.umich.edu panic("PhysicalMemory: unimplemented functional command %s", 3674999Sgblack@eecs.umich.edu pkt->cmdString()); 3684999Sgblack@eecs.umich.edu } 3694999Sgblack@eecs.umich.edu} 3704999Sgblack@eecs.umich.edu 3712623SN/A 3722623SN/APort * 3732623SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 3745177Sgblack@eecs.umich.edu{ 3755177Sgblack@eecs.umich.edu // Accept request for "functional" port for backwards compatibility 3765177Sgblack@eecs.umich.edu // with places where this function is called from C++. I'd prefer 3775177Sgblack@eecs.umich.edu // to move all these into Python someday. 3785177Sgblack@eecs.umich.edu if (if_name == "functional") { 3795177Sgblack@eecs.umich.edu return new MemoryPort(csprintf("%s-functional", name()), this); 3805177Sgblack@eecs.umich.edu } 3815177Sgblack@eecs.umich.edu 3825177Sgblack@eecs.umich.edu if (if_name != "port") { 3835177Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 3845177Sgblack@eecs.umich.edu } 3855177Sgblack@eecs.umich.edu 3865177Sgblack@eecs.umich.edu if (idx >= (int)ports.size()) { 3875177Sgblack@eecs.umich.edu ports.resize(idx + 1); 3885177Sgblack@eecs.umich.edu } 3895177Sgblack@eecs.umich.edu 3905177Sgblack@eecs.umich.edu if (ports[idx] != NULL) { 3915177Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: port %d already assigned", idx); 3925177Sgblack@eecs.umich.edu } 3935177Sgblack@eecs.umich.edu 3945177Sgblack@eecs.umich.edu MemoryPort *port = 3955177Sgblack@eecs.umich.edu new MemoryPort(csprintf("%s-port%d", name(), idx), this); 3965177Sgblack@eecs.umich.edu 3975177Sgblack@eecs.umich.edu ports[idx] = port; 3985177Sgblack@eecs.umich.edu return port; 3995177Sgblack@eecs.umich.edu} 4005177Sgblack@eecs.umich.edu 4015177Sgblack@eecs.umich.edu 4025177Sgblack@eecs.umich.eduvoid 4035177Sgblack@eecs.umich.eduPhysicalMemory::recvStatusChange(Port::Status status) 4045177Sgblack@eecs.umich.edu{ 4055177Sgblack@eecs.umich.edu} 4065177Sgblack@eecs.umich.edu 4075177Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 4085177Sgblack@eecs.umich.edu PhysicalMemory *_memory) 4095177Sgblack@eecs.umich.edu : SimpleTimingPort(_name, _memory), memory(_memory) 4105177Sgblack@eecs.umich.edu{ } 4115177Sgblack@eecs.umich.edu 4125177Sgblack@eecs.umich.eduvoid 4135177Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 4145177Sgblack@eecs.umich.edu{ 4155177Sgblack@eecs.umich.edu memory->recvStatusChange(status); 4165177Sgblack@eecs.umich.edu} 4175177Sgblack@eecs.umich.edu 4185177Sgblack@eecs.umich.eduvoid 4195177Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 4205177Sgblack@eecs.umich.edu bool &snoop) 4215177Sgblack@eecs.umich.edu{ 4225177Sgblack@eecs.umich.edu memory->getAddressRanges(resp, snoop); 4235177Sgblack@eecs.umich.edu} 4245177Sgblack@eecs.umich.edu 4255177Sgblack@eecs.umich.eduvoid 4265177Sgblack@eecs.umich.eduPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) 4275177Sgblack@eecs.umich.edu{ 4285177Sgblack@eecs.umich.edu snoop = false; 4292623SN/A resp.clear(); 4302623SN/A resp.push_back(RangeSize(start(), size())); 4312623SN/A} 4322623SN/A 4334115Ssaidi@eecs.umich.eduunsigned 4344115Ssaidi@eecs.umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() const 4354115Ssaidi@eecs.umich.edu{ 4364115Ssaidi@eecs.umich.edu return memory->deviceBlockSize(); 4374040Ssaidi@eecs.umich.edu} 4384040Ssaidi@eecs.umich.edu 4394040Ssaidi@eecs.umich.eduTick 4404040Ssaidi@eecs.umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4412623SN/A{ 4422623SN/A return memory->doAtomicAccess(pkt); 4432623SN/A} 4442623SN/A 4452623SN/Avoid 4462623SN/APhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4472623SN/A{ 4482623SN/A pkt->pushLabel(memory->name()); 4492623SN/A 4502623SN/A if (!checkFunctional(pkt)) { 4512623SN/A // Default implementation of SimpleTimingPort::recvFunctional() 4522623SN/A // calls recvAtomic() and throws away the latency; we can save a 4532623SN/A // little here by just not calculating the latency. 4542623SN/A memory->doFunctionalAccess(pkt); 4552623SN/A } 4562623SN/A 4572623SN/A pkt->popLabel(); 4582623SN/A} 4592623SN/A 4602623SN/Aunsigned int 4612623SN/APhysicalMemory::drain(Event *de) 4622623SN/A{ 4632623SN/A int count = 0; 4642623SN/A for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 4652623SN/A count += (*pi)->drain(de); 4662623SN/A } 4672623SN/A 4682623SN/A if (count) 4692623SN/A changeState(Draining); 4702623SN/A else 4712623SN/A changeState(Drained); 4722623SN/A return count; 4732623SN/A} 4742623SN/A 4752623SN/Avoid 4762623SN/APhysicalMemory::serialize(ostream &os) 4772623SN/A{ 4782623SN/A if (!pmemAddr) 4792623SN/A return; 4802623SN/A 4812623SN/A gzFile compressedMem; 4822623SN/A string filename = name() + ".physmem"; 4832623SN/A 4843169Sstever@eecs.umich.edu SERIALIZE_SCALAR(filename); 4854870Sstever@eecs.umich.edu SERIALIZE_SCALAR(_size); 4862623SN/A 4872623SN/A // write memory file 4882623SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 4892623SN/A int fd = creat(thefile.c_str(), 0664); 4902623SN/A if (fd < 0) { 4914999Sgblack@eecs.umich.edu perror("creat"); 4924999Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'\n", filename); 4934999Sgblack@eecs.umich.edu } 4944999Sgblack@eecs.umich.edu 4952623SN/A compressedMem = gzdopen(fd, "wb"); 4964999Sgblack@eecs.umich.edu if (compressedMem == NULL) 4972623SN/A fatal("Insufficient memory to allocate compression state for %s\n", 4984999Sgblack@eecs.umich.edu filename); 4994999Sgblack@eecs.umich.edu 5004999Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 5014999Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 5024999Sgblack@eecs.umich.edu filename); 5034999Sgblack@eecs.umich.edu } 5044999Sgblack@eecs.umich.edu 5054999Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 5064999Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 5074999Sgblack@eecs.umich.edu filename); 5084999Sgblack@eecs.umich.edu 5094999Sgblack@eecs.umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 5104999Sgblack@eecs.umich.edu 5114999Sgblack@eecs.umich.edu vector<Addr> lal_addr; 5124999Sgblack@eecs.umich.edu vector<int> lal_cid; 5134999Sgblack@eecs.umich.edu while (i != lockedAddrList.end()) { 5144999Sgblack@eecs.umich.edu lal_addr.push_back(i->addr); 5154999Sgblack@eecs.umich.edu lal_cid.push_back(i->contextId); 5164999Sgblack@eecs.umich.edu i++; 5174999Sgblack@eecs.umich.edu } 5184999Sgblack@eecs.umich.edu arrayParamOut(os, "lal_addr", lal_addr); 5194999Sgblack@eecs.umich.edu arrayParamOut(os, "lal_cid", lal_cid); 5204999Sgblack@eecs.umich.edu} 5214999Sgblack@eecs.umich.edu 5224999Sgblack@eecs.umich.eduvoid 5234999Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 5244999Sgblack@eecs.umich.edu{ 5254999Sgblack@eecs.umich.edu if (!pmemAddr) 5264999Sgblack@eecs.umich.edu return; 5274999Sgblack@eecs.umich.edu 5284999Sgblack@eecs.umich.edu gzFile compressedMem; 5294999Sgblack@eecs.umich.edu long *tempPage; 5304999Sgblack@eecs.umich.edu long *pmem_current; 5314999Sgblack@eecs.umich.edu uint64_t curSize; 5324999Sgblack@eecs.umich.edu uint32_t bytesRead; 5334999Sgblack@eecs.umich.edu const uint32_t chunkSize = 16384; 5344999Sgblack@eecs.umich.edu 5354999Sgblack@eecs.umich.edu string filename; 5364999Sgblack@eecs.umich.edu 5374999Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 5384999Sgblack@eecs.umich.edu 5394999Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 5404999Sgblack@eecs.umich.edu 5414999Sgblack@eecs.umich.edu // mmap memoryfile 5424999Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 5434999Sgblack@eecs.umich.edu if (fd < 0) { 5444999Sgblack@eecs.umich.edu perror("open"); 5454999Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 5464999Sgblack@eecs.umich.edu } 5474999Sgblack@eecs.umich.edu 5484999Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 5494999Sgblack@eecs.umich.edu if (compressedMem == NULL) 5504999Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 5514999Sgblack@eecs.umich.edu filename); 5524999Sgblack@eecs.umich.edu 5534999Sgblack@eecs.umich.edu // unmap file that was mmapped in the constructor 5544999Sgblack@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 5554999Sgblack@eecs.umich.edu // nice large space of memory before we reallocate it 5564999Sgblack@eecs.umich.edu munmap((char*)pmemAddr, size()); 5574878Sstever@eecs.umich.edu 5584040Ssaidi@eecs.umich.edu UNSERIALIZE_SCALAR(_size); 5594040Ssaidi@eecs.umich.edu if (size() > params()->range.size()) 5604999Sgblack@eecs.umich.edu fatal("Memory size has changed! size %lld, param size %lld\n", 5614999Sgblack@eecs.umich.edu size(), params()->range.size()); 5624999Sgblack@eecs.umich.edu 5632631SN/A pmemAddr = (uint8_t *)mmap(NULL, size(), 5644999Sgblack@eecs.umich.edu PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5654999Sgblack@eecs.umich.edu 5664999Sgblack@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 5674999Sgblack@eecs.umich.edu perror("mmap"); 5684999Sgblack@eecs.umich.edu fatal("Could not mmap physical memory!\n"); 5694999Sgblack@eecs.umich.edu } 5704999Sgblack@eecs.umich.edu 5715408Sgblack@eecs.umich.edu curSize = 0; 5725408Sgblack@eecs.umich.edu tempPage = (long*)malloc(chunkSize); 5735408Sgblack@eecs.umich.edu if (tempPage == NULL) 5744999Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 5753170Sstever@eecs.umich.edu 5763170Sstever@eecs.umich.edu /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 5774999Sgblack@eecs.umich.edu while (curSize < size()) { 5784999Sgblack@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 5794999Sgblack@eecs.umich.edu if (bytesRead == 0) 5804999Sgblack@eecs.umich.edu break; 5814999Sgblack@eecs.umich.edu 5824999Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 5834999Sgblack@eecs.umich.edu 5844999Sgblack@eecs.umich.edu for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 5854999Sgblack@eecs.umich.edu { 5864999Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 5872623SN/A pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 5882623SN/A *pmem_current = *(tempPage+x); 5892623SN/A } 5905177Sgblack@eecs.umich.edu } 5915177Sgblack@eecs.umich.edu curSize += bytesRead; 5925177Sgblack@eecs.umich.edu } 5935177Sgblack@eecs.umich.edu 5945177Sgblack@eecs.umich.edu free(tempPage); 5955177Sgblack@eecs.umich.edu 5965177Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 5975177Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 5985177Sgblack@eecs.umich.edu filename); 5995177Sgblack@eecs.umich.edu 6005177Sgblack@eecs.umich.edu vector<Addr> lal_addr; 6015177Sgblack@eecs.umich.edu vector<int> lal_cid; 6025177Sgblack@eecs.umich.edu arrayParamIn(cp, section, "lal_addr", lal_addr); 6035177Sgblack@eecs.umich.edu arrayParamIn(cp, section, "lal_cid", lal_cid); 6045177Sgblack@eecs.umich.edu for(int i = 0; i < lal_addr.size(); i++) 6055177Sgblack@eecs.umich.edu lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 6065177Sgblack@eecs.umich.edu} 6075177Sgblack@eecs.umich.edu 6085177Sgblack@eecs.umich.eduPhysicalMemory * 6095177Sgblack@eecs.umich.eduPhysicalMemoryParams::create() 6105177Sgblack@eecs.umich.edu{ 6115177Sgblack@eecs.umich.edu return new PhysicalMemory(this); 6125177Sgblack@eecs.umich.edu} 6135177Sgblack@eecs.umich.edu