mshr_queue.cc revision 10509
1/* 2 * Copyright (c) 2012-2013 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 _index) 56 : label(_label), numEntries(num_entries + reserve - 1), 57 numReserve(reserve), registers(numEntries), 58 drainManager(NULL), allocated(0), inServiceEntries(0), index(_index) 59{ 60 for (int i = 0; i < numEntries; ++i) { 61 registers[i].queue = this; 62 freeList.push_back(®isters[i]); 63 } 64} 65 66MSHR * 67MSHRQueue::findMatch(Addr addr, bool is_secure) const 68{ 69 MSHR::ConstIterator i = allocatedList.begin(); 70 MSHR::ConstIterator end = allocatedList.end(); 71 for (; i != end; ++i) { 72 MSHR *mshr = *i; 73 if (mshr->addr == addr && mshr->isSecure == is_secure) { 74 return mshr; 75 } 76 } 77 return NULL; 78} 79 80bool 81MSHRQueue::findMatches(Addr addr, bool is_secure, vector<MSHR*>& matches) const 82{ 83 // Need an empty vector 84 assert(matches.empty()); 85 bool retval = false; 86 MSHR::ConstIterator i = allocatedList.begin(); 87 MSHR::ConstIterator end = allocatedList.end(); 88 for (; i != end; ++i) { 89 MSHR *mshr = *i; 90 if (mshr->addr == addr && mshr->isSecure == is_secure) { 91 retval = true; 92 matches.push_back(mshr); 93 } 94 } 95 return retval; 96} 97 98 99bool 100MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) 101{ 102 pkt->pushLabel(label); 103 MSHR::ConstIterator i = allocatedList.begin(); 104 MSHR::ConstIterator end = allocatedList.end(); 105 for (; i != end; ++i) { 106 MSHR *mshr = *i; 107 if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) { 108 pkt->popLabel(); 109 return true; 110 } 111 } 112 pkt->popLabel(); 113 return false; 114} 115 116 117MSHR * 118MSHRQueue::findPending(Addr addr, int size, bool is_secure) const 119{ 120 MSHR::ConstIterator i = readyList.begin(); 121 MSHR::ConstIterator end = readyList.end(); 122 for (; i != end; ++i) { 123 MSHR *mshr = *i; 124 if (mshr->isSecure == is_secure) { 125 if (mshr->addr < addr) { 126 if (mshr->addr + mshr->size > addr) 127 return mshr; 128 } else { 129 if (addr + size > mshr->addr) 130 return mshr; 131 } 132 } 133 } 134 return NULL; 135} 136 137 138MSHR::Iterator 139MSHRQueue::addToReadyList(MSHR *mshr) 140{ 141 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) { 142 return readyList.insert(readyList.end(), mshr); 143 } 144 145 MSHR::Iterator i = readyList.begin(); 146 MSHR::Iterator end = readyList.end(); 147 for (; i != end; ++i) { 148 if ((*i)->readyTime > mshr->readyTime) { 149 return readyList.insert(i, mshr); 150 } 151 } 152 assert(false); 153 return end; // keep stupid compilers happy 154} 155 156 157MSHR * 158MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, 159 Tick when, Counter order) 160{ 161 assert(!freeList.empty()); 162 MSHR *mshr = freeList.front(); 163 assert(mshr->getNumTargets() == 0); 164 freeList.pop_front(); 165 166 mshr->allocate(addr, size, pkt, when, order); 167 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 168 mshr->readyIter = addToReadyList(mshr); 169 170 allocated += 1; 171 return mshr; 172} 173 174 175void 176MSHRQueue::deallocate(MSHR *mshr) 177{ 178 deallocateOne(mshr); 179} 180 181MSHR::Iterator 182MSHRQueue::deallocateOne(MSHR *mshr) 183{ 184 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); 185 freeList.push_front(mshr); 186 allocated--; 187 if (mshr->inService) { 188 inServiceEntries--; 189 } else { 190 readyList.erase(mshr->readyIter); 191 } 192 mshr->deallocate(); 193 if (drainManager && allocated == 0) { 194 // Notify the drain manager that we have completed draining if 195 // there are no other outstanding requests in this MSHR queue. 196 DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n"); 197 drainManager->signalDrainDone(); 198 drainManager = NULL; 199 setDrainState(Drainable::Drained); 200 } 201 return retval; 202} 203 204void 205MSHRQueue::moveToFront(MSHR *mshr) 206{ 207 if (!mshr->inService) { 208 assert(mshr == *(mshr->readyIter)); 209 readyList.erase(mshr->readyIter); 210 mshr->readyIter = readyList.insert(readyList.begin(), mshr); 211 } 212} 213 214void 215MSHRQueue::markInService(MSHR *mshr, PacketPtr pkt) 216{ 217 if (mshr->markInService(pkt)) { 218 deallocate(mshr); 219 } else { 220 readyList.erase(mshr->readyIter); 221 inServiceEntries += 1; 222 } 223} 224 225void 226MSHRQueue::markPending(MSHR *mshr) 227{ 228 assert(mshr->inService); 229 mshr->inService = false; 230 --inServiceEntries; 231 /** 232 * @ todo might want to add rerequests to front of pending list for 233 * performance. 234 */ 235 mshr->readyIter = addToReadyList(mshr); 236} 237 238bool 239MSHRQueue::forceDeallocateTarget(MSHR *mshr) 240{ 241 bool was_full = isFull(); 242 assert(mshr->hasTargets()); 243 // Pop the prefetch off of the target list 244 mshr->popTarget(); 245 // Delete mshr if no remaining targets 246 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) { 247 deallocateOne(mshr); 248 } 249 250 // Notify if MSHR queue no longer full 251 return was_full && !isFull(); 252} 253 254void 255MSHRQueue::squash(int threadNum) 256{ 257 MSHR::Iterator i = allocatedList.begin(); 258 MSHR::Iterator end = allocatedList.end(); 259 for (; i != end;) { 260 MSHR *mshr = *i; 261 if (mshr->threadNum == threadNum) { 262 while (mshr->hasTargets()) { 263 mshr->popTarget(); 264 assert(0/*target->req->threadId()*/ == threadNum); 265 } 266 assert(!mshr->hasTargets()); 267 assert(mshr->getNumTargets()==0); 268 if (!mshr->inService) { 269 i = deallocateOne(mshr); 270 } else { 271 //mshr->pkt->flags &= ~CACHE_LINE_FILL; 272 ++i; 273 } 274 } else { 275 ++i; 276 } 277 } 278} 279 280unsigned int 281MSHRQueue::drain(DrainManager *dm) 282{ 283 if (allocated == 0) { 284 setDrainState(Drainable::Drained); 285 return 0; 286 } else { 287 drainManager = dm; 288 setDrainState(Drainable::Draining); 289 return 1; 290 } 291} 292