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