lsq_unit_impl.hh revision 8545
16019Shines@cs.fsu.edu/*
26019Shines@cs.fsu.edu * Copyright (c) 2010 ARM Limited
310037SARM gem5 Developers * All rights reserved
47178Sgblack@eecs.umich.edu *
57178Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
67178Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
77178Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
87178Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
97178Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
107178Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
117178Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
127178Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
137178Sgblack@eecs.umich.edu *
147178Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
156019Shines@cs.fsu.edu * All rights reserved.
166019Shines@cs.fsu.edu *
176019Shines@cs.fsu.edu * Redistribution and use in source and binary forms, with or without
186019Shines@cs.fsu.edu * modification, are permitted provided that the following conditions are
196019Shines@cs.fsu.edu * met: redistributions of source code must retain the above copyright
206019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer;
216019Shines@cs.fsu.edu * redistributions in binary form must reproduce the above copyright
226019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer in the
236019Shines@cs.fsu.edu * documentation and/or other materials provided with the distribution;
246019Shines@cs.fsu.edu * neither the name of the copyright holders nor the names of its
256019Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from
266019Shines@cs.fsu.edu * this software without specific prior written permission.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
306019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
326019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
356019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396019Shines@cs.fsu.edu *
406019Shines@cs.fsu.edu * Authors: Kevin Lim
416019Shines@cs.fsu.edu *          Korey Sewell
426019Shines@cs.fsu.edu */
436019Shines@cs.fsu.edu
446019Shines@cs.fsu.edu#include "arch/locked_mem.hh"
456019Shines@cs.fsu.edu#include "base/str.hh"
466019Shines@cs.fsu.edu#include "config/the_isa.hh"
476019Shines@cs.fsu.edu#include "config/use_checker.hh"
487639Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh"
497639Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh"
507639Sgblack@eecs.umich.edu#include "debug/Activity.hh"
517639Sgblack@eecs.umich.edu#include "debug/IEW.hh"
527639Sgblack@eecs.umich.edu#include "debug/LSQUnit.hh"
537639Sgblack@eecs.umich.edu#include "mem/packet.hh"
547639Sgblack@eecs.umich.edu#include "mem/request.hh"
557639Sgblack@eecs.umich.edu
567639Sgblack@eecs.umich.edu#if USE_CHECKER
577639Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh"
587639Sgblack@eecs.umich.edu#endif
597639Sgblack@eecs.umich.edu
607639Sgblack@eecs.umich.edutemplate<class Impl>
617639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
627639Sgblack@eecs.umich.edu                                              LSQUnit *lsq_ptr)
637639Sgblack@eecs.umich.edu    : inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
647639Sgblack@eecs.umich.edu{
657639Sgblack@eecs.umich.edu    this->setFlags(Event::AutoDelete);
667639Sgblack@eecs.umich.edu}
677639Sgblack@eecs.umich.edu
687639Sgblack@eecs.umich.edutemplate<class Impl>
697639Sgblack@eecs.umich.eduvoid
707639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process()
717639Sgblack@eecs.umich.edu{
727639Sgblack@eecs.umich.edu    if (!lsqPtr->isSwitchedOut()) {
737639Sgblack@eecs.umich.edu        lsqPtr->writeback(inst, pkt);
747639Sgblack@eecs.umich.edu    }
757639Sgblack@eecs.umich.edu
767639Sgblack@eecs.umich.edu    if (pkt->senderState)
777639Sgblack@eecs.umich.edu        delete pkt->senderState;
787639Sgblack@eecs.umich.edu
797639Sgblack@eecs.umich.edu    delete pkt->req;
807639Sgblack@eecs.umich.edu    delete pkt;
817639Sgblack@eecs.umich.edu}
827639Sgblack@eecs.umich.edu
837639Sgblack@eecs.umich.edutemplate<class Impl>
847639Sgblack@eecs.umich.educonst char *
857639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() const
867639Sgblack@eecs.umich.edu{
877639Sgblack@eecs.umich.edu    return "Store writeback";
887639Sgblack@eecs.umich.edu}
897639Sgblack@eecs.umich.edu
907639Sgblack@eecs.umich.edutemplate<class Impl>
917639Sgblack@eecs.umich.eduvoid
927639Sgblack@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
937639Sgblack@eecs.umich.edu{
947356Sgblack@eecs.umich.edu    LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
957356Sgblack@eecs.umich.edu    DynInstPtr inst = state->inst;
967356Sgblack@eecs.umich.edu    DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum);
977435Sgblack@eecs.umich.edu    DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum);
987435Sgblack@eecs.umich.edu
997435Sgblack@eecs.umich.edu    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
1007435Sgblack@eecs.umich.edu
1017435Sgblack@eecs.umich.edu    assert(!pkt->wasNacked());
1027435Sgblack@eecs.umich.edu
1037435Sgblack@eecs.umich.edu    // If this is a split access, wait until all packets are received.
1047435Sgblack@eecs.umich.edu    if (TheISA::HasUnalignedMemAcc && !state->complete()) {
1057435Sgblack@eecs.umich.edu        delete pkt->req;
1067435Sgblack@eecs.umich.edu        delete pkt;
1077435Sgblack@eecs.umich.edu        return;
1087639Sgblack@eecs.umich.edu    }
1097639Sgblack@eecs.umich.edu
1107639Sgblack@eecs.umich.edu    if (isSwitchedOut() || inst->isSquashed()) {
1117435Sgblack@eecs.umich.edu        iewStage->decrWb(inst->seqNum);
1127639Sgblack@eecs.umich.edu    } else {
1137639Sgblack@eecs.umich.edu        if (!state->noWB) {
1147639Sgblack@eecs.umich.edu            if (!TheISA::HasUnalignedMemAcc || !state->isSplit ||
1157639Sgblack@eecs.umich.edu                !state->isLoad) {
1167639Sgblack@eecs.umich.edu                writeback(inst, pkt);
1177639Sgblack@eecs.umich.edu            } else {
1187639Sgblack@eecs.umich.edu                writeback(inst, state->mainPkt);
1197639Sgblack@eecs.umich.edu            }
1207639Sgblack@eecs.umich.edu        }
1217639Sgblack@eecs.umich.edu
1227639Sgblack@eecs.umich.edu        if (inst->isStore()) {
1237639Sgblack@eecs.umich.edu            completeStore(state->idx);
1247639Sgblack@eecs.umich.edu        }
1257639Sgblack@eecs.umich.edu    }
1267639Sgblack@eecs.umich.edu
1277639Sgblack@eecs.umich.edu    if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) {
1287639Sgblack@eecs.umich.edu        delete state->mainPkt->req;
1297639Sgblack@eecs.umich.edu        delete state->mainPkt;
1307639Sgblack@eecs.umich.edu    }
1317639Sgblack@eecs.umich.edu    delete state;
1327639Sgblack@eecs.umich.edu    delete pkt->req;
1337639Sgblack@eecs.umich.edu    delete pkt;
1347639Sgblack@eecs.umich.edu}
1357639Sgblack@eecs.umich.edu
1367639Sgblack@eecs.umich.edutemplate <class Impl>
1377639Sgblack@eecs.umich.eduLSQUnit<Impl>::LSQUnit()
1387639Sgblack@eecs.umich.edu    : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
1397639Sgblack@eecs.umich.edu      isStoreBlocked(false), isLoadBlocked(false),
1407639Sgblack@eecs.umich.edu      loadBlockedHandled(false), hasPendingPkt(false)
1417639Sgblack@eecs.umich.edu{
1427639Sgblack@eecs.umich.edu}
1437639Sgblack@eecs.umich.edu
1447639Sgblack@eecs.umich.edutemplate<class Impl>
1457639Sgblack@eecs.umich.eduvoid
1468144SAli.Saidi@ARM.comLSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
1477639Sgblack@eecs.umich.edu        LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries,
1487639Sgblack@eecs.umich.edu        unsigned id)
1497639Sgblack@eecs.umich.edu{
1507639Sgblack@eecs.umich.edu    cpu = cpu_ptr;
1517639Sgblack@eecs.umich.edu    iewStage = iew_ptr;
1527639Sgblack@eecs.umich.edu
1537639Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
15410037SARM gem5 Developers
1557639Sgblack@eecs.umich.edu    switchedOut = false;
1567639Sgblack@eecs.umich.edu
1577639Sgblack@eecs.umich.edu    cacheBlockMask = 0;
1587639Sgblack@eecs.umich.edu
1597639Sgblack@eecs.umich.edu    lsq = lsq_ptr;
1607639Sgblack@eecs.umich.edu
1617639Sgblack@eecs.umich.edu    lsqID = id;
1627639Sgblack@eecs.umich.edu
1637639Sgblack@eecs.umich.edu    // Add 1 for the sentinel entry (they are circular queues).
1647639Sgblack@eecs.umich.edu    LQEntries = maxLQEntries + 1;
1657639Sgblack@eecs.umich.edu    SQEntries = maxSQEntries + 1;
16610037SARM gem5 Developers
1677639Sgblack@eecs.umich.edu    loadQueue.resize(LQEntries);
1687639Sgblack@eecs.umich.edu    storeQueue.resize(SQEntries);
1697639Sgblack@eecs.umich.edu
1707639Sgblack@eecs.umich.edu    depCheckShift = params->LSQDepCheckShift;
1717639Sgblack@eecs.umich.edu    checkLoads = params->LSQCheckLoads;
1727639Sgblack@eecs.umich.edu
1737639Sgblack@eecs.umich.edu    loadHead = loadTail = 0;
1747639Sgblack@eecs.umich.edu
17510037SARM gem5 Developers    storeHead = storeWBIdx = storeTail = 0;
1767639Sgblack@eecs.umich.edu
1777639Sgblack@eecs.umich.edu    usedPorts = 0;
17810037SARM gem5 Developers    cachePorts = params->cachePorts;
1797639Sgblack@eecs.umich.edu
1807639Sgblack@eecs.umich.edu    retryPkt = NULL;
18110037SARM gem5 Developers    memDepViolator = NULL;
1827591SAli.Saidi@ARM.com
1837639Sgblack@eecs.umich.edu    blockedLoadSeqNum = 0;
1847435Sgblack@eecs.umich.edu}
1857435Sgblack@eecs.umich.edu
1867639Sgblack@eecs.umich.edutemplate<class Impl>
18710037SARM gem5 Developersstd::string
1887639Sgblack@eecs.umich.eduLSQUnit<Impl>::name() const
1897639Sgblack@eecs.umich.edu{
1907639Sgblack@eecs.umich.edu    if (Impl::MaxThreads == 1) {
1917639Sgblack@eecs.umich.edu        return iewStage->name() + ".lsq";
1927639Sgblack@eecs.umich.edu    } else {
1937639Sgblack@eecs.umich.edu        return iewStage->name() + ".lsq.thread" + to_string(lsqID);
1947639Sgblack@eecs.umich.edu    }
1957639Sgblack@eecs.umich.edu}
1967639Sgblack@eecs.umich.edu
1977639Sgblack@eecs.umich.edutemplate<class Impl>
1987639Sgblack@eecs.umich.eduvoid
1997639Sgblack@eecs.umich.eduLSQUnit<Impl>::regStats()
2007639Sgblack@eecs.umich.edu{
2017639Sgblack@eecs.umich.edu    lsqForwLoads
2027639Sgblack@eecs.umich.edu        .name(name() + ".forwLoads")
2037639Sgblack@eecs.umich.edu        .desc("Number of loads that had data forwarded from stores");
2047639Sgblack@eecs.umich.edu
2057639Sgblack@eecs.umich.edu    invAddrLoads
2067639Sgblack@eecs.umich.edu        .name(name() + ".invAddrLoads")
2077639Sgblack@eecs.umich.edu        .desc("Number of loads ignored due to an invalid address");
2087639Sgblack@eecs.umich.edu
2097639Sgblack@eecs.umich.edu    lsqSquashedLoads
2107639Sgblack@eecs.umich.edu        .name(name() + ".squashedLoads")
2117639Sgblack@eecs.umich.edu        .desc("Number of loads squashed");
2127639Sgblack@eecs.umich.edu
2137639Sgblack@eecs.umich.edu    lsqIgnoredResponses
2147639Sgblack@eecs.umich.edu        .name(name() + ".ignoredResponses")
2157639Sgblack@eecs.umich.edu        .desc("Number of memory responses ignored because the instruction is squashed");
2167639Sgblack@eecs.umich.edu
2177639Sgblack@eecs.umich.edu    lsqMemOrderViolation
2187639Sgblack@eecs.umich.edu        .name(name() + ".memOrderViolation")
2197639Sgblack@eecs.umich.edu        .desc("Number of memory ordering violations");
22010037SARM gem5 Developers
2217591SAli.Saidi@ARM.com    lsqSquashedStores
2227591SAli.Saidi@ARM.com        .name(name() + ".squashedStores")
2237639Sgblack@eecs.umich.edu        .desc("Number of stores squashed");
2247639Sgblack@eecs.umich.edu
2257639Sgblack@eecs.umich.edu    invAddrSwpfs
22610037SARM gem5 Developers        .name(name() + ".invAddrSwpfs")
2277639Sgblack@eecs.umich.edu        .desc("Number of software prefetches ignored due to an invalid address");
2287639Sgblack@eecs.umich.edu
2297639Sgblack@eecs.umich.edu    lsqBlockedLoads
2307639Sgblack@eecs.umich.edu        .name(name() + ".blockedLoads")
2317639Sgblack@eecs.umich.edu        .desc("Number of blocked loads due to partial load-store forwarding");
2327639Sgblack@eecs.umich.edu
2337639Sgblack@eecs.umich.edu    lsqRescheduledLoads
2347639Sgblack@eecs.umich.edu        .name(name() + ".rescheduledLoads")
23510037SARM gem5 Developers        .desc("Number of loads that were rescheduled");
2367639Sgblack@eecs.umich.edu
2377639Sgblack@eecs.umich.edu    lsqCacheBlocked
2387639Sgblack@eecs.umich.edu        .name(name() + ".cacheBlocked")
23910037SARM gem5 Developers        .desc("Number of times an access to memory failed due to the cache being blocked");
2407639Sgblack@eecs.umich.edu}
2417639Sgblack@eecs.umich.edu
2427639Sgblack@eecs.umich.edutemplate<class Impl>
2437435Sgblack@eecs.umich.eduvoid
2447435Sgblack@eecs.umich.eduLSQUnit<Impl>::setDcachePort(Port *dcache_port)
2457639Sgblack@eecs.umich.edu{
2467639Sgblack@eecs.umich.edu    dcachePort = dcache_port;
2477639Sgblack@eecs.umich.edu
2487639Sgblack@eecs.umich.edu#if USE_CHECKER
2497639Sgblack@eecs.umich.edu    if (cpu->checker) {
2507639Sgblack@eecs.umich.edu        cpu->checker->setDcachePort(dcachePort);
2517639Sgblack@eecs.umich.edu    }
2527639Sgblack@eecs.umich.edu#endif
25310037SARM gem5 Developers}
2547639Sgblack@eecs.umich.edu
25510037SARM gem5 Developerstemplate<class Impl>
2567639Sgblack@eecs.umich.eduvoid
2577639Sgblack@eecs.umich.eduLSQUnit<Impl>::clearLQ()
2587639Sgblack@eecs.umich.edu{
2597639Sgblack@eecs.umich.edu    loadQueue.clear();
2607639Sgblack@eecs.umich.edu}
2617639Sgblack@eecs.umich.edu
2627639Sgblack@eecs.umich.edutemplate<class Impl>
2637639Sgblack@eecs.umich.eduvoid
2647639Sgblack@eecs.umich.eduLSQUnit<Impl>::clearSQ()
2657639Sgblack@eecs.umich.edu{
2667639Sgblack@eecs.umich.edu    storeQueue.clear();
2677639Sgblack@eecs.umich.edu}
2687639Sgblack@eecs.umich.edu
2697639Sgblack@eecs.umich.edutemplate<class Impl>
2707639Sgblack@eecs.umich.eduvoid
2717639Sgblack@eecs.umich.eduLSQUnit<Impl>::switchOut()
2727639Sgblack@eecs.umich.edu{
2737639Sgblack@eecs.umich.edu    switchedOut = true;
2747639Sgblack@eecs.umich.edu    for (int i = 0; i < loadQueue.size(); ++i) {
2757639Sgblack@eecs.umich.edu        assert(!loadQueue[i]);
2767639Sgblack@eecs.umich.edu        loadQueue[i] = NULL;
2777639Sgblack@eecs.umich.edu    }
2787639Sgblack@eecs.umich.edu
2797639Sgblack@eecs.umich.edu    assert(storesToWB == 0);
2807639Sgblack@eecs.umich.edu}
2817639Sgblack@eecs.umich.edu
2827639Sgblack@eecs.umich.edutemplate<class Impl>
2837639Sgblack@eecs.umich.eduvoid
2847639Sgblack@eecs.umich.eduLSQUnit<Impl>::takeOverFrom()
2857639Sgblack@eecs.umich.edu{
2867639Sgblack@eecs.umich.edu    switchedOut = false;
2877639Sgblack@eecs.umich.edu    loads = stores = storesToWB = 0;
2887639Sgblack@eecs.umich.edu
2897639Sgblack@eecs.umich.edu    loadHead = loadTail = 0;
2907639Sgblack@eecs.umich.edu
2917639Sgblack@eecs.umich.edu    storeHead = storeWBIdx = storeTail = 0;
2927639Sgblack@eecs.umich.edu
2937639Sgblack@eecs.umich.edu    usedPorts = 0;
2947639Sgblack@eecs.umich.edu
2957639Sgblack@eecs.umich.edu    memDepViolator = NULL;
2967639Sgblack@eecs.umich.edu
2977639Sgblack@eecs.umich.edu    blockedLoadSeqNum = 0;
2987639Sgblack@eecs.umich.edu
2997639Sgblack@eecs.umich.edu    stalled = false;
3007639Sgblack@eecs.umich.edu    isLoadBlocked = false;
3017639Sgblack@eecs.umich.edu    loadBlockedHandled = false;
3027639Sgblack@eecs.umich.edu
3037639Sgblack@eecs.umich.edu    // Just incase the memory system changed out from under us
3047639Sgblack@eecs.umich.edu    cacheBlockMask = 0;
3057639Sgblack@eecs.umich.edu}
3067639Sgblack@eecs.umich.edu
3077639Sgblack@eecs.umich.edutemplate<class Impl>
3087639Sgblack@eecs.umich.eduvoid
3097639Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size)
3107639Sgblack@eecs.umich.edu{
3117639Sgblack@eecs.umich.edu    unsigned size_plus_sentinel = size + 1;
3127639Sgblack@eecs.umich.edu    assert(size_plus_sentinel >= LQEntries);
3137639Sgblack@eecs.umich.edu
3147639Sgblack@eecs.umich.edu    if (size_plus_sentinel > LQEntries) {
3157639Sgblack@eecs.umich.edu        while (size_plus_sentinel > loadQueue.size()) {
3167639Sgblack@eecs.umich.edu            DynInstPtr dummy;
3177639Sgblack@eecs.umich.edu            loadQueue.push_back(dummy);
3187639Sgblack@eecs.umich.edu            LQEntries++;
3197639Sgblack@eecs.umich.edu        }
3207639Sgblack@eecs.umich.edu    } else {
3217435Sgblack@eecs.umich.edu        LQEntries = size_plus_sentinel;
3227435Sgblack@eecs.umich.edu    }
3237639Sgblack@eecs.umich.edu
3247639Sgblack@eecs.umich.edu}
3257639Sgblack@eecs.umich.edu
3267591SAli.Saidi@ARM.comtemplate<class Impl>
3277639Sgblack@eecs.umich.eduvoid
3287639Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size)
3297435Sgblack@eecs.umich.edu{
3307435Sgblack@eecs.umich.edu    unsigned size_plus_sentinel = size + 1;
3317639Sgblack@eecs.umich.edu    if (size_plus_sentinel > SQEntries) {
3327639Sgblack@eecs.umich.edu        while (size_plus_sentinel > storeQueue.size()) {
3337435Sgblack@eecs.umich.edu            SQEntry dummy;
3347435Sgblack@eecs.umich.edu            storeQueue.push_back(dummy);
3357591SAli.Saidi@ARM.com            SQEntries++;
3367435Sgblack@eecs.umich.edu        }
3377435Sgblack@eecs.umich.edu    } else {
3387435Sgblack@eecs.umich.edu        SQEntries = size_plus_sentinel;
3397435Sgblack@eecs.umich.edu    }
3407435Sgblack@eecs.umich.edu}
3417435Sgblack@eecs.umich.edu
3427435Sgblack@eecs.umich.edutemplate <class Impl>
3437435Sgblack@eecs.umich.eduvoid
3447435Sgblack@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst)
3457435Sgblack@eecs.umich.edu{
3467435Sgblack@eecs.umich.edu    assert(inst->isMemRef());
3477639Sgblack@eecs.umich.edu
3487639Sgblack@eecs.umich.edu    assert(inst->isLoad() || inst->isStore());
3497639Sgblack@eecs.umich.edu
3507639Sgblack@eecs.umich.edu    if (inst->isLoad()) {
3517639Sgblack@eecs.umich.edu        insertLoad(inst);
3527639Sgblack@eecs.umich.edu    } else {
3537639Sgblack@eecs.umich.edu        insertStore(inst);
3547639Sgblack@eecs.umich.edu    }
3557639Sgblack@eecs.umich.edu
3567639Sgblack@eecs.umich.edu    inst->setInLSQ();
3577639Sgblack@eecs.umich.edu}
3587639Sgblack@eecs.umich.edu
3597639Sgblack@eecs.umich.edutemplate <class Impl>
3607435Sgblack@eecs.umich.eduvoid
3617435Sgblack@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
3627435Sgblack@eecs.umich.edu{
3637639Sgblack@eecs.umich.edu    assert((loadTail + 1) % LQEntries != loadHead);
3647639Sgblack@eecs.umich.edu    assert(loads < LQEntries);
3657639Sgblack@eecs.umich.edu
3667435Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
3677639Sgblack@eecs.umich.edu            load_inst->pcState(), loadTail, load_inst->seqNum);
3687639Sgblack@eecs.umich.edu
3697435Sgblack@eecs.umich.edu    load_inst->lqIdx = loadTail;
3707435Sgblack@eecs.umich.edu
3717639Sgblack@eecs.umich.edu    if (stores == 0) {
3727639Sgblack@eecs.umich.edu        load_inst->sqIdx = -1;
3737639Sgblack@eecs.umich.edu    } else {
3747639Sgblack@eecs.umich.edu        load_inst->sqIdx = storeTail;
3757435Sgblack@eecs.umich.edu    }
3767435Sgblack@eecs.umich.edu
3777435Sgblack@eecs.umich.edu    loadQueue[loadTail] = load_inst;
3787639Sgblack@eecs.umich.edu
3797639Sgblack@eecs.umich.edu    incrLdIdx(loadTail);
3807435Sgblack@eecs.umich.edu
3817435Sgblack@eecs.umich.edu    ++loads;
3827435Sgblack@eecs.umich.edu}
3837435Sgblack@eecs.umich.edu
3847639Sgblack@eecs.umich.edutemplate <class Impl>
3857639Sgblack@eecs.umich.eduvoid
3867639Sgblack@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
3877639Sgblack@eecs.umich.edu{
3887639Sgblack@eecs.umich.edu    // Make sure it is not full before inserting an instruction.
3897435Sgblack@eecs.umich.edu    assert((storeTail + 1) % SQEntries != storeHead);
3907639Sgblack@eecs.umich.edu    assert(stores < SQEntries);
3917639Sgblack@eecs.umich.edu
3927639Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
3937639Sgblack@eecs.umich.edu            store_inst->pcState(), storeTail, store_inst->seqNum);
3947639Sgblack@eecs.umich.edu
3957435Sgblack@eecs.umich.edu    store_inst->sqIdx = storeTail;
3967639Sgblack@eecs.umich.edu    store_inst->lqIdx = loadTail;
3977639Sgblack@eecs.umich.edu
3987639Sgblack@eecs.umich.edu    storeQueue[storeTail] = SQEntry(store_inst);
3997639Sgblack@eecs.umich.edu
4007639Sgblack@eecs.umich.edu    incrStIdx(storeTail);
4017435Sgblack@eecs.umich.edu
4027639Sgblack@eecs.umich.edu    ++stores;
4037639Sgblack@eecs.umich.edu}
4047639Sgblack@eecs.umich.edu
4057639Sgblack@eecs.umich.edutemplate <class Impl>
4067639Sgblack@eecs.umich.edutypename Impl::DynInstPtr
4077435Sgblack@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator()
4087435Sgblack@eecs.umich.edu{
4097435Sgblack@eecs.umich.edu    DynInstPtr temp = memDepViolator;
4107435Sgblack@eecs.umich.edu
4117639Sgblack@eecs.umich.edu    memDepViolator = NULL;
4127639Sgblack@eecs.umich.edu
4137639Sgblack@eecs.umich.edu    return temp;
4147639Sgblack@eecs.umich.edu}
4157639Sgblack@eecs.umich.edu
4167435Sgblack@eecs.umich.edutemplate <class Impl>
4177639Sgblack@eecs.umich.eduunsigned
4187639Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeEntries()
4197639Sgblack@eecs.umich.edu{
4207639Sgblack@eecs.umich.edu    unsigned free_lq_entries = LQEntries - loads;
4217639Sgblack@eecs.umich.edu    unsigned free_sq_entries = SQEntries - stores;
4227435Sgblack@eecs.umich.edu
4237639Sgblack@eecs.umich.edu    // Both the LQ and SQ entries have an extra dummy entry to differentiate
4247639Sgblack@eecs.umich.edu    // empty/full conditions.  Subtract 1 from the free entries.
4257639Sgblack@eecs.umich.edu    if (free_lq_entries < free_sq_entries) {
4267639Sgblack@eecs.umich.edu        return free_lq_entries - 1;
4277435Sgblack@eecs.umich.edu    } else {
4287639Sgblack@eecs.umich.edu        return free_sq_entries - 1;
4297639Sgblack@eecs.umich.edu    }
4307639Sgblack@eecs.umich.edu}
4317639Sgblack@eecs.umich.edu
4327639Sgblack@eecs.umich.edutemplate <class Impl>
4337639Sgblack@eecs.umich.eduint
4347639Sgblack@eecs.umich.eduLSQUnit<Impl>::numLoadsReady()
4357639Sgblack@eecs.umich.edu{
4367639Sgblack@eecs.umich.edu    int load_idx = loadHead;
4377639Sgblack@eecs.umich.edu    int retval = 0;
4387435Sgblack@eecs.umich.edu
4397435Sgblack@eecs.umich.edu    while (load_idx != loadTail) {
4407435Sgblack@eecs.umich.edu        assert(loadQueue[load_idx]);
4417639Sgblack@eecs.umich.edu
4427639Sgblack@eecs.umich.edu        if (loadQueue[load_idx]->readyToIssue()) {
4437639Sgblack@eecs.umich.edu            ++retval;
4447639Sgblack@eecs.umich.edu        }
4457639Sgblack@eecs.umich.edu    }
4467639Sgblack@eecs.umich.edu
4477639Sgblack@eecs.umich.edu    return retval;
4487435Sgblack@eecs.umich.edu}
4497435Sgblack@eecs.umich.edu
4507435Sgblack@eecs.umich.edutemplate <class Impl>
4517435Sgblack@eecs.umich.eduvoid
4527435Sgblack@eecs.umich.eduLSQUnit<Impl>::checkSnoop(PacketPtr pkt)
4537639Sgblack@eecs.umich.edu{
4547639Sgblack@eecs.umich.edu    int load_idx = loadHead;
4557639Sgblack@eecs.umich.edu
4567639Sgblack@eecs.umich.edu    if (!cacheBlockMask) {
4577639Sgblack@eecs.umich.edu        assert(dcachePort);
4587639Sgblack@eecs.umich.edu        Addr bs = dcachePort->peerBlockSize();
4597639Sgblack@eecs.umich.edu
4607435Sgblack@eecs.umich.edu        // Make sure we actually got a size
4617639Sgblack@eecs.umich.edu        assert(bs != 0);
4627639Sgblack@eecs.umich.edu
4637639Sgblack@eecs.umich.edu        cacheBlockMask = ~(bs - 1);
4647639Sgblack@eecs.umich.edu    }
4657435Sgblack@eecs.umich.edu
4667435Sgblack@eecs.umich.edu    // If this is the only load in the LSQ we don't care
4677435Sgblack@eecs.umich.edu    if (load_idx == loadTail)
4687639Sgblack@eecs.umich.edu        return;
4697639Sgblack@eecs.umich.edu    incrLdIdx(load_idx);
4707435Sgblack@eecs.umich.edu
4717639Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
4727639Sgblack@eecs.umich.edu    Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
4737435Sgblack@eecs.umich.edu    while (load_idx != loadTail) {
4747435Sgblack@eecs.umich.edu        DynInstPtr ld_inst = loadQueue[load_idx];
4757435Sgblack@eecs.umich.edu
4767639Sgblack@eecs.umich.edu        if (!ld_inst->effAddrValid || ld_inst->uncacheable()) {
4777639Sgblack@eecs.umich.edu            incrLdIdx(load_idx);
4787639Sgblack@eecs.umich.edu            continue;
4797639Sgblack@eecs.umich.edu        }
4807639Sgblack@eecs.umich.edu
4817639Sgblack@eecs.umich.edu        Addr load_addr = ld_inst->physEffAddr & cacheBlockMask;
4827639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
4837435Sgblack@eecs.umich.edu                    ld_inst->seqNum, load_addr, invalidate_addr);
4847639Sgblack@eecs.umich.edu
4857639Sgblack@eecs.umich.edu        if (load_addr == invalidate_addr) {
4867435Sgblack@eecs.umich.edu            if (ld_inst->possibleLoadViolation) {
4877435Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
4887435Sgblack@eecs.umich.edu                        ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum);
4897639Sgblack@eecs.umich.edu
4907639Sgblack@eecs.umich.edu                // Mark the load for re-execution
4917639Sgblack@eecs.umich.edu                ld_inst->fault = new ReExec;
4927639Sgblack@eecs.umich.edu            } else {
4937639Sgblack@eecs.umich.edu                // If a older load checks this and it's true
4947639Sgblack@eecs.umich.edu                // then we might have missed the snoop
4957639Sgblack@eecs.umich.edu                // in which case we need to invalidate to be sure
4967435Sgblack@eecs.umich.edu                ld_inst->hitExternalSnoop = true;
4977639Sgblack@eecs.umich.edu            }
4987639Sgblack@eecs.umich.edu        }
4997435Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
5007435Sgblack@eecs.umich.edu    }
5017435Sgblack@eecs.umich.edu    return;
5027639Sgblack@eecs.umich.edu}
5037639Sgblack@eecs.umich.edu
5047435Sgblack@eecs.umich.edutemplate <class Impl>
5057639Sgblack@eecs.umich.eduFault
5067639Sgblack@eecs.umich.eduLSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
5077435Sgblack@eecs.umich.edu{
5087435Sgblack@eecs.umich.edu    Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
5097435Sgblack@eecs.umich.edu    Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
5107639Sgblack@eecs.umich.edu
5117639Sgblack@eecs.umich.edu    /** @todo in theory you only need to check an instruction that has executed
5127435Sgblack@eecs.umich.edu     * however, there isn't a good way in the pipeline at the moment to check
5137435Sgblack@eecs.umich.edu     * all instructions that will execute before the store writes back. Thus,
5147639Sgblack@eecs.umich.edu     * like the implementation that came before it, we're overly conservative.
5157435Sgblack@eecs.umich.edu     */
5167435Sgblack@eecs.umich.edu    while (load_idx != loadTail) {
5177639Sgblack@eecs.umich.edu        DynInstPtr ld_inst = loadQueue[load_idx];
5187639Sgblack@eecs.umich.edu        if (!ld_inst->effAddrValid || ld_inst->uncacheable()) {
5197435Sgblack@eecs.umich.edu            incrLdIdx(load_idx);
5207435Sgblack@eecs.umich.edu            continue;
5217639Sgblack@eecs.umich.edu        }
5227639Sgblack@eecs.umich.edu
5237435Sgblack@eecs.umich.edu        Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
5247435Sgblack@eecs.umich.edu        Addr ld_eff_addr2 =
5257435Sgblack@eecs.umich.edu            (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
5267435Sgblack@eecs.umich.edu
5277435Sgblack@eecs.umich.edu        if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
5287639Sgblack@eecs.umich.edu            if (inst->isLoad()) {
5297639Sgblack@eecs.umich.edu                // If this load is to the same block as an external snoop
5307435Sgblack@eecs.umich.edu                // invalidate that we've observed then the load needs to be
5317639Sgblack@eecs.umich.edu                // squashed as it could have newer data
5327639Sgblack@eecs.umich.edu                if (ld_inst->hitExternalSnoop) {
5337435Sgblack@eecs.umich.edu                    if (!memDepViolator ||
5347435Sgblack@eecs.umich.edu                            ld_inst->seqNum < memDepViolator->seqNum) {
5357435Sgblack@eecs.umich.edu                        DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
5367639Sgblack@eecs.umich.edu                                " and [sn:%lli] at address %#x\n", inst->seqNum,
5377639Sgblack@eecs.umich.edu                                ld_inst->seqNum, ld_eff_addr1);
5387435Sgblack@eecs.umich.edu                        memDepViolator = ld_inst;
5397639Sgblack@eecs.umich.edu
5407639Sgblack@eecs.umich.edu                        ++lsqMemOrderViolation;
5417435Sgblack@eecs.umich.edu
5427435Sgblack@eecs.umich.edu                        return TheISA::genMachineCheckFault();
5437435Sgblack@eecs.umich.edu                    }
5447435Sgblack@eecs.umich.edu                }
5457435Sgblack@eecs.umich.edu
5467639Sgblack@eecs.umich.edu                // Otherwise, mark the load has a possible load violation
5477639Sgblack@eecs.umich.edu                // and if we see a snoop before it's commited, we need to squash
5487435Sgblack@eecs.umich.edu                ld_inst->possibleLoadViolation = true;
5497639Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x"
5507639Sgblack@eecs.umich.edu                        " between instructions [sn:%lli] and [sn:%lli]\n",
5517435Sgblack@eecs.umich.edu                        inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
5527435Sgblack@eecs.umich.edu            } else {
5537435Sgblack@eecs.umich.edu                // A load/store incorrectly passed this store.
5547639Sgblack@eecs.umich.edu                // Check if we already have a violator, or if it's newer
5557639Sgblack@eecs.umich.edu                // squash and refetch.
5567435Sgblack@eecs.umich.edu                if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
5577639Sgblack@eecs.umich.edu                    break;
5587639Sgblack@eecs.umich.edu
5597435Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and [sn:%lli]"
5607435Sgblack@eecs.umich.edu                        " at address %#x\n", inst->seqNum, ld_inst->seqNum,
5617435Sgblack@eecs.umich.edu                        ld_eff_addr1);
5628607Sgblack@eecs.umich.edu                memDepViolator = ld_inst;
5638607Sgblack@eecs.umich.edu
5647435Sgblack@eecs.umich.edu                ++lsqMemOrderViolation;
5658607Sgblack@eecs.umich.edu
5668607Sgblack@eecs.umich.edu                return TheISA::genMachineCheckFault();
5677435Sgblack@eecs.umich.edu            }
5688607Sgblack@eecs.umich.edu        }
5698607Sgblack@eecs.umich.edu
5707435Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
5717435Sgblack@eecs.umich.edu    }
5727435Sgblack@eecs.umich.edu    return NoFault;
5738607Sgblack@eecs.umich.edu}
5747435Sgblack@eecs.umich.edu
5757435Sgblack@eecs.umich.edu
5768607Sgblack@eecs.umich.edu
5778607Sgblack@eecs.umich.edu
5787435Sgblack@eecs.umich.edutemplate <class Impl>
5797435Sgblack@eecs.umich.eduFault
5807435Sgblack@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst)
5817639Sgblack@eecs.umich.edu{
5827639Sgblack@eecs.umich.edu    using namespace TheISA;
5837435Sgblack@eecs.umich.edu    // Execute a specific load.
5847639Sgblack@eecs.umich.edu    Fault load_fault = NoFault;
5857639Sgblack@eecs.umich.edu
5867435Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
5877435Sgblack@eecs.umich.edu            inst->pcState(), inst->seqNum);
5887435Sgblack@eecs.umich.edu
58910037SARM gem5 Developers    assert(!inst->isSquashed());
59010037SARM gem5 Developers
59110037SARM gem5 Developers    load_fault = inst->initiateAcc();
59210037SARM gem5 Developers
59310037SARM gem5 Developers    if (inst->isTranslationDelayed() &&
59410037SARM gem5 Developers        load_fault == NoFault)
59510037SARM gem5 Developers        return load_fault;
59610037SARM gem5 Developers
59710037SARM gem5 Developers    // If the instruction faulted or predicated false, then we need to send it
59810037SARM gem5 Developers    // along to commit without the instruction completing.
59910037SARM gem5 Developers    if (load_fault != NoFault || inst->readPredicate() == false) {
60010037SARM gem5 Developers        // Send this instruction to commit, also make sure iew stage
60110037SARM gem5 Developers        // realizes there is activity.
60210037SARM gem5 Developers        // Mark it as executed unless it is an uncached load that
60310037SARM gem5 Developers        // needs to hit the head of commit.
60410037SARM gem5 Developers        if (inst->readPredicate() == false)
60510037SARM gem5 Developers            inst->forwardOldRegs();
6067435Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
6077435Sgblack@eecs.umich.edu                inst->seqNum,
6087435Sgblack@eecs.umich.edu                (load_fault != NoFault ? "fault" : "predication"));
6097435Sgblack@eecs.umich.edu        if (!(inst->hasRequest() && inst->uncacheable()) ||
6107435Sgblack@eecs.umich.edu            inst->isAtCommit()) {
6117639Sgblack@eecs.umich.edu            inst->setExecuted();
6127639Sgblack@eecs.umich.edu        }
6137639Sgblack@eecs.umich.edu        iewStage->instToCommit(inst);
6147639Sgblack@eecs.umich.edu        iewStage->activityThisCycle();
6157639Sgblack@eecs.umich.edu    } else if (!loadBlocked()) {
6167435Sgblack@eecs.umich.edu        assert(inst->effAddrValid);
6177435Sgblack@eecs.umich.edu        int load_idx = inst->lqIdx;
6187435Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
6197435Sgblack@eecs.umich.edu
6207435Sgblack@eecs.umich.edu        if (checkLoads)
6217639Sgblack@eecs.umich.edu            return checkViolations(load_idx, inst);
6227639Sgblack@eecs.umich.edu    }
6237639Sgblack@eecs.umich.edu
6247639Sgblack@eecs.umich.edu    return load_fault;
6257639Sgblack@eecs.umich.edu}
6267435Sgblack@eecs.umich.edu
6277639Sgblack@eecs.umich.edutemplate <class Impl>
6287639Sgblack@eecs.umich.eduFault
6297639Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
6307639Sgblack@eecs.umich.edu{
6317639Sgblack@eecs.umich.edu    using namespace TheISA;
6327435Sgblack@eecs.umich.edu    // Make sure that a store exists.
6337435Sgblack@eecs.umich.edu    assert(stores != 0);
6347435Sgblack@eecs.umich.edu
6357435Sgblack@eecs.umich.edu    int store_idx = store_inst->sqIdx;
6367435Sgblack@eecs.umich.edu
6377639Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
6387639Sgblack@eecs.umich.edu            store_inst->pcState(), store_inst->seqNum);
6397639Sgblack@eecs.umich.edu
6407639Sgblack@eecs.umich.edu    assert(!store_inst->isSquashed());
6417639Sgblack@eecs.umich.edu
6427435Sgblack@eecs.umich.edu    // Check the recently completed loads to see if any match this store's
6437639Sgblack@eecs.umich.edu    // address.  If so, then we have a memory ordering violation.
6447639Sgblack@eecs.umich.edu    int load_idx = store_inst->lqIdx;
6457639Sgblack@eecs.umich.edu
6467639Sgblack@eecs.umich.edu    Fault store_fault = store_inst->initiateAcc();
6477639Sgblack@eecs.umich.edu
6487435Sgblack@eecs.umich.edu    if (store_inst->isTranslationDelayed() &&
6497435Sgblack@eecs.umich.edu        store_fault == NoFault)
6507435Sgblack@eecs.umich.edu        return store_fault;
6517639Sgblack@eecs.umich.edu
6527639Sgblack@eecs.umich.edu    if (store_inst->readPredicate() == false)
6537639Sgblack@eecs.umich.edu        store_inst->forwardOldRegs();
6547639Sgblack@eecs.umich.edu
6557639Sgblack@eecs.umich.edu    if (storeQueue[store_idx].size == 0) {
6567435Sgblack@eecs.umich.edu        DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
6577639Sgblack@eecs.umich.edu                store_inst->pcState(), store_inst->seqNum);
6587639Sgblack@eecs.umich.edu
6597639Sgblack@eecs.umich.edu        return store_fault;
6607639Sgblack@eecs.umich.edu    } else if (store_inst->readPredicate() == false) {
6617639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
6627435Sgblack@eecs.umich.edu                store_inst->seqNum);
6637435Sgblack@eecs.umich.edu        return store_fault;
6647435Sgblack@eecs.umich.edu    }
6657435Sgblack@eecs.umich.edu
6667435Sgblack@eecs.umich.edu    assert(store_fault == NoFault);
6677435Sgblack@eecs.umich.edu
6687435Sgblack@eecs.umich.edu    if (store_inst->isStoreConditional()) {
6697639Sgblack@eecs.umich.edu        // Store conditionals need to set themselves as able to
6707639Sgblack@eecs.umich.edu        // writeback if we haven't had a fault by here.
6717639Sgblack@eecs.umich.edu        storeQueue[store_idx].canWB = true;
6727639Sgblack@eecs.umich.edu
6737639Sgblack@eecs.umich.edu        ++storesToWB;
6747435Sgblack@eecs.umich.edu    }
6757639Sgblack@eecs.umich.edu
6767639Sgblack@eecs.umich.edu    return checkViolations(load_idx, store_inst);
6777639Sgblack@eecs.umich.edu
6787639Sgblack@eecs.umich.edu}
6797639Sgblack@eecs.umich.edu
6807435Sgblack@eecs.umich.edutemplate <class Impl>
6817435Sgblack@eecs.umich.eduvoid
6827435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad()
6837435Sgblack@eecs.umich.edu{
6847435Sgblack@eecs.umich.edu    assert(loadQueue[loadHead]);
6857435Sgblack@eecs.umich.edu
6867435Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
6877639Sgblack@eecs.umich.edu            loadQueue[loadHead]->pcState());
6887639Sgblack@eecs.umich.edu
6897639Sgblack@eecs.umich.edu    loadQueue[loadHead] = NULL;
6907639Sgblack@eecs.umich.edu
6917639Sgblack@eecs.umich.edu    incrLdIdx(loadHead);
6927435Sgblack@eecs.umich.edu
6937639Sgblack@eecs.umich.edu    --loads;
6947639Sgblack@eecs.umich.edu}
6957639Sgblack@eecs.umich.edu
6967639Sgblack@eecs.umich.edutemplate <class Impl>
6977639Sgblack@eecs.umich.eduvoid
6987435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
6997435Sgblack@eecs.umich.edu{
7007435Sgblack@eecs.umich.edu    assert(loads == 0 || loadQueue[loadHead]);
7017639Sgblack@eecs.umich.edu
7027639Sgblack@eecs.umich.edu    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
7037639Sgblack@eecs.umich.edu        commitLoad();
7047639Sgblack@eecs.umich.edu    }
7057639Sgblack@eecs.umich.edu}
7067435Sgblack@eecs.umich.edu
7077435Sgblack@eecs.umich.edutemplate <class Impl>
7087435Sgblack@eecs.umich.eduvoid
7097435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
7107435Sgblack@eecs.umich.edu{
7117435Sgblack@eecs.umich.edu    assert(stores == 0 || storeQueue[storeHead].inst);
7127435Sgblack@eecs.umich.edu
7137435Sgblack@eecs.umich.edu    int store_idx = storeHead;
7147435Sgblack@eecs.umich.edu
7157435Sgblack@eecs.umich.edu    while (store_idx != storeTail) {
7167435Sgblack@eecs.umich.edu        assert(storeQueue[store_idx].inst);
7177639Sgblack@eecs.umich.edu        // Mark any stores that are now committed and have not yet
7187639Sgblack@eecs.umich.edu        // been marked as able to write back.
7197639Sgblack@eecs.umich.edu        if (!storeQueue[store_idx].canWB) {
7207639Sgblack@eecs.umich.edu            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
7217639Sgblack@eecs.umich.edu                break;
7227435Sgblack@eecs.umich.edu            }
7237639Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
7247639Sgblack@eecs.umich.edu                    "%s [sn:%lli]\n",
7257639Sgblack@eecs.umich.edu                    storeQueue[store_idx].inst->pcState(),
7267639Sgblack@eecs.umich.edu                    storeQueue[store_idx].inst->seqNum);
7277639Sgblack@eecs.umich.edu
7287435Sgblack@eecs.umich.edu            storeQueue[store_idx].canWB = true;
7297435Sgblack@eecs.umich.edu
7307435Sgblack@eecs.umich.edu            ++storesToWB;
7317435Sgblack@eecs.umich.edu        }
7327435Sgblack@eecs.umich.edu
7337639Sgblack@eecs.umich.edu        incrStIdx(store_idx);
7347639Sgblack@eecs.umich.edu    }
7357639Sgblack@eecs.umich.edu}
7367639Sgblack@eecs.umich.edu
7377639Sgblack@eecs.umich.edutemplate <class Impl>
7387435Sgblack@eecs.umich.eduvoid
7397639Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackPendingStore()
7407639Sgblack@eecs.umich.edu{
7417639Sgblack@eecs.umich.edu    if (hasPendingPkt) {
7427639Sgblack@eecs.umich.edu        assert(pendingPkt != NULL);
7437639Sgblack@eecs.umich.edu
7447435Sgblack@eecs.umich.edu        // If the cache is blocked, this will store the packet for retry.
7457435Sgblack@eecs.umich.edu        if (sendStore(pendingPkt)) {
7467435Sgblack@eecs.umich.edu            storePostSend(pendingPkt);
7477639Sgblack@eecs.umich.edu        }
7487639Sgblack@eecs.umich.edu        pendingPkt = NULL;
7497639Sgblack@eecs.umich.edu        hasPendingPkt = false;
7507639Sgblack@eecs.umich.edu    }
7517639Sgblack@eecs.umich.edu}
7527435Sgblack@eecs.umich.edu
7537639Sgblack@eecs.umich.edutemplate <class Impl>
7547639Sgblack@eecs.umich.eduvoid
7557639Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackStores()
7567639Sgblack@eecs.umich.edu{
7577639Sgblack@eecs.umich.edu    // First writeback the second packet from any split store that didn't
7587435Sgblack@eecs.umich.edu    // complete last cycle because there weren't enough cache ports available.
7597435Sgblack@eecs.umich.edu    if (TheISA::HasUnalignedMemAcc) {
7607435Sgblack@eecs.umich.edu        writebackPendingStore();
7617435Sgblack@eecs.umich.edu    }
7627435Sgblack@eecs.umich.edu
7637435Sgblack@eecs.umich.edu    while (storesToWB > 0 &&
7647435Sgblack@eecs.umich.edu           storeWBIdx != storeTail &&
7657435Sgblack@eecs.umich.edu           storeQueue[storeWBIdx].inst &&
7667435Sgblack@eecs.umich.edu           storeQueue[storeWBIdx].canWB &&
7677435Sgblack@eecs.umich.edu           usedPorts < cachePorts) {
7687639Sgblack@eecs.umich.edu
7697639Sgblack@eecs.umich.edu        if (isStoreBlocked || lsq->cacheBlocked()) {
7707639Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
7717639Sgblack@eecs.umich.edu                    " is blocked!\n");
7727435Sgblack@eecs.umich.edu            break;
7737639Sgblack@eecs.umich.edu        }
7747639Sgblack@eecs.umich.edu
7757639Sgblack@eecs.umich.edu        // Store didn't write any data so no need to write it back to
7767639Sgblack@eecs.umich.edu        // memory.
7777639Sgblack@eecs.umich.edu        if (storeQueue[storeWBIdx].size == 0) {
7787853SMatt.Horsnell@ARM.com            completeStore(storeWBIdx);
7797853SMatt.Horsnell@ARM.com
7807853SMatt.Horsnell@ARM.com            incrStIdx(storeWBIdx);
7817853SMatt.Horsnell@ARM.com
7827853SMatt.Horsnell@ARM.com            continue;
7837853SMatt.Horsnell@ARM.com        }
7847853SMatt.Horsnell@ARM.com
7857853SMatt.Horsnell@ARM.com        ++usedPorts;
7867853SMatt.Horsnell@ARM.com
7877435Sgblack@eecs.umich.edu        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
7887435Sgblack@eecs.umich.edu            incrStIdx(storeWBIdx);
7897435Sgblack@eecs.umich.edu
7907639Sgblack@eecs.umich.edu            continue;
7917639Sgblack@eecs.umich.edu        }
7927639Sgblack@eecs.umich.edu
7937639Sgblack@eecs.umich.edu        assert(storeQueue[storeWBIdx].req);
7947435Sgblack@eecs.umich.edu        assert(!storeQueue[storeWBIdx].committed);
7957639Sgblack@eecs.umich.edu
7967639Sgblack@eecs.umich.edu        if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) {
7977639Sgblack@eecs.umich.edu            assert(storeQueue[storeWBIdx].sreqLow);
7987639Sgblack@eecs.umich.edu            assert(storeQueue[storeWBIdx].sreqHigh);
7997435Sgblack@eecs.umich.edu        }
8007435Sgblack@eecs.umich.edu
8017435Sgblack@eecs.umich.edu        DynInstPtr inst = storeQueue[storeWBIdx].inst;
8027639Sgblack@eecs.umich.edu
8037639Sgblack@eecs.umich.edu        Request *req = storeQueue[storeWBIdx].req;
8047639Sgblack@eecs.umich.edu        RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow;
8057639Sgblack@eecs.umich.edu        RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh;
8067639Sgblack@eecs.umich.edu
8077639Sgblack@eecs.umich.edu        storeQueue[storeWBIdx].committed = true;
8087639Sgblack@eecs.umich.edu
8097639Sgblack@eecs.umich.edu        assert(!inst->memData);
8107639Sgblack@eecs.umich.edu        inst->memData = new uint8_t[64];
8117639Sgblack@eecs.umich.edu
8127639Sgblack@eecs.umich.edu        memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
8137639Sgblack@eecs.umich.edu
8147639Sgblack@eecs.umich.edu        MemCmd command =
8157639Sgblack@eecs.umich.edu            req->isSwap() ? MemCmd::SwapReq :
8167639Sgblack@eecs.umich.edu            (req->isLLSC() ? MemCmd::StoreCondReq : MemCmd::WriteReq);
8177639Sgblack@eecs.umich.edu        PacketPtr data_pkt;
8187639Sgblack@eecs.umich.edu        PacketPtr snd_data_pkt = NULL;
8197639Sgblack@eecs.umich.edu
8207435Sgblack@eecs.umich.edu        LSQSenderState *state = new LSQSenderState;
8217435Sgblack@eecs.umich.edu        state->isLoad = false;
8227639Sgblack@eecs.umich.edu        state->idx = storeWBIdx;
8237639Sgblack@eecs.umich.edu        state->inst = inst;
8247639Sgblack@eecs.umich.edu
8257639Sgblack@eecs.umich.edu        if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) {
8267435Sgblack@eecs.umich.edu
8277639Sgblack@eecs.umich.edu            // Build a single data packet if the store isn't split.
8287639Sgblack@eecs.umich.edu            data_pkt = new Packet(req, command, Packet::Broadcast);
8297639Sgblack@eecs.umich.edu            data_pkt->dataStatic(inst->memData);
8307639Sgblack@eecs.umich.edu            data_pkt->senderState = state;
8317435Sgblack@eecs.umich.edu        } else {
8327435Sgblack@eecs.umich.edu            // Create two packets if the store is split in two.
8337435Sgblack@eecs.umich.edu            data_pkt = new Packet(sreqLow, command, Packet::Broadcast);
8347435Sgblack@eecs.umich.edu            snd_data_pkt = new Packet(sreqHigh, command, Packet::Broadcast);
8357435Sgblack@eecs.umich.edu
8367435Sgblack@eecs.umich.edu            data_pkt->dataStatic(inst->memData);
8377639Sgblack@eecs.umich.edu            snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize());
8387639Sgblack@eecs.umich.edu
8397639Sgblack@eecs.umich.edu            data_pkt->senderState = state;
8407639Sgblack@eecs.umich.edu            snd_data_pkt->senderState = state;
8417435Sgblack@eecs.umich.edu
8427639Sgblack@eecs.umich.edu            state->isSplit = true;
8437639Sgblack@eecs.umich.edu            state->outstanding = 2;
8447639Sgblack@eecs.umich.edu
8457639Sgblack@eecs.umich.edu            // Can delete the main request now.
8467435Sgblack@eecs.umich.edu            delete req;
8477435Sgblack@eecs.umich.edu            req = sreqLow;
8487435Sgblack@eecs.umich.edu        }
8497639Sgblack@eecs.umich.edu
8507639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
8517639Sgblack@eecs.umich.edu                "to Addr:%#x, data:%#x [sn:%lli]\n",
8527639Sgblack@eecs.umich.edu                storeWBIdx, inst->pcState(),
8537435Sgblack@eecs.umich.edu                req->getPaddr(), (int)*(inst->memData),
8547435Sgblack@eecs.umich.edu                inst->seqNum);
8557639Sgblack@eecs.umich.edu
8567639Sgblack@eecs.umich.edu        // @todo: Remove this SC hack once the memory system handles it.
8577639Sgblack@eecs.umich.edu        if (inst->isStoreConditional()) {
8587639Sgblack@eecs.umich.edu            assert(!storeQueue[storeWBIdx].isSplit);
8597435Sgblack@eecs.umich.edu            // Disable recording the result temporarily.  Writing to
8607639Sgblack@eecs.umich.edu            // misc regs normally updates the result, but this is not
8617639Sgblack@eecs.umich.edu            // the desired behavior when handling store conditionals.
8627639Sgblack@eecs.umich.edu            inst->recordResult = false;
8637639Sgblack@eecs.umich.edu            bool success = TheISA::handleLockedWrite(inst.get(), req);
8647435Sgblack@eecs.umich.edu            inst->recordResult = true;
8657435Sgblack@eecs.umich.edu
8667435Sgblack@eecs.umich.edu            if (!success) {
8677435Sgblack@eecs.umich.edu                // Instantly complete this store.
8687435Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed.  "
8697435Sgblack@eecs.umich.edu                        "Instantly completing it.\n",
8707435Sgblack@eecs.umich.edu                        inst->seqNum);
8717435Sgblack@eecs.umich.edu                WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
8727435Sgblack@eecs.umich.edu                cpu->schedule(wb, curTick() + 1);
8737435Sgblack@eecs.umich.edu                completeStore(storeWBIdx);
8747435Sgblack@eecs.umich.edu                incrStIdx(storeWBIdx);
8757435Sgblack@eecs.umich.edu                continue;
8767435Sgblack@eecs.umich.edu            }
8777435Sgblack@eecs.umich.edu        } else {
8787639Sgblack@eecs.umich.edu            // Non-store conditionals do not need a writeback.
8797639Sgblack@eecs.umich.edu            state->noWB = true;
8807639Sgblack@eecs.umich.edu        }
8817639Sgblack@eecs.umich.edu
8827639Sgblack@eecs.umich.edu        bool split =
8837639Sgblack@eecs.umich.edu            TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit;
8847639Sgblack@eecs.umich.edu
8857639Sgblack@eecs.umich.edu        ThreadContext *thread = cpu->tcBase(lsqID);
8867639Sgblack@eecs.umich.edu
8877639Sgblack@eecs.umich.edu        if (req->isMmappedIpr()) {
8887639Sgblack@eecs.umich.edu            assert(!inst->isStoreConditional());
8897639Sgblack@eecs.umich.edu            TheISA::handleIprWrite(thread, data_pkt);
8907639Sgblack@eecs.umich.edu            delete data_pkt;
8917639Sgblack@eecs.umich.edu            if (split) {
8927639Sgblack@eecs.umich.edu                assert(snd_data_pkt->req->isMmappedIpr());
8937639Sgblack@eecs.umich.edu                TheISA::handleIprWrite(thread, snd_data_pkt);
8947639Sgblack@eecs.umich.edu                delete snd_data_pkt;
8957639Sgblack@eecs.umich.edu                delete sreqLow;
8967639Sgblack@eecs.umich.edu                delete sreqHigh;
8977639Sgblack@eecs.umich.edu            }
8987639Sgblack@eecs.umich.edu            delete state;
8997639Sgblack@eecs.umich.edu            delete req;
9007639Sgblack@eecs.umich.edu            completeStore(storeWBIdx);
9017639Sgblack@eecs.umich.edu            incrStIdx(storeWBIdx);
9027639Sgblack@eecs.umich.edu        } else if (!sendStore(data_pkt)) {
9037639Sgblack@eecs.umich.edu            DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
9047435Sgblack@eecs.umich.edu                    "retry later\n",
9057435Sgblack@eecs.umich.edu                    inst->seqNum);
9067435Sgblack@eecs.umich.edu
9077639Sgblack@eecs.umich.edu            // Need to store the second packet, if split.
9087639Sgblack@eecs.umich.edu            if (split) {
9097435Sgblack@eecs.umich.edu                state->pktToSend = true;
9107639Sgblack@eecs.umich.edu                state->pendingPacket = snd_data_pkt;
9117639Sgblack@eecs.umich.edu            }
9127435Sgblack@eecs.umich.edu        } else {
9137639Sgblack@eecs.umich.edu
9147639Sgblack@eecs.umich.edu            // If split, try to send the second packet too
9157435Sgblack@eecs.umich.edu            if (split) {
9167639Sgblack@eecs.umich.edu                assert(snd_data_pkt);
9177639Sgblack@eecs.umich.edu
9187435Sgblack@eecs.umich.edu                // Ensure there are enough ports to use.
9197435Sgblack@eecs.umich.edu                if (usedPorts < cachePorts) {
9207639Sgblack@eecs.umich.edu                    ++usedPorts;
9217639Sgblack@eecs.umich.edu                    if (sendStore(snd_data_pkt)) {
9227435Sgblack@eecs.umich.edu                        storePostSend(snd_data_pkt);
9237435Sgblack@eecs.umich.edu                    } else {
9247435Sgblack@eecs.umich.edu                        DPRINTF(IEW, "D-Cache became blocked when writing"
9257435Sgblack@eecs.umich.edu                                " [sn:%lli] second packet, will retry later\n",
9267435Sgblack@eecs.umich.edu                                inst->seqNum);
9277639Sgblack@eecs.umich.edu                    }
9287639Sgblack@eecs.umich.edu                } else {
9297435Sgblack@eecs.umich.edu
9307639Sgblack@eecs.umich.edu                    // Store the packet for when there's free ports.
9317639Sgblack@eecs.umich.edu                    assert(pendingPkt == NULL);
9327435Sgblack@eecs.umich.edu                    pendingPkt = snd_data_pkt;
9337435Sgblack@eecs.umich.edu                    hasPendingPkt = true;
9347435Sgblack@eecs.umich.edu                }
9357639Sgblack@eecs.umich.edu            } else {
9367639Sgblack@eecs.umich.edu
9377639Sgblack@eecs.umich.edu                // Not a split store.
9387639Sgblack@eecs.umich.edu                storePostSend(data_pkt);
9397639Sgblack@eecs.umich.edu            }
9407639Sgblack@eecs.umich.edu        }
9417639Sgblack@eecs.umich.edu    }
9427639Sgblack@eecs.umich.edu
9437639Sgblack@eecs.umich.edu    // Not sure this should set it to 0.
9447639Sgblack@eecs.umich.edu    usedPorts = 0;
9457639Sgblack@eecs.umich.edu
9467639Sgblack@eecs.umich.edu    assert(stores >= 0 && storesToWB >= 0);
9477435Sgblack@eecs.umich.edu}
9487435Sgblack@eecs.umich.edu
9497435Sgblack@eecs.umich.edu/*template <class Impl>
9507435Sgblack@eecs.umich.eduvoid
9517639Sgblack@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
9527639Sgblack@eecs.umich.edu{
9537435Sgblack@eecs.umich.edu    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
9547639Sgblack@eecs.umich.edu                                              mshrSeqNums.end(),
9557639Sgblack@eecs.umich.edu                                              seqNum);
9567435Sgblack@eecs.umich.edu
9577435Sgblack@eecs.umich.edu    if (mshr_it != mshrSeqNums.end()) {
9587435Sgblack@eecs.umich.edu        mshrSeqNums.erase(mshr_it);
9597435Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
9607639Sgblack@eecs.umich.edu    }
9617639Sgblack@eecs.umich.edu}*/
9627639Sgblack@eecs.umich.edu
9637435Sgblack@eecs.umich.edutemplate <class Impl>
9647639Sgblack@eecs.umich.eduvoid
9657639Sgblack@eecs.umich.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
9667435Sgblack@eecs.umich.edu{
9677435Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
9687435Sgblack@eecs.umich.edu            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
9697435Sgblack@eecs.umich.edu
9707435Sgblack@eecs.umich.edu    int load_idx = loadTail;
9717639Sgblack@eecs.umich.edu    decrLdIdx(load_idx);
9727639Sgblack@eecs.umich.edu
9737435Sgblack@eecs.umich.edu    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
9747435Sgblack@eecs.umich.edu        DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
9757639Sgblack@eecs.umich.edu                "[sn:%lli]\n",
9767639Sgblack@eecs.umich.edu                loadQueue[load_idx]->pcState(),
9777639Sgblack@eecs.umich.edu                loadQueue[load_idx]->seqNum);
9787639Sgblack@eecs.umich.edu
9797639Sgblack@eecs.umich.edu        if (isStalled() && load_idx == stallingLoadIdx) {
9807639Sgblack@eecs.umich.edu            stalled = false;
9817639Sgblack@eecs.umich.edu            stallingStoreIsn = 0;
9827639Sgblack@eecs.umich.edu            stallingLoadIdx = 0;
9837639Sgblack@eecs.umich.edu        }
9847639Sgblack@eecs.umich.edu
9857639Sgblack@eecs.umich.edu        // Clear the smart pointer to make sure it is decremented.
9867639Sgblack@eecs.umich.edu        loadQueue[load_idx]->setSquashed();
9877639Sgblack@eecs.umich.edu        loadQueue[load_idx] = NULL;
9887639Sgblack@eecs.umich.edu        --loads;
9897639Sgblack@eecs.umich.edu
9907639Sgblack@eecs.umich.edu        // Inefficient!
9917639Sgblack@eecs.umich.edu        loadTail = load_idx;
9927639Sgblack@eecs.umich.edu
9937639Sgblack@eecs.umich.edu        decrLdIdx(load_idx);
9947639Sgblack@eecs.umich.edu        ++lsqSquashedLoads;
9957639Sgblack@eecs.umich.edu    }
9967639Sgblack@eecs.umich.edu
9977639Sgblack@eecs.umich.edu    if (isLoadBlocked) {
9987435Sgblack@eecs.umich.edu        if (squashed_num < blockedLoadSeqNum) {
9997435Sgblack@eecs.umich.edu            isLoadBlocked = false;
10007435Sgblack@eecs.umich.edu            loadBlockedHandled = false;
10017639Sgblack@eecs.umich.edu            blockedLoadSeqNum = 0;
10027639Sgblack@eecs.umich.edu        }
10037639Sgblack@eecs.umich.edu    }
10047639Sgblack@eecs.umich.edu
10057639Sgblack@eecs.umich.edu    if (memDepViolator && squashed_num < memDepViolator->seqNum) {
10067639Sgblack@eecs.umich.edu        memDepViolator = NULL;
10077639Sgblack@eecs.umich.edu    }
10087639Sgblack@eecs.umich.edu
10097639Sgblack@eecs.umich.edu    int store_idx = storeTail;
10107639Sgblack@eecs.umich.edu    decrStIdx(store_idx);
10117639Sgblack@eecs.umich.edu
10127639Sgblack@eecs.umich.edu    while (stores != 0 &&
10137639Sgblack@eecs.umich.edu           storeQueue[store_idx].inst->seqNum > squashed_num) {
10147639Sgblack@eecs.umich.edu        // Instructions marked as can WB are already committed.
10157639Sgblack@eecs.umich.edu        if (storeQueue[store_idx].canWB) {
10167639Sgblack@eecs.umich.edu            break;
10177639Sgblack@eecs.umich.edu        }
10187639Sgblack@eecs.umich.edu
10197639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
10207639Sgblack@eecs.umich.edu                "idx:%i [sn:%lli]\n",
10217435Sgblack@eecs.umich.edu                storeQueue[store_idx].inst->pcState(),
10227435Sgblack@eecs.umich.edu                store_idx, storeQueue[store_idx].inst->seqNum);
10237435Sgblack@eecs.umich.edu
10247435Sgblack@eecs.umich.edu        // I don't think this can happen.  It should have been cleared
10257435Sgblack@eecs.umich.edu        // by the stalling load.
10267435Sgblack@eecs.umich.edu        if (isStalled() &&
10277435Sgblack@eecs.umich.edu            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
10287435Sgblack@eecs.umich.edu            panic("Is stalled should have been cleared by stalling load!\n");
10297435Sgblack@eecs.umich.edu            stalled = false;
10307435Sgblack@eecs.umich.edu            stallingStoreIsn = 0;
10317639Sgblack@eecs.umich.edu        }
10327639Sgblack@eecs.umich.edu
10337639Sgblack@eecs.umich.edu        // Clear the smart pointer to make sure it is decremented.
10347639Sgblack@eecs.umich.edu        storeQueue[store_idx].inst->setSquashed();
10357639Sgblack@eecs.umich.edu        storeQueue[store_idx].inst = NULL;
10367639Sgblack@eecs.umich.edu        storeQueue[store_idx].canWB = 0;
10377639Sgblack@eecs.umich.edu
10387639Sgblack@eecs.umich.edu        // Must delete request now that it wasn't handed off to
10397639Sgblack@eecs.umich.edu        // memory.  This is quite ugly.  @todo: Figure out the proper
10407639Sgblack@eecs.umich.edu        // place to really handle request deletes.
10417435Sgblack@eecs.umich.edu        delete storeQueue[store_idx].req;
10427435Sgblack@eecs.umich.edu        if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) {
10437639Sgblack@eecs.umich.edu            delete storeQueue[store_idx].sreqLow;
10447639Sgblack@eecs.umich.edu            delete storeQueue[store_idx].sreqHigh;
10457435Sgblack@eecs.umich.edu
10467639Sgblack@eecs.umich.edu            storeQueue[store_idx].sreqLow = NULL;
10477639Sgblack@eecs.umich.edu            storeQueue[store_idx].sreqHigh = NULL;
10487435Sgblack@eecs.umich.edu        }
10497639Sgblack@eecs.umich.edu
10507639Sgblack@eecs.umich.edu        storeQueue[store_idx].req = NULL;
10517435Sgblack@eecs.umich.edu        --stores;
10527639Sgblack@eecs.umich.edu
10537639Sgblack@eecs.umich.edu        // Inefficient!
10547435Sgblack@eecs.umich.edu        storeTail = store_idx;
10557435Sgblack@eecs.umich.edu
10567639Sgblack@eecs.umich.edu        decrStIdx(store_idx);
10577639Sgblack@eecs.umich.edu        ++lsqSquashedStores;
10587435Sgblack@eecs.umich.edu    }
10597639Sgblack@eecs.umich.edu}
10607639Sgblack@eecs.umich.edu
10617435Sgblack@eecs.umich.edutemplate <class Impl>
10627435Sgblack@eecs.umich.eduvoid
10637639Sgblack@eecs.umich.eduLSQUnit<Impl>::storePostSend(PacketPtr pkt)
10647639Sgblack@eecs.umich.edu{
10657435Sgblack@eecs.umich.edu    if (isStalled() &&
10667435Sgblack@eecs.umich.edu        storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
10677639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
10687639Sgblack@eecs.umich.edu                "load idx:%i\n",
10697435Sgblack@eecs.umich.edu                stallingStoreIsn, stallingLoadIdx);
10707639Sgblack@eecs.umich.edu        stalled = false;
10717639Sgblack@eecs.umich.edu        stallingStoreIsn = 0;
10727435Sgblack@eecs.umich.edu        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
10737435Sgblack@eecs.umich.edu    }
10747435Sgblack@eecs.umich.edu
10757639Sgblack@eecs.umich.edu    if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
10767639Sgblack@eecs.umich.edu        // The store is basically completed at this time. This
10777435Sgblack@eecs.umich.edu        // only works so long as the checker doesn't try to
10787639Sgblack@eecs.umich.edu        // verify the value in memory for stores.
10797639Sgblack@eecs.umich.edu        storeQueue[storeWBIdx].inst->setCompleted();
10807435Sgblack@eecs.umich.edu#if USE_CHECKER
10817435Sgblack@eecs.umich.edu        if (cpu->checker) {
10827639Sgblack@eecs.umich.edu            cpu->checker->verify(storeQueue[storeWBIdx].inst);
10837639Sgblack@eecs.umich.edu        }
10847435Sgblack@eecs.umich.edu#endif
10857639Sgblack@eecs.umich.edu    }
10867639Sgblack@eecs.umich.edu
10877435Sgblack@eecs.umich.edu    incrStIdx(storeWBIdx);
10887639Sgblack@eecs.umich.edu}
10897639Sgblack@eecs.umich.edu
10907435Sgblack@eecs.umich.edutemplate <class Impl>
10917639Sgblack@eecs.umich.eduvoid
10927639Sgblack@eecs.umich.eduLSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
10937435Sgblack@eecs.umich.edu{
10947435Sgblack@eecs.umich.edu    iewStage->wakeCPU();
10957639Sgblack@eecs.umich.edu
10967435Sgblack@eecs.umich.edu    // Squashed instructions do not need to complete their access.
10977435Sgblack@eecs.umich.edu    if (inst->isSquashed()) {
10987639Sgblack@eecs.umich.edu        iewStage->decrWb(inst->seqNum);
10997639Sgblack@eecs.umich.edu        assert(!inst->isStore());
11007435Sgblack@eecs.umich.edu        ++lsqIgnoredResponses;
11017435Sgblack@eecs.umich.edu        return;
11027639Sgblack@eecs.umich.edu    }
11037639Sgblack@eecs.umich.edu
11047435Sgblack@eecs.umich.edu    if (!inst->isExecuted()) {
11057639Sgblack@eecs.umich.edu        inst->setExecuted();
11067435Sgblack@eecs.umich.edu
11077435Sgblack@eecs.umich.edu        // Complete access to copy data to proper place.
11087639Sgblack@eecs.umich.edu        inst->completeAcc(pkt);
11097639Sgblack@eecs.umich.edu    }
11107435Sgblack@eecs.umich.edu
11117435Sgblack@eecs.umich.edu    // Need to insert instruction into queue to commit
11127639Sgblack@eecs.umich.edu    iewStage->instToCommit(inst);
11137639Sgblack@eecs.umich.edu
11147435Sgblack@eecs.umich.edu    iewStage->activityThisCycle();
11157435Sgblack@eecs.umich.edu
11167435Sgblack@eecs.umich.edu    // see if this load changed the PC
11177435Sgblack@eecs.umich.edu    iewStage->checkMisprediction(inst);
11187435Sgblack@eecs.umich.edu}
11197435Sgblack@eecs.umich.edu
11207435Sgblack@eecs.umich.edutemplate <class Impl>
11217435Sgblack@eecs.umich.eduvoid
11227435Sgblack@eecs.umich.eduLSQUnit<Impl>::completeStore(int store_idx)
11237639Sgblack@eecs.umich.edu{
11247639Sgblack@eecs.umich.edu    assert(storeQueue[store_idx].inst);
11257639Sgblack@eecs.umich.edu    storeQueue[store_idx].completed = true;
11267639Sgblack@eecs.umich.edu    --storesToWB;
11277639Sgblack@eecs.umich.edu    // A bit conservative because a store completion may not free up entries,
11287639Sgblack@eecs.umich.edu    // but hopefully avoids two store completions in one cycle from making
11297639Sgblack@eecs.umich.edu    // the CPU tick twice.
11307639Sgblack@eecs.umich.edu    cpu->wakeCPU();
11317639Sgblack@eecs.umich.edu    cpu->activityThisCycle();
11327639Sgblack@eecs.umich.edu
11337639Sgblack@eecs.umich.edu    if (store_idx == storeHead) {
11347639Sgblack@eecs.umich.edu        do {
11357435Sgblack@eecs.umich.edu            incrStIdx(storeHead);
11367435Sgblack@eecs.umich.edu
11377639Sgblack@eecs.umich.edu            --stores;
11387639Sgblack@eecs.umich.edu        } while (storeQueue[storeHead].completed &&
11397639Sgblack@eecs.umich.edu                 storeHead != storeTail);
11407639Sgblack@eecs.umich.edu
11417639Sgblack@eecs.umich.edu        iewStage->updateLSQNextCycle = true;
11427639Sgblack@eecs.umich.edu    }
11437639Sgblack@eecs.umich.edu
11447639Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
11457639Sgblack@eecs.umich.edu            "idx:%i\n",
11467639Sgblack@eecs.umich.edu            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
11477639Sgblack@eecs.umich.edu
11487639Sgblack@eecs.umich.edu    if (isStalled() &&
11497639Sgblack@eecs.umich.edu        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
11507639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
11517639Sgblack@eecs.umich.edu                "load idx:%i\n",
11527639Sgblack@eecs.umich.edu                stallingStoreIsn, stallingLoadIdx);
11537639Sgblack@eecs.umich.edu        stalled = false;
11547639Sgblack@eecs.umich.edu        stallingStoreIsn = 0;
11557639Sgblack@eecs.umich.edu        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
11567435Sgblack@eecs.umich.edu    }
11577639Sgblack@eecs.umich.edu
11587639Sgblack@eecs.umich.edu    storeQueue[store_idx].inst->setCompleted();
11597639Sgblack@eecs.umich.edu
11607639Sgblack@eecs.umich.edu    // Tell the checker we've completed this instruction.  Some stores
11617435Sgblack@eecs.umich.edu    // may get reported twice to the checker, but the checker can
11627639Sgblack@eecs.umich.edu    // handle that case.
11637639Sgblack@eecs.umich.edu#if USE_CHECKER
11647639Sgblack@eecs.umich.edu    if (cpu->checker) {
11657639Sgblack@eecs.umich.edu        cpu->checker->verify(storeQueue[store_idx].inst);
11667639Sgblack@eecs.umich.edu    }
11677639Sgblack@eecs.umich.edu#endif
11687639Sgblack@eecs.umich.edu}
11697639Sgblack@eecs.umich.edu
11707639Sgblack@eecs.umich.edutemplate <class Impl>
11717639Sgblack@eecs.umich.edubool
11727639Sgblack@eecs.umich.eduLSQUnit<Impl>::sendStore(PacketPtr data_pkt)
11737639Sgblack@eecs.umich.edu{
11747639Sgblack@eecs.umich.edu    if (!dcachePort->sendTiming(data_pkt)) {
11757639Sgblack@eecs.umich.edu        // Need to handle becoming blocked on a store.
11767639Sgblack@eecs.umich.edu        isStoreBlocked = true;
11777639Sgblack@eecs.umich.edu        ++lsqCacheBlocked;
11787639Sgblack@eecs.umich.edu        assert(retryPkt == NULL);
11797639Sgblack@eecs.umich.edu        retryPkt = data_pkt;
11807639Sgblack@eecs.umich.edu        lsq->setRetryTid(lsqID);
11817435Sgblack@eecs.umich.edu        return false;
11827639Sgblack@eecs.umich.edu    }
11837639Sgblack@eecs.umich.edu    return true;
11847639Sgblack@eecs.umich.edu}
11857639Sgblack@eecs.umich.edu
11867435Sgblack@eecs.umich.edutemplate <class Impl>
11877639Sgblack@eecs.umich.eduvoid
11887639Sgblack@eecs.umich.eduLSQUnit<Impl>::recvRetry()
11897639Sgblack@eecs.umich.edu{
11907639Sgblack@eecs.umich.edu    if (isStoreBlocked) {
11917639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Receiving retry: store blocked\n");
11927639Sgblack@eecs.umich.edu        assert(retryPkt != NULL);
11937639Sgblack@eecs.umich.edu
11947639Sgblack@eecs.umich.edu        if (dcachePort->sendTiming(retryPkt)) {
11957639Sgblack@eecs.umich.edu            LSQSenderState *state =
11967639Sgblack@eecs.umich.edu                dynamic_cast<LSQSenderState *>(retryPkt->senderState);
11977639Sgblack@eecs.umich.edu
11987639Sgblack@eecs.umich.edu            // Don't finish the store unless this is the last packet.
11997639Sgblack@eecs.umich.edu            if (!TheISA::HasUnalignedMemAcc || !state->pktToSend ||
12007639Sgblack@eecs.umich.edu                    state->pendingPacket == retryPkt) {
12017639Sgblack@eecs.umich.edu                state->pktToSend = false;
12027639Sgblack@eecs.umich.edu                storePostSend(retryPkt);
12037639Sgblack@eecs.umich.edu            }
12047639Sgblack@eecs.umich.edu            retryPkt = NULL;
12057639Sgblack@eecs.umich.edu            isStoreBlocked = false;
12067435Sgblack@eecs.umich.edu            lsq->setRetryTid(InvalidThreadID);
12077639Sgblack@eecs.umich.edu
12087639Sgblack@eecs.umich.edu            // Send any outstanding packet.
12097639Sgblack@eecs.umich.edu            if (TheISA::HasUnalignedMemAcc && state->pktToSend) {
12107639Sgblack@eecs.umich.edu                assert(state->pendingPacket);
12117639Sgblack@eecs.umich.edu                if (sendStore(state->pendingPacket)) {
12127639Sgblack@eecs.umich.edu                    storePostSend(state->pendingPacket);
12137639Sgblack@eecs.umich.edu                }
12147639Sgblack@eecs.umich.edu            }
12157639Sgblack@eecs.umich.edu        } else {
12167639Sgblack@eecs.umich.edu            // Still blocked!
12177639Sgblack@eecs.umich.edu            ++lsqCacheBlocked;
12187639Sgblack@eecs.umich.edu            lsq->setRetryTid(lsqID);
12197639Sgblack@eecs.umich.edu        }
12207639Sgblack@eecs.umich.edu    } else if (isLoadBlocked) {
12217639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
12227639Sgblack@eecs.umich.edu                "no need to resend packet.\n");
12237639Sgblack@eecs.umich.edu    } else {
12247639Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n");
12257639Sgblack@eecs.umich.edu    }
12267435Sgblack@eecs.umich.edu}
12277435Sgblack@eecs.umich.edu
12287435Sgblack@eecs.umich.edutemplate <class Impl>
12297435Sgblack@eecs.umich.eduinline void
12307639Sgblack@eecs.umich.eduLSQUnit<Impl>::incrStIdx(int &store_idx)
12317639Sgblack@eecs.umich.edu{
12327639Sgblack@eecs.umich.edu    if (++store_idx >= SQEntries)
12337639Sgblack@eecs.umich.edu        store_idx = 0;
12347639Sgblack@eecs.umich.edu}
12357639Sgblack@eecs.umich.edu
12367639Sgblack@eecs.umich.edutemplate <class Impl>
12377639Sgblack@eecs.umich.eduinline void
12387435Sgblack@eecs.umich.eduLSQUnit<Impl>::decrStIdx(int &store_idx)
12397435Sgblack@eecs.umich.edu{
12407435Sgblack@eecs.umich.edu    if (--store_idx < 0)
12417435Sgblack@eecs.umich.edu        store_idx += SQEntries;
12427435Sgblack@eecs.umich.edu}
12437639Sgblack@eecs.umich.edu
12447639Sgblack@eecs.umich.edutemplate <class Impl>
12457639Sgblack@eecs.umich.eduinline void
12467639Sgblack@eecs.umich.eduLSQUnit<Impl>::incrLdIdx(int &load_idx)
12477639Sgblack@eecs.umich.edu{
12487639Sgblack@eecs.umich.edu    if (++load_idx >= LQEntries)
12497639Sgblack@eecs.umich.edu        load_idx = 0;
12507639Sgblack@eecs.umich.edu}
12517435Sgblack@eecs.umich.edu
12527435Sgblack@eecs.umich.edutemplate <class Impl>
12537639Sgblack@eecs.umich.eduinline void
12547639Sgblack@eecs.umich.eduLSQUnit<Impl>::decrLdIdx(int &load_idx)
12557639Sgblack@eecs.umich.edu{
12567639Sgblack@eecs.umich.edu    if (--load_idx < 0)
12577639Sgblack@eecs.umich.edu        load_idx += LQEntries;
12587639Sgblack@eecs.umich.edu}
12597639Sgblack@eecs.umich.edu
12607639Sgblack@eecs.umich.edutemplate <class Impl>
12617639Sgblack@eecs.umich.eduvoid
12627639Sgblack@eecs.umich.eduLSQUnit<Impl>::dumpInsts()
12637639Sgblack@eecs.umich.edu{
12647639Sgblack@eecs.umich.edu    cprintf("Load store queue: Dumping instructions.\n");
12657639Sgblack@eecs.umich.edu    cprintf("Load queue size: %i\n", loads);
12667639Sgblack@eecs.umich.edu    cprintf("Load queue: ");
12677639Sgblack@eecs.umich.edu
12687639Sgblack@eecs.umich.edu    int load_idx = loadHead;
12697639Sgblack@eecs.umich.edu
12707639Sgblack@eecs.umich.edu    while (load_idx != loadTail && loadQueue[load_idx]) {
12717639Sgblack@eecs.umich.edu        cprintf("%s ", loadQueue[load_idx]->pcState());
12727435Sgblack@eecs.umich.edu
12737639Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
12747639Sgblack@eecs.umich.edu    }
12757639Sgblack@eecs.umich.edu
12767639Sgblack@eecs.umich.edu    cprintf("Store queue size: %i\n", stores);
12777435Sgblack@eecs.umich.edu    cprintf("Store queue: ");
12787639Sgblack@eecs.umich.edu
12797639Sgblack@eecs.umich.edu    int store_idx = storeHead;
12807639Sgblack@eecs.umich.edu
12817639Sgblack@eecs.umich.edu    while (store_idx != storeTail && storeQueue[store_idx].inst) {
12827639Sgblack@eecs.umich.edu        cprintf("%s ", storeQueue[store_idx].inst->pcState());
12837639Sgblack@eecs.umich.edu
12847639Sgblack@eecs.umich.edu        incrStIdx(store_idx);
12857639Sgblack@eecs.umich.edu    }
12867639Sgblack@eecs.umich.edu
12877639Sgblack@eecs.umich.edu    cprintf("\n");
12887639Sgblack@eecs.umich.edu}
12897639Sgblack@eecs.umich.edu