mshr_queue.cc revision 10766
1/* 2 * Copyright (c) 2012-2013, 2015 ARM Limited 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2003-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Erik Hallnor 41 * Andreas Sandberg 42 */ 43 44/** @file 45 * Definition of MSHRQueue class functions. 46 */ 47 48#include "base/trace.hh" 49#include "mem/cache/mshr_queue.hh" 50#include "debug/Drain.hh" 51 52using namespace std; 53 54MSHRQueue::MSHRQueue(const std::string &_label, 55 int num_entries, int reserve, int demand_reserve, 56 int _index) 57 : label(_label), numEntries(num_entries + reserve - 1), 58 numReserve(reserve), demandReserve(demand_reserve), 59 registers(numEntries), drainManager(NULL), allocated(0), 60 inServiceEntries(0), index(_index) 61{ 62 for (int i = 0; i < numEntries; ++i) { 63 registers[i].queue = this; 64 freeList.push_back(®isters[i]); 65 } 66} 67 68MSHR * 69MSHRQueue::findMatch(Addr blk_addr, bool is_secure) const 70{ 71 for (const auto& mshr : allocatedList) { 72 if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) { 73 return mshr; 74 } 75 } 76 return NULL; 77} 78 79bool 80MSHRQueue::findMatches(Addr blk_addr, bool is_secure, 81 vector<MSHR*>& matches) const 82{ 83 // Need an empty vector 84 assert(matches.empty()); 85 bool retval = false; 86 for (const auto& mshr : allocatedList) { 87 if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) { 88 retval = true; 89 matches.push_back(mshr); 90 } 91 } 92 return retval; 93} 94 95 96bool 97MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) 98{ 99 pkt->pushLabel(label); 100 for (const auto& mshr : allocatedList) { 101 if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) { 102 pkt->popLabel(); 103 return true; 104 } 105 } 106 pkt->popLabel(); 107 return false; 108} 109 110 111MSHR * 112MSHRQueue::findPending(Addr blk_addr, bool is_secure) const 113{ 114 for (const auto& mshr : readyList) { 115 if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) { 116 return mshr; 117 } 118 } 119 return NULL; 120} 121 122 123MSHR::Iterator 124MSHRQueue::addToReadyList(MSHR *mshr) 125{ 126 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) { 127 return readyList.insert(readyList.end(), mshr); 128 } 129 130 for (auto i = readyList.begin(); i != readyList.end(); ++i) { 131 if ((*i)->readyTime > mshr->readyTime) { 132 return readyList.insert(i, mshr); 133 } 134 } 135 assert(false); 136 return readyList.end(); // keep stupid compilers happy 137} 138 139 140MSHR * 141MSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt, 142 Tick when_ready, Counter order) 143{ 144 assert(!freeList.empty()); 145 MSHR *mshr = freeList.front(); 146 assert(mshr->getNumTargets() == 0); 147 freeList.pop_front(); 148 149 mshr->allocate(blk_addr, blk_size, pkt, when_ready, order); 150 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 151 mshr->readyIter = addToReadyList(mshr); 152 153 allocated += 1; 154 return mshr; 155} 156 157 158void 159MSHRQueue::deallocate(MSHR *mshr) 160{ 161 deallocateOne(mshr); 162} 163 164MSHR::Iterator 165MSHRQueue::deallocateOne(MSHR *mshr) 166{ 167 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); 168 freeList.push_front(mshr); 169 allocated--; 170 if (mshr->inService) { 171 inServiceEntries--; 172 } else { 173 readyList.erase(mshr->readyIter); 174 } 175 mshr->deallocate(); 176 if (drainManager && allocated == 0) { 177 // Notify the drain manager that we have completed draining if 178 // there are no other outstanding requests in this MSHR queue. 179 DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n"); 180 drainManager->signalDrainDone(); 181 drainManager = NULL; 182 setDrainState(Drainable::Drained); 183 } 184 return retval; 185} 186 187void 188MSHRQueue::moveToFront(MSHR *mshr) 189{ 190 if (!mshr->inService) { 191 assert(mshr == *(mshr->readyIter)); 192 readyList.erase(mshr->readyIter); 193 mshr->readyIter = readyList.insert(readyList.begin(), mshr); 194 } 195} 196 197void 198MSHRQueue::markInService(MSHR *mshr, bool pending_dirty_resp) 199{ 200 if (mshr->markInService(pending_dirty_resp)) { 201 deallocate(mshr); 202 } else { 203 readyList.erase(mshr->readyIter); 204 inServiceEntries += 1; 205 } 206} 207 208void 209MSHRQueue::markPending(MSHR *mshr) 210{ 211 assert(mshr->inService); 212 mshr->inService = false; 213 --inServiceEntries; 214 /** 215 * @ todo might want to add rerequests to front of pending list for 216 * performance. 217 */ 218 mshr->readyIter = addToReadyList(mshr); 219} 220 221bool 222MSHRQueue::forceDeallocateTarget(MSHR *mshr) 223{ 224 bool was_full = isFull(); 225 assert(mshr->hasTargets()); 226 // Pop the prefetch off of the target list 227 mshr->popTarget(); 228 // Delete mshr if no remaining targets 229 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) { 230 deallocateOne(mshr); 231 } 232 233 // Notify if MSHR queue no longer full 234 return was_full && !isFull(); 235} 236 237void 238MSHRQueue::squash(int threadNum) 239{ 240 for (auto i = allocatedList.begin(); i != allocatedList.end();) { 241 MSHR *mshr = *i; 242 if (mshr->threadNum == threadNum) { 243 while (mshr->hasTargets()) { 244 mshr->popTarget(); 245 assert(0/*target->req->threadId()*/ == threadNum); 246 } 247 assert(!mshr->hasTargets()); 248 assert(mshr->getNumTargets()==0); 249 if (!mshr->inService) { 250 i = deallocateOne(mshr); 251 } else { 252 //mshr->pkt->flags &= ~CACHE_LINE_FILL; 253 ++i; 254 } 255 } else { 256 ++i; 257 } 258 } 259} 260 261unsigned int 262MSHRQueue::drain(DrainManager *dm) 263{ 264 if (allocated == 0) { 265 setDrainState(Drainable::Drained); 266 return 0; 267 } else { 268 drainManager = dm; 269 setDrainState(Drainable::Draining); 270 return 1; 271 } 272} 273