mshr_queue.cc revision 4626
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) 40 : numEntries(num_entries + reserve - 1), numReserve(reserve) 41{ 42 allocated = 0; 43 inServiceEntries = 0; 44 registers = new MSHR[numEntries]; 45 for (int i = 0; i < numEntries; ++i) { 46 registers[i].queue = this; 47 freeList.push_back(®isters[i]); 48 } 49} 50 51MSHRQueue::~MSHRQueue() 52{ 53 delete [] registers; 54} 55 56MSHR * 57MSHRQueue::findMatch(Addr addr) const 58{ 59 MSHR::ConstIterator i = allocatedList.begin(); 60 MSHR::ConstIterator end = allocatedList.end(); 61 for (; i != end; ++i) { 62 MSHR *mshr = *i; 63 if (mshr->addr == addr) { 64 return mshr; 65 } 66 } 67 return NULL; 68} 69 70bool 71MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const 72{ 73 // Need an empty vector 74 assert(matches.empty()); 75 bool retval = false; 76 MSHR::ConstIterator i = allocatedList.begin(); 77 MSHR::ConstIterator end = allocatedList.end(); 78 for (; i != end; ++i) { 79 MSHR *mshr = *i; 80 if (mshr->addr == addr) { 81 retval = true; 82 matches.push_back(mshr); 83 } 84 } 85 return retval; 86 87} 88 89MSHR * 90MSHRQueue::findPending(Addr addr, int size) const 91{ 92 MSHR::ConstIterator i = pendingList.begin(); 93 MSHR::ConstIterator end = pendingList.end(); 94 for (; i != end; ++i) { 95 MSHR *mshr = *i; 96 if (mshr->addr < addr) { 97 if (mshr->addr + mshr->size > addr) { 98 return mshr; 99 } 100 } else { 101 if (addr + size > mshr->addr) { 102 return mshr; 103 } 104 } 105 } 106 return NULL; 107} 108 109MSHR * 110MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, bool isFill) 111{ 112 assert(!freeList.empty()); 113 MSHR *mshr = freeList.front(); 114 assert(mshr->getNumTargets() == 0); 115 freeList.pop_front(); 116 117 mshr->allocate(addr, size, pkt, isFill); 118 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 119 mshr->readyIter = pendingList.insert(pendingList.end(), mshr); 120 121 allocated += 1; 122 return mshr; 123} 124 125 126void 127MSHRQueue::deallocate(MSHR *mshr) 128{ 129 deallocateOne(mshr); 130} 131 132MSHR::Iterator 133MSHRQueue::deallocateOne(MSHR *mshr) 134{ 135 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); 136 freeList.push_front(mshr); 137 allocated--; 138 if (mshr->inService) { 139 inServiceEntries--; 140 } else { 141 pendingList.erase(mshr->readyIter); 142 } 143 mshr->deallocate(); 144 return retval; 145} 146 147void 148MSHRQueue::moveToFront(MSHR *mshr) 149{ 150 if (!mshr->inService) { 151 assert(mshr == *(mshr->readyIter)); 152 pendingList.erase(mshr->readyIter); 153 mshr->readyIter = pendingList.insert(pendingList.begin(), mshr); 154 } 155} 156 157void 158MSHRQueue::markInService(MSHR *mshr) 159{ 160 //assert(mshr == pendingList.front()); 161#if 0 162 if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == MemCmd::UpgradeReq)) { 163 assert(mshr->getNumTargets() == 0); 164 deallocate(mshr); 165 return; 166 } 167#endif 168 mshr->inService = true; 169 pendingList.erase(mshr->readyIter); 170 //mshr->readyIter = NULL; 171 inServiceEntries += 1; 172 //pendingList.pop_front(); 173} 174 175void 176MSHRQueue::markPending(MSHR *mshr) 177{ 178 //assert(mshr->readyIter == NULL); 179 mshr->inService = false; 180 --inServiceEntries; 181 /** 182 * @ todo might want to add rerequests to front of pending list for 183 * performance. 184 */ 185 mshr->readyIter = pendingList.insert(pendingList.end(), mshr); 186} 187 188void 189MSHRQueue::squash(int threadNum) 190{ 191 MSHR::Iterator i = allocatedList.begin(); 192 MSHR::Iterator end = allocatedList.end(); 193 for (; i != end;) { 194 MSHR *mshr = *i; 195 if (mshr->threadNum == threadNum) { 196 while (mshr->hasTargets()) { 197 mshr->popTarget(); 198 assert(0/*target->req->getThreadNum()*/ == threadNum); 199 } 200 assert(!mshr->hasTargets()); 201 assert(mshr->ntargets==0); 202 if (!mshr->inService) { 203 i = deallocateOne(mshr); 204 } else { 205 //mshr->pkt->flags &= ~CACHE_LINE_FILL; 206 ++i; 207 } 208 } else { 209 ++i; 210 } 211 } 212} 213