mshr_queue.cc revision 10764
12810Srdreslin@umich.edu/*
211051Sandreas.hansson@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited
311051Sandreas.hansson@arm.com * All rights reserved.
411051Sandreas.hansson@arm.com *
511051Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
611051Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
711051Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
811051Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
911051Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1011051Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1111051Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1211051Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1311051Sandreas.hansson@arm.com *
1411051Sandreas.hansson@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
1511051Sandreas.hansson@arm.com * All rights reserved.
162810Srdreslin@umich.edu *
172810Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without
182810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are
192810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright
202810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer;
212810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright
222810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the
232810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution;
242810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its
252810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from
262810Srdreslin@umich.edu * this software without specific prior written permission.
272810Srdreslin@umich.edu *
282810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392810Srdreslin@umich.edu *
402810Srdreslin@umich.edu * Authors: Erik Hallnor
412810Srdreslin@umich.edu *          Andreas Sandberg
4211051Sandreas.hansson@arm.com */
4311051Sandreas.hansson@arm.com
442810Srdreslin@umich.edu/** @file
4511051Sandreas.hansson@arm.com * Definition of MSHRQueue class functions.
4611051Sandreas.hansson@arm.com */
472810Srdreslin@umich.edu
482810Srdreslin@umich.edu#include "base/trace.hh"
492810Srdreslin@umich.edu#include "mem/cache/mshr_queue.hh"
502810Srdreslin@umich.edu#include "debug/Drain.hh"
5111051Sandreas.hansson@arm.com
522810Srdreslin@umich.eduusing namespace std;
532810Srdreslin@umich.edu
5411051Sandreas.hansson@arm.comMSHRQueue::MSHRQueue(const std::string &_label,
552810Srdreslin@umich.edu                     int num_entries, int reserve, int demand_reserve,
5611051Sandreas.hansson@arm.com                     int _index)
5711051Sandreas.hansson@arm.com    : label(_label), numEntries(num_entries + reserve - 1),
5811051Sandreas.hansson@arm.com      numReserve(reserve), demandReserve(demand_reserve),
5911051Sandreas.hansson@arm.com      registers(numEntries), drainManager(NULL), allocated(0),
6011051Sandreas.hansson@arm.com      inServiceEntries(0), index(_index)
6111051Sandreas.hansson@arm.com{
6211051Sandreas.hansson@arm.com    for (int i = 0; i < numEntries; ++i) {
6311051Sandreas.hansson@arm.com        registers[i].queue = this;
6411051Sandreas.hansson@arm.com        freeList.push_back(&registers[i]);
6511051Sandreas.hansson@arm.com    }
6611053Sandreas.hansson@arm.com}
6711053Sandreas.hansson@arm.com
6811051Sandreas.hansson@arm.comMSHR *
6911051Sandreas.hansson@arm.comMSHRQueue::findMatch(Addr blk_addr, bool is_secure) const
7011051Sandreas.hansson@arm.com{
7111197Sandreas.hansson@arm.com    MSHR::ConstIterator i = allocatedList.begin();
7211197Sandreas.hansson@arm.com    MSHR::ConstIterator end = allocatedList.end();
7311199Sandreas.hansson@arm.com    for (; i != end; ++i) {
7411197Sandreas.hansson@arm.com        MSHR *mshr = *i;
7511197Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
7611197Sandreas.hansson@arm.com            return mshr;
7711051Sandreas.hansson@arm.com        }
7811051Sandreas.hansson@arm.com    }
7911051Sandreas.hansson@arm.com    return NULL;
8011051Sandreas.hansson@arm.com}
8111051Sandreas.hansson@arm.com
8211051Sandreas.hansson@arm.combool
8311051Sandreas.hansson@arm.comMSHRQueue::findMatches(Addr blk_addr, bool is_secure,
8411051Sandreas.hansson@arm.com                       vector<MSHR*>& matches) const
8511051Sandreas.hansson@arm.com{
8611051Sandreas.hansson@arm.com    // Need an empty vector
8711051Sandreas.hansson@arm.com    assert(matches.empty());
8811051Sandreas.hansson@arm.com    bool retval = false;
8911051Sandreas.hansson@arm.com    MSHR::ConstIterator i = allocatedList.begin();
9011051Sandreas.hansson@arm.com    MSHR::ConstIterator end = allocatedList.end();
9111051Sandreas.hansson@arm.com    for (; i != end; ++i) {
9211051Sandreas.hansson@arm.com        MSHR *mshr = *i;
9311051Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
9411051Sandreas.hansson@arm.com            retval = true;
9511051Sandreas.hansson@arm.com            matches.push_back(mshr);
9611051Sandreas.hansson@arm.com        }
9711051Sandreas.hansson@arm.com    }
9811051Sandreas.hansson@arm.com    return retval;
9911051Sandreas.hansson@arm.com}
10011051Sandreas.hansson@arm.com
10111051Sandreas.hansson@arm.com
10211051Sandreas.hansson@arm.combool
10311051Sandreas.hansson@arm.comMSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
10411051Sandreas.hansson@arm.com{
10511051Sandreas.hansson@arm.com    pkt->pushLabel(label);
10611051Sandreas.hansson@arm.com    MSHR::ConstIterator i = allocatedList.begin();
10711051Sandreas.hansson@arm.com    MSHR::ConstIterator end = allocatedList.end();
10811051Sandreas.hansson@arm.com    for (; i != end; ++i) {
10911051Sandreas.hansson@arm.com        MSHR *mshr = *i;
11011051Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) {
11111051Sandreas.hansson@arm.com            pkt->popLabel();
11211051Sandreas.hansson@arm.com            return true;
11311051Sandreas.hansson@arm.com        }
11411051Sandreas.hansson@arm.com    }
11511051Sandreas.hansson@arm.com    pkt->popLabel();
11611051Sandreas.hansson@arm.com    return false;
11711051Sandreas.hansson@arm.com}
11811051Sandreas.hansson@arm.com
11911051Sandreas.hansson@arm.com
12011051Sandreas.hansson@arm.comMSHR *
12111051Sandreas.hansson@arm.comMSHRQueue::findPending(Addr blk_addr, bool is_secure) const
12211051Sandreas.hansson@arm.com{
12311051Sandreas.hansson@arm.com    MSHR::ConstIterator i = readyList.begin();
12411051Sandreas.hansson@arm.com    MSHR::ConstIterator end = readyList.end();
12511051Sandreas.hansson@arm.com    for (; i != end; ++i) {
12611051Sandreas.hansson@arm.com        MSHR *mshr = *i;
12711051Sandreas.hansson@arm.com        if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
12811051Sandreas.hansson@arm.com            return mshr;
12911051Sandreas.hansson@arm.com        }
13011051Sandreas.hansson@arm.com    }
13111051Sandreas.hansson@arm.com    return NULL;
13211051Sandreas.hansson@arm.com}
13311051Sandreas.hansson@arm.com
13411051Sandreas.hansson@arm.com
13511051Sandreas.hansson@arm.comMSHR::Iterator
13611051Sandreas.hansson@arm.comMSHRQueue::addToReadyList(MSHR *mshr)
13711051Sandreas.hansson@arm.com{
13811051Sandreas.hansson@arm.com    if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
13911051Sandreas.hansson@arm.com        return readyList.insert(readyList.end(), mshr);
14011051Sandreas.hansson@arm.com    }
14111051Sandreas.hansson@arm.com
14211051Sandreas.hansson@arm.com    MSHR::Iterator i = readyList.begin();
14311051Sandreas.hansson@arm.com    MSHR::Iterator end = readyList.end();
14411051Sandreas.hansson@arm.com    for (; i != end; ++i) {
14511051Sandreas.hansson@arm.com        if ((*i)->readyTime > mshr->readyTime) {
14611051Sandreas.hansson@arm.com            return readyList.insert(i, mshr);
14711051Sandreas.hansson@arm.com        }
14811051Sandreas.hansson@arm.com    }
14911051Sandreas.hansson@arm.com    assert(false);
15011051Sandreas.hansson@arm.com    return end;  // keep stupid compilers happy
15111051Sandreas.hansson@arm.com}
15211051Sandreas.hansson@arm.com
15311051Sandreas.hansson@arm.com
15411051Sandreas.hansson@arm.comMSHR *
15511051Sandreas.hansson@arm.comMSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
15611051Sandreas.hansson@arm.com                    Tick when_ready, Counter order)
15711051Sandreas.hansson@arm.com{
15811051Sandreas.hansson@arm.com    assert(!freeList.empty());
15911051Sandreas.hansson@arm.com    MSHR *mshr = freeList.front();
16011284Sandreas.hansson@arm.com    assert(mshr->getNumTargets() == 0);
16111051Sandreas.hansson@arm.com    freeList.pop_front();
16211051Sandreas.hansson@arm.com
16311051Sandreas.hansson@arm.com    mshr->allocate(blk_addr, blk_size, pkt, when_ready, order);
16411051Sandreas.hansson@arm.com    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
16511051Sandreas.hansson@arm.com    mshr->readyIter = addToReadyList(mshr);
16611051Sandreas.hansson@arm.com
16711051Sandreas.hansson@arm.com    allocated += 1;
16811284Sandreas.hansson@arm.com    return mshr;
16911284Sandreas.hansson@arm.com}
17011284Sandreas.hansson@arm.com
17111284Sandreas.hansson@arm.com
17211051Sandreas.hansson@arm.comvoid
17311284Sandreas.hansson@arm.comMSHRQueue::deallocate(MSHR *mshr)
17411051Sandreas.hansson@arm.com{
17511051Sandreas.hansson@arm.com    deallocateOne(mshr);
17611051Sandreas.hansson@arm.com}
17711284Sandreas.hansson@arm.com
17811284Sandreas.hansson@arm.comMSHR::Iterator
17911284Sandreas.hansson@arm.comMSHRQueue::deallocateOne(MSHR *mshr)
18011284Sandreas.hansson@arm.com{
18111051Sandreas.hansson@arm.com    MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
18211051Sandreas.hansson@arm.com    freeList.push_front(mshr);
18311051Sandreas.hansson@arm.com    allocated--;
18411051Sandreas.hansson@arm.com    if (mshr->inService) {
18511051Sandreas.hansson@arm.com        inServiceEntries--;
18611051Sandreas.hansson@arm.com    } else {
18711051Sandreas.hansson@arm.com        readyList.erase(mshr->readyIter);
18811051Sandreas.hansson@arm.com    }
18911051Sandreas.hansson@arm.com    mshr->deallocate();
19011051Sandreas.hansson@arm.com    if (drainManager && allocated == 0) {
19111051Sandreas.hansson@arm.com        // Notify the drain manager that we have completed draining if
19211051Sandreas.hansson@arm.com        // there are no other outstanding requests in this MSHR queue.
19311051Sandreas.hansson@arm.com        DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
19411051Sandreas.hansson@arm.com        drainManager->signalDrainDone();
19511051Sandreas.hansson@arm.com        drainManager = NULL;
19611051Sandreas.hansson@arm.com        setDrainState(Drainable::Drained);
19711051Sandreas.hansson@arm.com    }
19811051Sandreas.hansson@arm.com    return retval;
19911051Sandreas.hansson@arm.com}
20011284Sandreas.hansson@arm.com
20111051Sandreas.hansson@arm.comvoid
20211051Sandreas.hansson@arm.comMSHRQueue::moveToFront(MSHR *mshr)
20311051Sandreas.hansson@arm.com{
20411051Sandreas.hansson@arm.com    if (!mshr->inService) {
20511051Sandreas.hansson@arm.com        assert(mshr == *(mshr->readyIter));
20611284Sandreas.hansson@arm.com        readyList.erase(mshr->readyIter);
20711051Sandreas.hansson@arm.com        mshr->readyIter = readyList.insert(readyList.begin(), mshr);
20811284Sandreas.hansson@arm.com    }
20911051Sandreas.hansson@arm.com}
21011197Sandreas.hansson@arm.com
21111197Sandreas.hansson@arm.comvoid
21211197Sandreas.hansson@arm.comMSHRQueue::markInService(MSHR *mshr, bool pending_dirty_resp)
21311197Sandreas.hansson@arm.com{
21411051Sandreas.hansson@arm.com    if (mshr->markInService(pending_dirty_resp)) {
21511284Sandreas.hansson@arm.com        deallocate(mshr);
21611051Sandreas.hansson@arm.com    } else {
21711284Sandreas.hansson@arm.com        readyList.erase(mshr->readyIter);
21811284Sandreas.hansson@arm.com        inServiceEntries += 1;
21911284Sandreas.hansson@arm.com    }
22011051Sandreas.hansson@arm.com}
22111051Sandreas.hansson@arm.com
22211051Sandreas.hansson@arm.comvoid
22311284Sandreas.hansson@arm.comMSHRQueue::markPending(MSHR *mshr)
22411284Sandreas.hansson@arm.com{
22511284Sandreas.hansson@arm.com    assert(mshr->inService);
22611284Sandreas.hansson@arm.com    mshr->inService = false;
22711051Sandreas.hansson@arm.com    --inServiceEntries;
22811051Sandreas.hansson@arm.com    /**
22911051Sandreas.hansson@arm.com     * @ todo might want to add rerequests to front of pending list for
23011284Sandreas.hansson@arm.com     * performance.
23111284Sandreas.hansson@arm.com     */
23211284Sandreas.hansson@arm.com    mshr->readyIter = addToReadyList(mshr);
23311197Sandreas.hansson@arm.com}
23411284Sandreas.hansson@arm.com
23511284Sandreas.hansson@arm.combool
23611284Sandreas.hansson@arm.comMSHRQueue::forceDeallocateTarget(MSHR *mshr)
23711284Sandreas.hansson@arm.com{
23811284Sandreas.hansson@arm.com    bool was_full = isFull();
23911284Sandreas.hansson@arm.com    assert(mshr->hasTargets());
24011284Sandreas.hansson@arm.com    // Pop the prefetch off of the target list
24111284Sandreas.hansson@arm.com    mshr->popTarget();
24211284Sandreas.hansson@arm.com    // Delete mshr if no remaining targets
24311284Sandreas.hansson@arm.com    if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
24411284Sandreas.hansson@arm.com        deallocateOne(mshr);
24511284Sandreas.hansson@arm.com    }
24611284Sandreas.hansson@arm.com
24711284Sandreas.hansson@arm.com    // Notify if MSHR queue no longer full
24811284Sandreas.hansson@arm.com    return was_full && !isFull();
24911197Sandreas.hansson@arm.com}
25011284Sandreas.hansson@arm.com
25111284Sandreas.hansson@arm.comvoid
25211284Sandreas.hansson@arm.comMSHRQueue::squash(int threadNum)
25311284Sandreas.hansson@arm.com{
25411284Sandreas.hansson@arm.com    MSHR::Iterator i = allocatedList.begin();
25511284Sandreas.hansson@arm.com    MSHR::Iterator end = allocatedList.end();
25611284Sandreas.hansson@arm.com    for (; i != end;) {
25711197Sandreas.hansson@arm.com        MSHR *mshr = *i;
25811051Sandreas.hansson@arm.com        if (mshr->threadNum == threadNum) {
25911051Sandreas.hansson@arm.com            while (mshr->hasTargets()) {
26011051Sandreas.hansson@arm.com                mshr->popTarget();
26111051Sandreas.hansson@arm.com                assert(0/*target->req->threadId()*/ == threadNum);
26211051Sandreas.hansson@arm.com            }
26311284Sandreas.hansson@arm.com            assert(!mshr->hasTargets());
26411284Sandreas.hansson@arm.com            assert(mshr->getNumTargets()==0);
26511051Sandreas.hansson@arm.com            if (!mshr->inService) {
26611051Sandreas.hansson@arm.com                i = deallocateOne(mshr);
26711051Sandreas.hansson@arm.com            } else {
26811051Sandreas.hansson@arm.com                //mshr->pkt->flags &= ~CACHE_LINE_FILL;
26911284Sandreas.hansson@arm.com                ++i;
27011051Sandreas.hansson@arm.com            }
27111051Sandreas.hansson@arm.com        } else {
27211051Sandreas.hansson@arm.com            ++i;
27311284Sandreas.hansson@arm.com        }
27411051Sandreas.hansson@arm.com    }
27511197Sandreas.hansson@arm.com}
27611197Sandreas.hansson@arm.com
27711197Sandreas.hansson@arm.comunsigned int
27811197Sandreas.hansson@arm.comMSHRQueue::drain(DrainManager *dm)
27911051Sandreas.hansson@arm.com{
28011051Sandreas.hansson@arm.com    if (allocated == 0) {
28111051Sandreas.hansson@arm.com        setDrainState(Drainable::Drained);
28211051Sandreas.hansson@arm.com        return 0;
28311051Sandreas.hansson@arm.com    } else {
28411051Sandreas.hansson@arm.com        drainManager = dm;
28511051Sandreas.hansson@arm.com        setDrainState(Drainable::Draining);
28611051Sandreas.hansson@arm.com        return 1;
28711051Sandreas.hansson@arm.com    }
28811051Sandreas.hansson@arm.com}
28911051Sandreas.hansson@arm.com