mshr.cc revision 4903
1/* 2 * Copyright (c) 2002-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 * Dave Greene 30 */ 31 32/** 33 * @file 34 * Miss Status and Handling Register (MSHR) definitions. 35 */ 36 37#include <assert.h> 38#include <string> 39#include <vector> 40#include <algorithm> 41 42#include "mem/cache/miss/mshr.hh" 43#include "sim/core.hh" // for curTick 44#include "sim/host.hh" 45#include "base/misc.hh" 46#include "mem/cache/cache.hh" 47 48using namespace std; 49 50MSHR::MSHR() 51{ 52 inService = false; 53 ntargets = 0; 54 threadNum = -1; 55 targets = new TargetList(); 56 deferredTargets = new TargetList(); 57} 58 59 60MSHR::TargetList::TargetList() 61 : needsExclusive(false), hasUpgrade(false) 62{} 63 64 65inline void 66MSHR::TargetList::add(PacketPtr pkt, Tick readyTime, Counter order, bool cpuSide) 67{ 68 if (cpuSide) { 69 if (pkt->needsExclusive()) { 70 needsExclusive = true; 71 } 72 73 if (pkt->cmd == MemCmd::UpgradeReq) { 74 hasUpgrade = true; 75 } 76 } 77 78 push_back(Target(pkt, readyTime, order, cpuSide)); 79} 80 81 82void 83MSHR::TargetList::replaceUpgrades() 84{ 85 if (!hasUpgrade) 86 return; 87 88 Iterator end_i = end(); 89 for (Iterator i = begin(); i != end_i; ++i) { 90 if (i->pkt->cmd == MemCmd::UpgradeReq) { 91 i->pkt->cmd = MemCmd::ReadExReq; 92 DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 93 } 94 } 95 96 hasUpgrade = false; 97} 98 99 100void 101MSHR::allocate(Addr _addr, int _size, PacketPtr target, 102 Tick whenReady, Counter _order) 103{ 104 addr = _addr; 105 size = _size; 106 readyTime = whenReady; 107 order = _order; 108 assert(target); 109 isCacheFill = false; 110 _isUncacheable = target->req->isUncacheable(); 111 inService = false; 112 threadNum = 0; 113 ntargets = 1; 114 // Don't know of a case where we would allocate a new MSHR for a 115 // snoop (mem-side request), so set cpuSide to true here. 116 assert(targets->isReset()); 117 targets->add(target, whenReady, _order, true); 118 assert(deferredTargets->isReset()); 119 pendingInvalidate = false; 120 pendingShared = false; 121 data = NULL; 122} 123 124void 125MSHR::deallocate() 126{ 127 assert(targets->empty()); 128 targets->resetFlags(); 129 assert(deferredTargets->isReset()); 130 assert(ntargets == 0); 131 inService = false; 132 //allocIter = NULL; 133 //readyIter = NULL; 134} 135 136/* 137 * Adds a target to an MSHR 138 */ 139void 140MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 141{ 142 // if there's a request already in service for this MSHR, we will 143 // have to defer the new target until after the response if any of 144 // the following are true: 145 // - there are other targets already deferred 146 // - there's a pending invalidate to be applied after the response 147 // comes back (but before this target is processed) 148 // - the outstanding request is for a non-exclusive block and this 149 // target requires an exclusive block 150 if (inService && 151 (!deferredTargets->empty() || pendingInvalidate || 152 (!targets->needsExclusive && pkt->needsExclusive()))) { 153 // need to put on deferred list 154 deferredTargets->add(pkt, whenReady, _order, true); 155 } else { 156 // no request outstanding, or still OK to append to 157 // outstanding request 158 targets->add(pkt, whenReady, _order, true); 159 } 160 161 ++ntargets; 162} 163 164bool 165MSHR::handleSnoop(PacketPtr pkt, Counter _order) 166{ 167 if (!inService || (pkt->isExpressSnoop() && !pkt->isDeferredSnoop())) { 168 // Request has not been issued yet, or it's been issued 169 // locally but is buffered unissued at some downstream cache 170 // which is forwarding us this snoop. Either way, the packet 171 // we're snooping logically precedes this MSHR's request, so 172 // the snoop has no impact on the MSHR, but must be processed 173 // in the standard way by the cache. The only exception is 174 // that if we're an L2+ cache buffering an UpgradeReq from a 175 // higher-level cache, and the snoop is invalidating, then our 176 // buffered upgrades must be converted to read exclusives, 177 // since the upper-level cache no longer has a valid copy. 178 // That is, even though the upper-level cache got out on its 179 // local bus first, some other invalidating transaction 180 // reached the global bus before the upgrade did. 181 if (pkt->needsExclusive()) { 182 targets->replaceUpgrades(); 183 deferredTargets->replaceUpgrades(); 184 } 185 186 return false; 187 } 188 189 // From here on down, the request issued by this MSHR logically 190 // precedes the request we're snooping. 191 192 if (pkt->needsExclusive()) { 193 // snooped request still precedes the re-request we'll have to 194 // issue for deferred targets, if any... 195 deferredTargets->replaceUpgrades(); 196 } 197 198 if (pendingInvalidate) { 199 // a prior snoop has already appended an invalidation, so 200 // logically we don't have the block anymore; no need for 201 // further snooping. 202 return true; 203 } 204 205 if (targets->needsExclusive || pkt->needsExclusive()) { 206 // actual target device (typ. PhysicalMemory) will delete the 207 // packet on reception, so we need to save a copy here 208 targets->add(new Packet(pkt), curTick, _order, false); 209 ++ntargets; 210 211 if (targets->needsExclusive) { 212 // We're awaiting an exclusive copy, so ownership is pending. 213 // It's up to us to respond once the data arrives. 214 pkt->assertMemInhibit(); 215 } 216 217 if (pkt->needsExclusive()) { 218 // This transaction will take away our pending copy 219 pendingInvalidate = true; 220 } 221 } else { 222 // Read to a read: no conflict, so no need to record as 223 // target, but make sure neither reader thinks he's getting an 224 // exclusive copy 225 pendingShared = true; 226 pkt->assertShared(); 227 } 228 229 return true; 230} 231 232 233bool 234MSHR::promoteDeferredTargets() 235{ 236 assert(targets->empty()); 237 if (deferredTargets->empty()) { 238 return false; 239 } 240 241 // swap targets & deferredTargets lists 242 TargetList *tmp = targets; 243 targets = deferredTargets; 244 deferredTargets = tmp; 245 246 assert(targets->size() == ntargets); 247 248 // clear deferredTargets flags 249 deferredTargets->resetFlags(); 250 251 pendingInvalidate = false; 252 pendingShared = false; 253 order = targets->front().order; 254 readyTime = std::max(curTick, targets->front().readyTime); 255 256 return true; 257} 258 259 260void 261MSHR::handleFill(Packet *pkt, CacheBlk *blk) 262{ 263 if (pendingShared) { 264 // we snooped another read while this read was in 265 // service... assert shared line on its behalf 266 pkt->assertShared(); 267 } 268} 269 270 271void 272MSHR::dump() 273{ 274 ccprintf(cerr, 275 "inService: %d thread: %d\n" 276 "Addr: %x ntargets %d\n" 277 "Targets:\n", 278 inService, threadNum, addr, ntargets); 279#if 0 280 TargetListIterator tar_it = targets->begin(); 281 for (int i = 0; i < ntargets; i++) { 282 assert(tar_it != targets->end()); 283 284 ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 285 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 286 287 tar_it++; 288 } 289#endif 290 ccprintf(cerr, "\n"); 291} 292 293MSHR::~MSHR() 294{ 295} 296