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