mshr.cc revision 5314
110447Snilay@cs.wisc.edu/* 210447Snilay@cs.wisc.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 310447Snilay@cs.wisc.edu * All rights reserved. 410447Snilay@cs.wisc.edu * 510447Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without 610447Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 710447Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright 810447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer; 910447Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright 1010447Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the 1110447Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution; 1210447Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its 1310447Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 1410447Snilay@cs.wisc.edu * this software without specific prior written permission. 1510447Snilay@cs.wisc.edu * 1610447Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710447Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810447Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910447Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010447Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110447Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210447Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310447Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410447Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510447Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610447Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710447Snilay@cs.wisc.edu * 2810447Snilay@cs.wisc.edu * Authors: Erik Hallnor 2910447Snilay@cs.wisc.edu * Dave Greene 3010447Snilay@cs.wisc.edu */ 3110447Snilay@cs.wisc.edu 3210447Snilay@cs.wisc.edu/** 3310447Snilay@cs.wisc.edu * @file 3410447Snilay@cs.wisc.edu * Miss Status and Handling Register (MSHR) definitions. 3510447Snilay@cs.wisc.edu */ 3610447Snilay@cs.wisc.edu 3710447Snilay@cs.wisc.edu#include <assert.h> 3810447Snilay@cs.wisc.edu#include <string> 3910447Snilay@cs.wisc.edu#include <vector> 4010447Snilay@cs.wisc.edu#include <algorithm> 4110447Snilay@cs.wisc.edu 4210447Snilay@cs.wisc.edu#include "mem/cache/miss/mshr.hh" 4310447Snilay@cs.wisc.edu#include "sim/core.hh" // for curTick 4410447Snilay@cs.wisc.edu#include "sim/host.hh" 4510447Snilay@cs.wisc.edu#include "base/misc.hh" 4610447Snilay@cs.wisc.edu#include "mem/cache/cache.hh" 4710447Snilay@cs.wisc.edu 4810447Snilay@cs.wisc.eduusing namespace std; 4910447Snilay@cs.wisc.edu 5010447Snilay@cs.wisc.eduMSHR::MSHR() 5110447Snilay@cs.wisc.edu{ 5210447Snilay@cs.wisc.edu inService = false; 5310447Snilay@cs.wisc.edu ntargets = 0; 5410447Snilay@cs.wisc.edu threadNum = -1; 5510447Snilay@cs.wisc.edu targets = new TargetList(); 5610447Snilay@cs.wisc.edu deferredTargets = new TargetList(); 5710447Snilay@cs.wisc.edu} 5810447Snilay@cs.wisc.edu 5910447Snilay@cs.wisc.edu 6010447Snilay@cs.wisc.eduMSHR::TargetList::TargetList() 6110447Snilay@cs.wisc.edu : needsExclusive(false), hasUpgrade(false) 6210447Snilay@cs.wisc.edu{} 6310447Snilay@cs.wisc.edu 6410447Snilay@cs.wisc.edu 6510447Snilay@cs.wisc.eduinline void 6610447Snilay@cs.wisc.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 6710447Snilay@cs.wisc.edu Counter order, bool cpuSide) 6810447Snilay@cs.wisc.edu{ 6910447Snilay@cs.wisc.edu if (cpuSide) { 7010447Snilay@cs.wisc.edu if (pkt->needsExclusive()) { 7110447Snilay@cs.wisc.edu needsExclusive = true; 7210447Snilay@cs.wisc.edu } 7310447Snilay@cs.wisc.edu 7410447Snilay@cs.wisc.edu if (pkt->cmd == MemCmd::UpgradeReq) { 7510447Snilay@cs.wisc.edu hasUpgrade = true; 7610447Snilay@cs.wisc.edu } 7710447Snilay@cs.wisc.edu 7810447Snilay@cs.wisc.edu MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 7910447Snilay@cs.wisc.edu if (mshr != NULL) { 8010447Snilay@cs.wisc.edu assert(!mshr->downstreamPending); 8110447Snilay@cs.wisc.edu mshr->downstreamPending = true; 8210447Snilay@cs.wisc.edu } 8310447Snilay@cs.wisc.edu } 8410447Snilay@cs.wisc.edu 8510447Snilay@cs.wisc.edu push_back(Target(pkt, readyTime, order, cpuSide)); 8610447Snilay@cs.wisc.edu} 8710447Snilay@cs.wisc.edu 8810447Snilay@cs.wisc.edu 8910447Snilay@cs.wisc.eduvoid 9010447Snilay@cs.wisc.eduMSHR::TargetList::replaceUpgrades() 9110447Snilay@cs.wisc.edu{ 9210447Snilay@cs.wisc.edu if (!hasUpgrade) 9310447Snilay@cs.wisc.edu return; 9410447Snilay@cs.wisc.edu 9510447Snilay@cs.wisc.edu Iterator end_i = end(); 9610447Snilay@cs.wisc.edu for (Iterator i = begin(); i != end_i; ++i) { 9710447Snilay@cs.wisc.edu if (i->pkt->cmd == MemCmd::UpgradeReq) { 9810447Snilay@cs.wisc.edu i->pkt->cmd = MemCmd::ReadExReq; 9910447Snilay@cs.wisc.edu DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 10010447Snilay@cs.wisc.edu } 10110447Snilay@cs.wisc.edu } 10210447Snilay@cs.wisc.edu 10310447Snilay@cs.wisc.edu hasUpgrade = false; 10410447Snilay@cs.wisc.edu} 10510447Snilay@cs.wisc.edu 10610447Snilay@cs.wisc.edu 10710447Snilay@cs.wisc.eduvoid 10810447Snilay@cs.wisc.eduMSHR::TargetList::clearDownstreamPending() 10910447Snilay@cs.wisc.edu{ 11010447Snilay@cs.wisc.edu Iterator end_i = end(); 11110447Snilay@cs.wisc.edu for (Iterator i = begin(); i != end_i; ++i) { 11210447Snilay@cs.wisc.edu MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 11310447Snilay@cs.wisc.edu if (mshr != NULL) { 11410447Snilay@cs.wisc.edu assert(mshr->downstreamPending); 11510447Snilay@cs.wisc.edu mshr->downstreamPending = false; 11610447Snilay@cs.wisc.edu } 11710447Snilay@cs.wisc.edu } 11810447Snilay@cs.wisc.edu} 11910447Snilay@cs.wisc.edu 12010447Snilay@cs.wisc.edu 12110447Snilay@cs.wisc.edubool 12210447Snilay@cs.wisc.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 12310447Snilay@cs.wisc.edu{ 12410447Snilay@cs.wisc.edu Iterator end_i = end(); 12510447Snilay@cs.wisc.edu for (Iterator i = begin(); i != end_i; ++i) { 12610447Snilay@cs.wisc.edu if (pkt->checkFunctional(i->pkt)) { 12710447Snilay@cs.wisc.edu return true; 12810447Snilay@cs.wisc.edu } 12910447Snilay@cs.wisc.edu } 13010447Snilay@cs.wisc.edu 13110447Snilay@cs.wisc.edu return false; 13210447Snilay@cs.wisc.edu} 13310447Snilay@cs.wisc.edu 13410447Snilay@cs.wisc.edu 13510447Snilay@cs.wisc.eduvoid 13610447Snilay@cs.wisc.eduMSHR::TargetList:: 13710447Snilay@cs.wisc.eduprint(std::ostream &os, int verbosity, const std::string &prefix) const 13810447Snilay@cs.wisc.edu{ 13910447Snilay@cs.wisc.edu ConstIterator end_i = end(); 14010447Snilay@cs.wisc.edu for (ConstIterator i = begin(); i != end_i; ++i) { 14110447Snilay@cs.wisc.edu ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); 14210447Snilay@cs.wisc.edu i->pkt->print(os, verbosity, ""); 14310447Snilay@cs.wisc.edu } 14410447Snilay@cs.wisc.edu} 14510447Snilay@cs.wisc.edu 14610447Snilay@cs.wisc.edu 14710447Snilay@cs.wisc.eduvoid 14810447Snilay@cs.wisc.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target, 14910447Snilay@cs.wisc.edu Tick whenReady, Counter _order) 15010447Snilay@cs.wisc.edu{ 15110447Snilay@cs.wisc.edu addr = _addr; 15210447Snilay@cs.wisc.edu size = _size; 15310447Snilay@cs.wisc.edu readyTime = whenReady; 15410447Snilay@cs.wisc.edu order = _order; 15510447Snilay@cs.wisc.edu assert(target); 15610447Snilay@cs.wisc.edu isCacheFill = false; 15710447Snilay@cs.wisc.edu _isUncacheable = target->req->isUncacheable(); 15810447Snilay@cs.wisc.edu inService = false; 15910447Snilay@cs.wisc.edu downstreamPending = false; 16010447Snilay@cs.wisc.edu threadNum = 0; 16110447Snilay@cs.wisc.edu ntargets = 1; 16210447Snilay@cs.wisc.edu // Don't know of a case where we would allocate a new MSHR for a 16310447Snilay@cs.wisc.edu // snoop (mem-side request), so set cpuSide to true here. 16410447Snilay@cs.wisc.edu assert(targets->isReset()); 16510447Snilay@cs.wisc.edu targets->add(target, whenReady, _order, true); 16610447Snilay@cs.wisc.edu assert(deferredTargets->isReset()); 16710447Snilay@cs.wisc.edu pendingInvalidate = false; 16810447Snilay@cs.wisc.edu pendingShared = false; 16910447Snilay@cs.wisc.edu data = NULL; 17010447Snilay@cs.wisc.edu} 17110447Snilay@cs.wisc.edu 17210447Snilay@cs.wisc.edu 17310447Snilay@cs.wisc.edubool 17410447Snilay@cs.wisc.eduMSHR::markInService() 17510447Snilay@cs.wisc.edu{ 17610447Snilay@cs.wisc.edu assert(!inService); 17710447Snilay@cs.wisc.edu if (isSimpleForward()) { 17810447Snilay@cs.wisc.edu // we just forwarded the request packet & don't expect a 17910447Snilay@cs.wisc.edu // response, so get rid of it 18010447Snilay@cs.wisc.edu assert(getNumTargets() == 1); 18110447Snilay@cs.wisc.edu popTarget(); 18210447Snilay@cs.wisc.edu return true; 18310447Snilay@cs.wisc.edu } 18410447Snilay@cs.wisc.edu inService = true; 18510447Snilay@cs.wisc.edu if (!downstreamPending) { 18610447Snilay@cs.wisc.edu // let upstream caches know that the request has made it to a 18710447Snilay@cs.wisc.edu // level where it's going to get a response 18810447Snilay@cs.wisc.edu targets->clearDownstreamPending(); 18910447Snilay@cs.wisc.edu } 19010447Snilay@cs.wisc.edu return false; 19110447Snilay@cs.wisc.edu} 19210447Snilay@cs.wisc.edu 19310447Snilay@cs.wisc.edu 19410447Snilay@cs.wisc.eduvoid 19510447Snilay@cs.wisc.eduMSHR::deallocate() 19610447Snilay@cs.wisc.edu{ 19710447Snilay@cs.wisc.edu assert(targets->empty()); 19810447Snilay@cs.wisc.edu targets->resetFlags(); 19910447Snilay@cs.wisc.edu assert(deferredTargets->isReset()); 20010447Snilay@cs.wisc.edu assert(ntargets == 0); 20110447Snilay@cs.wisc.edu inService = false; 20210447Snilay@cs.wisc.edu //allocIter = NULL; 20310447Snilay@cs.wisc.edu //readyIter = NULL; 20410447Snilay@cs.wisc.edu} 20510447Snilay@cs.wisc.edu 20610447Snilay@cs.wisc.edu/* 20710447Snilay@cs.wisc.edu * Adds a target to an MSHR 20810447Snilay@cs.wisc.edu */ 20910447Snilay@cs.wisc.eduvoid 21010447Snilay@cs.wisc.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 21110447Snilay@cs.wisc.edu{ 21210447Snilay@cs.wisc.edu // if there's a request already in service for this MSHR, we will 21310447Snilay@cs.wisc.edu // have to defer the new target until after the response if any of 21410447Snilay@cs.wisc.edu // the following are true: 21510447Snilay@cs.wisc.edu // - there are other targets already deferred 21610447Snilay@cs.wisc.edu // - there's a pending invalidate to be applied after the response 217 // comes back (but before this target is processed) 218 // - the outstanding request is for a non-exclusive block and this 219 // target requires an exclusive block 220 if (inService && 221 (!deferredTargets->empty() || pendingInvalidate || 222 (!targets->needsExclusive && pkt->needsExclusive()))) { 223 // need to put on deferred list 224 deferredTargets->add(pkt, whenReady, _order, true); 225 } else { 226 // no request outstanding, or still OK to append to 227 // outstanding request 228 targets->add(pkt, whenReady, _order, true); 229 } 230 231 ++ntargets; 232} 233 234bool 235MSHR::handleSnoop(PacketPtr pkt, Counter _order) 236{ 237 if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 238 // Request has not been issued yet, or it's been issued 239 // locally but is buffered unissued at some downstream cache 240 // which is forwarding us this snoop. Either way, the packet 241 // we're snooping logically precedes this MSHR's request, so 242 // the snoop has no impact on the MSHR, but must be processed 243 // in the standard way by the cache. The only exception is 244 // that if we're an L2+ cache buffering an UpgradeReq from a 245 // higher-level cache, and the snoop is invalidating, then our 246 // buffered upgrades must be converted to read exclusives, 247 // since the upper-level cache no longer has a valid copy. 248 // That is, even though the upper-level cache got out on its 249 // local bus first, some other invalidating transaction 250 // reached the global bus before the upgrade did. 251 if (pkt->needsExclusive()) { 252 targets->replaceUpgrades(); 253 deferredTargets->replaceUpgrades(); 254 } 255 256 return false; 257 } 258 259 // From here on down, the request issued by this MSHR logically 260 // precedes the request we're snooping. 261 262 if (pkt->needsExclusive()) { 263 // snooped request still precedes the re-request we'll have to 264 // issue for deferred targets, if any... 265 deferredTargets->replaceUpgrades(); 266 } 267 268 if (pendingInvalidate) { 269 // a prior snoop has already appended an invalidation, so 270 // logically we don't have the block anymore; no need for 271 // further snooping. 272 return true; 273 } 274 275 if (targets->needsExclusive || pkt->needsExclusive()) { 276 // actual target device (typ. PhysicalMemory) will delete the 277 // packet on reception, so we need to save a copy here 278 PacketPtr cp_pkt = new Packet(pkt, true); 279 targets->add(cp_pkt, curTick, _order, false); 280 ++ntargets; 281 282 if (targets->needsExclusive) { 283 // We're awaiting an exclusive copy, so ownership is pending. 284 // It's up to us to respond once the data arrives. 285 pkt->assertMemInhibit(); 286 pkt->setSupplyExclusive(); 287 } else { 288 // Someone else may respond before we get around to 289 // processing this snoop, which means the copied request 290 // pointer will no longer be valid 291 cp_pkt->req = NULL; 292 } 293 294 if (pkt->needsExclusive()) { 295 // This transaction will take away our pending copy 296 pendingInvalidate = true; 297 } 298 } else { 299 // Read to a read: no conflict, so no need to record as 300 // target, but make sure neither reader thinks he's getting an 301 // exclusive copy 302 pendingShared = true; 303 pkt->assertShared(); 304 } 305 306 return true; 307} 308 309 310bool 311MSHR::promoteDeferredTargets() 312{ 313 assert(targets->empty()); 314 if (deferredTargets->empty()) { 315 return false; 316 } 317 318 // swap targets & deferredTargets lists 319 TargetList *tmp = targets; 320 targets = deferredTargets; 321 deferredTargets = tmp; 322 323 assert(targets->size() == ntargets); 324 325 // clear deferredTargets flags 326 deferredTargets->resetFlags(); 327 328 pendingInvalidate = false; 329 pendingShared = false; 330 order = targets->front().order; 331 readyTime = std::max(curTick, targets->front().readyTime); 332 333 return true; 334} 335 336 337void 338MSHR::handleFill(Packet *pkt, CacheBlk *blk) 339{ 340 if (pendingShared) { 341 // we snooped another read while this read was in 342 // service... assert shared line on its behalf 343 pkt->assertShared(); 344 } 345 346 if (!pkt->sharedAsserted() && !pendingInvalidate 347 && deferredTargets->needsExclusive) { 348 // We got an exclusive response, but we have deferred targets 349 // which are waiting to request an exclusive copy (not because 350 // of a pending invalidate). This can happen if the original 351 // request was for a read-only (non-exclusive) block, but we 352 // got an exclusive copy anyway because of the E part of the 353 // MOESI/MESI protocol. Since we got the exclusive copy 354 // there's no need to defer the targets, so move them up to 355 // the regular target list. 356 assert(!targets->needsExclusive); 357 targets->needsExclusive = true; 358 // this clears out deferredTargets too 359 targets->splice(targets->end(), *deferredTargets); 360 deferredTargets->resetFlags(); 361 } 362} 363 364 365bool 366MSHR::checkFunctional(PacketPtr pkt) 367{ 368 // For printing, we treat the MSHR as a whole as single entity. 369 // For other requests, we iterate over the individual targets 370 // since that's where the actual data lies. 371 if (pkt->isPrint()) { 372 pkt->checkFunctional(this, addr, size, NULL); 373 return false; 374 } else { 375 return (targets->checkFunctional(pkt) || 376 deferredTargets->checkFunctional(pkt)); 377 } 378} 379 380 381void 382MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 383{ 384 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 385 prefix, addr, addr+size-1, 386 isCacheFill ? "Fill" : "", 387 needsExclusive() ? "Excl" : "", 388 _isUncacheable ? "Unc" : "", 389 inService ? "InSvc" : "", 390 downstreamPending ? "DwnPend" : "", 391 pendingInvalidate ? "PendInv" : "", 392 pendingShared ? "PendShared" : ""); 393 394 ccprintf(os, "%s Targets:\n", prefix); 395 targets->print(os, verbosity, prefix + " "); 396 if (!deferredTargets->empty()) { 397 ccprintf(os, "%s Deferred Targets:\n", prefix); 398 deferredTargets->print(os, verbosity, prefix + " "); 399 } 400} 401 402MSHR::~MSHR() 403{ 404} 405