base.cc revision 3606
1955SN/A/* 2955SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 312230Sgiacomo.travaglini@arm.com * All rights reserved. 49812Sandreas.hansson@arm.com * 59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 149812Sandreas.hansson@arm.com * this software without specific prior written permission. 157816Ssteve.reinhardt@amd.com * 165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 28955SN/A * Authors: Erik Hallnor 29955SN/A */ 30955SN/A 31955SN/A/** 32955SN/A * @file 33955SN/A * Definition of BaseCache functions. 34955SN/A */ 35955SN/A 36955SN/A#include "cpu/base.hh" 37955SN/A#include "cpu/smt.hh" 38955SN/A#include "mem/cache/base_cache.hh" 39955SN/A#include "mem/cache/miss/mshr.hh" 40955SN/A 41955SN/Ausing namespace std; 422665Ssaidi@eecs.umich.edu 432665Ssaidi@eecs.umich.eduBaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, 445863Snate@binkert.org bool _isCpuSide) 45955SN/A : Port(_name, _cache), cache(_cache), isCpuSide(_isCpuSide) 46955SN/A{ 47955SN/A blocked = false; 48955SN/A waitingOnRetry = false; 49955SN/A //Start ports at null if more than one is created we should panic 508878Ssteve.reinhardt@amd.com //cpuSidePort = NULL; 512632Sstever@eecs.umich.edu //memSidePort = NULL; 528878Ssteve.reinhardt@amd.com} 532632Sstever@eecs.umich.edu 54955SN/Avoid 558878Ssteve.reinhardt@amd.comBaseCache::CachePort::recvStatusChange(Port::Status status) 562632Sstever@eecs.umich.edu{ 572761Sstever@eecs.umich.edu cache->recvStatusChange(status, isCpuSide); 582632Sstever@eecs.umich.edu} 592632Sstever@eecs.umich.edu 602632Sstever@eecs.umich.eduvoid 612761Sstever@eecs.umich.eduBaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp, 622761Sstever@eecs.umich.edu AddrRangeList &snoop) 632761Sstever@eecs.umich.edu{ 648878Ssteve.reinhardt@amd.com cache->getAddressRanges(resp, snoop, isCpuSide); 658878Ssteve.reinhardt@amd.com} 662761Sstever@eecs.umich.edu 672761Sstever@eecs.umich.eduint 682761Sstever@eecs.umich.eduBaseCache::CachePort::deviceBlockSize() 692761Sstever@eecs.umich.edu{ 702761Sstever@eecs.umich.edu return cache->getBlockSize(); 718878Ssteve.reinhardt@amd.com} 728878Ssteve.reinhardt@amd.com 732632Sstever@eecs.umich.edubool 742632Sstever@eecs.umich.eduBaseCache::CachePort::recvTiming(PacketPtr pkt) 758878Ssteve.reinhardt@amd.com{ 768878Ssteve.reinhardt@amd.com if (isCpuSide 772632Sstever@eecs.umich.edu && !pkt->req->isUncacheable() 78955SN/A && pkt->isInvalidate() 79955SN/A && !pkt->isRead() && !pkt->isWrite()) { 80955SN/A //Upgrade or Invalidate 8112563Sgabeblack@google.com //Look into what happens if two slave caches on bus 8212563Sgabeblack@google.com DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr()); 836654Snate@binkert.org 8410196SCurtis.Dunham@arm.com assert(!(pkt->flags & SATISFIED)); 85955SN/A pkt->flags |= SATISFIED; 865396Ssaidi@eecs.umich.edu //Invalidates/Upgrades need no response if they get the bus 8711401Sandreas.sandberg@arm.com return true; 885863Snate@binkert.org } 895863Snate@binkert.org 904202Sbinkertn@umich.edu if (pkt->isRequest() && blocked) 915863Snate@binkert.org { 925863Snate@binkert.org DPRINTF(Cache,"Scheduling a retry while blocked\n"); 935863Snate@binkert.org mustSendRetry = true; 945863Snate@binkert.org return false; 95955SN/A } 966654Snate@binkert.org return cache->doTimingAccess(pkt, this, isCpuSide); 975273Sstever@gmail.com} 985871Snate@binkert.org 995273Sstever@gmail.comTick 1006654Snate@binkert.orgBaseCache::CachePort::recvAtomic(PacketPtr pkt) 1015396Ssaidi@eecs.umich.edu{ 1028120Sgblack@eecs.umich.edu return cache->doAtomicAccess(pkt, isCpuSide); 1038120Sgblack@eecs.umich.edu} 1048120Sgblack@eecs.umich.edu 1058120Sgblack@eecs.umich.edubool 1068120Sgblack@eecs.umich.eduBaseCache::CachePort::checkFunctional(PacketPtr pkt) 1078120Sgblack@eecs.umich.edu{ 1088120Sgblack@eecs.umich.edu //Check storage here first 1098120Sgblack@eecs.umich.edu list<PacketPtr>::iterator i = drainList.begin(); 1108879Ssteve.reinhardt@amd.com list<PacketPtr>::iterator iend = drainList.end(); 1118879Ssteve.reinhardt@amd.com bool notDone = true; 1128879Ssteve.reinhardt@amd.com while (i != iend && notDone) { 1138879Ssteve.reinhardt@amd.com PacketPtr target = *i; 1148879Ssteve.reinhardt@amd.com // If the target contains data, and it overlaps the 1158879Ssteve.reinhardt@amd.com // probed request, need to update data 1168879Ssteve.reinhardt@amd.com if (target->intersect(pkt)) { 1178879Ssteve.reinhardt@amd.com notDone = fixPacket(pkt, target); 1188879Ssteve.reinhardt@amd.com } 1198879Ssteve.reinhardt@amd.com i++; 1208879Ssteve.reinhardt@amd.com } 1218879Ssteve.reinhardt@amd.com //Also check the response not yet ready to be on the list 1228879Ssteve.reinhardt@amd.com std::list<std::pair<Tick,PacketPtr> >::iterator j = transmitList.begin(); 1238120Sgblack@eecs.umich.edu std::list<std::pair<Tick,PacketPtr> >::iterator jend = transmitList.end(); 1248120Sgblack@eecs.umich.edu 1258120Sgblack@eecs.umich.edu while (j != jend && notDone) { 1268120Sgblack@eecs.umich.edu PacketPtr target = j->second; 1278120Sgblack@eecs.umich.edu // If the target contains data, and it overlaps the 1288120Sgblack@eecs.umich.edu // probed request, need to update data 1298120Sgblack@eecs.umich.edu if (target->intersect(pkt)) 1308120Sgblack@eecs.umich.edu notDone = fixPacket(pkt, target); 1318120Sgblack@eecs.umich.edu j++; 1328120Sgblack@eecs.umich.edu } 1338120Sgblack@eecs.umich.edu return notDone; 1348120Sgblack@eecs.umich.edu} 1358120Sgblack@eecs.umich.edu 1368120Sgblack@eecs.umich.eduvoid 1378879Ssteve.reinhardt@amd.comBaseCache::CachePort::recvFunctional(PacketPtr pkt) 1388879Ssteve.reinhardt@amd.com{ 1398879Ssteve.reinhardt@amd.com bool notDone = checkFunctional(pkt); 1408879Ssteve.reinhardt@amd.com if (notDone) 14110458Sandreas.hansson@arm.com cache->doFunctionalAccess(pkt, isCpuSide); 14210458Sandreas.hansson@arm.com} 14310458Sandreas.hansson@arm.com 1448879Ssteve.reinhardt@amd.comvoid 1458879Ssteve.reinhardt@amd.comBaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt) 1468879Ssteve.reinhardt@amd.com{ 1478879Ssteve.reinhardt@amd.com bool notDone = checkFunctional(pkt); 1489227Sandreas.hansson@arm.com if (notDone) 1499227Sandreas.hansson@arm.com sendFunctional(pkt); 15012063Sgabeblack@google.com} 15112063Sgabeblack@google.com 15212063Sgabeblack@google.comvoid 1538879Ssteve.reinhardt@amd.comBaseCache::CachePort::recvRetry() 1548879Ssteve.reinhardt@amd.com{ 1558879Ssteve.reinhardt@amd.com PacketPtr pkt; 1568879Ssteve.reinhardt@amd.com assert(waitingOnRetry); 15710453SAndrew.Bardsley@arm.com if (!drainList.empty()) { 15810453SAndrew.Bardsley@arm.com DPRINTF(CachePort, "%s attempting to send a retry for response\n", name()); 15910453SAndrew.Bardsley@arm.com //We have some responses to drain first 16010456SCurtis.Dunham@arm.com if (sendTiming(drainList.front())) { 16110456SCurtis.Dunham@arm.com DPRINTF(CachePort, "%s sucessful in sending a retry for response\n", name()); 16210456SCurtis.Dunham@arm.com drainList.pop_front(); 16310457Sandreas.hansson@arm.com if (!drainList.empty() || 16410457Sandreas.hansson@arm.com !isCpuSide && cache->doMasterRequest() || 16511342Sandreas.hansson@arm.com isCpuSide && cache->doSlaveRequest()) { 16611342Sandreas.hansson@arm.com 1678120Sgblack@eecs.umich.edu DPRINTF(CachePort, "%s has more responses/requests\n", name()); 16812063Sgabeblack@google.com BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false); 16912563Sgabeblack@google.com reqCpu->schedule(curTick + 1); 17012063Sgabeblack@google.com } 17112063Sgabeblack@google.com waitingOnRetry = false; 1725871Snate@binkert.org } 1735871Snate@binkert.org // Check if we're done draining once this list is empty 1746121Snate@binkert.org if (drainList.empty()) 1755871Snate@binkert.org cache->checkDrain(); 1765871Snate@binkert.org } 1779926Sstan.czerniawski@arm.com else if (!isCpuSide) 17812243Sgabeblack@google.com { 1791533SN/A DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name()); 18012246Sgabeblack@google.com if (!cache->doMasterRequest()) { 18112246Sgabeblack@google.com //This can happen if I am the owner of a block and see an upgrade 18212246Sgabeblack@google.com //while the block was in my WB Buffers. I just remove the 18312246Sgabeblack@google.com //wb and de-assert the masterRequest 1849239Sandreas.hansson@arm.com waitingOnRetry = false; 1859239Sandreas.hansson@arm.com return; 1869239Sandreas.hansson@arm.com } 1879239Sandreas.hansson@arm.com pkt = cache->getPacket(); 18812563Sgabeblack@google.com MSHR* mshr = (MSHR*) pkt->senderState; 1899239Sandreas.hansson@arm.com //Copy the packet, it may be modified/destroyed elsewhere 1909239Sandreas.hansson@arm.com PacketPtr copyPkt = new Packet(*pkt); 191955SN/A copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); 192955SN/A mshr->pkt = copyPkt; 1932632Sstever@eecs.umich.edu 1942632Sstever@eecs.umich.edu bool success = sendTiming(pkt); 195955SN/A DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 196955SN/A pkt->getAddr(), success ? "succesful" : "unsuccesful"); 197955SN/A 198955SN/A waitingOnRetry = !success; 1998878Ssteve.reinhardt@amd.com if (waitingOnRetry) { 200955SN/A DPRINTF(CachePort, "%s now waiting on a retry\n", name()); 2012632Sstever@eecs.umich.edu } 2022632Sstever@eecs.umich.edu 2032632Sstever@eecs.umich.edu cache->sendResult(pkt, mshr, success); 2042632Sstever@eecs.umich.edu 2052632Sstever@eecs.umich.edu if (success && cache->doMasterRequest()) 2062632Sstever@eecs.umich.edu { 2072632Sstever@eecs.umich.edu DPRINTF(CachePort, "%s has more requests\n", name()); 2088268Ssteve.reinhardt@amd.com //Still more to issue, rerequest in 1 cycle 2098268Ssteve.reinhardt@amd.com BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false); 2108268Ssteve.reinhardt@amd.com reqCpu->schedule(curTick + 1); 2118268Ssteve.reinhardt@amd.com } 2128268Ssteve.reinhardt@amd.com } 2138268Ssteve.reinhardt@amd.com else 2148268Ssteve.reinhardt@amd.com { 2152632Sstever@eecs.umich.edu assert(cache->doSlaveRequest()); 2162632Sstever@eecs.umich.edu //pkt = cache->getCoherencePacket(); 2172632Sstever@eecs.umich.edu //We save the packet, no reordering on CSHRS 2182632Sstever@eecs.umich.edu pkt = cache->getCoherencePacket(); 2198268Ssteve.reinhardt@amd.com MSHR* cshr = (MSHR*)pkt->senderState; 2202632Sstever@eecs.umich.edu bool success = sendTiming(pkt); 2218268Ssteve.reinhardt@amd.com cache->sendCoherenceResult(pkt, cshr, success); 2228268Ssteve.reinhardt@amd.com waitingOnRetry = !success; 2238268Ssteve.reinhardt@amd.com if (success && cache->doSlaveRequest()) 2248268Ssteve.reinhardt@amd.com { 2253718Sstever@eecs.umich.edu DPRINTF(CachePort, "%s has more requests\n", name()); 2262634Sstever@eecs.umich.edu //Still more to issue, rerequest in 1 cycle 2272634Sstever@eecs.umich.edu BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false); 2285863Snate@binkert.org reqCpu->schedule(curTick + 1); 2292638Sstever@eecs.umich.edu } 2308268Ssteve.reinhardt@amd.com } 2312632Sstever@eecs.umich.edu if (waitingOnRetry) DPRINTF(CachePort, "%s STILL Waiting on retry\n", name()); 2322632Sstever@eecs.umich.edu else DPRINTF(CachePort, "%s no longer waiting on retry\n", name()); 2332632Sstever@eecs.umich.edu return; 2342632Sstever@eecs.umich.edu} 23512563Sgabeblack@google.comvoid 2361858SN/ABaseCache::CachePort::setBlocked() 2373716Sstever@eecs.umich.edu{ 2382638Sstever@eecs.umich.edu assert(!blocked); 2392638Sstever@eecs.umich.edu DPRINTF(Cache, "Cache Blocking\n"); 2402638Sstever@eecs.umich.edu blocked = true; 2412638Sstever@eecs.umich.edu //Clear the retry flag 24212563Sgabeblack@google.com mustSendRetry = false; 24312563Sgabeblack@google.com} 2442638Sstever@eecs.umich.edu 2455863Snate@binkert.orgvoid 2465863Snate@binkert.orgBaseCache::CachePort::clearBlocked() 2475863Snate@binkert.org{ 248955SN/A assert(blocked); 2495341Sstever@gmail.com DPRINTF(Cache, "Cache Unblocking\n"); 2505341Sstever@gmail.com blocked = false; 2515863Snate@binkert.org if (mustSendRetry) 2527756SAli.Saidi@ARM.com { 2535341Sstever@gmail.com DPRINTF(Cache, "Cache Sending Retry\n"); 2546121Snate@binkert.org mustSendRetry = false; 2554494Ssaidi@eecs.umich.edu sendRetry(); 2566121Snate@binkert.org } 2571105SN/A} 2582667Sstever@eecs.umich.edu 2592667Sstever@eecs.umich.eduBaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, bool _newResponse) 2602667Sstever@eecs.umich.edu : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort), 2612667Sstever@eecs.umich.edu newResponse(_newResponse) 2626121Snate@binkert.org{ 2632667Sstever@eecs.umich.edu if (!newResponse) 2645341Sstever@gmail.com this->setFlags(AutoDelete); 2655863Snate@binkert.org pkt = NULL; 2665341Sstever@gmail.com} 2675341Sstever@gmail.com 2685341Sstever@gmail.comvoid 2698120Sgblack@eecs.umich.eduBaseCache::CacheEvent::process() 2705341Sstever@gmail.com{ 2718120Sgblack@eecs.umich.edu if (!newResponse) 2725341Sstever@gmail.com { 2738120Sgblack@eecs.umich.edu if (cachePort->waitingOnRetry) return; 2746121Snate@binkert.org //We have some responses to drain first 2756121Snate@binkert.org if (!cachePort->drainList.empty()) { 2769396Sandreas.hansson@arm.com DPRINTF(CachePort, "%s trying to drain a response\n", cachePort->name()); 2775397Ssaidi@eecs.umich.edu if (cachePort->sendTiming(cachePort->drainList.front())) { 2785397Ssaidi@eecs.umich.edu DPRINTF(CachePort, "%s drains a response succesfully\n", cachePort->name()); 2797727SAli.Saidi@ARM.com cachePort->drainList.pop_front(); 2808268Ssteve.reinhardt@amd.com if (!cachePort->drainList.empty() || 2816168Snate@binkert.org !cachePort->isCpuSide && cachePort->cache->doMasterRequest() || 2825341Sstever@gmail.com cachePort->isCpuSide && cachePort->cache->doSlaveRequest()) { 2838120Sgblack@eecs.umich.edu 2848120Sgblack@eecs.umich.edu DPRINTF(CachePort, "%s still has outstanding bus reqs\n", cachePort->name()); 2858120Sgblack@eecs.umich.edu this->schedule(curTick + 1); 2866814Sgblack@eecs.umich.edu } 2875863Snate@binkert.org } 2888120Sgblack@eecs.umich.edu else { 2895341Sstever@gmail.com cachePort->waitingOnRetry = true; 2905863Snate@binkert.org DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 2918268Ssteve.reinhardt@amd.com } 2926121Snate@binkert.org } 2936121Snate@binkert.org else if (!cachePort->isCpuSide) 2948268Ssteve.reinhardt@amd.com { //MSHR 2955742Snate@binkert.org DPRINTF(CachePort, "%s trying to send a MSHR request\n", cachePort->name()); 2965742Snate@binkert.org if (!cachePort->cache->doMasterRequest()) { 2975341Sstever@gmail.com //This can happen if I am the owner of a block and see an upgrade 2985742Snate@binkert.org //while the block was in my WB Buffers. I just remove the 2995742Snate@binkert.org //wb and de-assert the masterRequest 3005341Sstever@gmail.com return; 3016017Snate@binkert.org } 3026121Snate@binkert.org 3036017Snate@binkert.org pkt = cachePort->cache->getPacket(); 30412158Sandreas.sandberg@arm.com MSHR* mshr = (MSHR*) pkt->senderState; 30512158Sandreas.sandberg@arm.com //Copy the packet, it may be modified/destroyed elsewhere 30612158Sandreas.sandberg@arm.com PacketPtr copyPkt = new Packet(*pkt); 3078120Sgblack@eecs.umich.edu copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>()); 3087756SAli.Saidi@ARM.com mshr->pkt = copyPkt; 3097756SAli.Saidi@ARM.com 3107756SAli.Saidi@ARM.com bool success = cachePort->sendTiming(pkt); 3117756SAli.Saidi@ARM.com DPRINTF(Cache, "Address %x was %s in sending the timing request\n", 3127816Ssteve.reinhardt@amd.com pkt->getAddr(), success ? "succesful" : "unsuccesful"); 3137816Ssteve.reinhardt@amd.com 3147816Ssteve.reinhardt@amd.com cachePort->waitingOnRetry = !success; 3157816Ssteve.reinhardt@amd.com if (cachePort->waitingOnRetry) { 3167816Ssteve.reinhardt@amd.com DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 31711979Sgabeblack@google.com } 3187816Ssteve.reinhardt@amd.com 3197816Ssteve.reinhardt@amd.com cachePort->cache->sendResult(pkt, mshr, success); 3207816Ssteve.reinhardt@amd.com if (success && cachePort->cache->doMasterRequest()) 3217816Ssteve.reinhardt@amd.com { 3227756SAli.Saidi@ARM.com DPRINTF(CachePort, "%s still more MSHR requests to send\n", 3237756SAli.Saidi@ARM.com cachePort->name()); 3249227Sandreas.hansson@arm.com //Still more to issue, rerequest in 1 cycle 3259227Sandreas.hansson@arm.com pkt = NULL; 3269227Sandreas.hansson@arm.com this->schedule(curTick+1); 3279227Sandreas.hansson@arm.com } 3289590Sandreas@sandberg.pp.se } 3299590Sandreas@sandberg.pp.se else 3309590Sandreas@sandberg.pp.se { 3319590Sandreas@sandberg.pp.se //CSHR 3329590Sandreas@sandberg.pp.se assert(cachePort->cache->doSlaveRequest()); 3339590Sandreas@sandberg.pp.se pkt = cachePort->cache->getCoherencePacket(); 3346654Snate@binkert.org MSHR* cshr = (MSHR*) pkt->senderState; 3356654Snate@binkert.org bool success = cachePort->sendTiming(pkt); 3365871Snate@binkert.org cachePort->cache->sendCoherenceResult(pkt, cshr, success); 3376121Snate@binkert.org cachePort->waitingOnRetry = !success; 3388946Sandreas.hansson@arm.com if (cachePort->waitingOnRetry) 3399419Sandreas.hansson@arm.com DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name()); 34012563Sgabeblack@google.com if (success && cachePort->cache->doSlaveRequest()) 3413918Ssaidi@eecs.umich.edu { 3423918Ssaidi@eecs.umich.edu DPRINTF(CachePort, "%s still more CSHR requests to send\n", 3431858SN/A cachePort->name()); 3449556Sandreas.hansson@arm.com //Still more to issue, rerequest in 1 cycle 3459556Sandreas.hansson@arm.com pkt = NULL; 3469556Sandreas.hansson@arm.com this->schedule(curTick+1); 3479556Sandreas.hansson@arm.com } 34811294Sandreas.hansson@arm.com } 34911294Sandreas.hansson@arm.com return; 35011294Sandreas.hansson@arm.com } 35111294Sandreas.hansson@arm.com //Else it's a response Response 35210878Sandreas.hansson@arm.com assert(cachePort->transmitList.size()); 35310878Sandreas.hansson@arm.com assert(cachePort->transmitList.front().first <= curTick); 35411811Sbaz21@cam.ac.uk pkt = cachePort->transmitList.front().second; 35511811Sbaz21@cam.ac.uk cachePort->transmitList.pop_front(); 35611811Sbaz21@cam.ac.uk if (!cachePort->transmitList.empty()) { 35711982Sgabeblack@google.com Tick time = cachePort->transmitList.front().first; 35811982Sgabeblack@google.com schedule(time <= curTick ? curTick+1 : time); 35911982Sgabeblack@google.com } 36011982Sgabeblack@google.com 36111992Sgabeblack@google.com if (pkt->flags & NACKED_LINE) 36211982Sgabeblack@google.com pkt->result = Packet::Nacked; 36311982Sgabeblack@google.com else 36412305Sgabeblack@google.com pkt->result = Packet::Success; 36512305Sgabeblack@google.com pkt->makeTimingResponse(); 36612305Sgabeblack@google.com DPRINTF(CachePort, "%s attempting to send a response\n", cachePort->name()); 36712305Sgabeblack@google.com if (!cachePort->drainList.empty() || cachePort->waitingOnRetry) { 36812305Sgabeblack@google.com //Already have a list, just append 36912305Sgabeblack@google.com cachePort->drainList.push_back(pkt); 37012305Sgabeblack@google.com DPRINTF(CachePort, "%s appending response onto drain list\n", cachePort->name()); 3719556Sandreas.hansson@arm.com } 37212563Sgabeblack@google.com else if (!cachePort->sendTiming(pkt)) { 37312563Sgabeblack@google.com //It failed, save it to list of drain events 37412563Sgabeblack@google.com DPRINTF(CachePort, "%s now waiting for a retry\n", cachePort->name()); 37512563Sgabeblack@google.com cachePort->drainList.push_back(pkt); 3769556Sandreas.hansson@arm.com cachePort->waitingOnRetry = true; 37712563Sgabeblack@google.com } 37812563Sgabeblack@google.com 3799556Sandreas.hansson@arm.com // Check if we're done draining once this list is empty 38012563Sgabeblack@google.com if (cachePort->drainList.empty() && cachePort->transmitList.empty()) 38112563Sgabeblack@google.com cachePort->cache->checkDrain(); 38212563Sgabeblack@google.com} 38312563Sgabeblack@google.com 38412563Sgabeblack@google.comconst char * 38512563Sgabeblack@google.comBaseCache::CacheEvent::description() 38612563Sgabeblack@google.com{ 38712563Sgabeblack@google.com return "timing event\n"; 3889556Sandreas.hansson@arm.com} 3899556Sandreas.hansson@arm.com 3906121Snate@binkert.orgPort* 39111500Sandreas.hansson@arm.comBaseCache::getPort(const std::string &if_name, int idx) 39210238Sandreas.hansson@arm.com{ 39310878Sandreas.hansson@arm.com if (if_name == "") 3949420Sandreas.hansson@arm.com { 39511500Sandreas.hansson@arm.com if(cpuSidePort == NULL) { 39612563Sgabeblack@google.com cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 39712563Sgabeblack@google.com sendEvent = new CacheEvent(cpuSidePort, true); 3989420Sandreas.hansson@arm.com } 3999420Sandreas.hansson@arm.com return cpuSidePort; 4009420Sandreas.hansson@arm.com } 4019420Sandreas.hansson@arm.com else if (if_name == "functional") 40212063Sgabeblack@google.com { 40312063Sgabeblack@google.com return new CachePort(name() + "-cpu_side_port", this, true); 40412063Sgabeblack@google.com } 40512063Sgabeblack@google.com else if (if_name == "cpu_side") 40612063Sgabeblack@google.com { 40712063Sgabeblack@google.com if(cpuSidePort == NULL) { 40812063Sgabeblack@google.com cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); 40912063Sgabeblack@google.com sendEvent = new CacheEvent(cpuSidePort, true); 41012063Sgabeblack@google.com } 41112063Sgabeblack@google.com return cpuSidePort; 41212063Sgabeblack@google.com } 41312063Sgabeblack@google.com else if (if_name == "mem_side") 41412063Sgabeblack@google.com { 41512063Sgabeblack@google.com if (memSidePort != NULL) 41612063Sgabeblack@google.com panic("Already have a mem side for this cache\n"); 41712063Sgabeblack@google.com memSidePort = new CachePort(name() + "-mem_side_port", this, false); 41812063Sgabeblack@google.com memSendEvent = new CacheEvent(memSidePort, true); 41912063Sgabeblack@google.com return memSidePort; 42012063Sgabeblack@google.com } 42112063Sgabeblack@google.com else panic("Port name %s unrecognized\n", if_name); 42212063Sgabeblack@google.com} 42312063Sgabeblack@google.com 42410264Sandreas.hansson@arm.comvoid 42510264Sandreas.hansson@arm.comBaseCache::init() 42610264Sandreas.hansson@arm.com{ 42710264Sandreas.hansson@arm.com if (!cpuSidePort || !memSidePort) 42811925Sgabeblack@google.com panic("Cache not hooked up on both sides\n"); 42911925Sgabeblack@google.com cpuSidePort->sendStatusChange(Port::RangeChange); 43011500Sandreas.hansson@arm.com} 43110264Sandreas.hansson@arm.com 43211500Sandreas.hansson@arm.comvoid 43311500Sandreas.hansson@arm.comBaseCache::regStats() 43411500Sandreas.hansson@arm.com{ 43511500Sandreas.hansson@arm.com Request temp_req((Addr) NULL, 4, 0); 43610866Sandreas.hansson@arm.com Packet::Command temp_cmd = Packet::ReadReq; 43711500Sandreas.hansson@arm.com Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary 43812563Sgabeblack@google.com temp_pkt.allocate(); //Temp allocate, all need data 43912563Sgabeblack@google.com 44012563Sgabeblack@google.com using namespace Stats; 44112563Sgabeblack@google.com 44212563Sgabeblack@google.com // Hit statistics 44312563Sgabeblack@google.com for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 44410264Sandreas.hansson@arm.com Packet::Command cmd = (Packet::Command)access_idx; 44510457Sandreas.hansson@arm.com const string &cstr = temp_pkt.cmdIdxToString(cmd); 44610457Sandreas.hansson@arm.com 44710457Sandreas.hansson@arm.com hits[access_idx] 44810457Sandreas.hansson@arm.com .init(maxThreadsPerCPU) 44910457Sandreas.hansson@arm.com .name(name() + "." + cstr + "_hits") 45012563Sgabeblack@google.com .desc("number of " + cstr + " hits") 45112563Sgabeblack@google.com .flags(total | nozero | nonan) 45212563Sgabeblack@google.com ; 45310457Sandreas.hansson@arm.com } 45412063Sgabeblack@google.com 45512063Sgabeblack@google.com demandHits 45612063Sgabeblack@google.com .name(name() + ".demand_hits") 45712563Sgabeblack@google.com .desc("number of demand (read+write) hits") 45812563Sgabeblack@google.com .flags(total) 45912563Sgabeblack@google.com ; 46012563Sgabeblack@google.com demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; 46112563Sgabeblack@google.com 46212563Sgabeblack@google.com overallHits 46312063Sgabeblack@google.com .name(name() + ".overall_hits") 46412063Sgabeblack@google.com .desc("number of overall hits") 46510238Sandreas.hansson@arm.com .flags(total) 46610238Sandreas.hansson@arm.com ; 46710238Sandreas.hansson@arm.com overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] 46812063Sgabeblack@google.com + hits[Packet::Writeback]; 46910238Sandreas.hansson@arm.com 47010238Sandreas.hansson@arm.com // Miss statistics 47110416Sandreas.hansson@arm.com for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 47210238Sandreas.hansson@arm.com Packet::Command cmd = (Packet::Command)access_idx; 4739227Sandreas.hansson@arm.com const string &cstr = temp_pkt.cmdIdxToString(cmd); 47410238Sandreas.hansson@arm.com 47510416Sandreas.hansson@arm.com misses[access_idx] 47610416Sandreas.hansson@arm.com .init(maxThreadsPerCPU) 4779227Sandreas.hansson@arm.com .name(name() + "." + cstr + "_misses") 4789590Sandreas@sandberg.pp.se .desc("number of " + cstr + " misses") 4799590Sandreas@sandberg.pp.se .flags(total | nozero | nonan) 4809590Sandreas@sandberg.pp.se ; 48112304Sgabeblack@google.com } 48212304Sgabeblack@google.com 48312304Sgabeblack@google.com demandMisses 48412688Sgiacomo.travaglini@arm.com .name(name() + ".demand_misses") 48512688Sgiacomo.travaglini@arm.com .desc("number of demand (read+write) misses") 48612688Sgiacomo.travaglini@arm.com .flags(total) 48712304Sgabeblack@google.com ; 48812304Sgabeblack@google.com demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; 48912688Sgiacomo.travaglini@arm.com 49012688Sgiacomo.travaglini@arm.com overallMisses 49112304Sgabeblack@google.com .name(name() + ".overall_misses") 49212304Sgabeblack@google.com .desc("number of overall misses") 49312304Sgabeblack@google.com .flags(total) 49412304Sgabeblack@google.com ; 49512304Sgabeblack@google.com overallMisses = demandMisses + misses[Packet::SoftPFReq] + 49612688Sgiacomo.travaglini@arm.com misses[Packet::HardPFReq] + misses[Packet::Writeback]; 49712688Sgiacomo.travaglini@arm.com 49812688Sgiacomo.travaglini@arm.com // Miss latency statistics 49912304Sgabeblack@google.com for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 5008737Skoansin.tan@gmail.com Packet::Command cmd = (Packet::Command)access_idx; 50110878Sandreas.hansson@arm.com const string &cstr = temp_pkt.cmdIdxToString(cmd); 50211500Sandreas.hansson@arm.com 5039420Sandreas.hansson@arm.com missLatency[access_idx] 5048737Skoansin.tan@gmail.com .init(maxThreadsPerCPU) 50510106SMitch.Hayenga@arm.com .name(name() + "." + cstr + "_miss_latency") 5068737Skoansin.tan@gmail.com .desc("number of " + cstr + " miss cycles") 5078737Skoansin.tan@gmail.com .flags(total | nozero | nonan) 50810878Sandreas.hansson@arm.com ; 50912563Sgabeblack@google.com } 51012563Sgabeblack@google.com 5118737Skoansin.tan@gmail.com demandMissLatency 5128737Skoansin.tan@gmail.com .name(name() + ".demand_miss_latency") 51312563Sgabeblack@google.com .desc("number of demand (read+write) miss cycles") 5148737Skoansin.tan@gmail.com .flags(total) 5158737Skoansin.tan@gmail.com ; 51611294Sandreas.hansson@arm.com demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; 5179556Sandreas.hansson@arm.com 5189556Sandreas.hansson@arm.com overallMissLatency 5199556Sandreas.hansson@arm.com .name(name() + ".overall_miss_latency") 52011294Sandreas.hansson@arm.com .desc("number of overall miss cycles") 52110278SAndreas.Sandberg@ARM.com .flags(total) 52210278SAndreas.Sandberg@ARM.com ; 52310278SAndreas.Sandberg@ARM.com overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + 52410278SAndreas.Sandberg@ARM.com missLatency[Packet::HardPFReq]; 52510278SAndreas.Sandberg@ARM.com 52610278SAndreas.Sandberg@ARM.com // access formulas 5279556Sandreas.hansson@arm.com for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 5289590Sandreas@sandberg.pp.se Packet::Command cmd = (Packet::Command)access_idx; 5299590Sandreas@sandberg.pp.se const string &cstr = temp_pkt.cmdIdxToString(cmd); 5309420Sandreas.hansson@arm.com 5319846Sandreas.hansson@arm.com accesses[access_idx] 5329846Sandreas.hansson@arm.com .name(name() + "." + cstr + "_accesses") 5339846Sandreas.hansson@arm.com .desc("number of " + cstr + " accesses(hits+misses)") 5349846Sandreas.hansson@arm.com .flags(total | nozero | nonan) 5358946Sandreas.hansson@arm.com ; 53611811Sbaz21@cam.ac.uk 53711811Sbaz21@cam.ac.uk accesses[access_idx] = hits[access_idx] + misses[access_idx]; 53811811Sbaz21@cam.ac.uk } 53911811Sbaz21@cam.ac.uk 54012304Sgabeblack@google.com demandAccesses 54112304Sgabeblack@google.com .name(name() + ".demand_accesses") 54212304Sgabeblack@google.com .desc("number of demand (read+write) accesses") 54312304Sgabeblack@google.com .flags(total) 54412304Sgabeblack@google.com ; 54512304Sgabeblack@google.com demandAccesses = demandHits + demandMisses; 54612304Sgabeblack@google.com 54712304Sgabeblack@google.com overallAccesses 54812304Sgabeblack@google.com .name(name() + ".overall_accesses") 54912304Sgabeblack@google.com .desc("number of overall (read+write) accesses") 55012304Sgabeblack@google.com .flags(total) 55112304Sgabeblack@google.com ; 55212304Sgabeblack@google.com overallAccesses = overallHits + overallMisses; 55312304Sgabeblack@google.com 55412304Sgabeblack@google.com // miss rate formulas 55512304Sgabeblack@google.com for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 5563918Ssaidi@eecs.umich.edu Packet::Command cmd = (Packet::Command)access_idx; 55712563Sgabeblack@google.com const string &cstr = temp_pkt.cmdIdxToString(cmd); 55812563Sgabeblack@google.com 55912563Sgabeblack@google.com missRate[access_idx] 56012563Sgabeblack@google.com .name(name() + "." + cstr + "_miss_rate") 5619068SAli.Saidi@ARM.com .desc("miss rate for " + cstr + " accesses") 56212563Sgabeblack@google.com .flags(total | nozero | nonan) 56312563Sgabeblack@google.com ; 5649068SAli.Saidi@ARM.com 56512563Sgabeblack@google.com missRate[access_idx] = misses[access_idx] / accesses[access_idx]; 56612563Sgabeblack@google.com } 56712563Sgabeblack@google.com 56812563Sgabeblack@google.com demandMissRate 56912563Sgabeblack@google.com .name(name() + ".demand_miss_rate") 57012563Sgabeblack@google.com .desc("miss rate for demand accesses") 57112563Sgabeblack@google.com .flags(total) 57212563Sgabeblack@google.com ; 5733918Ssaidi@eecs.umich.edu demandMissRate = demandMisses / demandAccesses; 5743918Ssaidi@eecs.umich.edu 5756157Snate@binkert.org overallMissRate 5766157Snate@binkert.org .name(name() + ".overall_miss_rate") 5776157Snate@binkert.org .desc("miss rate for overall accesses") 5786157Snate@binkert.org .flags(total) 5795397Ssaidi@eecs.umich.edu ; 5805397Ssaidi@eecs.umich.edu overallMissRate = overallMisses / overallAccesses; 5816121Snate@binkert.org 5826121Snate@binkert.org // miss latency formulas 5836121Snate@binkert.org for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { 5846121Snate@binkert.org Packet::Command cmd = (Packet::Command)access_idx; 5856121Snate@binkert.org const string &cstr = temp_pkt.cmdIdxToString(cmd); 5866121Snate@binkert.org 5875397Ssaidi@eecs.umich.edu avgMissLatency[access_idx] 5881851SN/A .name(name() + "." + cstr + "_avg_miss_latency") 5891851SN/A .desc("average " + cstr + " miss latency") 5907739Sgblack@eecs.umich.edu .flags(total | nozero | nonan) 591955SN/A ; 5929396Sandreas.hansson@arm.com 5939396Sandreas.hansson@arm.com avgMissLatency[access_idx] = 5949396Sandreas.hansson@arm.com missLatency[access_idx] / misses[access_idx]; 5959396Sandreas.hansson@arm.com } 5969396Sandreas.hansson@arm.com 5979396Sandreas.hansson@arm.com demandAvgMissLatency 59812563Sgabeblack@google.com .name(name() + ".demand_avg_miss_latency") 59912563Sgabeblack@google.com .desc("average overall miss latency") 60012563Sgabeblack@google.com .flags(total) 60112563Sgabeblack@google.com ; 6029396Sandreas.hansson@arm.com demandAvgMissLatency = demandMissLatency / demandMisses; 6039396Sandreas.hansson@arm.com 6049396Sandreas.hansson@arm.com overallAvgMissLatency 6059396Sandreas.hansson@arm.com .name(name() + ".overall_avg_miss_latency") 6069396Sandreas.hansson@arm.com .desc("average overall miss latency") 6079396Sandreas.hansson@arm.com .flags(total) 60812563Sgabeblack@google.com ; 60912563Sgabeblack@google.com overallAvgMissLatency = overallMissLatency / overallMisses; 61012563Sgabeblack@google.com 61112563Sgabeblack@google.com blocked_cycles.init(NUM_BLOCKED_CAUSES); 61212563Sgabeblack@google.com blocked_cycles 6139477Sandreas.hansson@arm.com .name(name() + ".blocked_cycles") 6149477Sandreas.hansson@arm.com .desc("number of cycles access was blocked") 6159477Sandreas.hansson@arm.com .subname(Blocked_NoMSHRs, "no_mshrs") 6169477Sandreas.hansson@arm.com .subname(Blocked_NoTargets, "no_targets") 6179477Sandreas.hansson@arm.com ; 6189477Sandreas.hansson@arm.com 6199477Sandreas.hansson@arm.com 6209477Sandreas.hansson@arm.com blocked_causes.init(NUM_BLOCKED_CAUSES); 6219477Sandreas.hansson@arm.com blocked_causes 6229477Sandreas.hansson@arm.com .name(name() + ".blocked") 6239477Sandreas.hansson@arm.com .desc("number of cycles access was blocked") 6249477Sandreas.hansson@arm.com .subname(Blocked_NoMSHRs, "no_mshrs") 6259477Sandreas.hansson@arm.com .subname(Blocked_NoTargets, "no_targets") 6269477Sandreas.hansson@arm.com ; 62712563Sgabeblack@google.com 62812563Sgabeblack@google.com avg_blocked 62912563Sgabeblack@google.com .name(name() + ".avg_blocked_cycles") 6309396Sandreas.hansson@arm.com .desc("average number of cycles each access was blocked") 6312667Sstever@eecs.umich.edu .subname(Blocked_NoMSHRs, "no_mshrs") 63210710Sandreas.hansson@arm.com .subname(Blocked_NoTargets, "no_targets") 63310710Sandreas.hansson@arm.com ; 63410710Sandreas.hansson@arm.com 63511811Sbaz21@cam.ac.uk avg_blocked = blocked_cycles / blocked_causes; 63611811Sbaz21@cam.ac.uk 63711811Sbaz21@cam.ac.uk fastWrites 63811811Sbaz21@cam.ac.uk .name(name() + ".fast_writes") 63911811Sbaz21@cam.ac.uk .desc("number of fast writes performed") 64011811Sbaz21@cam.ac.uk ; 64110710Sandreas.hansson@arm.com 64210710Sandreas.hansson@arm.com cacheCopies 64310710Sandreas.hansson@arm.com .name(name() + ".cache_copies") 64410710Sandreas.hansson@arm.com .desc("number of cache copies performed") 64510384SCurtis.Dunham@arm.com ; 6469986Sandreas@sandberg.pp.se 6479986Sandreas@sandberg.pp.se} 6489986Sandreas@sandberg.pp.se 6499986Sandreas@sandberg.pp.seunsigned int 6509986Sandreas@sandberg.pp.seBaseCache::drain(Event *de) 6519986Sandreas@sandberg.pp.se{ 6529986Sandreas@sandberg.pp.se // Set status 6539986Sandreas@sandberg.pp.se if (!canDrain()) { 6549986Sandreas@sandberg.pp.se drainEvent = de; 6559986Sandreas@sandberg.pp.se 6569986Sandreas@sandberg.pp.se changeState(SimObject::Draining); 6579986Sandreas@sandberg.pp.se return 1; 6589986Sandreas@sandberg.pp.se } 6599986Sandreas@sandberg.pp.se 6609986Sandreas@sandberg.pp.se changeState(SimObject::Drained); 6619986Sandreas@sandberg.pp.se return 0; 6629986Sandreas@sandberg.pp.se} 6639986Sandreas@sandberg.pp.se