abstract_mem.cc revision 6820
12221SN/A/* 22221SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 32221SN/A * All rights reserved. 42221SN/A * 52221SN/A * Redistribution and use in source and binary forms, with or without 62221SN/A * modification, are permitted provided that the following conditions are 72221SN/A * met: redistributions of source code must retain the above copyright 82221SN/A * notice, this list of conditions and the following disclaimer; 92221SN/A * redistributions in binary form must reproduce the above copyright 102221SN/A * notice, this list of conditions and the following disclaimer in the 112221SN/A * documentation and/or other materials provided with the distribution; 122221SN/A * neither the name of the copyright holders nor the names of its 132221SN/A * contributors may be used to endorse or promote products derived from 142221SN/A * this software without specific prior written permission. 152221SN/A * 162221SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192221SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202221SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212221SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222221SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232221SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242221SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252221SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262221SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu * Ali Saidi 302221SN/A */ 312221SN/A 323415Sgblack@eecs.umich.edu#include <sys/types.h> 333415Sgblack@eecs.umich.edu#include <sys/mman.h> 342223SN/A#include <errno.h> 353415Sgblack@eecs.umich.edu#include <fcntl.h> 363578Sgblack@eecs.umich.edu#include <unistd.h> 373415Sgblack@eecs.umich.edu#include <zlib.h> 383415Sgblack@eecs.umich.edu 393523Sgblack@eecs.umich.edu#include <cstdio> 403415Sgblack@eecs.umich.edu#include <iostream> 412680Sktlim@umich.edu#include <string> 422800Ssaidi@eecs.umich.edu 433523Sgblack@eecs.umich.edu#include "arch/registers.hh" 443415Sgblack@eecs.umich.edu#include "base/misc.hh" 452800Ssaidi@eecs.umich.edu#include "base/random.hh" 462800Ssaidi@eecs.umich.edu#include "base/types.hh" 472221SN/A#include "config/full_system.hh" 483415Sgblack@eecs.umich.edu#include "config/the_isa.hh" 493415Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 502223SN/A#include "mem/physical.hh" 512221SN/A#include "sim/eventq.hh" 522221SN/A 533573Sgblack@eecs.umich.eduusing namespace std; 543576Sgblack@eecs.umich.eduusing namespace TheISA; 553576Sgblack@eecs.umich.edu 562221SN/APhysicalMemory::PhysicalMemory(const Params *p) 573573Sgblack@eecs.umich.edu : MemObject(p), pmemAddr(NULL), pagePtr(0), 583576Sgblack@eecs.umich.edu lat(p->latency), lat_var(p->latency_var), 593576Sgblack@eecs.umich.edu cachedSize(params()->range.size()), cachedStart(params()->range.start) 602221SN/A{ 613573Sgblack@eecs.umich.edu if (params()->range.size() % TheISA::PageBytes != 0) 623576Sgblack@eecs.umich.edu panic("Memory Size not divisible by page size\n"); 633576Sgblack@eecs.umich.edu 642221SN/A if (params()->null) 653573Sgblack@eecs.umich.edu return; 663576Sgblack@eecs.umich.edu 673576Sgblack@eecs.umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 682221SN/A pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(), 693573Sgblack@eecs.umich.edu PROT_READ | PROT_WRITE, map_flags, -1, 0); 703576Sgblack@eecs.umich.edu 713576Sgblack@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 722221SN/A perror("mmap"); 733573Sgblack@eecs.umich.edu fatal("Could not mmap!\n"); 743576Sgblack@eecs.umich.edu } 753576Sgblack@eecs.umich.edu 762221SN/A //If requested, initialize all the memory to 0 773573Sgblack@eecs.umich.edu if (p->zero) 783576Sgblack@eecs.umich.edu memset(pmemAddr, 0, p->range.size()); 793576Sgblack@eecs.umich.edu} 803576Sgblack@eecs.umich.edu 813576Sgblack@eecs.umich.eduvoid 823576Sgblack@eecs.umich.eduPhysicalMemory::init() 833576Sgblack@eecs.umich.edu{ 843576Sgblack@eecs.umich.edu if (ports.size() == 0) { 852221SN/A fatal("PhysicalMemory object %s is unconnected!", name()); 863573Sgblack@eecs.umich.edu } 873576Sgblack@eecs.umich.edu 883576Sgblack@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 892221SN/A if (*pi) 903573Sgblack@eecs.umich.edu (*pi)->sendStatusChange(Port::RangeChange); 913576Sgblack@eecs.umich.edu } 923576Sgblack@eecs.umich.edu} 932221SN/A 943573Sgblack@eecs.umich.eduPhysicalMemory::~PhysicalMemory() 953576Sgblack@eecs.umich.edu{ 963576Sgblack@eecs.umich.edu if (pmemAddr) 973576Sgblack@eecs.umich.edu munmap((char*)pmemAddr, params()->range.size()); 983576Sgblack@eecs.umich.edu //Remove memPorts? 993576Sgblack@eecs.umich.edu} 1003576Sgblack@eecs.umich.edu 1013576Sgblack@eecs.umich.eduAddr 1023576Sgblack@eecs.umich.eduPhysicalMemory::new_page() 1033576Sgblack@eecs.umich.edu{ 1043576Sgblack@eecs.umich.edu Addr return_addr = pagePtr << LogVMPageSize; 1053576Sgblack@eecs.umich.edu return_addr += start(); 1063576Sgblack@eecs.umich.edu 1072221SN/A ++pagePtr; 1083573Sgblack@eecs.umich.edu return return_addr; 1093576Sgblack@eecs.umich.edu} 1103576Sgblack@eecs.umich.edu 1112221SN/Aunsigned 1123573Sgblack@eecs.umich.eduPhysicalMemory::deviceBlockSize() const 1133576Sgblack@eecs.umich.edu{ 1143576Sgblack@eecs.umich.edu //Can accept anysize request 1152221SN/A return 0; 1163573Sgblack@eecs.umich.edu} 1173576Sgblack@eecs.umich.edu 1183576Sgblack@eecs.umich.eduTick 1192221SN/APhysicalMemory::calculateLatency(PacketPtr pkt) 1203573Sgblack@eecs.umich.edu{ 1213576Sgblack@eecs.umich.edu Tick latency = lat; 1223576Sgblack@eecs.umich.edu if (lat_var != 0) 1232221SN/A latency += random_mt.random<Tick>(0, lat_var); 1243573Sgblack@eecs.umich.edu return latency; 1253576Sgblack@eecs.umich.edu} 1263576Sgblack@eecs.umich.edu 1272221SN/A 1283573Sgblack@eecs.umich.edu 1293576Sgblack@eecs.umich.edu// Add load-locked to tracking list. Should only be called if the 1303576Sgblack@eecs.umich.edu// operation is a load and the LLSC flag is set. 1312223SN/Avoid 1323573Sgblack@eecs.umich.eduPhysicalMemory::trackLoadLocked(PacketPtr pkt) 1333576Sgblack@eecs.umich.edu{ 1343576Sgblack@eecs.umich.edu Request *req = pkt->req; 1352223SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1363573Sgblack@eecs.umich.edu 1373576Sgblack@eecs.umich.edu // first we check if we already have a locked addr for this 1383576Sgblack@eecs.umich.edu // xc. Since each xc only gets one, we just update the 1392223SN/A // existing record with the new address. 1403573Sgblack@eecs.umich.edu list<LockedAddr>::iterator i; 1413576Sgblack@eecs.umich.edu 1423576Sgblack@eecs.umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1432223SN/A if (i->matchesContext(req)) { 1443573Sgblack@eecs.umich.edu DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 1453576Sgblack@eecs.umich.edu req->contextId(), paddr); 1463576Sgblack@eecs.umich.edu i->addr = paddr; 1473576Sgblack@eecs.umich.edu return; 1483576Sgblack@eecs.umich.edu } 1493576Sgblack@eecs.umich.edu } 1503576Sgblack@eecs.umich.edu 1513576Sgblack@eecs.umich.edu // no record for this xc: need to allocate a new one 1522223SN/A DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 1533573Sgblack@eecs.umich.edu req->contextId(), paddr); 1543576Sgblack@eecs.umich.edu lockedAddrList.push_front(LockedAddr(req)); 1553576Sgblack@eecs.umich.edu} 1562223SN/A 1573573Sgblack@eecs.umich.edu 1583576Sgblack@eecs.umich.edu// Called on *writes* only... both regular stores and 1593576Sgblack@eecs.umich.edu// store-conditional operations. Check for conventional stores which 1602223SN/A// conflict with locked addresses, and for success/failure of store 1613573Sgblack@eecs.umich.edu// conditionals. 1623576Sgblack@eecs.umich.edubool 1633576Sgblack@eecs.umich.eduPhysicalMemory::checkLockedAddrList(PacketPtr pkt) 1642223SN/A{ 1653573Sgblack@eecs.umich.edu Request *req = pkt->req; 1663576Sgblack@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1673576Sgblack@eecs.umich.edu bool isLLSC = pkt->isLLSC(); 1682223SN/A 1693573Sgblack@eecs.umich.edu // Initialize return value. Non-conditional stores always 1703576Sgblack@eecs.umich.edu // succeed. Assume conditional stores will fail until proven 1713576Sgblack@eecs.umich.edu // otherwise. 1722223SN/A bool success = !isLLSC; 1733573Sgblack@eecs.umich.edu 1743576Sgblack@eecs.umich.edu // Iterate over list. Note that there could be multiple matching 1753576Sgblack@eecs.umich.edu // records, as more than one context could have done a load locked 1762223SN/A // to this location. 1773573Sgblack@eecs.umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 1783576Sgblack@eecs.umich.edu 1793576Sgblack@eecs.umich.edu while (i != lockedAddrList.end()) { 1802223SN/A 1813573Sgblack@eecs.umich.edu if (i->addr == paddr) { 1823576Sgblack@eecs.umich.edu // we have a matching address 1833576Sgblack@eecs.umich.edu 1842223SN/A if (isLLSC && i->matchesContext(req)) { 1853573Sgblack@eecs.umich.edu // it's a store conditional, and as far as the memory 1863576Sgblack@eecs.umich.edu // system can tell, the requesting context's lock is 1873576Sgblack@eecs.umich.edu // still valid. 1882223SN/A DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 1893573Sgblack@eecs.umich.edu req->contextId(), paddr); 1903576Sgblack@eecs.umich.edu success = true; 1913576Sgblack@eecs.umich.edu } 1922223SN/A 1933576Sgblack@eecs.umich.edu // Get rid of our record of this lock and advance to next 1943576Sgblack@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 1953576Sgblack@eecs.umich.edu i->contextId, paddr); 1963576Sgblack@eecs.umich.edu i = lockedAddrList.erase(i); 1972527SN/A } 1983573Sgblack@eecs.umich.edu else { 1993576Sgblack@eecs.umich.edu // no match: advance to next record 2003890Ssaidi@eecs.umich.edu ++i; 2012223SN/A } 2023573Sgblack@eecs.umich.edu } 2033576Sgblack@eecs.umich.edu 2043576Sgblack@eecs.umich.edu if (isLLSC) { 2052223SN/A req->setExtraData(success ? 1 : 0); 2063573Sgblack@eecs.umich.edu } 2073576Sgblack@eecs.umich.edu 2083576Sgblack@eecs.umich.edu return success; 2092223SN/A} 2103573Sgblack@eecs.umich.edu 2113576Sgblack@eecs.umich.edu 2123576Sgblack@eecs.umich.edu#if TRACING_ON 2132223SN/A 2143573Sgblack@eecs.umich.edu#define CASE(A, T) \ 2153576Sgblack@eecs.umich.edu case sizeof(T): \ 2163576Sgblack@eecs.umich.edu DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 2172223SN/A A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2183573Sgblack@eecs.umich.edu break 2193576Sgblack@eecs.umich.edu 2203576Sgblack@eecs.umich.edu 2213576Sgblack@eecs.umich.edu#define TRACE_PACKET(A) \ 2223576Sgblack@eecs.umich.edu do { \ 2233576Sgblack@eecs.umich.edu switch (pkt->getSize()) { \ 2243576Sgblack@eecs.umich.edu CASE(A, uint64_t); \ 2253576Sgblack@eecs.umich.edu CASE(A, uint32_t); \ 2263576Sgblack@eecs.umich.edu CASE(A, uint16_t); \ 2273576Sgblack@eecs.umich.edu CASE(A, uint8_t); \ 2283576Sgblack@eecs.umich.edu default: \ 2293576Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 2303576Sgblack@eecs.umich.edu A, pkt->getSize(), pkt->getAddr()); \ 2313576Sgblack@eecs.umich.edu } \ 2323576Sgblack@eecs.umich.edu } while (0) 2333576Sgblack@eecs.umich.edu 2343576Sgblack@eecs.umich.edu#else 2353576Sgblack@eecs.umich.edu 2363576Sgblack@eecs.umich.edu#define TRACE_PACKET(A) 2373576Sgblack@eecs.umich.edu 2383576Sgblack@eecs.umich.edu#endif 2393576Sgblack@eecs.umich.edu 2403576Sgblack@eecs.umich.eduTick 2413576Sgblack@eecs.umich.eduPhysicalMemory::doAtomicAccess(PacketPtr pkt) 2423576Sgblack@eecs.umich.edu{ 2433893Shsul@eecs.umich.edu assert(pkt->getAddr() >= start() && 2443576Sgblack@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 2453576Sgblack@eecs.umich.edu 2463576Sgblack@eecs.umich.edu if (pkt->memInhibitAsserted()) { 2473576Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 2483576Sgblack@eecs.umich.edu pkt->getAddr()); 2493576Sgblack@eecs.umich.edu return 0; 2503576Sgblack@eecs.umich.edu } 2513576Sgblack@eecs.umich.edu 2523576Sgblack@eecs.umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 2533576Sgblack@eecs.umich.edu 2543576Sgblack@eecs.umich.edu if (pkt->cmd == MemCmd::SwapReq) { 2553576Sgblack@eecs.umich.edu IntReg overwrite_val; 2563576Sgblack@eecs.umich.edu bool overwrite_mem; 2573576Sgblack@eecs.umich.edu uint64_t condition_val64; 2583576Sgblack@eecs.umich.edu uint32_t condition_val32; 2593576Sgblack@eecs.umich.edu 2603576Sgblack@eecs.umich.edu if (!pmemAddr) 2613576Sgblack@eecs.umich.edu panic("Swap only works if there is real memory (i.e. null=False)"); 2623576Sgblack@eecs.umich.edu assert(sizeof(IntReg) >= pkt->getSize()); 2633576Sgblack@eecs.umich.edu 2643576Sgblack@eecs.umich.edu overwrite_mem = true; 2652223SN/A // keep a copy of our possible write value, and copy what is at the 2662800Ssaidi@eecs.umich.edu // memory address into the packet 2673573Sgblack@eecs.umich.edu std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2683576Sgblack@eecs.umich.edu std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2693576Sgblack@eecs.umich.edu 2702800Ssaidi@eecs.umich.edu if (pkt->req->isCondSwap()) { 2712800Ssaidi@eecs.umich.edu if (pkt->getSize() == sizeof(uint64_t)) { 2723415Sgblack@eecs.umich.edu condition_val64 = pkt->req->getExtraData(); 2733578Sgblack@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 2743578Sgblack@eecs.umich.edu sizeof(uint64_t)); 2753415Sgblack@eecs.umich.edu } else if (pkt->getSize() == sizeof(uint32_t)) { 2763415Sgblack@eecs.umich.edu condition_val32 = (uint32_t)pkt->req->getExtraData(); 2773578Sgblack@eecs.umich.edu overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 2783415Sgblack@eecs.umich.edu sizeof(uint32_t)); 2793578Sgblack@eecs.umich.edu } else 2803578Sgblack@eecs.umich.edu panic("Invalid size for conditional read/write\n"); 2813578Sgblack@eecs.umich.edu } 2823578Sgblack@eecs.umich.edu 2833578Sgblack@eecs.umich.edu if (overwrite_mem) 2843578Sgblack@eecs.umich.edu std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 2853578Sgblack@eecs.umich.edu 2863595Sgblack@eecs.umich.edu assert(!pkt->req->isInstFetch()); 2873746Sgblack@eecs.umich.edu TRACE_PACKET("Read/Write"); 2883746Sgblack@eecs.umich.edu } else if (pkt->isRead()) { 2893746Sgblack@eecs.umich.edu assert(!pkt->isWrite()); 2903746Sgblack@eecs.umich.edu if (pkt->isLLSC()) { 2913746Sgblack@eecs.umich.edu trackLoadLocked(pkt); 2923578Sgblack@eecs.umich.edu } 2933578Sgblack@eecs.umich.edu if (pmemAddr) 2943578Sgblack@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2953578Sgblack@eecs.umich.edu TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 2963578Sgblack@eecs.umich.edu } else if (pkt->isWrite()) { 2973578Sgblack@eecs.umich.edu if (writeOK(pkt)) { 2983578Sgblack@eecs.umich.edu if (pmemAddr) 2993578Sgblack@eecs.umich.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3003578Sgblack@eecs.umich.edu assert(!pkt->req->isInstFetch()); 3013578Sgblack@eecs.umich.edu TRACE_PACKET("Write"); 3023578Sgblack@eecs.umich.edu } 3033578Sgblack@eecs.umich.edu } else if (pkt->isInvalidate()) { 3043578Sgblack@eecs.umich.edu //upgrade or invalidate 3053578Sgblack@eecs.umich.edu if (pkt->needsResponse()) { 3063578Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3073578Sgblack@eecs.umich.edu } 3083578Sgblack@eecs.umich.edu } else { 3093578Sgblack@eecs.umich.edu panic("unimplemented"); 3103578Sgblack@eecs.umich.edu } 3113578Sgblack@eecs.umich.edu 3123578Sgblack@eecs.umich.edu if (pkt->needsResponse()) { 3133578Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3143578Sgblack@eecs.umich.edu } 3153578Sgblack@eecs.umich.edu return calculateLatency(pkt); 3163578Sgblack@eecs.umich.edu} 3173578Sgblack@eecs.umich.edu 3183578Sgblack@eecs.umich.edu 3193578Sgblack@eecs.umich.eduvoid 3203578Sgblack@eecs.umich.eduPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 3213578Sgblack@eecs.umich.edu{ 3223578Sgblack@eecs.umich.edu assert(pkt->getAddr() >= start() && 3233578Sgblack@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 3243578Sgblack@eecs.umich.edu 3253578Sgblack@eecs.umich.edu 3263578Sgblack@eecs.umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3273578Sgblack@eecs.umich.edu 3283578Sgblack@eecs.umich.edu if (pkt->isRead()) { 3293578Sgblack@eecs.umich.edu if (pmemAddr) 3303578Sgblack@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3313578Sgblack@eecs.umich.edu TRACE_PACKET("Read"); 3323578Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3333578Sgblack@eecs.umich.edu } else if (pkt->isWrite()) { 3343578Sgblack@eecs.umich.edu if (pmemAddr) 3353578Sgblack@eecs.umich.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3363578Sgblack@eecs.umich.edu TRACE_PACKET("Write"); 3373578Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3383578Sgblack@eecs.umich.edu } else if (pkt->isPrint()) { 3393578Sgblack@eecs.umich.edu Packet::PrintReqState *prs = 3403578Sgblack@eecs.umich.edu dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 3413578Sgblack@eecs.umich.edu // Need to call printLabels() explicitly since we're not going 3423578Sgblack@eecs.umich.edu // through printObj(). 3433926Ssaidi@eecs.umich.edu prs->printLabels(); 3443926Ssaidi@eecs.umich.edu // Right now we just print the single byte at the specified address. 3453578Sgblack@eecs.umich.edu ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 3463578Sgblack@eecs.umich.edu } else { 3473578Sgblack@eecs.umich.edu panic("PhysicalMemory: unimplemented functional command %s", 3483578Sgblack@eecs.umich.edu pkt->cmdString()); 3493578Sgblack@eecs.umich.edu } 3503578Sgblack@eecs.umich.edu} 3513578Sgblack@eecs.umich.edu 3523578Sgblack@eecs.umich.edu 3533578Sgblack@eecs.umich.eduPort * 3543578Sgblack@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name, int idx) 3553578Sgblack@eecs.umich.edu{ 3563578Sgblack@eecs.umich.edu // Accept request for "functional" port for backwards compatibility 3573578Sgblack@eecs.umich.edu // with places where this function is called from C++. I'd prefer 3583578Sgblack@eecs.umich.edu // to move all these into Python someday. 3593578Sgblack@eecs.umich.edu if (if_name == "functional") { 3603578Sgblack@eecs.umich.edu return new MemoryPort(csprintf("%s-functional", name()), this); 3613578Sgblack@eecs.umich.edu } 3623578Sgblack@eecs.umich.edu 3633578Sgblack@eecs.umich.edu if (if_name != "port") { 3643578Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 3653578Sgblack@eecs.umich.edu } 3663578Sgblack@eecs.umich.edu 3673578Sgblack@eecs.umich.edu if (idx >= (int)ports.size()) { 3683578Sgblack@eecs.umich.edu ports.resize(idx + 1); 3693578Sgblack@eecs.umich.edu } 3703578Sgblack@eecs.umich.edu 3713578Sgblack@eecs.umich.edu if (ports[idx] != NULL) { 3723578Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: port %d already assigned", idx); 3733578Sgblack@eecs.umich.edu } 3743578Sgblack@eecs.umich.edu 3753578Sgblack@eecs.umich.edu MemoryPort *port = 3763578Sgblack@eecs.umich.edu new MemoryPort(csprintf("%s-port%d", name(), idx), this); 3773578Sgblack@eecs.umich.edu 3783578Sgblack@eecs.umich.edu ports[idx] = port; 3793578Sgblack@eecs.umich.edu return port; 3803578Sgblack@eecs.umich.edu} 3813578Sgblack@eecs.umich.edu 3823578Sgblack@eecs.umich.edu 3833578Sgblack@eecs.umich.eduvoid 3843578Sgblack@eecs.umich.eduPhysicalMemory::recvStatusChange(Port::Status status) 3853578Sgblack@eecs.umich.edu{ 3863578Sgblack@eecs.umich.edu} 3873578Sgblack@eecs.umich.edu 3883578Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 3893578Sgblack@eecs.umich.edu PhysicalMemory *_memory) 3903578Sgblack@eecs.umich.edu : SimpleTimingPort(_name, _memory), memory(_memory) 3913578Sgblack@eecs.umich.edu{ } 3923415Sgblack@eecs.umich.edu 3933415Sgblack@eecs.umich.eduvoid 3943415Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 3953415Sgblack@eecs.umich.edu{ 3963415Sgblack@eecs.umich.edu memory->recvStatusChange(status); 3973415Sgblack@eecs.umich.edu} 3983415Sgblack@eecs.umich.edu 3993415Sgblack@eecs.umich.eduvoid 4003415Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 4013415Sgblack@eecs.umich.edu bool &snoop) 4023415Sgblack@eecs.umich.edu{ 4033415Sgblack@eecs.umich.edu memory->getAddressRanges(resp, snoop); 4043415Sgblack@eecs.umich.edu} 4053415Sgblack@eecs.umich.edu 4063415Sgblack@eecs.umich.eduvoid 4073415Sgblack@eecs.umich.eduPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) 4083415Sgblack@eecs.umich.edu{ 4093415Sgblack@eecs.umich.edu snoop = false; 4103415Sgblack@eecs.umich.edu resp.clear(); 4113415Sgblack@eecs.umich.edu resp.push_back(RangeSize(start(), params()->range.size())); 4123415Sgblack@eecs.umich.edu} 4133415Sgblack@eecs.umich.edu 4143415Sgblack@eecs.umich.eduunsigned 4153415Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() const 4163415Sgblack@eecs.umich.edu{ 4173415Sgblack@eecs.umich.edu return memory->deviceBlockSize(); 4183415Sgblack@eecs.umich.edu} 4193415Sgblack@eecs.umich.edu 4203415Sgblack@eecs.umich.eduTick 4213415Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4223415Sgblack@eecs.umich.edu{ 4233415Sgblack@eecs.umich.edu return memory->doAtomicAccess(pkt); 4243415Sgblack@eecs.umich.edu} 4253893Shsul@eecs.umich.edu 4263578Sgblack@eecs.umich.eduvoid 4273415Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4283578Sgblack@eecs.umich.edu{ 4293415Sgblack@eecs.umich.edu pkt->pushLabel(memory->name()); 4303415Sgblack@eecs.umich.edu 4313926Ssaidi@eecs.umich.edu if (!checkFunctional(pkt)) { 4323926Ssaidi@eecs.umich.edu // Default implementation of SimpleTimingPort::recvFunctional() 4333926Ssaidi@eecs.umich.edu // calls recvAtomic() and throws away the latency; we can save a 4343415Sgblack@eecs.umich.edu // little here by just not calculating the latency. 4353415Sgblack@eecs.umich.edu memory->doFunctionalAccess(pkt); 4363415Sgblack@eecs.umich.edu } 4373893Shsul@eecs.umich.edu 4383415Sgblack@eecs.umich.edu pkt->popLabel(); 4393926Ssaidi@eecs.umich.edu} 4403926Ssaidi@eecs.umich.edu 4413926Ssaidi@eecs.umich.eduunsigned int 4423926Ssaidi@eecs.umich.eduPhysicalMemory::drain(Event *de) 4433926Ssaidi@eecs.umich.edu{ 4443415Sgblack@eecs.umich.edu int count = 0; 4453415Sgblack@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 4463926Ssaidi@eecs.umich.edu count += (*pi)->drain(de); 4473926Ssaidi@eecs.umich.edu } 4483926Ssaidi@eecs.umich.edu 4493415Sgblack@eecs.umich.edu if (count) 4503926Ssaidi@eecs.umich.edu changeState(Draining); 4513926Ssaidi@eecs.umich.edu else 4523415Sgblack@eecs.umich.edu changeState(Drained); 4533415Sgblack@eecs.umich.edu return count; 4543893Shsul@eecs.umich.edu} 4553415Sgblack@eecs.umich.edu 4563893Shsul@eecs.umich.eduvoid 4573415Sgblack@eecs.umich.eduPhysicalMemory::serialize(ostream &os) 4583893Shsul@eecs.umich.edu{ 4593415Sgblack@eecs.umich.edu if (!pmemAddr) 4603415Sgblack@eecs.umich.edu return; 4613415Sgblack@eecs.umich.edu 4623420Sgblack@eecs.umich.edu gzFile compressedMem; 4633893Shsul@eecs.umich.edu string filename = name() + ".physmem"; 4643415Sgblack@eecs.umich.edu 4653415Sgblack@eecs.umich.edu SERIALIZE_SCALAR(filename); 4663415Sgblack@eecs.umich.edu 4673415Sgblack@eecs.umich.edu // write memory file 4683415Sgblack@eecs.umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 4693415Sgblack@eecs.umich.edu int fd = creat(thefile.c_str(), 0664); 4703595Sgblack@eecs.umich.edu if (fd < 0) { 4713578Sgblack@eecs.umich.edu perror("creat"); 4723585Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'\n", filename); 4733603Ssaidi@eecs.umich.edu } 4743595Sgblack@eecs.umich.edu 4753578Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "wb"); 4763578Sgblack@eecs.umich.edu if (compressedMem == NULL) 4773578Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 4783585Sgblack@eecs.umich.edu filename); 4793578Sgblack@eecs.umich.edu 4803585Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, params()->range.size()) != 4813578Sgblack@eecs.umich.edu (int)params()->range.size()) { 4823578Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 4833578Sgblack@eecs.umich.edu filename); 4843578Sgblack@eecs.umich.edu } 4853585Sgblack@eecs.umich.edu 4863578Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 4873585Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 4883578Sgblack@eecs.umich.edu filename); 4893578Sgblack@eecs.umich.edu} 4903578Sgblack@eecs.umich.edu 4913578Sgblack@eecs.umich.eduvoid 4923578Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 4933578Sgblack@eecs.umich.edu{ 4942221SN/A if (!pmemAddr) 4952221SN/A return; 4963573Sgblack@eecs.umich.edu 4972221SN/A gzFile compressedMem; 4983825Ssaidi@eecs.umich.edu long *tempPage; 4992680Sktlim@umich.edu long *pmem_current; 5002223SN/A uint64_t curSize; 5012221SN/A uint32_t bytesRead; 5023578Sgblack@eecs.umich.edu const uint32_t chunkSize = 16384; 5033578Sgblack@eecs.umich.edu 5043893Shsul@eecs.umich.edu string filename; 5053893Shsul@eecs.umich.edu 5063893Shsul@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 5073893Shsul@eecs.umich.edu 5083578Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 5093578Sgblack@eecs.umich.edu 5103578Sgblack@eecs.umich.edu // mmap memoryfile 5113578Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 5123893Shsul@eecs.umich.edu if (fd < 0) { 5133746Sgblack@eecs.umich.edu perror("open"); 5143893Shsul@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 5153578Sgblack@eecs.umich.edu } 5163578Sgblack@eecs.umich.edu 5173746Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 5183578Sgblack@eecs.umich.edu if (compressedMem == NULL) 5193578Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 5203578Sgblack@eecs.umich.edu filename); 5213893Shsul@eecs.umich.edu 5223595Sgblack@eecs.umich.edu // unmap file that was mmaped in the constructor 5233893Shsul@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 5243746Sgblack@eecs.umich.edu // nice large space of memory before we reallocate it 5253746Sgblack@eecs.umich.edu munmap((char*)pmemAddr, params()->range.size()); 5263578Sgblack@eecs.umich.edu 5273893Shsul@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(), 5283825Ssaidi@eecs.umich.edu PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5293578Sgblack@eecs.umich.edu 5303578Sgblack@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 5313578Sgblack@eecs.umich.edu perror("mmap"); 5323893Shsul@eecs.umich.edu fatal("Could not mmap physical memory!\n"); 5333578Sgblack@eecs.umich.edu } 5343578Sgblack@eecs.umich.edu 5353585Sgblack@eecs.umich.edu curSize = 0; 5363893Shsul@eecs.umich.edu tempPage = (long*)malloc(chunkSize); 5373826Ssaidi@eecs.umich.edu if (tempPage == NULL) 5383578Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 5393585Sgblack@eecs.umich.edu 5403826Ssaidi@eecs.umich.edu /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 5413578Sgblack@eecs.umich.edu while (curSize < params()->range.size()) { 5423893Shsul@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 5433578Sgblack@eecs.umich.edu if (bytesRead == 0) 5443578Sgblack@eecs.umich.edu break; 5453578Sgblack@eecs.umich.edu 5463578Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 5473578Sgblack@eecs.umich.edu 5483420Sgblack@eecs.umich.edu for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 5492221SN/A { 5503523Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 5513523Sgblack@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 5523523Sgblack@eecs.umich.edu *pmem_current = *(tempPage+x); 5533523Sgblack@eecs.umich.edu } 5543523Sgblack@eecs.umich.edu } 5553595Sgblack@eecs.umich.edu curSize += bytesRead; 5563595Sgblack@eecs.umich.edu } 5573595Sgblack@eecs.umich.edu 5583595Sgblack@eecs.umich.edu free(tempPage); 5593595Sgblack@eecs.umich.edu 5603746Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 5613746Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 5623595Sgblack@eecs.umich.edu filename); 5633595Sgblack@eecs.umich.edu 5643628Sgblack@eecs.umich.edu} 5653628Sgblack@eecs.umich.edu 5663628Sgblack@eecs.umich.eduPhysicalMemory * 5673628Sgblack@eecs.umich.eduPhysicalMemoryParams::create() 5683628Sgblack@eecs.umich.edu{ 5693628Sgblack@eecs.umich.edu return new PhysicalMemory(this); 5703628Sgblack@eecs.umich.edu} 5713628Sgblack@eecs.umich.edu