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(®isters[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