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 &section)
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