mshr_queue.cc revision 10768
111986Sandreas.sandberg@arm.com/*
212037Sandreas.sandberg@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited
311986Sandreas.sandberg@arm.com * All rights reserved.
411986Sandreas.sandberg@arm.com *
511986Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
612037Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
712037Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
811986Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
912037Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1012037Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1111986Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1212037Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1312037Sandreas.sandberg@arm.com *
1411986Sandreas.sandberg@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
1512037Sandreas.sandberg@arm.com * All rights reserved.
1612037Sandreas.sandberg@arm.com *
1712037Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
1812037Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
1912037Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
2011986Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
2112037Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
2212037Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
2311986Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
2412037Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
2512037Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
2611986Sandreas.sandberg@arm.com * this software without specific prior written permission.
2712037Sandreas.sandberg@arm.com *
2812037Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912037Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012037Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3112037Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3212037Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3312037Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412037Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512037Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612037Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712037Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3812037Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3912037Sandreas.sandberg@arm.com *
4012037Sandreas.sandberg@arm.com * Authors: Erik Hallnor
4112037Sandreas.sandberg@arm.com *          Andreas Sandberg
4212037Sandreas.sandberg@arm.com */
4312037Sandreas.sandberg@arm.com
4412037Sandreas.sandberg@arm.com/** @file
4512037Sandreas.sandberg@arm.com * Definition of MSHRQueue class functions.
4612037Sandreas.sandberg@arm.com */
4712037Sandreas.sandberg@arm.com
4812037Sandreas.sandberg@arm.com#include "base/trace.hh"
4912037Sandreas.sandberg@arm.com#include "mem/cache/mshr_queue.hh"
5012037Sandreas.sandberg@arm.com#include "debug/Drain.hh"
5112037Sandreas.sandberg@arm.com
5212037Sandreas.sandberg@arm.comusing namespace std;
5312037Sandreas.sandberg@arm.com
5412037Sandreas.sandberg@arm.comMSHRQueue::MSHRQueue(const std::string &_label,
5512037Sandreas.sandberg@arm.com                     int num_entries, int reserve, int demand_reserve,
5612037Sandreas.sandberg@arm.com                     int _index)
5711986Sandreas.sandberg@arm.com    : label(_label), numEntries(num_entries + reserve - 1),
5811986Sandreas.sandberg@arm.com      numReserve(reserve), demandReserve(demand_reserve),
5911986Sandreas.sandberg@arm.com      registers(numEntries), drainManager(NULL), allocated(0),
6012391Sjason@lowepower.com      inServiceEntries(0), index(_index)
6111986Sandreas.sandberg@arm.com{
6211986Sandreas.sandberg@arm.com    for (int i = 0; i < numEntries; ++i) {
6311986Sandreas.sandberg@arm.com        registers[i].queue = this;
6412037Sandreas.sandberg@arm.com        freeList.push_back(&registers[i]);
6512037Sandreas.sandberg@arm.com    }
6612037Sandreas.sandberg@arm.com}
6712037Sandreas.sandberg@arm.com
6812037Sandreas.sandberg@arm.comMSHR *
6912037Sandreas.sandberg@arm.comMSHRQueue::findMatch(Addr blk_addr, bool is_secure) const
7012037Sandreas.sandberg@arm.com{
7112037Sandreas.sandberg@arm.com    for (const auto& mshr : allocatedList) {
7212037Sandreas.sandberg@arm.com        // we ignore any MSHRs allocated for uncacheable accesses and
7312037Sandreas.sandberg@arm.com        // simply ignore them when matching, in the cache we never
7412037Sandreas.sandberg@arm.com        // check for matches when adding new uncacheable entries, and
7512037Sandreas.sandberg@arm.com        // we do not want normal cacheable accesses being added to an
7612037Sandreas.sandberg@arm.com        // MSHR serving an uncacheable access
7712037Sandreas.sandberg@arm.com        if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
7812037Sandreas.sandberg@arm.com            mshr->isSecure == is_secure) {
7912037Sandreas.sandberg@arm.com            return mshr;
8012037Sandreas.sandberg@arm.com        }
8112037Sandreas.sandberg@arm.com    }
8212037Sandreas.sandberg@arm.com    return NULL;
8312037Sandreas.sandberg@arm.com}
8412037Sandreas.sandberg@arm.com
8512037Sandreas.sandberg@arm.combool
8612037Sandreas.sandberg@arm.comMSHRQueue::findMatches(Addr blk_addr, bool is_secure,
8712037Sandreas.sandberg@arm.com                       vector<MSHR*>& matches) const
8812037Sandreas.sandberg@arm.com{
8912037Sandreas.sandberg@arm.com    // Need an empty vector
9012037Sandreas.sandberg@arm.com    assert(matches.empty());
9112037Sandreas.sandberg@arm.com    bool retval = false;
9212037Sandreas.sandberg@arm.com    for (const auto& mshr : allocatedList) {
9312037Sandreas.sandberg@arm.com        if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
9412037Sandreas.sandberg@arm.com            mshr->isSecure == is_secure) {
9512037Sandreas.sandberg@arm.com            retval = true;
9612037Sandreas.sandberg@arm.com            matches.push_back(mshr);
9712037Sandreas.sandberg@arm.com        }
9812037Sandreas.sandberg@arm.com    }
9912037Sandreas.sandberg@arm.com    return retval;
10012037Sandreas.sandberg@arm.com}
10112037Sandreas.sandberg@arm.com
10212037Sandreas.sandberg@arm.com
10312037Sandreas.sandberg@arm.combool
10412037Sandreas.sandberg@arm.comMSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
10512037Sandreas.sandberg@arm.com{
10612037Sandreas.sandberg@arm.com    pkt->pushLabel(label);
10712037Sandreas.sandberg@arm.com    for (const auto& mshr : allocatedList) {
10812037Sandreas.sandberg@arm.com        if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) {
10912037Sandreas.sandberg@arm.com            pkt->popLabel();
11012037Sandreas.sandberg@arm.com            return true;
11112037Sandreas.sandberg@arm.com        }
11212037Sandreas.sandberg@arm.com    }
11312037Sandreas.sandberg@arm.com    pkt->popLabel();
11412037Sandreas.sandberg@arm.com    return false;
11512037Sandreas.sandberg@arm.com}
11612037Sandreas.sandberg@arm.com
11712037Sandreas.sandberg@arm.com
11812037Sandreas.sandberg@arm.comMSHR *
11912037Sandreas.sandberg@arm.comMSHRQueue::findPending(Addr blk_addr, bool is_secure) const
12012037Sandreas.sandberg@arm.com{
12112037Sandreas.sandberg@arm.com    for (const auto& mshr : readyList) {
12212037Sandreas.sandberg@arm.com        if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
12312037Sandreas.sandberg@arm.com            return mshr;
12412037Sandreas.sandberg@arm.com        }
12512037Sandreas.sandberg@arm.com    }
12612037Sandreas.sandberg@arm.com    return NULL;
12712037Sandreas.sandberg@arm.com}
12812037Sandreas.sandberg@arm.com
12912037Sandreas.sandberg@arm.com
13012037Sandreas.sandberg@arm.comMSHR::Iterator
13112037Sandreas.sandberg@arm.comMSHRQueue::addToReadyList(MSHR *mshr)
13212037Sandreas.sandberg@arm.com{
13312037Sandreas.sandberg@arm.com    if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
13412037Sandreas.sandberg@arm.com        return readyList.insert(readyList.end(), mshr);
13512037Sandreas.sandberg@arm.com    }
13612037Sandreas.sandberg@arm.com
13712037Sandreas.sandberg@arm.com    for (auto i = readyList.begin(); i != readyList.end(); ++i) {
13812037Sandreas.sandberg@arm.com        if ((*i)->readyTime > mshr->readyTime) {
13912037Sandreas.sandberg@arm.com            return readyList.insert(i, mshr);
14012037Sandreas.sandberg@arm.com        }
14112037Sandreas.sandberg@arm.com    }
14212037Sandreas.sandberg@arm.com    assert(false);
14312037Sandreas.sandberg@arm.com    return readyList.end();  // keep stupid compilers happy
14412037Sandreas.sandberg@arm.com}
14512037Sandreas.sandberg@arm.com
14612037Sandreas.sandberg@arm.com
14712037Sandreas.sandberg@arm.comMSHR *
14812037Sandreas.sandberg@arm.comMSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
14912037Sandreas.sandberg@arm.com                    Tick when_ready, Counter order)
15012037Sandreas.sandberg@arm.com{
15112037Sandreas.sandberg@arm.com    assert(!freeList.empty());
15212037Sandreas.sandberg@arm.com    MSHR *mshr = freeList.front();
15312037Sandreas.sandberg@arm.com    assert(mshr->getNumTargets() == 0);
15412037Sandreas.sandberg@arm.com    freeList.pop_front();
15512037Sandreas.sandberg@arm.com
15612037Sandreas.sandberg@arm.com    mshr->allocate(blk_addr, blk_size, pkt, when_ready, order);
15712037Sandreas.sandberg@arm.com    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
15812037Sandreas.sandberg@arm.com    mshr->readyIter = addToReadyList(mshr);
15912037Sandreas.sandberg@arm.com
16012037Sandreas.sandberg@arm.com    allocated += 1;
16112037Sandreas.sandberg@arm.com    return mshr;
16212037Sandreas.sandberg@arm.com}
16312037Sandreas.sandberg@arm.com
16412037Sandreas.sandberg@arm.com
16512037Sandreas.sandberg@arm.comvoid
16612037Sandreas.sandberg@arm.comMSHRQueue::deallocate(MSHR *mshr)
16712037Sandreas.sandberg@arm.com{
16812037Sandreas.sandberg@arm.com    deallocateOne(mshr);
16912037Sandreas.sandberg@arm.com}
17012037Sandreas.sandberg@arm.com
17112037Sandreas.sandberg@arm.comMSHR::Iterator
17212037Sandreas.sandberg@arm.comMSHRQueue::deallocateOne(MSHR *mshr)
17312037Sandreas.sandberg@arm.com{
17412037Sandreas.sandberg@arm.com    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
17512037Sandreas.sandberg@arm.com    freeList.push_front(mshr);
17612037Sandreas.sandberg@arm.com    allocated--;
17712037Sandreas.sandberg@arm.com    if (mshr->inService) {
17812037Sandreas.sandberg@arm.com        inServiceEntries--;
17912037Sandreas.sandberg@arm.com    } else {
18012037Sandreas.sandberg@arm.com        readyList.erase(mshr->readyIter);
18112037Sandreas.sandberg@arm.com    }
18212037Sandreas.sandberg@arm.com    mshr->deallocate();
18312037Sandreas.sandberg@arm.com    if (drainManager && allocated == 0) {
18412037Sandreas.sandberg@arm.com        // Notify the drain manager that we have completed draining if
18512037Sandreas.sandberg@arm.com        // there are no other outstanding requests in this MSHR queue.
18612037Sandreas.sandberg@arm.com        DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
18712037Sandreas.sandberg@arm.com        drainManager->signalDrainDone();
18812037Sandreas.sandberg@arm.com        drainManager = NULL;
18912037Sandreas.sandberg@arm.com        setDrainState(Drainable::Drained);
19012037Sandreas.sandberg@arm.com    }
19112037Sandreas.sandberg@arm.com    return retval;
19212037Sandreas.sandberg@arm.com}
19312037Sandreas.sandberg@arm.com
19412037Sandreas.sandberg@arm.comvoid
19512037Sandreas.sandberg@arm.comMSHRQueue::moveToFront(MSHR *mshr)
19612037Sandreas.sandberg@arm.com{
19712037Sandreas.sandberg@arm.com    if (!mshr->inService) {
19812037Sandreas.sandberg@arm.com        assert(mshr == *(mshr->readyIter));
19912037Sandreas.sandberg@arm.com        readyList.erase(mshr->readyIter);
20012037Sandreas.sandberg@arm.com        mshr->readyIter = readyList.insert(readyList.begin(), mshr);
20112037Sandreas.sandberg@arm.com    }
20212037Sandreas.sandberg@arm.com}
20312037Sandreas.sandberg@arm.com
20412037Sandreas.sandberg@arm.comvoid
20512037Sandreas.sandberg@arm.comMSHRQueue::markInService(MSHR *mshr, bool pending_dirty_resp)
20612037Sandreas.sandberg@arm.com{
20712037Sandreas.sandberg@arm.com    if (mshr->markInService(pending_dirty_resp)) {
20812037Sandreas.sandberg@arm.com        deallocate(mshr);
20912037Sandreas.sandberg@arm.com    } else {
21012037Sandreas.sandberg@arm.com        readyList.erase(mshr->readyIter);
21112037Sandreas.sandberg@arm.com        inServiceEntries += 1;
21212037Sandreas.sandberg@arm.com    }
21312037Sandreas.sandberg@arm.com}
21412037Sandreas.sandberg@arm.com
21512037Sandreas.sandberg@arm.comvoid
21612037Sandreas.sandberg@arm.comMSHRQueue::markPending(MSHR *mshr)
21712037Sandreas.sandberg@arm.com{
21812037Sandreas.sandberg@arm.com    assert(mshr->inService);
21912037Sandreas.sandberg@arm.com    mshr->inService = false;
22012037Sandreas.sandberg@arm.com    --inServiceEntries;
22112037Sandreas.sandberg@arm.com    /**
22212037Sandreas.sandberg@arm.com     * @ todo might want to add rerequests to front of pending list for
22312037Sandreas.sandberg@arm.com     * performance.
22412037Sandreas.sandberg@arm.com     */
22512037Sandreas.sandberg@arm.com    mshr->readyIter = addToReadyList(mshr);
22612037Sandreas.sandberg@arm.com}
22712037Sandreas.sandberg@arm.com
22812037Sandreas.sandberg@arm.combool
22912037Sandreas.sandberg@arm.comMSHRQueue::forceDeallocateTarget(MSHR *mshr)
23012037Sandreas.sandberg@arm.com{
23112037Sandreas.sandberg@arm.com    bool was_full = isFull();
23212037Sandreas.sandberg@arm.com    assert(mshr->hasTargets());
23312037Sandreas.sandberg@arm.com    // Pop the prefetch off of the target list
23412037Sandreas.sandberg@arm.com    mshr->popTarget();
23512037Sandreas.sandberg@arm.com    // Delete mshr if no remaining targets
23612037Sandreas.sandberg@arm.com    if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
23712037Sandreas.sandberg@arm.com        deallocateOne(mshr);
23812037Sandreas.sandberg@arm.com    }
23912037Sandreas.sandberg@arm.com
24012037Sandreas.sandberg@arm.com    // Notify if MSHR queue no longer full
24112037Sandreas.sandberg@arm.com    return was_full && !isFull();
24212037Sandreas.sandberg@arm.com}
24312037Sandreas.sandberg@arm.com
24412037Sandreas.sandberg@arm.comvoid
24512037Sandreas.sandberg@arm.comMSHRQueue::squash(int threadNum)
24612037Sandreas.sandberg@arm.com{
24712037Sandreas.sandberg@arm.com    for (auto i = allocatedList.begin(); i != allocatedList.end();) {
24812037Sandreas.sandberg@arm.com        MSHR *mshr = *i;
24912037Sandreas.sandberg@arm.com        if (mshr->threadNum == threadNum) {
25012037Sandreas.sandberg@arm.com            while (mshr->hasTargets()) {
25112037Sandreas.sandberg@arm.com                mshr->popTarget();
25212037Sandreas.sandberg@arm.com                assert(0/*target->req->threadId()*/ == threadNum);
25312037Sandreas.sandberg@arm.com            }
25412037Sandreas.sandberg@arm.com            assert(!mshr->hasTargets());
25512391Sjason@lowepower.com            assert(mshr->getNumTargets()==0);
25612037Sandreas.sandberg@arm.com            if (!mshr->inService) {
25712037Sandreas.sandberg@arm.com                i = deallocateOne(mshr);
25812391Sjason@lowepower.com            } else {
25912391Sjason@lowepower.com                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
26012037Sandreas.sandberg@arm.com                ++i;
26112037Sandreas.sandberg@arm.com            }
26212037Sandreas.sandberg@arm.com        } else {
26312037Sandreas.sandberg@arm.com            ++i;
26412037Sandreas.sandberg@arm.com        }
26512037Sandreas.sandberg@arm.com    }
26612037Sandreas.sandberg@arm.com}
26712037Sandreas.sandberg@arm.com
26812037Sandreas.sandberg@arm.comunsigned int
26912037Sandreas.sandberg@arm.comMSHRQueue::drain(DrainManager *dm)
27012037Sandreas.sandberg@arm.com{
27112037Sandreas.sandberg@arm.com    if (allocated == 0) {
27212037Sandreas.sandberg@arm.com        setDrainState(Drainable::Drained);
27312037Sandreas.sandberg@arm.com        return 0;
27412037Sandreas.sandberg@arm.com    } else {
27512037Sandreas.sandberg@arm.com        drainManager = dm;
27612037Sandreas.sandberg@arm.com        setDrainState(Drainable::Draining);
27712037Sandreas.sandberg@arm.com        return 1;
27812037Sandreas.sandberg@arm.com    }
27912037Sandreas.sandberg@arm.com}
28012037Sandreas.sandberg@arm.com