mshr_queue.cc revision 4920
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Erik Hallnor 29 */ 30 31/** @file 32 * Definition of MSHRQueue class functions. 33 */ 34 35#include "mem/cache/miss/mshr_queue.hh" 36 37using namespace std; 38 39MSHRQueue::MSHRQueue(int num_entries, int reserve, int _index) 40 : numEntries(num_entries + reserve - 1), numReserve(reserve), 41 index(_index) 42{ 43 allocated = 0; 44 inServiceEntries = 0; 45 registers = new MSHR[numEntries]; 46 for (int i = 0; i < numEntries; ++i) { 47 registers[i].queue = this; 48 freeList.push_back(®isters[i]); 49 } 50} 51 52MSHRQueue::~MSHRQueue() 53{ 54 delete [] registers; 55} 56 57MSHR * 58MSHRQueue::findMatch(Addr addr) const 59{ 60 MSHR::ConstIterator i = allocatedList.begin(); 61 MSHR::ConstIterator end = allocatedList.end(); 62 for (; i != end; ++i) { 63 MSHR *mshr = *i; 64 if (mshr->addr == addr) { 65 return mshr; 66 } 67 } 68 return NULL; 69} 70 71bool 72MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const 73{ 74 // Need an empty vector 75 assert(matches.empty()); 76 bool retval = false; 77 MSHR::ConstIterator i = allocatedList.begin(); 78 MSHR::ConstIterator end = allocatedList.end(); 79 for (; i != end; ++i) { 80 MSHR *mshr = *i; 81 if (mshr->addr == addr) { 82 retval = true; 83 matches.push_back(mshr); 84 } 85 } 86 return retval; 87} 88 89 90bool 91MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) 92{ 93 MSHR::ConstIterator i = allocatedList.begin(); 94 MSHR::ConstIterator end = allocatedList.end(); 95 for (; i != end; ++i) { 96 MSHR *mshr = *i; 97 if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) { 98 return true; 99 } 100 } 101 return false; 102} 103 104 105MSHR * 106MSHRQueue::findPending(Addr addr, int size) const 107{ 108 MSHR::ConstIterator i = readyList.begin(); 109 MSHR::ConstIterator end = readyList.end(); 110 for (; i != end; ++i) { 111 MSHR *mshr = *i; 112 if (mshr->addr < addr) { 113 if (mshr->addr + mshr->size > addr) { 114 return mshr; 115 } 116 } else { 117 if (addr + size > mshr->addr) { 118 return mshr; 119 } 120 } 121 } 122 return NULL; 123} 124 125 126MSHR::Iterator 127MSHRQueue::addToReadyList(MSHR *mshr) 128{ 129 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) { 130 return readyList.insert(readyList.end(), mshr); 131 } 132 133 MSHR::Iterator i = readyList.begin(); 134 MSHR::Iterator end = readyList.end(); 135 for (; i != end; ++i) { 136 if ((*i)->readyTime > mshr->readyTime) { 137 return readyList.insert(i, mshr); 138 } 139 } 140 assert(false); 141 return end; // keep stupid compilers happy 142} 143 144 145MSHR * 146MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, 147 Tick when, Counter order) 148{ 149 assert(!freeList.empty()); 150 MSHR *mshr = freeList.front(); 151 assert(mshr->getNumTargets() == 0); 152 freeList.pop_front(); 153 154 mshr->allocate(addr, size, pkt, when, order); 155 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 156 mshr->readyIter = addToReadyList(mshr); 157 158 allocated += 1; 159 return mshr; 160} 161 162 163void 164MSHRQueue::deallocate(MSHR *mshr) 165{ 166 deallocateOne(mshr); 167} 168 169MSHR::Iterator 170MSHRQueue::deallocateOne(MSHR *mshr) 171{ 172 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); 173 freeList.push_front(mshr); 174 allocated--; 175 if (mshr->inService) { 176 inServiceEntries--; 177 } else { 178 readyList.erase(mshr->readyIter); 179 } 180 mshr->deallocate(); 181 return retval; 182} 183 184void 185MSHRQueue::moveToFront(MSHR *mshr) 186{ 187 if (!mshr->inService) { 188 assert(mshr == *(mshr->readyIter)); 189 readyList.erase(mshr->readyIter); 190 mshr->readyIter = readyList.insert(readyList.begin(), mshr); 191 } 192} 193 194void 195MSHRQueue::markInService(MSHR *mshr) 196{ 197 if (mshr->markInService()) { 198 deallocate(mshr); 199 } else { 200 readyList.erase(mshr->readyIter); 201 inServiceEntries += 1; 202 } 203} 204 205void 206MSHRQueue::markPending(MSHR *mshr) 207{ 208 assert(mshr->inService); 209 mshr->inService = false; 210 --inServiceEntries; 211 /** 212 * @ todo might want to add rerequests to front of pending list for 213 * performance. 214 */ 215 mshr->readyIter = addToReadyList(mshr); 216} 217 218void 219MSHRQueue::squash(int threadNum) 220{ 221 MSHR::Iterator i = allocatedList.begin(); 222 MSHR::Iterator end = allocatedList.end(); 223 for (; i != end;) { 224 MSHR *mshr = *i; 225 if (mshr->threadNum == threadNum) { 226 while (mshr->hasTargets()) { 227 mshr->popTarget(); 228 assert(0/*target->req->getThreadNum()*/ == threadNum); 229 } 230 assert(!mshr->hasTargets()); 231 assert(mshr->ntargets==0); 232 if (!mshr->inService) { 233 i = deallocateOne(mshr); 234 } else { 235 //mshr->pkt->flags &= ~CACHE_LINE_FILL; 236 ++i; 237 } 238 } else { 239 ++i; 240 } 241 } 242} 243