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