mshr_queue.cc revision 11284
12810SN/A/*
210764Sandreas.hansson@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited
39347SAndreas.Sandberg@arm.com * All rights reserved.
49347SAndreas.Sandberg@arm.com *
59347SAndreas.Sandberg@arm.com * The license below extends only to copyright in the software and shall
69347SAndreas.Sandberg@arm.com * not be construed as granting a license to any other intellectual
79347SAndreas.Sandberg@arm.com * property including but not limited to intellectual property relating
89347SAndreas.Sandberg@arm.com * to a hardware implementation of the functionality of the software
99347SAndreas.Sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
109347SAndreas.Sandberg@arm.com * terms below provided that you ensure that this notice is replicated
119347SAndreas.Sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
129347SAndreas.Sandberg@arm.com * modified or unmodified, in source code or in binary form.
139347SAndreas.Sandberg@arm.com *
142810SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152810SN/A * All rights reserved.
162810SN/A *
172810SN/A * Redistribution and use in source and binary forms, with or without
182810SN/A * modification, are permitted provided that the following conditions are
192810SN/A * met: redistributions of source code must retain the above copyright
202810SN/A * notice, this list of conditions and the following disclaimer;
212810SN/A * redistributions in binary form must reproduce the above copyright
222810SN/A * notice, this list of conditions and the following disclaimer in the
232810SN/A * documentation and/or other materials provided with the distribution;
242810SN/A * neither the name of the copyright holders nor the names of its
252810SN/A * contributors may be used to endorse or promote products derived from
262810SN/A * this software without specific prior written permission.
272810SN/A *
282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392810SN/A *
402810SN/A * Authors: Erik Hallnor
419347SAndreas.Sandberg@arm.com *          Andreas Sandberg
422810SN/A */
432810SN/A
442810SN/A/** @file
454626SN/A * Definition of MSHRQueue class functions.
462810SN/A */
472810SN/A
4810509SAli.Saidi@ARM.com#include "base/trace.hh"
495338Sstever@gmail.com#include "mem/cache/mshr_queue.hh"
5010509SAli.Saidi@ARM.com#include "debug/Drain.hh"
512810SN/A
522810SN/Ausing namespace std;
532810SN/A
545314SN/AMSHRQueue::MSHRQueue(const std::string &_label,
5510622Smitch.hayenga@arm.com                     int num_entries, int reserve, int demand_reserve,
5610622Smitch.hayenga@arm.com                     int _index)
579725Sandreas.hansson@arm.com    : label(_label), numEntries(num_entries + reserve - 1),
5810622Smitch.hayenga@arm.com      numReserve(reserve), demandReserve(demand_reserve),
5910913Sandreas.sandberg@arm.com      registers(numEntries), allocated(0),
6010622Smitch.hayenga@arm.com      inServiceEntries(0), index(_index)
612810SN/A{
624626SN/A    for (int i = 0; i < numEntries; ++i) {
634626SN/A        registers[i].queue = this;
642810SN/A        freeList.push_back(&registers[i]);
652810SN/A    }
662810SN/A}
672810SN/A
684626SN/AMSHR *
6910764Sandreas.hansson@arm.comMSHRQueue::findMatch(Addr blk_addr, bool is_secure) const
702810SN/A{
7110766Sandreas.hansson@arm.com    for (const auto& mshr : allocatedList) {
7210768Sandreas.hansson@arm.com        // we ignore any MSHRs allocated for uncacheable accesses and
7310768Sandreas.hansson@arm.com        // simply ignore them when matching, in the cache we never
7410768Sandreas.hansson@arm.com        // check for matches when adding new uncacheable entries, and
7510768Sandreas.hansson@arm.com        // we do not want normal cacheable accesses being added to an
7610768Sandreas.hansson@arm.com        // MSHR serving an uncacheable access
7710768Sandreas.hansson@arm.com        if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
7810768Sandreas.hansson@arm.com            mshr->isSecure == is_secure) {
792810SN/A            return mshr;
802810SN/A        }
812810SN/A    }
822810SN/A    return NULL;
832810SN/A}
842810SN/A
852810SN/Abool
8610764Sandreas.hansson@arm.comMSHRQueue::findMatches(Addr blk_addr, bool is_secure,
8710764Sandreas.hansson@arm.com                       vector<MSHR*>& matches) const
882810SN/A{
892810SN/A    // Need an empty vector
902810SN/A    assert(matches.empty());
912810SN/A    bool retval = false;
9210766Sandreas.hansson@arm.com    for (const auto& mshr : allocatedList) {
9310768Sandreas.hansson@arm.com        if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
9410768Sandreas.hansson@arm.com            mshr->isSecure == is_secure) {
952810SN/A            retval = true;
962810SN/A            matches.push_back(mshr);
972810SN/A        }
982810SN/A    }
992810SN/A    return retval;
1004920SN/A}
1012810SN/A
1024920SN/A
1034920SN/Abool
1044920SN/AMSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
1054920SN/A{
1065314SN/A    pkt->pushLabel(label);
10710766Sandreas.hansson@arm.com    for (const auto& mshr : allocatedList) {
10810764Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) {
1095314SN/A            pkt->popLabel();
1104920SN/A            return true;
1114920SN/A        }
1124920SN/A    }
1135314SN/A    pkt->popLabel();
1144920SN/A    return false;
1152810SN/A}
1162810SN/A
1174920SN/A
1184626SN/AMSHR *
11910764Sandreas.hansson@arm.comMSHRQueue::findPending(Addr blk_addr, bool is_secure) const
1202810SN/A{
12110766Sandreas.hansson@arm.com    for (const auto& mshr : readyList) {
12210764Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
12310764Sandreas.hansson@arm.com            return mshr;
1242810SN/A        }
1252810SN/A    }
1262810SN/A    return NULL;
1272810SN/A}
1282810SN/A
1294666SN/A
1304666SN/AMSHR::Iterator
1314666SN/AMSHRQueue::addToReadyList(MSHR *mshr)
1324666SN/A{
1334871SN/A    if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
1344666SN/A        return readyList.insert(readyList.end(), mshr);
1354666SN/A    }
1364666SN/A
13710766Sandreas.hansson@arm.com    for (auto i = readyList.begin(); i != readyList.end(); ++i) {
1384871SN/A        if ((*i)->readyTime > mshr->readyTime) {
1394666SN/A            return readyList.insert(i, mshr);
1404666SN/A        }
1414666SN/A    }
1424666SN/A    assert(false);
14310766Sandreas.hansson@arm.com    return readyList.end();  // keep stupid compilers happy
1444666SN/A}
1454666SN/A
1464666SN/A
1474626SN/AMSHR *
14810764Sandreas.hansson@arm.comMSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
14911197Sandreas.hansson@arm.com                    Tick when_ready, Counter order, bool alloc_on_fill)
1502810SN/A{
1513149SN/A    assert(!freeList.empty());
1522810SN/A    MSHR *mshr = freeList.front();
1532810SN/A    assert(mshr->getNumTargets() == 0);
1542810SN/A    freeList.pop_front();
1552810SN/A
15611197Sandreas.hansson@arm.com    mshr->allocate(blk_addr, blk_size, pkt, when_ready, order, alloc_on_fill);
1572810SN/A    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
1584666SN/A    mshr->readyIter = addToReadyList(mshr);
1592810SN/A
1602810SN/A    allocated += 1;
1612810SN/A    return mshr;
1622810SN/A}
1632810SN/A
1642810SN/A
1652810SN/Avoid
1664626SN/AMSHRQueue::deallocate(MSHR *mshr)
1672810SN/A{
1682810SN/A    deallocateOne(mshr);
1692810SN/A}
1702810SN/A
1712810SN/AMSHR::Iterator
1724626SN/AMSHRQueue::deallocateOne(MSHR *mshr)
1732810SN/A{
1742810SN/A    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
1752810SN/A    freeList.push_front(mshr);
1762810SN/A    allocated--;
1772810SN/A    if (mshr->inService) {
1784626SN/A        inServiceEntries--;
1792810SN/A    } else {
1804666SN/A        readyList.erase(mshr->readyIter);
1812810SN/A    }
1822810SN/A    mshr->deallocate();
18310913Sandreas.sandberg@arm.com    if (drainState() == DrainState::Draining && allocated == 0) {
1849347SAndreas.Sandberg@arm.com        // Notify the drain manager that we have completed draining if
1859347SAndreas.Sandberg@arm.com        // there are no other outstanding requests in this MSHR queue.
18610509SAli.Saidi@ARM.com        DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
18710913Sandreas.sandberg@arm.com        signalDrainDone();
1889347SAndreas.Sandberg@arm.com    }
1892810SN/A    return retval;
1902810SN/A}
1912810SN/A
1922810SN/Avoid
1932810SN/AMSHRQueue::moveToFront(MSHR *mshr)
1942810SN/A{
1952810SN/A    if (!mshr->inService) {
1962810SN/A        assert(mshr == *(mshr->readyIter));
1974666SN/A        readyList.erase(mshr->readyIter);
1984666SN/A        mshr->readyIter = readyList.insert(readyList.begin(), mshr);
1992810SN/A    }
2002810SN/A}
2012810SN/A
2022810SN/Avoid
20311284Sandreas.hansson@arm.comMSHRQueue::markInService(MSHR *mshr, bool pending_modified_resp)
2042810SN/A{
20511284Sandreas.hansson@arm.com    if (mshr->markInService(pending_modified_resp)) {
2062810SN/A        deallocate(mshr);
2074908SN/A    } else {
2084908SN/A        readyList.erase(mshr->readyIter);
2094908SN/A        inServiceEntries += 1;
2102810SN/A    }
2112810SN/A}
2122810SN/A
2132810SN/Avoid
2144626SN/AMSHRQueue::markPending(MSHR *mshr)
2152810SN/A{
2164666SN/A    assert(mshr->inService);
2172810SN/A    mshr->inService = false;
2184626SN/A    --inServiceEntries;
2192810SN/A    /**
2202810SN/A     * @ todo might want to add rerequests to front of pending list for
2212810SN/A     * performance.
2222810SN/A     */
2234666SN/A    mshr->readyIter = addToReadyList(mshr);
2242810SN/A}
2252810SN/A
22610192Smitch.hayenga@arm.combool
22710192Smitch.hayenga@arm.comMSHRQueue::forceDeallocateTarget(MSHR *mshr)
22810192Smitch.hayenga@arm.com{
22910192Smitch.hayenga@arm.com    bool was_full = isFull();
23010192Smitch.hayenga@arm.com    assert(mshr->hasTargets());
23110192Smitch.hayenga@arm.com    // Pop the prefetch off of the target list
23210192Smitch.hayenga@arm.com    mshr->popTarget();
23310192Smitch.hayenga@arm.com    // Delete mshr if no remaining targets
23410192Smitch.hayenga@arm.com    if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
23510192Smitch.hayenga@arm.com        deallocateOne(mshr);
23610192Smitch.hayenga@arm.com    }
23710192Smitch.hayenga@arm.com
23810192Smitch.hayenga@arm.com    // Notify if MSHR queue no longer full
23910192Smitch.hayenga@arm.com    return was_full && !isFull();
24010192Smitch.hayenga@arm.com}
24110192Smitch.hayenga@arm.com
24210913Sandreas.sandberg@arm.comDrainState
24310913Sandreas.sandberg@arm.comMSHRQueue::drain()
2449347SAndreas.Sandberg@arm.com{
24510913Sandreas.sandberg@arm.com    return allocated == 0 ? DrainState::Drained : DrainState::Draining;
2469347SAndreas.Sandberg@arm.com}
247