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