mshr_queue.cc revision 2810
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 the MSHRQueue. 33 */ 34 35#include "mem/cache/miss/mshr_queue.hh" 36#include "sim/eventq.hh" 37 38using namespace std; 39 40MSHRQueue::MSHRQueue(int num_mshrs, int reserve) 41 : numMSHRs(num_mshrs + reserve - 1), numReserve(reserve) 42{ 43 allocated = 0; 44 inServiceMSHRs = 0; 45 allocatedTargets = 0; 46 registers = new MSHR[numMSHRs]; 47 for (int i = 0; i < numMSHRs; ++i) { 48 freeList.push_back(®isters[i]); 49 } 50} 51 52MSHRQueue::~MSHRQueue() 53{ 54 delete [] registers; 55} 56 57MSHR* 58MSHRQueue::findMatch(Addr addr, int asid) 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, int asid, 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 90MSHR* 91MSHRQueue::findPending(Packet * &pkt) const 92{ 93 MSHR::ConstIterator i = pendingList.begin(); 94 MSHR::ConstIterator end = pendingList.end(); 95 for (; i != end; ++i) { 96 MSHR *mshr = *i; 97 if (mshr->addr < pkt->addr) { 98 if (mshr->addr + mshr->pkt->size > pkt->addr) { 99 return mshr; 100 } 101 } else { 102 if (pkt->addr + pkt->size > mshr->addr) { 103 return mshr; 104 } 105 } 106 107 //need to check destination address for copies. 108 if (mshr->pkt->cmd == Copy) { 109 Addr dest = mshr->pkt->dest; 110 if (dest < pkt->addr) { 111 if (dest + mshr->pkt->size > pkt->addr) { 112 return mshr; 113 } 114 } else { 115 if (pkt->addr + pkt->size > dest) { 116 return mshr; 117 } 118 } 119 } 120 } 121 return NULL; 122} 123 124MSHR* 125MSHRQueue::allocate(Packet * &pkt, int size) 126{ 127 Addr aligned_addr = pkt->addr & ~((Addr)size - 1); 128 MSHR *mshr = freeList.front(); 129 assert(mshr->getNumTargets() == 0); 130 freeList.pop_front(); 131 132 if (pkt->cmd.isNoResponse()) { 133 mshr->allocateAsBuffer(pkt); 134 } else { 135 assert(size !=0); 136 mshr->allocate(pkt->cmd, aligned_addr, pkt->req->req->asid, size, pkt); 137 allocatedTargets += 1; 138 } 139 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 140 mshr->readyIter = pendingList.insert(pendingList.end(), mshr); 141 142 allocated += 1; 143 return mshr; 144} 145 146MSHR* 147MSHRQueue::allocateFetch(Addr addr, int asid, int size, Packet * &target) 148{ 149 MSHR *mshr = freeList.front(); 150 assert(mshr->getNumTargets() == 0); 151 freeList.pop_front(); 152 mshr->allocate(Read, addr, asid, size, target); 153 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 154 mshr->readyIter = pendingList.insert(pendingList.end(), mshr); 155 156 allocated += 1; 157 return mshr; 158} 159 160MSHR* 161MSHRQueue::allocateTargetList(Addr addr, int asid, int size) 162{ 163 MSHR *mshr = freeList.front(); 164 assert(mshr->getNumTargets() == 0); 165 freeList.pop_front(); 166 Packet * dummy; 167 mshr->allocate(Read, addr, asid, size, dummy); 168 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); 169 mshr->inService = true; 170 ++inServiceMSHRs; 171 ++allocated; 172 return mshr; 173} 174 175 176void 177MSHRQueue::deallocate(MSHR* mshr) 178{ 179 deallocateOne(mshr); 180} 181 182MSHR::Iterator 183MSHRQueue::deallocateOne(MSHR* mshr) 184{ 185 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); 186 freeList.push_front(mshr); 187 allocated--; 188 allocatedTargets -= mshr->getNumTargets(); 189 if (mshr->inService) { 190 inServiceMSHRs--; 191 } else { 192 pendingList.erase(mshr->readyIter); 193 } 194 mshr->deallocate(); 195 return retval; 196} 197 198void 199MSHRQueue::moveToFront(MSHR *mshr) 200{ 201 if (!mshr->inService) { 202 assert(mshr == *(mshr->readyIter)); 203 pendingList.erase(mshr->readyIter); 204 mshr->readyIter = pendingList.insert(pendingList.begin(), mshr); 205 } 206} 207 208void 209MSHRQueue::markInService(MSHR* mshr) 210{ 211 //assert(mshr == pendingList.front()); 212 if (mshr->pkt->cmd.isNoResponse()) { 213 assert(mshr->getNumTargets() == 0); 214 deallocate(mshr); 215 return; 216 } 217 mshr->inService = true; 218 pendingList.erase(mshr->readyIter); 219 mshr->readyIter = NULL; 220 inServiceMSHRs += 1; 221 //pendingList.pop_front(); 222} 223 224void 225MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd) 226{ 227 assert(mshr->readyIter == NULL); 228 mshr->pkt->cmd = cmd; 229 mshr->pkt->flags &= ~SATISFIED; 230 mshr->inService = false; 231 --inServiceMSHRs; 232 /** 233 * @ todo might want to add rerequests to front of pending list for 234 * performance. 235 */ 236 mshr->readyIter = pendingList.insert(pendingList.end(), mshr); 237} 238 239void 240MSHRQueue::squash(int thread_number) 241{ 242 MSHR::Iterator i = allocatedList.begin(); 243 MSHR::Iterator end = allocatedList.end(); 244 for (; i != end;) { 245 MSHR *mshr = *i; 246 if (mshr->threadNum == thread_number) { 247 while (mshr->hasTargets()) { 248 Packet * target = mshr->getTarget(); 249 mshr->popTarget(); 250 251 assert(target->thread_num == thread_number); 252 if (target->completionEvent != NULL) { 253 delete target->completionEvent; 254 } 255 target = NULL; 256 } 257 assert(!mshr->hasTargets()); 258 assert(mshr->ntargets==0); 259 if (!mshr->inService) { 260 i = deallocateOne(mshr); 261 } else { 262 //mshr->pkt->flags &= ~CACHE_LINE_FILL; 263 ++i; 264 } 265 } else { 266 ++i; 267 } 268 } 269} 270