mshr_queue.cc revision 9347
12810SN/A/*
29347SAndreas.Sandberg@arm.com * Copyright (c) 2012 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
485338Sstever@gmail.com#include "mem/cache/mshr_queue.hh"
492810SN/A
502810SN/Ausing namespace std;
512810SN/A
525314SN/AMSHRQueue::MSHRQueue(const std::string &_label,
535314SN/A                     int num_entries, int reserve, int _index)
545314SN/A    : label(_label),
555314SN/A      numEntries(num_entries + reserve - 1), numReserve(reserve),
569347SAndreas.Sandberg@arm.com      drainManager(NULL), index(_index)
572810SN/A{
582810SN/A    allocated = 0;
594626SN/A    inServiceEntries = 0;
604626SN/A    registers = new MSHR[numEntries];
614626SN/A    for (int i = 0; i < numEntries; ++i) {
624626SN/A        registers[i].queue = this;
632810SN/A        freeList.push_back(&registers[i]);
642810SN/A    }
652810SN/A}
662810SN/A
672810SN/AMSHRQueue::~MSHRQueue()
682810SN/A{
692810SN/A    delete [] registers;
702810SN/A}
712810SN/A
724626SN/AMSHR *
732991SN/AMSHRQueue::findMatch(Addr addr) const
742810SN/A{
752810SN/A    MSHR::ConstIterator i = allocatedList.begin();
762810SN/A    MSHR::ConstIterator end = allocatedList.end();
772810SN/A    for (; i != end; ++i) {
782810SN/A        MSHR *mshr = *i;
792810SN/A        if (mshr->addr == addr) {
802810SN/A            return mshr;
812810SN/A        }
822810SN/A    }
832810SN/A    return NULL;
842810SN/A}
852810SN/A
862810SN/Abool
872991SN/AMSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
882810SN/A{
892810SN/A    // Need an empty vector
902810SN/A    assert(matches.empty());
912810SN/A    bool retval = false;
922810SN/A    MSHR::ConstIterator i = allocatedList.begin();
932810SN/A    MSHR::ConstIterator end = allocatedList.end();
942810SN/A    for (; i != end; ++i) {
952810SN/A        MSHR *mshr = *i;
962810SN/A        if (mshr->addr == addr) {
972810SN/A            retval = true;
982810SN/A            matches.push_back(mshr);
992810SN/A        }
1002810SN/A    }
1012810SN/A    return retval;
1024920SN/A}
1032810SN/A
1044920SN/A
1054920SN/Abool
1064920SN/AMSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
1074920SN/A{
1085314SN/A    pkt->pushLabel(label);
1094920SN/A    MSHR::ConstIterator i = allocatedList.begin();
1104920SN/A    MSHR::ConstIterator end = allocatedList.end();
1114920SN/A    for (; i != end; ++i) {
1124920SN/A        MSHR *mshr = *i;
1134920SN/A        if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) {
1145314SN/A            pkt->popLabel();
1154920SN/A            return true;
1164920SN/A        }
1174920SN/A    }
1185314SN/A    pkt->popLabel();
1194920SN/A    return false;
1202810SN/A}
1212810SN/A
1224920SN/A
1234626SN/AMSHR *
1244626SN/AMSHRQueue::findPending(Addr addr, int size) const
1252810SN/A{
1264666SN/A    MSHR::ConstIterator i = readyList.begin();
1274666SN/A    MSHR::ConstIterator end = readyList.end();
1282810SN/A    for (; i != end; ++i) {
1292810SN/A        MSHR *mshr = *i;
1304626SN/A        if (mshr->addr < addr) {
1314626SN/A            if (mshr->addr + mshr->size > addr) {
1322810SN/A                return mshr;
1332810SN/A            }
1342810SN/A        } else {
1354626SN/A            if (addr + size > mshr->addr) {
1362810SN/A                return mshr;
1372810SN/A            }
1382810SN/A        }
1392810SN/A    }
1402810SN/A    return NULL;
1412810SN/A}
1422810SN/A
1434666SN/A
1444666SN/AMSHR::Iterator
1454666SN/AMSHRQueue::addToReadyList(MSHR *mshr)
1464666SN/A{
1474871SN/A    if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
1484666SN/A        return readyList.insert(readyList.end(), mshr);
1494666SN/A    }
1504666SN/A
1514666SN/A    MSHR::Iterator i = readyList.begin();
1524666SN/A    MSHR::Iterator end = readyList.end();
1534666SN/A    for (; i != end; ++i) {
1544871SN/A        if ((*i)->readyTime > mshr->readyTime) {
1554666SN/A            return readyList.insert(i, mshr);
1564666SN/A        }
1574666SN/A    }
1584666SN/A    assert(false);
1594904SN/A    return end;  // keep stupid compilers happy
1604666SN/A}
1614666SN/A
1624666SN/A
1634626SN/AMSHR *
1644666SN/AMSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
1654666SN/A                    Tick when, Counter order)
1662810SN/A{
1673149SN/A    assert(!freeList.empty());
1682810SN/A    MSHR *mshr = freeList.front();
1692810SN/A    assert(mshr->getNumTargets() == 0);
1702810SN/A    freeList.pop_front();
1712810SN/A
1724666SN/A    mshr->allocate(addr, size, pkt, when, order);
1732810SN/A    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
1744666SN/A    mshr->readyIter = addToReadyList(mshr);
1752810SN/A
1762810SN/A    allocated += 1;
1772810SN/A    return mshr;
1782810SN/A}
1792810SN/A
1802810SN/A
1812810SN/Avoid
1824626SN/AMSHRQueue::deallocate(MSHR *mshr)
1832810SN/A{
1842810SN/A    deallocateOne(mshr);
1852810SN/A}
1862810SN/A
1872810SN/AMSHR::Iterator
1884626SN/AMSHRQueue::deallocateOne(MSHR *mshr)
1892810SN/A{
1902810SN/A    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
1912810SN/A    freeList.push_front(mshr);
1922810SN/A    allocated--;
1932810SN/A    if (mshr->inService) {
1944626SN/A        inServiceEntries--;
1952810SN/A    } else {
1964666SN/A        readyList.erase(mshr->readyIter);
1972810SN/A    }
1982810SN/A    mshr->deallocate();
1999347SAndreas.Sandberg@arm.com    if (drainManager && allocated == 0) {
2009347SAndreas.Sandberg@arm.com        // Notify the drain manager that we have completed draining if
2019347SAndreas.Sandberg@arm.com        // there are no other outstanding requests in this MSHR queue.
2029347SAndreas.Sandberg@arm.com        drainManager->signalDrainDone();
2039347SAndreas.Sandberg@arm.com        drainManager = NULL;
2049347SAndreas.Sandberg@arm.com        setDrainState(Drainable::Drained);
2059347SAndreas.Sandberg@arm.com    }
2062810SN/A    return retval;
2072810SN/A}
2082810SN/A
2092810SN/Avoid
2102810SN/AMSHRQueue::moveToFront(MSHR *mshr)
2112810SN/A{
2122810SN/A    if (!mshr->inService) {
2132810SN/A        assert(mshr == *(mshr->readyIter));
2144666SN/A        readyList.erase(mshr->readyIter);
2154666SN/A        mshr->readyIter = readyList.insert(readyList.begin(), mshr);
2162810SN/A    }
2172810SN/A}
2182810SN/A
2192810SN/Avoid
2207667Ssteve.reinhardt@amd.comMSHRQueue::markInService(MSHR *mshr, PacketPtr pkt)
2212810SN/A{
2227667Ssteve.reinhardt@amd.com    if (mshr->markInService(pkt)) {
2232810SN/A        deallocate(mshr);
2244908SN/A    } else {
2254908SN/A        readyList.erase(mshr->readyIter);
2264908SN/A        inServiceEntries += 1;
2272810SN/A    }
2282810SN/A}
2292810SN/A
2302810SN/Avoid
2314626SN/AMSHRQueue::markPending(MSHR *mshr)
2322810SN/A{
2334666SN/A    assert(mshr->inService);
2342810SN/A    mshr->inService = false;
2354626SN/A    --inServiceEntries;
2362810SN/A    /**
2372810SN/A     * @ todo might want to add rerequests to front of pending list for
2382810SN/A     * performance.
2392810SN/A     */
2404666SN/A    mshr->readyIter = addToReadyList(mshr);
2412810SN/A}
2422810SN/A
2432810SN/Avoid
2442813SN/AMSHRQueue::squash(int threadNum)
2452810SN/A{
2462810SN/A    MSHR::Iterator i = allocatedList.begin();
2472810SN/A    MSHR::Iterator end = allocatedList.end();
2482810SN/A    for (; i != end;) {
2492810SN/A        MSHR *mshr = *i;
2502813SN/A        if (mshr->threadNum == threadNum) {
2512810SN/A            while (mshr->hasTargets()) {
2522810SN/A                mshr->popTarget();
2535715Shsul@eecs.umich.edu                assert(0/*target->req->threadId()*/ == threadNum);
2542810SN/A            }
2552810SN/A            assert(!mshr->hasTargets());
2562810SN/A            assert(mshr->ntargets==0);
2572810SN/A            if (!mshr->inService) {
2582810SN/A                i = deallocateOne(mshr);
2592810SN/A            } else {
2602810SN/A                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
2612810SN/A                ++i;
2622810SN/A            }
2632810SN/A        } else {
2642810SN/A            ++i;
2652810SN/A        }
2662810SN/A    }
2672810SN/A}
2689347SAndreas.Sandberg@arm.com
2699347SAndreas.Sandberg@arm.comunsigned int
2709347SAndreas.Sandberg@arm.comMSHRQueue::drain(DrainManager *dm)
2719347SAndreas.Sandberg@arm.com{
2729347SAndreas.Sandberg@arm.com    if (allocated == 0) {
2739347SAndreas.Sandberg@arm.com        setDrainState(Drainable::Drained);
2749347SAndreas.Sandberg@arm.com        return 0;
2759347SAndreas.Sandberg@arm.com    } else {
2769347SAndreas.Sandberg@arm.com        drainManager = dm;
2779347SAndreas.Sandberg@arm.com        setDrainState(Drainable::Draining);
2789347SAndreas.Sandberg@arm.com        return 1;
2799347SAndreas.Sandberg@arm.com    }
2809347SAndreas.Sandberg@arm.com}
281