abstract_mem.cc revision 9405:c0a0593510db
11689SN/A/*
22329SN/A * Copyright (c) 2010-2012 ARM Limited
31689SN/A * All rights reserved
41689SN/A *
51689SN/A * The license below extends only to copyright in the software and shall
61689SN/A * not be construed as granting a license to any other intellectual
71689SN/A * property including but not limited to intellectual property relating
81689SN/A * to a hardware implementation of the functionality of the software
91689SN/A * licensed hereunder.  You may use the software subject to the license
101689SN/A * terms below provided that you ensure that this notice is replicated
111689SN/A * unmodified and in its entirety in all distributions of the software,
121689SN/A * modified or unmodified, in source code or in binary form.
131689SN/A *
141689SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
151689SN/A * All rights reserved.
161689SN/A *
171689SN/A * Redistribution and use in source and binary forms, with or without
181689SN/A * modification, are permitted provided that the following conditions are
191689SN/A * met: redistributions of source code must retain the above copyright
201689SN/A * notice, this list of conditions and the following disclaimer;
211689SN/A * redistributions in binary form must reproduce the above copyright
221689SN/A * notice, this list of conditions and the following disclaimer in the
231689SN/A * documentation and/or other materials provided with the distribution;
241689SN/A * neither the name of the copyright holders nor the names of its
251689SN/A * contributors may be used to endorse or promote products derived from
261689SN/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
291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
318230Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
328230Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
338230Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346658Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
351717SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
368230Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376221Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
381060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396221Snate@binkert.org *
405529Snate@binkert.org * Authors: Ron Dreslinski
411060SN/A *          Ali Saidi
425529Snate@binkert.org *          Andreas Hansson
434329Sktlim@umich.edu */
444329Sktlim@umich.edu
452292SN/A#include "arch/registers.hh"
462292SN/A#include "config/the_isa.hh"
472292SN/A#include "debug/LLSC.hh"
482292SN/A#include "debug/MemoryAccess.hh"
495529Snate@binkert.org#include "mem/abstract_mem.hh"
501060SN/A#include "mem/packet_access.hh"
512292SN/A#include "sim/system.hh"
522292SN/A
532348SN/Ausing namespace std;
546221Snate@binkert.org
556221Snate@binkert.orgAbstractMemory::AbstractMemory(const Params *p) :
562292SN/A    MemObject(p), range(params()->range), pmemAddr(NULL),
576221Snate@binkert.org    confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map),
586221Snate@binkert.org    _system(NULL)
596221Snate@binkert.org{
602292SN/A    if (size() % TheISA::PageBytes != 0)
612292SN/A        panic("Memory Size not divisible by page size\n");
622292SN/A}
632292SN/A
642292SN/Avoid
652292SN/AAbstractMemory::setBackingStore(uint8_t* pmem_addr)
662292SN/A{
672292SN/A    pmemAddr = pmem_addr;
682292SN/A}
692292SN/A
702292SN/Avoid
711060SN/AAbstractMemory::regStats()
721060SN/A{
731062SN/A    using namespace Stats;
741062SN/A
752292SN/A    assert(system());
761062SN/A
771062SN/A    bytesRead
782307SN/A        .init(system()->maxMasters())
791062SN/A        .name(name() + ".bytes_read")
801062SN/A        .desc("Number of bytes read from this memory")
811062SN/A        .flags(total | nozero | nonan)
822307SN/A        ;
831062SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
841062SN/A        bytesRead.subname(i, system()->getMasterName(i));
852292SN/A    }
862307SN/A    bytesInstRead
872292SN/A        .init(system()->maxMasters())
882292SN/A        .name(name() + ".bytes_inst_read")
891062SN/A        .desc("Number of instructions bytes read from this memory")
902307SN/A        .flags(total | nozero | nonan)
911062SN/A        ;
921062SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
931062SN/A        bytesInstRead.subname(i, system()->getMasterName(i));
942307SN/A    }
951062SN/A    bytesWritten
961062SN/A        .init(system()->maxMasters())
972307SN/A        .name(name() + ".bytes_written")
982307SN/A        .desc("Number of bytes written to this memory")
992307SN/A        .flags(total | nozero | nonan)
1002307SN/A        ;
1011062SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1022307SN/A        bytesWritten.subname(i, system()->getMasterName(i));
1031062SN/A    }
1041062SN/A    numReads
1051062SN/A        .init(system()->maxMasters())
1062307SN/A        .name(name() + ".num_reads")
1071062SN/A        .desc("Number of read requests responded to by this memory")
1081062SN/A        .flags(total | nozero | nonan)
1091062SN/A        ;
1101062SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1112307SN/A        numReads.subname(i, system()->getMasterName(i));
1121062SN/A    }
1131062SN/A    numWrites
1141062SN/A        .init(system()->maxMasters())
1152307SN/A        .name(name() + ".num_writes")
1161062SN/A        .desc("Number of write requests responded to by this memory")
1171062SN/A        .flags(total | nozero | nonan)
1181062SN/A        ;
1191062SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1201060SN/A        numWrites.subname(i, system()->getMasterName(i));
1211060SN/A    }
1222292SN/A    numOther
1231060SN/A        .init(system()->maxMasters())
1241060SN/A        .name(name() + ".num_other")
1251060SN/A        .desc("Number of other requests responded to by this memory")
1261060SN/A        .flags(total | nozero | nonan)
1271060SN/A        ;
1281060SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1291060SN/A        numOther.subname(i, system()->getMasterName(i));
1301060SN/A    }
1311060SN/A    bwRead
1321060SN/A        .name(name() + ".bw_read")
1331060SN/A        .desc("Total read bandwidth from this memory (bytes/s)")
1341060SN/A        .precision(0)
1351060SN/A        .prereq(bytesRead)
1361060SN/A        .flags(total | nozero | nonan)
1372292SN/A        ;
1381060SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1391060SN/A        bwRead.subname(i, system()->getMasterName(i));
1401060SN/A    }
1411060SN/A
1421060SN/A    bwInstRead
1431060SN/A        .name(name() + ".bw_inst_read")
1441060SN/A        .desc("Instruction read bandwidth from this memory (bytes/s)")
1451060SN/A        .precision(0)
1461060SN/A        .prereq(bytesInstRead)
1472292SN/A        .flags(total | nozero | nonan)
1481060SN/A        ;
1491060SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1501060SN/A        bwInstRead.subname(i, system()->getMasterName(i));
1511060SN/A    }
1521060SN/A    bwWrite
1531060SN/A        .name(name() + ".bw_write")
1541060SN/A        .desc("Write bandwidth from this memory (bytes/s)")
1551060SN/A        .precision(0)
1562292SN/A        .prereq(bytesWritten)
1576221Snate@binkert.org        .flags(total | nozero | nonan)
1582292SN/A        ;
1592292SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1602292SN/A        bwWrite.subname(i, system()->getMasterName(i));
1612292SN/A    }
1622307SN/A    bwTotal
1632863Sktlim@umich.edu        .name(name() + ".bw_total")
1642843Sktlim@umich.edu        .desc("Total bandwidth to/from this memory (bytes/s)")
1652307SN/A        .precision(0)
1662843Sktlim@umich.edu        .prereq(bwTotal)
1672843Sktlim@umich.edu        .flags(total | nozero | nonan)
1682863Sktlim@umich.edu        ;
1692307SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
1702307SN/A        bwTotal.subname(i, system()->getMasterName(i));
1712307SN/A    }
1722307SN/A    bwRead = bytesRead / simSeconds;
1732307SN/A    bwInstRead = bytesInstRead / simSeconds;
1742307SN/A    bwWrite = bytesWritten / simSeconds;
1752307SN/A    bwTotal = (bytesRead + bytesWritten) / simSeconds;
1762307SN/A}
1772348SN/A
1786221Snate@binkert.orgAddrRange
1796221Snate@binkert.orgAbstractMemory::getAddrRange() const
1802307SN/A{
1816221Snate@binkert.org    return range;
1826221Snate@binkert.org}
1836221Snate@binkert.org
1846221Snate@binkert.org// Add load-locked to tracking list.  Should only be called if the
1856221Snate@binkert.org// operation is a load and the LLSC flag is set.
1866221Snate@binkert.orgvoid
1876221Snate@binkert.orgAbstractMemory::trackLoadLocked(PacketPtr pkt)
1886221Snate@binkert.org{
1892307SN/A    Request *req = pkt->req;
1902307SN/A    Addr paddr = LockedAddr::mask(req->getPaddr());
1912307SN/A
1922307SN/A    // first we check if we already have a locked addr for this
1932292SN/A    // xc.  Since each xc only gets one, we just update the
1942292SN/A    // existing record with the new address.
1956221Snate@binkert.org    list<LockedAddr>::iterator i;
1962292SN/A
1972292SN/A    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
1982292SN/A        if (i->matchesContext(req)) {
1992292SN/A            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
2002292SN/A                    req->contextId(), paddr);
2012292SN/A            i->addr = paddr;
2022292SN/A            return;
2032292SN/A        }
2042292SN/A    }
2052292SN/A
2062292SN/A    // no record for this xc: need to allocate a new one
2072292SN/A    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
2082292SN/A            req->contextId(), paddr);
2092292SN/A    lockedAddrList.push_front(LockedAddr(req));
2102292SN/A}
2112292SN/A
2122292SN/A
2132292SN/A// Called on *writes* only... both regular stores and
2141681SN/A// store-conditional operations.  Check for conventional stores which
2152292SN/A// conflict with locked addresses, and for success/failure of store
2161681SN/A// conditionals.
2171681SN/Abool
2181681SN/AAbstractMemory::checkLockedAddrList(PacketPtr pkt)
2191681SN/A{
2201681SN/A    Request *req = pkt->req;
2212292SN/A    Addr paddr = LockedAddr::mask(req->getPaddr());
2226221Snate@binkert.org    bool isLLSC = pkt->isLLSC();
2231060SN/A
2242292SN/A    // Initialize return value.  Non-conditional stores always
2251060SN/A    // succeed.  Assume conditional stores will fail until proven
2261060SN/A    // otherwise.
2271060SN/A    bool allowStore = !isLLSC;
2282292SN/A
2291060SN/A    // Iterate over list.  Note that there could be multiple matching records,
2302348SN/A    // as more than one context could have done a load locked to this location.
2312348SN/A    // Only remove records when we succeed in finding a record for (xc, addr);
2322348SN/A    // then, remove all records with this address.  Failed store-conditionals do
2332292SN/A    // not blow unrelated reservations.
2342292SN/A    list<LockedAddr>::iterator i = lockedAddrList.begin();
2352292SN/A
2362348SN/A    if (isLLSC) {
2372348SN/A        while (i != lockedAddrList.end()) {
2382348SN/A            if (i->addr == paddr && i->matchesContext(req)) {
2392348SN/A                // it's a store conditional, and as far as the memory system can
2402348SN/A                // tell, the requesting context's lock is still valid.
2412348SN/A                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
2422292SN/A                        req->contextId(), paddr);
2432292SN/A                allowStore = true;
2442292SN/A                break;
2452292SN/A            }
2461060SN/A            // If we didn't find a match, keep searching!  Someone else may well
2471060SN/A            // have a reservation on this line here but we may find ours in just
2481060SN/A            // a little while.
2492292SN/A            i++;
2506221Snate@binkert.org        }
2511060SN/A        req->setExtraData(allowStore ? 1 : 0);
2522292SN/A    }
2532292SN/A    // LLSCs that succeeded AND non-LLSC stores both fall into here:
2542292SN/A    if (allowStore) {
2552292SN/A        // We write address paddr.  However, there may be several entries with a
2562292SN/A        // reservation on this address (for other contextIds) and they must all
2571060SN/A        // be removed.
2582292SN/A        i = lockedAddrList.begin();
2592292SN/A        while (i != lockedAddrList.end()) {
2601060SN/A            if (i->addr == paddr) {
2611681SN/A                DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
2622329SN/A                        i->contextId, paddr);
2632329SN/A                i = lockedAddrList.erase(i);
2642292SN/A            } else {
2651060SN/A                i++;
2661060SN/A            }
2671060SN/A        }
2681060SN/A    }
2696221Snate@binkert.org
2701060SN/A    return allowStore;
2717720Sgblack@eecs.umich.edu}
2727720Sgblack@eecs.umich.edu
2732292SN/A
2742348SN/A#if TRACING_ON
2752292SN/A
2762935Sksewell@umich.edu#define CASE(A, T)                                                      \
2776036Sksewell@umich.edu  case sizeof(T):                                                       \
2782292SN/A    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
2796036Sksewell@umich.edu            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
2807720Sgblack@eecs.umich.edu  break
2816036Sksewell@umich.edu
2823093Sksewell@umich.edu
2832935Sksewell@umich.edu#define TRACE_PACKET(A)                                                 \
2842348SN/A    do {                                                                \
2852292SN/A        switch (pkt->getSize()) {                                       \
2862292SN/A          CASE(A, uint64_t);                                            \
2872292SN/A          CASE(A, uint32_t);                                            \
2882292SN/A          CASE(A, uint16_t);                                            \
2892292SN/A          CASE(A, uint8_t);                                             \
2901060SN/A          default:                                                      \
2912292SN/A            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
2921060SN/A                    A, pkt->getSize(), pkt->getAddr());                 \
2932292SN/A            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
2942292SN/A        }                                                               \
2952935Sksewell@umich.edu    } while (0)
2962731Sktlim@umich.edu
2972292SN/A#else
2982292SN/A
2992292SN/A#define TRACE_PACKET(A)
3002348SN/A
3012348SN/A#endif
3022292SN/A
3032292SN/Avoid
3042292SN/AAbstractMemory::access(PacketPtr pkt)
3051060SN/A{
3062292SN/A    assert(AddrRange(pkt->getAddr(),
3072292SN/A                     pkt->getAddr() + pkt->getSize() - 1).isSubset(range));
3082292SN/A
3092292SN/A    if (pkt->memInhibitAsserted()) {
3102292SN/A        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
3112935Sksewell@umich.edu                pkt->getAddr());
3122292SN/A        return;
3132292SN/A    }
3142292SN/A
3152292SN/A    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
3166221Snate@binkert.org
3172292SN/A    if (pkt->cmd == MemCmd::SwapReq) {
3182292SN/A        TheISA::IntReg overwrite_val;
3192292SN/A        bool overwrite_mem;
3202292SN/A        uint64_t condition_val64;
3212292SN/A        uint32_t condition_val32;
3222292SN/A
3232292SN/A        if (!pmemAddr)
3242292SN/A            panic("Swap only works if there is real memory (i.e. null=False)");
3252292SN/A        assert(sizeof(TheISA::IntReg) >= pkt->getSize());
3262329SN/A
3272292SN/A        overwrite_mem = true;
3282292SN/A        // keep a copy of our possible write value, and copy what is at the
3292292SN/A        // memory address into the packet
3302292SN/A        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
3312292SN/A        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3322292SN/A
3332292SN/A        if (pkt->req->isCondSwap()) {
3342292SN/A            if (pkt->getSize() == sizeof(uint64_t)) {
3352292SN/A                condition_val64 = pkt->req->getExtraData();
3362292SN/A                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
3372292SN/A                                             sizeof(uint64_t));
3382292SN/A            } else if (pkt->getSize() == sizeof(uint32_t)) {
3392292SN/A                condition_val32 = (uint32_t)pkt->req->getExtraData();
3402292SN/A                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
3412292SN/A                                             sizeof(uint32_t));
3422292SN/A            } else
3432292SN/A                panic("Invalid size for conditional read/write\n");
3442292SN/A        }
3452731Sktlim@umich.edu
3462292SN/A        if (overwrite_mem)
3472292SN/A            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
3482292SN/A
3492292SN/A        assert(!pkt->req->isInstFetch());
3502348SN/A        TRACE_PACKET("Read/Write");
3512348SN/A        numOther[pkt->req->masterId()]++;
3522292SN/A    } else if (pkt->isRead()) {
3532292SN/A        assert(!pkt->isWrite());
3542292SN/A        if (pkt->isLLSC()) {
3552292SN/A            trackLoadLocked(pkt);
3562292SN/A        }
3572292SN/A        if (pmemAddr)
3582292SN/A            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3592292SN/A        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
3602292SN/A        numReads[pkt->req->masterId()]++;
3612292SN/A        bytesRead[pkt->req->masterId()] += pkt->getSize();
3622292SN/A        if (pkt->req->isInstFetch())
3632292SN/A            bytesInstRead[pkt->req->masterId()] += pkt->getSize();
3642292SN/A    } else if (pkt->isWrite()) {
3656221Snate@binkert.org        if (writeOK(pkt)) {
3662292SN/A            if (pmemAddr)
3672292SN/A                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
3682292SN/A            assert(!pkt->req->isInstFetch());
3692292SN/A            TRACE_PACKET("Write");
3702292SN/A            numWrites[pkt->req->masterId()]++;
3712292SN/A            bytesWritten[pkt->req->masterId()] += pkt->getSize();
3722292SN/A        }
3732292SN/A    } else if (pkt->isInvalidate()) {
3742292SN/A        // no need to do anything
3752292SN/A    } else {
3767720Sgblack@eecs.umich.edu        panic("unimplemented");
3777720Sgblack@eecs.umich.edu    }
3782292SN/A
3792292SN/A    if (pkt->needsResponse()) {
3802292SN/A        pkt->makeResponse();
3812292SN/A    }
3822329SN/A}
3832292SN/A
3842292SN/Avoid
3852292SN/AAbstractMemory::functionalAccess(PacketPtr pkt)
3862292SN/A{
3872292SN/A    assert(AddrRange(pkt->getAddr(),
3882292SN/A                     pkt->getAddr() + pkt->getSize() - 1).isSubset(range));
3892292SN/A
3902292SN/A    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
3916221Snate@binkert.org
3926221Snate@binkert.org    if (pkt->isRead()) {
3932292SN/A        if (pmemAddr)
3943867Sbinkertn@umich.edu            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3956221Snate@binkert.org        TRACE_PACKET("Read");
3963867Sbinkertn@umich.edu        pkt->makeResponse();
3972292SN/A    } else if (pkt->isWrite()) {
3982292SN/A        if (pmemAddr)
3992292SN/A            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
4002292SN/A        TRACE_PACKET("Write");
4012292SN/A        pkt->makeResponse();
4022292SN/A    } else if (pkt->isPrint()) {
4032292SN/A        Packet::PrintReqState *prs =
4042292SN/A            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
4052292SN/A        assert(prs);
4062292SN/A        // Need to call printLabels() explicitly since we're not going
4072292SN/A        // through printObj().
4082292SN/A        prs->printLabels();
4096221Snate@binkert.org        // Right now we just print the single byte at the specified address.
4106221Snate@binkert.org        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
4112292SN/A    } else {
4123867Sbinkertn@umich.edu        panic("AbstractMemory: unimplemented functional command %s",
4136221Snate@binkert.org              pkt->cmdString());
4142292SN/A    }
4152292SN/A}
4162292SN/A