abstract_mem.cc revision 3879
15647Sgblack@eecs.umich.edu/* 25647Sgblack@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan 35647Sgblack@eecs.umich.edu * All rights reserved. 45647Sgblack@eecs.umich.edu * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 135647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 157087Snate@binkert.org * 167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275647Sgblack@eecs.umich.edu * 285647Sgblack@eecs.umich.edu * Authors: Ron Dreslinski 295647Sgblack@eecs.umich.edu * Ali Saidi 305647Sgblack@eecs.umich.edu */ 315647Sgblack@eecs.umich.edu 325647Sgblack@eecs.umich.edu#include <sys/types.h> 335647Sgblack@eecs.umich.edu#include <sys/mman.h> 345647Sgblack@eecs.umich.edu#include <errno.h> 355647Sgblack@eecs.umich.edu#include <fcntl.h> 365647Sgblack@eecs.umich.edu#include <unistd.h> 375647Sgblack@eecs.umich.edu#include <zlib.h> 385647Sgblack@eecs.umich.edu 395647Sgblack@eecs.umich.edu#include <iostream> 405648Sgblack@eecs.umich.edu#include <string> 415647Sgblack@eecs.umich.edu 425654Sgblack@eecs.umich.edu#include "arch/isa_traits.hh" 435647Sgblack@eecs.umich.edu#include "base/misc.hh" 446137Sgblack@eecs.umich.edu#include "config/full_system.hh" 456137Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 466137Sgblack@eecs.umich.edu#include "mem/physical.hh" 475654Sgblack@eecs.umich.edu#include "sim/builder.hh" 486046Sgblack@eecs.umich.edu#include "sim/eventq.hh" 495647Sgblack@eecs.umich.edu#include "sim/host.hh" 505648Sgblack@eecs.umich.edu 515648Sgblack@eecs.umich.eduusing namespace std; 525647Sgblack@eecs.umich.eduusing namespace TheISA; 535647Sgblack@eecs.umich.edu 545647Sgblack@eecs.umich.eduPhysicalMemory::PhysicalMemory(Params *p) 555647Sgblack@eecs.umich.edu : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) 565647Sgblack@eecs.umich.edu{ 575647Sgblack@eecs.umich.edu if (params()->addrRange.size() % TheISA::PageBytes != 0) 585647Sgblack@eecs.umich.edu panic("Memory Size not divisible by page size\n"); 595647Sgblack@eecs.umich.edu 605647Sgblack@eecs.umich.edu int map_flags = MAP_ANON | MAP_PRIVATE; 615648Sgblack@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 625647Sgblack@eecs.umich.edu map_flags, -1, 0); 635648Sgblack@eecs.umich.edu 645648Sgblack@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 655648Sgblack@eecs.umich.edu perror("mmap"); 665648Sgblack@eecs.umich.edu fatal("Could not mmap!\n"); 675648Sgblack@eecs.umich.edu } 685648Sgblack@eecs.umich.edu 695648Sgblack@eecs.umich.edu //If requested, initialize all the memory to 0 705648Sgblack@eecs.umich.edu if(params()->zero) 715648Sgblack@eecs.umich.edu memset(pmemAddr, 0, params()->addrRange.size()); 725648Sgblack@eecs.umich.edu 735648Sgblack@eecs.umich.edu pagePtr = 0; 745648Sgblack@eecs.umich.edu} 755648Sgblack@eecs.umich.edu 765648Sgblack@eecs.umich.eduvoid 775648Sgblack@eecs.umich.eduPhysicalMemory::init() 785648Sgblack@eecs.umich.edu{ 795648Sgblack@eecs.umich.edu if (!port) 805648Sgblack@eecs.umich.edu panic("PhysicalMemory not connected to anything!"); 815648Sgblack@eecs.umich.edu port->sendStatusChange(Port::RangeChange); 825648Sgblack@eecs.umich.edu} 835648Sgblack@eecs.umich.edu 845648Sgblack@eecs.umich.eduPhysicalMemory::~PhysicalMemory() 855648Sgblack@eecs.umich.edu{ 865648Sgblack@eecs.umich.edu if (pmemAddr) 875648Sgblack@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 885648Sgblack@eecs.umich.edu //Remove memPorts? 895648Sgblack@eecs.umich.edu} 905648Sgblack@eecs.umich.edu 915648Sgblack@eecs.umich.eduAddr 925648Sgblack@eecs.umich.eduPhysicalMemory::new_page() 935648Sgblack@eecs.umich.edu{ 945648Sgblack@eecs.umich.edu Addr return_addr = pagePtr << LogVMPageSize; 955648Sgblack@eecs.umich.edu return_addr += params()->addrRange.start; 965648Sgblack@eecs.umich.edu 975648Sgblack@eecs.umich.edu ++pagePtr; 985648Sgblack@eecs.umich.edu return return_addr; 995648Sgblack@eecs.umich.edu} 1005648Sgblack@eecs.umich.edu 1015648Sgblack@eecs.umich.eduint 1025648Sgblack@eecs.umich.eduPhysicalMemory::deviceBlockSize() 1035648Sgblack@eecs.umich.edu{ 1045648Sgblack@eecs.umich.edu //Can accept anysize request 1055648Sgblack@eecs.umich.edu return 0; 1065648Sgblack@eecs.umich.edu} 1075648Sgblack@eecs.umich.edu 1085648Sgblack@eecs.umich.eduTick 1095648Sgblack@eecs.umich.eduPhysicalMemory::calculateLatency(PacketPtr pkt) 1105648Sgblack@eecs.umich.edu{ 1115648Sgblack@eecs.umich.edu return lat; 1125648Sgblack@eecs.umich.edu} 1135648Sgblack@eecs.umich.edu 1145648Sgblack@eecs.umich.edu 1155648Sgblack@eecs.umich.edu 1165648Sgblack@eecs.umich.edu// Add load-locked to tracking list. Should only be called if the 1175648Sgblack@eecs.umich.edu// operation is a load and the LOCKED flag is set. 1185648Sgblack@eecs.umich.eduvoid 1195648Sgblack@eecs.umich.eduPhysicalMemory::trackLoadLocked(Request *req) 1205648Sgblack@eecs.umich.edu{ 1215648Sgblack@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1225648Sgblack@eecs.umich.edu 1235648Sgblack@eecs.umich.edu // first we check if we already have a locked addr for this 1245648Sgblack@eecs.umich.edu // xc. Since each xc only gets one, we just update the 1255648Sgblack@eecs.umich.edu // existing record with the new address. 1265648Sgblack@eecs.umich.edu list<LockedAddr>::iterator i; 1275648Sgblack@eecs.umich.edu 1285648Sgblack@eecs.umich.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1295648Sgblack@eecs.umich.edu if (i->matchesContext(req)) { 1305648Sgblack@eecs.umich.edu DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 1315648Sgblack@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1325648Sgblack@eecs.umich.edu i->addr = paddr; 1335648Sgblack@eecs.umich.edu return; 1345648Sgblack@eecs.umich.edu } 1355648Sgblack@eecs.umich.edu } 1365648Sgblack@eecs.umich.edu 1375648Sgblack@eecs.umich.edu // no record for this xc: need to allocate a new one 1385648Sgblack@eecs.umich.edu DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 1395648Sgblack@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1405648Sgblack@eecs.umich.edu lockedAddrList.push_front(LockedAddr(req)); 1415648Sgblack@eecs.umich.edu} 1425648Sgblack@eecs.umich.edu 1435648Sgblack@eecs.umich.edu 1445648Sgblack@eecs.umich.edu// Called on *writes* only... both regular stores and 1455648Sgblack@eecs.umich.edu// store-conditional operations. Check for conventional stores which 1465648Sgblack@eecs.umich.edu// conflict with locked addresses, and for success/failure of store 1475648Sgblack@eecs.umich.edu// conditionals. 1485648Sgblack@eecs.umich.edubool 1495648Sgblack@eecs.umich.eduPhysicalMemory::checkLockedAddrList(Request *req) 1505648Sgblack@eecs.umich.edu{ 1515648Sgblack@eecs.umich.edu Addr paddr = LockedAddr::mask(req->getPaddr()); 1525648Sgblack@eecs.umich.edu bool isLocked = req->isLocked(); 1535648Sgblack@eecs.umich.edu 1545648Sgblack@eecs.umich.edu // Initialize return value. Non-conditional stores always 1555648Sgblack@eecs.umich.edu // succeed. Assume conditional stores will fail until proven 1565648Sgblack@eecs.umich.edu // otherwise. 1575648Sgblack@eecs.umich.edu bool success = !isLocked; 1585648Sgblack@eecs.umich.edu 1595648Sgblack@eecs.umich.edu // Iterate over list. Note that there could be multiple matching 1605648Sgblack@eecs.umich.edu // records, as more than one context could have done a load locked 1615648Sgblack@eecs.umich.edu // to this location. 1625648Sgblack@eecs.umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 1635648Sgblack@eecs.umich.edu 1645648Sgblack@eecs.umich.edu while (i != lockedAddrList.end()) { 1655648Sgblack@eecs.umich.edu 1665648Sgblack@eecs.umich.edu if (i->addr == paddr) { 1675648Sgblack@eecs.umich.edu // we have a matching address 1685648Sgblack@eecs.umich.edu 1695648Sgblack@eecs.umich.edu if (isLocked && i->matchesContext(req)) { 1705648Sgblack@eecs.umich.edu // it's a store conditional, and as far as the memory 1715648Sgblack@eecs.umich.edu // system can tell, the requesting context's lock is 1725648Sgblack@eecs.umich.edu // still valid. 1735648Sgblack@eecs.umich.edu DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 1745648Sgblack@eecs.umich.edu req->getCpuNum(), req->getThreadNum(), paddr); 1755648Sgblack@eecs.umich.edu success = true; 1765648Sgblack@eecs.umich.edu } 1775648Sgblack@eecs.umich.edu 1785648Sgblack@eecs.umich.edu // Get rid of our record of this lock and advance to next 1795648Sgblack@eecs.umich.edu DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 1805648Sgblack@eecs.umich.edu i->cpuNum, i->threadNum, paddr); 1815648Sgblack@eecs.umich.edu i = lockedAddrList.erase(i); 1825648Sgblack@eecs.umich.edu } 1835648Sgblack@eecs.umich.edu else { 1845648Sgblack@eecs.umich.edu // no match: advance to next record 1855648Sgblack@eecs.umich.edu ++i; 1865648Sgblack@eecs.umich.edu } 1875648Sgblack@eecs.umich.edu } 1885648Sgblack@eecs.umich.edu 1895648Sgblack@eecs.umich.edu if (isLocked) { 1905648Sgblack@eecs.umich.edu req->setScResult(success ? 1 : 0); 1915648Sgblack@eecs.umich.edu } 1925648Sgblack@eecs.umich.edu 1935648Sgblack@eecs.umich.edu return success; 1945648Sgblack@eecs.umich.edu} 1955648Sgblack@eecs.umich.edu 1965648Sgblack@eecs.umich.eduvoid 1975648Sgblack@eecs.umich.eduPhysicalMemory::doFunctionalAccess(PacketPtr pkt) 1985648Sgblack@eecs.umich.edu{ 1995648Sgblack@eecs.umich.edu assert(pkt->getAddr() >= params()->addrRange.start && 2005648Sgblack@eecs.umich.edu pkt->getAddr() + pkt->getSize() <= params()->addrRange.start + 2015648Sgblack@eecs.umich.edu params()->addrRange.size()); 2025648Sgblack@eecs.umich.edu 2035648Sgblack@eecs.umich.edu if (pkt->isRead()) { 2045648Sgblack@eecs.umich.edu if (pkt->req->isLocked()) { 2055648Sgblack@eecs.umich.edu trackLoadLocked(pkt->req); 2065649Sgblack@eecs.umich.edu } 2075649Sgblack@eecs.umich.edu memcpy(pkt->getPtr<uint8_t>(), 2085649Sgblack@eecs.umich.edu pmemAddr + pkt->getAddr() - params()->addrRange.start, 2095648Sgblack@eecs.umich.edu pkt->getSize()); 2105898Sgblack@eecs.umich.edu#if TRACING_ON 2115648Sgblack@eecs.umich.edu switch (pkt->getSize()) { 2125648Sgblack@eecs.umich.edu case sizeof(uint64_t): 2135648Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2145648Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 2155648Sgblack@eecs.umich.edu break; 2165648Sgblack@eecs.umich.edu case sizeof(uint32_t): 2175648Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2185648Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 2195648Sgblack@eecs.umich.edu break; 2205648Sgblack@eecs.umich.edu case sizeof(uint16_t): 2215648Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2225648Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 2235648Sgblack@eecs.umich.edu break; 2245649Sgblack@eecs.umich.edu case sizeof(uint8_t): 2255649Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2265649Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 2275648Sgblack@eecs.umich.edu break; 2285898Sgblack@eecs.umich.edu default: 2295648Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Read of size %i on address 0x%x\n", 2305647Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr()); 2315691Sgblack@eecs.umich.edu } 2325691Sgblack@eecs.umich.edu#endif 2335691Sgblack@eecs.umich.edu } 2345691Sgblack@eecs.umich.edu else if (pkt->isWrite()) { 2355691Sgblack@eecs.umich.edu if (writeOK(pkt->req)) { 2365691Sgblack@eecs.umich.edu memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, 2375691Sgblack@eecs.umich.edu pkt->getPtr<uint8_t>(), pkt->getSize()); 2385691Sgblack@eecs.umich.edu#if TRACING_ON 2395691Sgblack@eecs.umich.edu switch (pkt->getSize()) { 2405691Sgblack@eecs.umich.edu case sizeof(uint64_t): 2415691Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2425691Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 2435691Sgblack@eecs.umich.edu break; 2445691Sgblack@eecs.umich.edu case sizeof(uint32_t): 2455691Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2465691Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 2475691Sgblack@eecs.umich.edu break; 2485691Sgblack@eecs.umich.edu case sizeof(uint16_t): 2495691Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2505691Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 2515691Sgblack@eecs.umich.edu break; 2525691Sgblack@eecs.umich.edu case sizeof(uint8_t): 2535691Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2545691Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 2555691Sgblack@eecs.umich.edu break; 2565691Sgblack@eecs.umich.edu default: 2575691Sgblack@eecs.umich.edu DPRINTF(MemoryAccess, "Write of size %i on address 0x%x\n", 2585691Sgblack@eecs.umich.edu pkt->getSize(), pkt->getAddr()); 2595691Sgblack@eecs.umich.edu } 2605691Sgblack@eecs.umich.edu#endif 2615691Sgblack@eecs.umich.edu } 2625691Sgblack@eecs.umich.edu } 2635691Sgblack@eecs.umich.edu else if (pkt->isInvalidate()) { 2645691Sgblack@eecs.umich.edu //upgrade or invalidate 2655691Sgblack@eecs.umich.edu pkt->flags |= SATISFIED; 2665691Sgblack@eecs.umich.edu } 2675691Sgblack@eecs.umich.edu else { 2685691Sgblack@eecs.umich.edu panic("unimplemented"); 2695691Sgblack@eecs.umich.edu } 2706066Sgblack@eecs.umich.edu 2716066Sgblack@eecs.umich.edu pkt->result = Packet::Success; 2726050Sgblack@eecs.umich.edu} 2736050Sgblack@eecs.umich.edu 2745691Sgblack@eecs.umich.eduPort * 2755691Sgblack@eecs.umich.eduPhysicalMemory::getPort(const std::string &if_name, int idx) 2765811Sgblack@eecs.umich.edu{ 2775691Sgblack@eecs.umich.edu if (if_name == "port" && idx == -1) { 2785647Sgblack@eecs.umich.edu if (port != NULL) 2796041Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: additional port requested to memory!"); 2806041Sgblack@eecs.umich.edu port = new MemoryPort(name() + "-port", this); 2816041Sgblack@eecs.umich.edu return port; 2826041Sgblack@eecs.umich.edu } else if (if_name == "functional") { 2836136Sgblack@eecs.umich.edu /* special port for functional writes at startup. And for memtester */ 2846136Sgblack@eecs.umich.edu return new MemoryPort(name() + "-funcport", this); 2856136Sgblack@eecs.umich.edu } else { 2866136Sgblack@eecs.umich.edu panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 2876136Sgblack@eecs.umich.edu } 2886041Sgblack@eecs.umich.edu} 2896136Sgblack@eecs.umich.edu 2906136Sgblack@eecs.umich.eduvoid 2916041Sgblack@eecs.umich.eduPhysicalMemory::recvStatusChange(Port::Status status) 2926041Sgblack@eecs.umich.edu{ 2936041Sgblack@eecs.umich.edu} 2946137Sgblack@eecs.umich.edu 2956137Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 2966137Sgblack@eecs.umich.edu PhysicalMemory *_memory) 2976137Sgblack@eecs.umich.edu : SimpleTimingPort(_name), memory(_memory) 2986137Sgblack@eecs.umich.edu{ } 2996137Sgblack@eecs.umich.edu 3006137Sgblack@eecs.umich.eduvoid 3016137Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 3026137Sgblack@eecs.umich.edu{ 3036137Sgblack@eecs.umich.edu memory->recvStatusChange(status); 3045651Sgblack@eecs.umich.edu} 3055651Sgblack@eecs.umich.edu 3065651Sgblack@eecs.umich.eduvoid 3076136Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 3085651Sgblack@eecs.umich.edu AddrRangeList &snoop) 3095651Sgblack@eecs.umich.edu{ 3105651Sgblack@eecs.umich.edu memory->getAddressRanges(resp, snoop); 3115651Sgblack@eecs.umich.edu} 3125654Sgblack@eecs.umich.edu 3135654Sgblack@eecs.umich.eduvoid 3145654Sgblack@eecs.umich.eduPhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 3155654Sgblack@eecs.umich.edu{ 3165697Snate@binkert.org snoop.clear(); 3175655Sgblack@eecs.umich.edu resp.clear(); 3185691Sgblack@eecs.umich.edu resp.push_back(RangeSize(params()->addrRange.start, 3195691Sgblack@eecs.umich.edu params()->addrRange.size())); 3205654Sgblack@eecs.umich.edu} 3215651Sgblack@eecs.umich.edu 3225651Sgblack@eecs.umich.eduint 3235651Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() 3245651Sgblack@eecs.umich.edu{ 3255651Sgblack@eecs.umich.edu return memory->deviceBlockSize(); 3265651Sgblack@eecs.umich.edu} 3276064Sgblack@eecs.umich.edu 3285651Sgblack@eecs.umich.eduTick 3295651Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 3305651Sgblack@eecs.umich.edu{ 3315651Sgblack@eecs.umich.edu memory->doFunctionalAccess(pkt); 3326065Sgblack@eecs.umich.edu return memory->calculateLatency(pkt); 3336065Sgblack@eecs.umich.edu} 3346065Sgblack@eecs.umich.edu 3356065Sgblack@eecs.umich.eduvoid 3366065Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 3376069Sgblack@eecs.umich.edu{ 3386069Sgblack@eecs.umich.edu //Since we are overriding the function, make sure to have the impl of the 3396069Sgblack@eecs.umich.edu //check or functional accesses here. 3406069Sgblack@eecs.umich.edu std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin(); 3416069Sgblack@eecs.umich.edu std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end(); 3426069Sgblack@eecs.umich.edu bool notDone = true; 3436065Sgblack@eecs.umich.edu 3446065Sgblack@eecs.umich.edu while (i != end && notDone) { 3456065Sgblack@eecs.umich.edu PacketPtr target = i->second; 3466065Sgblack@eecs.umich.edu // If the target contains data, and it overlaps the 3476065Sgblack@eecs.umich.edu // probed request, need to update data 3486065Sgblack@eecs.umich.edu if (target->intersect(pkt)) 3496065Sgblack@eecs.umich.edu notDone = fixPacket(pkt, target); 3506041Sgblack@eecs.umich.edu i++; 3516041Sgblack@eecs.umich.edu } 3526041Sgblack@eecs.umich.edu 3536041Sgblack@eecs.umich.edu // Default implementation of SimpleTimingPort::recvFunctional() 3546136Sgblack@eecs.umich.edu // calls recvAtomic() and throws away the latency; we can save a 3556136Sgblack@eecs.umich.edu // little here by just not calculating the latency. 3566136Sgblack@eecs.umich.edu memory->doFunctionalAccess(pkt); 3576061Sgblack@eecs.umich.edu} 3586061Sgblack@eecs.umich.edu 3596041Sgblack@eecs.umich.eduunsigned int 3606041Sgblack@eecs.umich.eduPhysicalMemory::drain(Event *de) 3616041Sgblack@eecs.umich.edu{ 3626041Sgblack@eecs.umich.edu int count = port->drain(de); 3636041Sgblack@eecs.umich.edu if (count) 3646041Sgblack@eecs.umich.edu changeState(Draining); 3656041Sgblack@eecs.umich.edu else 3666136Sgblack@eecs.umich.edu changeState(Drained); 3676136Sgblack@eecs.umich.edu return count; 3686136Sgblack@eecs.umich.edu} 3696041Sgblack@eecs.umich.edu 3706041Sgblack@eecs.umich.eduvoid 3716041Sgblack@eecs.umich.eduPhysicalMemory::serialize(ostream &os) 3725647Sgblack@eecs.umich.edu{ 3735648Sgblack@eecs.umich.edu gzFile compressedMem; 3745647Sgblack@eecs.umich.edu string filename = name() + ".physmem"; 3755647Sgblack@eecs.umich.edu 3765647Sgblack@eecs.umich.edu SERIALIZE_SCALAR(filename); 3775647Sgblack@eecs.umich.edu 3785647Sgblack@eecs.umich.edu // write memory file 3795647Sgblack@eecs.umich.edu string thefile = Checkpoint::dir() + "/" + filename.c_str(); 3805647Sgblack@eecs.umich.edu int fd = creat(thefile.c_str(), 0664); 3815647Sgblack@eecs.umich.edu if (fd < 0) { 3825647Sgblack@eecs.umich.edu perror("creat"); 3835647Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'\n", filename); 3845647Sgblack@eecs.umich.edu } 3855647Sgblack@eecs.umich.edu 3865647Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "wb"); 3875647Sgblack@eecs.umich.edu if (compressedMem == NULL) 3885647Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 3895647Sgblack@eecs.umich.edu filename); 3905647Sgblack@eecs.umich.edu 3915848Sgblack@eecs.umich.edu if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) { 3925848Sgblack@eecs.umich.edu fatal("Write failed on physical memory checkpoint file '%s'\n", 3935848Sgblack@eecs.umich.edu filename); 3945848Sgblack@eecs.umich.edu } 3955848Sgblack@eecs.umich.edu 3965848Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 3975848Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 3985848Sgblack@eecs.umich.edu filename); 3995848Sgblack@eecs.umich.edu} 4005848Sgblack@eecs.umich.edu 4015848Sgblack@eecs.umich.eduvoid 4025848Sgblack@eecs.umich.eduPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 4035848Sgblack@eecs.umich.edu{ 4045647Sgblack@eecs.umich.edu gzFile compressedMem; 4055647Sgblack@eecs.umich.edu long *tempPage; 4065647Sgblack@eecs.umich.edu long *pmem_current; 4075647Sgblack@eecs.umich.edu uint64_t curSize; 4085648Sgblack@eecs.umich.edu uint32_t bytesRead; 4095647Sgblack@eecs.umich.edu const int chunkSize = 16384; 4105647Sgblack@eecs.umich.edu 4115647Sgblack@eecs.umich.edu 4125648Sgblack@eecs.umich.edu string filename; 4135647Sgblack@eecs.umich.edu 4145647Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(filename); 4155647Sgblack@eecs.umich.edu 4165647Sgblack@eecs.umich.edu filename = cp->cptDir + "/" + filename; 4175647Sgblack@eecs.umich.edu 4185647Sgblack@eecs.umich.edu // mmap memoryfile 4195647Sgblack@eecs.umich.edu int fd = open(filename.c_str(), O_RDONLY); 4205647Sgblack@eecs.umich.edu if (fd < 0) { 4215647Sgblack@eecs.umich.edu perror("open"); 4225647Sgblack@eecs.umich.edu fatal("Can't open physical memory checkpoint file '%s'", filename); 4235647Sgblack@eecs.umich.edu } 4245647Sgblack@eecs.umich.edu 4255647Sgblack@eecs.umich.edu compressedMem = gzdopen(fd, "rb"); 4265647Sgblack@eecs.umich.edu if (compressedMem == NULL) 4275647Sgblack@eecs.umich.edu fatal("Insufficient memory to allocate compression state for %s\n", 4285647Sgblack@eecs.umich.edu filename); 4295647Sgblack@eecs.umich.edu 4305647Sgblack@eecs.umich.edu // unmap file that was mmaped in the constructor 4315647Sgblack@eecs.umich.edu // This is done here to make sure that gzip and open don't muck with our 4325647Sgblack@eecs.umich.edu // nice large space of memory before we reallocate it 4335647Sgblack@eecs.umich.edu munmap(pmemAddr, params()->addrRange.size()); 4345647Sgblack@eecs.umich.edu 4355647Sgblack@eecs.umich.edu pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE, 4365647Sgblack@eecs.umich.edu MAP_ANON | MAP_PRIVATE, -1, 0); 4375647Sgblack@eecs.umich.edu 4385647Sgblack@eecs.umich.edu if (pmemAddr == (void *)MAP_FAILED) { 4395647Sgblack@eecs.umich.edu perror("mmap"); 4405647Sgblack@eecs.umich.edu fatal("Could not mmap physical memory!\n"); 4415647Sgblack@eecs.umich.edu } 4425647Sgblack@eecs.umich.edu 4435647Sgblack@eecs.umich.edu curSize = 0; 4445647Sgblack@eecs.umich.edu tempPage = (long*)malloc(chunkSize); 4455690Sgblack@eecs.umich.edu if (tempPage == NULL) 4465690Sgblack@eecs.umich.edu fatal("Unable to malloc memory to read file %s\n", filename); 4475690Sgblack@eecs.umich.edu 4485690Sgblack@eecs.umich.edu /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 4495647Sgblack@eecs.umich.edu while (curSize < params()->addrRange.size()) { 4505647Sgblack@eecs.umich.edu bytesRead = gzread(compressedMem, tempPage, chunkSize); 4515647Sgblack@eecs.umich.edu if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize) 4525647Sgblack@eecs.umich.edu fatal("Read failed on physical memory checkpoint file '%s'" 4535647Sgblack@eecs.umich.edu " got %d bytes, expected %d or %d bytes\n", 4545647Sgblack@eecs.umich.edu filename, bytesRead, chunkSize, params()->addrRange.size()-curSize); 4555647Sgblack@eecs.umich.edu 4565647Sgblack@eecs.umich.edu assert(bytesRead % sizeof(long) == 0); 4575647Sgblack@eecs.umich.edu 4585647Sgblack@eecs.umich.edu for (int x = 0; x < bytesRead/sizeof(long); x++) 4595647Sgblack@eecs.umich.edu { 4605647Sgblack@eecs.umich.edu if (*(tempPage+x) != 0) { 4615647Sgblack@eecs.umich.edu pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 4625647Sgblack@eecs.umich.edu *pmem_current = *(tempPage+x); 4635647Sgblack@eecs.umich.edu } 4645647Sgblack@eecs.umich.edu } 4655647Sgblack@eecs.umich.edu curSize += bytesRead; 4665647Sgblack@eecs.umich.edu } 4675647Sgblack@eecs.umich.edu 4685647Sgblack@eecs.umich.edu free(tempPage); 4695647Sgblack@eecs.umich.edu 4705647Sgblack@eecs.umich.edu if (gzclose(compressedMem)) 4715647Sgblack@eecs.umich.edu fatal("Close failed on physical memory checkpoint file '%s'\n", 4725647Sgblack@eecs.umich.edu filename); 4735647Sgblack@eecs.umich.edu 4746046Sgblack@eecs.umich.edu} 4756046Sgblack@eecs.umich.edu 4766046Sgblack@eecs.umich.edu 4776046Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4786046Sgblack@eecs.umich.edu 4796046Sgblack@eecs.umich.edu Param<string> file; 4806046Sgblack@eecs.umich.edu Param<Range<Addr> > range; 4816046Sgblack@eecs.umich.edu Param<Tick> latency; 4826046Sgblack@eecs.umich.edu Param<bool> zero; 4836046Sgblack@eecs.umich.edu 4846046Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) 4856712Snate@binkert.org 4866046Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4876046Sgblack@eecs.umich.edu 4886046Sgblack@eecs.umich.edu INIT_PARAM_DFLT(file, "memory mapped file", ""), 4896046Sgblack@eecs.umich.edu INIT_PARAM(range, "Device Address Range"), 4906046Sgblack@eecs.umich.edu INIT_PARAM(latency, "Memory access latency"), 4916046Sgblack@eecs.umich.edu INIT_PARAM(zero, "Zero initialize memory") 4926046Sgblack@eecs.umich.edu 4936065Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) 4946065Sgblack@eecs.umich.edu 4956138Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(PhysicalMemory) 4966138Sgblack@eecs.umich.edu{ 4976046Sgblack@eecs.umich.edu PhysicalMemory::Params *p = new PhysicalMemory::Params; 4986046Sgblack@eecs.umich.edu p->name = getInstanceName(); 4996138Sgblack@eecs.umich.edu p->addrRange = range; 5006138Sgblack@eecs.umich.edu p->latency = latency; 5016138Sgblack@eecs.umich.edu p->zero = zero; 5026138Sgblack@eecs.umich.edu return new PhysicalMemory(p); 5036138Sgblack@eecs.umich.edu} 5046138Sgblack@eecs.umich.edu 5056138Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) 5066138Sgblack@eecs.umich.edu