lsq_unit_impl.hh revision 3221:669a04468c0d
12SN/A/*
211147Smitch.hayenga@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
39920Syasuko.eckert@amd.com * All rights reserved.
47338SAli.Saidi@ARM.com *
57338SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67338SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77338SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97338SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117338SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127338SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137338SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147338SAli.Saidi@ARM.com * this software without specific prior written permission.
151762SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A *
282SN/A * Authors: Kevin Lim
292SN/A *          Korey Sewell
302SN/A */
312SN/A
322SN/A#include "config/use_checker.hh"
332SN/A
342SN/A#include "cpu/o3/lsq.hh"
352SN/A#include "cpu/o3/lsq_unit.hh"
362SN/A#include "base/str.hh"
372SN/A#include "mem/packet.hh"
382SN/A#include "mem/request.hh"
392SN/A
402665Ssaidi@eecs.umich.edu#if USE_CHECKER
412665Ssaidi@eecs.umich.edu#include "cpu/checker/cpu.hh"
422SN/A#endif
432SN/A
4411793Sbrandon.potter@amd.comtemplate<class Impl>
4511793Sbrandon.potter@amd.comLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
468779Sgblack@eecs.umich.edu                                              LSQUnit *lsq_ptr)
478779Sgblack@eecs.umich.edu    : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
488779Sgblack@eecs.umich.edu{
492439SN/A    this->setFlags(Event::AutoDelete);
508779Sgblack@eecs.umich.edu}
516216Snate@binkert.org
52146SN/Atemplate<class Impl>
53146SN/Avoid
5411793Sbrandon.potter@amd.comLSQUnit<Impl>::WritebackEvent::process()
55146SN/A{
56146SN/A    if (!lsqPtr->isSwitchedOut()) {
57146SN/A        lsqPtr->writeback(inst, pkt);
586216Snate@binkert.org    }
596658Snate@binkert.org    delete pkt;
601717SN/A}
618887Sgeoffrey.blake@arm.com
628887Sgeoffrey.blake@arm.comtemplate<class Impl>
63146SN/Aconst char *
6410061Sandreas@sandberg.pp.seLSQUnit<Impl>::WritebackEvent::description()
651977SN/A{
6611147Smitch.hayenga@arm.com    return "Store writeback event";
672683Sktlim@umich.edu}
681717SN/A
69146SN/Atemplate<class Impl>
702683Sktlim@umich.eduvoid
718232Snate@binkert.orgLSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
728232Snate@binkert.org{
738232Snate@binkert.org    LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
748779Sgblack@eecs.umich.edu    DynInstPtr inst = state->inst;
753348Sbinkertn@umich.edu    DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum);
766105Ssteve.reinhardt@amd.com    DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum);
776216Snate@binkert.org
782036SN/A    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
79146SN/A
808817Sgblack@eecs.umich.edu    if (isSwitchedOut() || inst->isSquashed()) {
818793Sgblack@eecs.umich.edu        iewStage->decrWb(inst->seqNum);
8256SN/A        delete state;
8356SN/A        delete pkt;
84695SN/A        return;
852901Ssaidi@eecs.umich.edu    } else {
862SN/A        if (!state->noWB) {
872SN/A            writeback(inst, pkt);
882449SN/A        }
891355SN/A
905529Snate@binkert.org        if (inst->isStore()) {
9110061Sandreas@sandberg.pp.se            completeStore(state->idx);
9211147Smitch.hayenga@arm.com        }
9310061Sandreas@sandberg.pp.se    }
9411147Smitch.hayenga@arm.com
9511147Smitch.hayenga@arm.com    delete state;
9611147Smitch.hayenga@arm.com    delete pkt;
97224SN/A}
9811147Smitch.hayenga@arm.com
992SN/Atemplate <class Impl>
10011147Smitch.hayenga@arm.comLSQUnit<Impl>::LSQUnit()
10111147Smitch.hayenga@arm.com    : loads(0), stores(0), storesToWB(0), stalled(false),
10211147Smitch.hayenga@arm.com      isStoreBlocked(false), isLoadBlocked(false),
10311147Smitch.hayenga@arm.com      loadBlockedHandled(false)
10411147Smitch.hayenga@arm.com{
10511147Smitch.hayenga@arm.com}
10611147Smitch.hayenga@arm.com
10711147Smitch.hayenga@arm.comtemplate<class Impl>
10811147Smitch.hayenga@arm.comvoid
10911147Smitch.hayenga@arm.comLSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
11011147Smitch.hayenga@arm.com                    unsigned maxSQEntries, unsigned id)
11111147Smitch.hayenga@arm.com{
1122SN/A    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
1138733Sgeoffrey.blake@arm.com
11411147Smitch.hayenga@arm.com    switchedOut = false;
11511147Smitch.hayenga@arm.com
11611147Smitch.hayenga@arm.com    lsq = lsq_ptr;
1178733Sgeoffrey.blake@arm.com
1188733Sgeoffrey.blake@arm.com    lsqID = id;
1198733Sgeoffrey.blake@arm.com
1208733Sgeoffrey.blake@arm.com    // Add 1 for the sentinel entry (they are circular queues).
12111147Smitch.hayenga@arm.com    LQEntries = maxLQEntries + 1;
12211147Smitch.hayenga@arm.com    SQEntries = maxSQEntries + 1;
1238733Sgeoffrey.blake@arm.com
1248733Sgeoffrey.blake@arm.com    loadQueue.resize(LQEntries);
1258733Sgeoffrey.blake@arm.com    storeQueue.resize(SQEntries);
12611147Smitch.hayenga@arm.com
1278733Sgeoffrey.blake@arm.com    loadHead = loadTail = 0;
12811147Smitch.hayenga@arm.com
12911147Smitch.hayenga@arm.com    storeHead = storeWBIdx = storeTail = 0;
13011147Smitch.hayenga@arm.com
13111147Smitch.hayenga@arm.com    usedPorts = 0;
1322SN/A    cachePorts = params->cachePorts;
13311147Smitch.hayenga@arm.com
13411147Smitch.hayenga@arm.com    memDepViolator = NULL;
13511147Smitch.hayenga@arm.com
1364377Sgblack@eecs.umich.edu    blockedLoadSeqNum = 0;
13711147Smitch.hayenga@arm.com}
13811147Smitch.hayenga@arm.com
13911147Smitch.hayenga@arm.comtemplate<class Impl>
14011147Smitch.hayenga@arm.comvoid
14111147Smitch.hayenga@arm.comLSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
14211147Smitch.hayenga@arm.com{
1435169Ssaidi@eecs.umich.edu    cpu = cpu_ptr;
14411147Smitch.hayenga@arm.com
14511147Smitch.hayenga@arm.com#if USE_CHECKER
14611147Smitch.hayenga@arm.com    if (cpu->checker) {
14711147Smitch.hayenga@arm.com        cpu->checker->setDcachePort(dcachePort);
14811147Smitch.hayenga@arm.com    }
14911147Smitch.hayenga@arm.com#endif
15011147Smitch.hayenga@arm.com}
15111147Smitch.hayenga@arm.com
15211147Smitch.hayenga@arm.comtemplate<class Impl>
15311147Smitch.hayenga@arm.comstd::string
15411147Smitch.hayenga@arm.comLSQUnit<Impl>::name() const
15511147Smitch.hayenga@arm.com{
15611147Smitch.hayenga@arm.com    if (Impl::MaxThreads == 1) {
15711147Smitch.hayenga@arm.com        return iewStage->name() + ".lsq";
15811147Smitch.hayenga@arm.com    } else {
15911147Smitch.hayenga@arm.com        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
16011147Smitch.hayenga@arm.com    }
16111147Smitch.hayenga@arm.com}
16211147Smitch.hayenga@arm.com
16311147Smitch.hayenga@arm.comtemplate<class Impl>
16411147Smitch.hayenga@arm.comvoid
16511147Smitch.hayenga@arm.comLSQUnit<Impl>::regStats()
16611147Smitch.hayenga@arm.com{
16711147Smitch.hayenga@arm.com    lsqForwLoads
16811147Smitch.hayenga@arm.com        .name(name() + ".forwLoads")
16911147Smitch.hayenga@arm.com        .desc("Number of loads that had data forwarded from stores");
17011147Smitch.hayenga@arm.com
17111147Smitch.hayenga@arm.com    invAddrLoads
17211147Smitch.hayenga@arm.com        .name(name() + ".invAddrLoads")
17311147Smitch.hayenga@arm.com        .desc("Number of loads ignored due to an invalid address");
17411147Smitch.hayenga@arm.com
17511147Smitch.hayenga@arm.com    lsqSquashedLoads
17611147Smitch.hayenga@arm.com        .name(name() + ".squashedLoads")
17711147Smitch.hayenga@arm.com        .desc("Number of loads squashed");
17811147Smitch.hayenga@arm.com
17911147Smitch.hayenga@arm.com    lsqIgnoredResponses
18011147Smitch.hayenga@arm.com        .name(name() + ".ignoredResponses")
18111147Smitch.hayenga@arm.com        .desc("Number of memory responses ignored because the instruction is squashed");
18211147Smitch.hayenga@arm.com
18311147Smitch.hayenga@arm.com    lsqMemOrderViolation
18411147Smitch.hayenga@arm.com        .name(name() + ".memOrderViolation")
18511147Smitch.hayenga@arm.com        .desc("Number of memory ordering violations");
18611147Smitch.hayenga@arm.com
18711147Smitch.hayenga@arm.com    lsqSquashedStores
18811147Smitch.hayenga@arm.com        .name(name() + ".squashedStores")
18911147Smitch.hayenga@arm.com        .desc("Number of stores squashed");
19011147Smitch.hayenga@arm.com
19111147Smitch.hayenga@arm.com    invAddrSwpfs
19211147Smitch.hayenga@arm.com        .name(name() + ".invAddrSwpfs")
19311147Smitch.hayenga@arm.com        .desc("Number of software prefetches ignored due to an invalid address");
19411147Smitch.hayenga@arm.com
19511147Smitch.hayenga@arm.com    lsqBlockedLoads
19611147Smitch.hayenga@arm.com        .name(name() + ".blockedLoads")
19711147Smitch.hayenga@arm.com        .desc("Number of blocked loads due to partial load-store forwarding");
19811147Smitch.hayenga@arm.com
19911147Smitch.hayenga@arm.com    lsqRescheduledLoads
20011147Smitch.hayenga@arm.com        .name(name() + ".rescheduledLoads")
20111147Smitch.hayenga@arm.com        .desc("Number of loads that were rescheduled");
20211147Smitch.hayenga@arm.com
20311147Smitch.hayenga@arm.com    lsqCacheBlocked
20411147Smitch.hayenga@arm.com        .name(name() + ".cacheBlocked")
20511147Smitch.hayenga@arm.com        .desc("Number of times an access to memory failed due to the cache being blocked");
20611147Smitch.hayenga@arm.com}
2072SN/A
2082SN/Atemplate<class Impl>
2092623SN/Avoid
2102SN/ALSQUnit<Impl>::clearLQ()
2112SN/A{
2122SN/A    loadQueue.clear();
213180SN/A}
2148737Skoansin.tan@gmail.com
215393SN/Atemplate<class Impl>
216393SN/Avoid
217393SN/ALSQUnit<Impl>::clearSQ()
218393SN/A{
219384SN/A    storeQueue.clear();
220189SN/A}
221189SN/A
2222623SN/Atemplate<class Impl>
2232SN/Avoid
224729SN/ALSQUnit<Impl>::switchOut()
225334SN/A{
2262SN/A    switchedOut = true;
2272SN/A    for (int i = 0; i < loadQueue.size(); ++i) {
22811147Smitch.hayenga@arm.com        assert(!loadQueue[i]);
22911147Smitch.hayenga@arm.com        loadQueue[i] = NULL;
2308834Satgutier@umich.edu    }
23111147Smitch.hayenga@arm.com
23211147Smitch.hayenga@arm.com    assert(storesToWB == 0);
23311147Smitch.hayenga@arm.com}
2342SN/A
23511147Smitch.hayenga@arm.comtemplate<class Impl>
23611147Smitch.hayenga@arm.comvoid
23711147Smitch.hayenga@arm.comLSQUnit<Impl>::takeOverFrom()
23811147Smitch.hayenga@arm.com{
2397897Shestness@cs.utexas.edu    switchedOut = false;
24011147Smitch.hayenga@arm.com    loads = stores = storesToWB = 0;
24111147Smitch.hayenga@arm.com
24211147Smitch.hayenga@arm.com    loadHead = loadTail = 0;
24311147Smitch.hayenga@arm.com
2447897Shestness@cs.utexas.edu    storeHead = storeWBIdx = storeTail = 0;
24511147Smitch.hayenga@arm.com
24611147Smitch.hayenga@arm.com    usedPorts = 0;
24711147Smitch.hayenga@arm.com
24811147Smitch.hayenga@arm.com    memDepViolator = NULL;
2497897Shestness@cs.utexas.edu
25011147Smitch.hayenga@arm.com    blockedLoadSeqNum = 0;
25111147Smitch.hayenga@arm.com
25211147Smitch.hayenga@arm.com    stalled = false;
25311147Smitch.hayenga@arm.com    isLoadBlocked = false;
2547897Shestness@cs.utexas.edu    loadBlockedHandled = false;
25511147Smitch.hayenga@arm.com}
25611147Smitch.hayenga@arm.com
25711147Smitch.hayenga@arm.comtemplate<class Impl>
25811147Smitch.hayenga@arm.comvoid
2597897Shestness@cs.utexas.eduLSQUnit<Impl>::resizeLQ(unsigned size)
26011147Smitch.hayenga@arm.com{
26111147Smitch.hayenga@arm.com    unsigned size_plus_sentinel = size + 1;
26211147Smitch.hayenga@arm.com    assert(size_plus_sentinel >= LQEntries);
26311147Smitch.hayenga@arm.com
2647897Shestness@cs.utexas.edu    if (size_plus_sentinel > LQEntries) {
26511147Smitch.hayenga@arm.com        while (size_plus_sentinel > loadQueue.size()) {
26611147Smitch.hayenga@arm.com            DynInstPtr dummy;
26711147Smitch.hayenga@arm.com            loadQueue.push_back(dummy);
26811147Smitch.hayenga@arm.com            LQEntries++;
2697897Shestness@cs.utexas.edu        }
27011147Smitch.hayenga@arm.com    } else {
27111147Smitch.hayenga@arm.com        LQEntries = size_plus_sentinel;
27211147Smitch.hayenga@arm.com    }
27311147Smitch.hayenga@arm.com
2747897Shestness@cs.utexas.edu}
27511147Smitch.hayenga@arm.com
27611147Smitch.hayenga@arm.comtemplate<class Impl>
27711147Smitch.hayenga@arm.comvoid
27811147Smitch.hayenga@arm.comLSQUnit<Impl>::resizeSQ(unsigned size)
2797897Shestness@cs.utexas.edu{
28011147Smitch.hayenga@arm.com    unsigned size_plus_sentinel = size + 1;
28111147Smitch.hayenga@arm.com    if (size_plus_sentinel > SQEntries) {
28211147Smitch.hayenga@arm.com        while (size_plus_sentinel > storeQueue.size()) {
28311147Smitch.hayenga@arm.com            SQEntry dummy;
2847897Shestness@cs.utexas.edu            storeQueue.push_back(dummy);
28511147Smitch.hayenga@arm.com            SQEntries++;
28611147Smitch.hayenga@arm.com        }
28711147Smitch.hayenga@arm.com    } else {
28811147Smitch.hayenga@arm.com        SQEntries = size_plus_sentinel;
2899920Syasuko.eckert@amd.com    }
29011147Smitch.hayenga@arm.com}
29111147Smitch.hayenga@arm.com
29211147Smitch.hayenga@arm.comtemplate <class Impl>
29311147Smitch.hayenga@arm.comvoid
2949920Syasuko.eckert@amd.comLSQUnit<Impl>::insert(DynInstPtr &inst)
29511147Smitch.hayenga@arm.com{
29611147Smitch.hayenga@arm.com    assert(inst->isMemRef());
29711147Smitch.hayenga@arm.com
29811147Smitch.hayenga@arm.com    assert(inst->isLoad() || inst->isStore());
29911147Smitch.hayenga@arm.com
3007897Shestness@cs.utexas.edu    if (inst->isLoad()) {
30111147Smitch.hayenga@arm.com        insertLoad(inst);
30211147Smitch.hayenga@arm.com    } else {
30311147Smitch.hayenga@arm.com        insertStore(inst);
30411147Smitch.hayenga@arm.com    }
30511147Smitch.hayenga@arm.com
3067897Shestness@cs.utexas.edu    inst->setInLSQ();
30711147Smitch.hayenga@arm.com}
30811147Smitch.hayenga@arm.com
30911147Smitch.hayenga@arm.comtemplate <class Impl>
31011147Smitch.hayenga@arm.comvoid
3112SN/ALSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
31211147Smitch.hayenga@arm.com{
31311147Smitch.hayenga@arm.com    assert((loadTail + 1) % LQEntries != loadHead);
31411147Smitch.hayenga@arm.com    assert(loads < LQEntries);
31511147Smitch.hayenga@arm.com
3161001SN/A    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
31711147Smitch.hayenga@arm.com            load_inst->readPC(), loadTail, load_inst->seqNum);
31811147Smitch.hayenga@arm.com
31911147Smitch.hayenga@arm.com    load_inst->lqIdx = loadTail;
32011147Smitch.hayenga@arm.com
3212SN/A    if (stores == 0) {
32211147Smitch.hayenga@arm.com        load_inst->sqIdx = -1;
32311147Smitch.hayenga@arm.com    } else {
32411147Smitch.hayenga@arm.com        load_inst->sqIdx = storeTail;
32511147Smitch.hayenga@arm.com    }
3267897Shestness@cs.utexas.edu
32711147Smitch.hayenga@arm.com    loadQueue[loadTail] = load_inst;
32811147Smitch.hayenga@arm.com
32911147Smitch.hayenga@arm.com    incrLdIdx(loadTail);
33011147Smitch.hayenga@arm.com
3317897Shestness@cs.utexas.edu    ++loads;
33211147Smitch.hayenga@arm.com}
33311147Smitch.hayenga@arm.com
33411147Smitch.hayenga@arm.comtemplate <class Impl>
33511147Smitch.hayenga@arm.comvoid
3362SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
33711147Smitch.hayenga@arm.com{
33811147Smitch.hayenga@arm.com    // Make sure it is not full before inserting an instruction.
33911147Smitch.hayenga@arm.com    assert((storeTail + 1) % SQEntries != storeHead);
34011147Smitch.hayenga@arm.com    assert(stores < SQEntries);
3412SN/A
34211147Smitch.hayenga@arm.com    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
34311147Smitch.hayenga@arm.com            store_inst->readPC(), storeTail, store_inst->seqNum);
34411147Smitch.hayenga@arm.com
34511147Smitch.hayenga@arm.com    store_inst->sqIdx = storeTail;
34611147Smitch.hayenga@arm.com    store_inst->lqIdx = loadTail;
34711147Smitch.hayenga@arm.com
34811147Smitch.hayenga@arm.com    storeQueue[storeTail] = SQEntry(store_inst);
34911147Smitch.hayenga@arm.com
35011147Smitch.hayenga@arm.com    incrStIdx(storeTail);
35111147Smitch.hayenga@arm.com
35211147Smitch.hayenga@arm.com    ++stores;
35311147Smitch.hayenga@arm.com}
35411147Smitch.hayenga@arm.com
35511147Smitch.hayenga@arm.comtemplate <class Impl>
35611147Smitch.hayenga@arm.comtypename Impl::DynInstPtr
35711147Smitch.hayenga@arm.comLSQUnit<Impl>::getMemDepViolator()
35811147Smitch.hayenga@arm.com{
35911147Smitch.hayenga@arm.com    DynInstPtr temp = memDepViolator;
36011147Smitch.hayenga@arm.com
36111147Smitch.hayenga@arm.com    memDepViolator = NULL;
36211147Smitch.hayenga@arm.com
36311147Smitch.hayenga@arm.com    return temp;
36411147Smitch.hayenga@arm.com}
36511147Smitch.hayenga@arm.com
36611147Smitch.hayenga@arm.comtemplate <class Impl>
36711147Smitch.hayenga@arm.comunsigned
36811147Smitch.hayenga@arm.comLSQUnit<Impl>::numFreeEntries()
36911147Smitch.hayenga@arm.com{
37011147Smitch.hayenga@arm.com    unsigned free_lq_entries = LQEntries - loads;
37111147Smitch.hayenga@arm.com    unsigned free_sq_entries = SQEntries - stores;
37211147Smitch.hayenga@arm.com
37311147Smitch.hayenga@arm.com    // Both the LQ and SQ entries have an extra dummy entry to differentiate
37411147Smitch.hayenga@arm.com    // empty/full conditions.  Subtract 1 from the free entries.
37511147Smitch.hayenga@arm.com    if (free_lq_entries < free_sq_entries) {
37611147Smitch.hayenga@arm.com        return free_lq_entries - 1;
37711147Smitch.hayenga@arm.com    } else {
37811147Smitch.hayenga@arm.com        return free_sq_entries - 1;
37911147Smitch.hayenga@arm.com    }
38011147Smitch.hayenga@arm.com}
38111147Smitch.hayenga@arm.com
38211147Smitch.hayenga@arm.comtemplate <class Impl>
38310193SCurtis.Dunham@arm.comint
3842SN/ALSQUnit<Impl>::numLoadsReady()
3852SN/A{
3862SN/A    int load_idx = loadHead;
3872623SN/A    int retval = 0;
388334SN/A
38911147Smitch.hayenga@arm.com    while (load_idx != loadTail) {
39011147Smitch.hayenga@arm.com        assert(loadQueue[load_idx]);
39111147Smitch.hayenga@arm.com
392334SN/A        if (loadQueue[load_idx]->readyToIssue()) {
393334SN/A            ++retval;
394334SN/A        }
39510905Sandreas.sandberg@arm.com    }
3962SN/A
3979448SAndreas.Sandberg@ARM.com    return retval;
3989448SAndreas.Sandberg@ARM.com}
39911147Smitch.hayenga@arm.com
4002SN/Atemplate <class Impl>
4012SN/AFault
4022SN/ALSQUnit<Impl>::executeLoad(DynInstPtr &inst)
40310905Sandreas.sandberg@arm.com{
4042SN/A    // Execute a specific load.
40511147Smitch.hayenga@arm.com    Fault load_fault = NoFault;
4062SN/A
4072SN/A    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
4082SN/A            inst->readPC(),inst->seqNum);
4096221Snate@binkert.org
4102SN/A    load_fault = inst->initiateAcc();
4112SN/A
4122SN/A    // If the instruction faulted, then we need to send it along to commit
4132SN/A    // without the instruction completing.
4142623SN/A    if (load_fault != NoFault) {
4152SN/A        // Send this instruction to commit, also make sure iew stage
41611147Smitch.hayenga@arm.com        // realizes there is activity.
4172SN/A        // Mark it as executed unless it is an uncached load that
4182SN/A        // needs to hit the head of commit.
4192SN/A        if (!(inst->req->getFlags() & UNCACHEABLE) || inst->isAtCommit()) {
42011151Smitch.hayenga@arm.com            inst->setExecuted();
4212SN/A        }
42211151Smitch.hayenga@arm.com        iewStage->instToCommit(inst);
42311151Smitch.hayenga@arm.com        iewStage->activityThisCycle();
42411151Smitch.hayenga@arm.com    }
42511151Smitch.hayenga@arm.com
42611151Smitch.hayenga@arm.com    return load_fault;
42711147Smitch.hayenga@arm.com}
4282SN/A
4292SN/Atemplate <class Impl>
4302SN/AFault
4312623SN/ALSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
4322SN/A{
43311147Smitch.hayenga@arm.com    using namespace TheISA;
43411147Smitch.hayenga@arm.com    // Make sure that a store exists.
43511147Smitch.hayenga@arm.com    assert(stores != 0);
43611147Smitch.hayenga@arm.com
4375704Snate@binkert.org    int store_idx = store_inst->sqIdx;
43811150Smitch.hayenga@arm.com
4392SN/A    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
4403520Sgblack@eecs.umich.edu            store_inst->readPC(), store_inst->seqNum);
44111147Smitch.hayenga@arm.com
44211150Smitch.hayenga@arm.com    // Check the recently completed loads to see if any match this store's
4433520Sgblack@eecs.umich.edu    // address.  If so, then we have a memory ordering violation.
4449023Sgblack@eecs.umich.edu    int load_idx = store_inst->lqIdx;
4452SN/A
4462SN/A    Fault store_fault = store_inst->initiateAcc();
4472623SN/A
4482SN/A    if (storeQueue[store_idx].size == 0) {
4492623SN/A        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
4505894Sgblack@eecs.umich.edu                store_inst->readPC(),store_inst->seqNum);
4512662Sstever@eecs.umich.edu
4522623SN/A        return store_fault;
45311147Smitch.hayenga@arm.com    }
45411147Smitch.hayenga@arm.com
45511147Smitch.hayenga@arm.com    assert(store_fault == NoFault);
4567720Sgblack@eecs.umich.edu
4574495Sacolyte@umich.edu    if (store_inst->isStoreConditional()) {
4582623SN/A        // Store conditionals need to set themselves as able to
4597720Sgblack@eecs.umich.edu        // writeback if we haven't had a fault by here.
4602623SN/A        storeQueue[store_idx].canWB = true;
46111147Smitch.hayenga@arm.com
4628832SAli.Saidi@ARM.com        ++storesToWB;
4638832SAli.Saidi@ARM.com    }
4642623SN/A
4652623SN/A    if (!memDepViolator) {
4662623SN/A        while (load_idx != loadTail) {
4672623SN/A            // Really only need to check loads that have actually executed
4682623SN/A            // It's safe to check all loads because effAddr is set to
4692623SN/A            // InvalAddr when the dyn inst is created.
47011147Smitch.hayenga@arm.com
47111147Smitch.hayenga@arm.com            // @todo: For now this is extra conservative, detecting a
47211147Smitch.hayenga@arm.com            // violation if the addresses match assuming all accesses
4732SN/A            // are quad word accesses.
4742683Sktlim@umich.edu
4752427SN/A            // @todo: Fix this, magic number being used here
4762683Sktlim@umich.edu            if ((loadQueue[load_idx]->effAddr >> 8) ==
4772427SN/A                (store_inst->effAddr >> 8)) {
4782SN/A                // A load incorrectly passed this store.  Squash and refetch.
4792623SN/A                // For now return a fault to show that it was unsuccessful.
48011147Smitch.hayenga@arm.com                memDepViolator = loadQueue[load_idx];
4817897Shestness@cs.utexas.edu                ++lsqMemOrderViolation;
4822SN/A
4832623SN/A                return genMachineCheckFault();
4842623SN/A            }
4854377Sgblack@eecs.umich.edu
4867720Sgblack@eecs.umich.edu            incrLdIdx(load_idx);
4874377Sgblack@eecs.umich.edu        }
4887720Sgblack@eecs.umich.edu
48911147Smitch.hayenga@arm.com        // If we've reached this point, there was no violation.
4907720Sgblack@eecs.umich.edu        memDepViolator = NULL;
4917720Sgblack@eecs.umich.edu    }
4925665Sgblack@eecs.umich.edu
4935665Sgblack@eecs.umich.edu    return store_fault;
4944181Sgblack@eecs.umich.edu}
4954181Sgblack@eecs.umich.edu
4969023Sgblack@eecs.umich.edutemplate <class Impl>
4979023Sgblack@eecs.umich.eduvoid
4984181Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad()
4994182Sgblack@eecs.umich.edu{
50011147Smitch.hayenga@arm.com    assert(loadQueue[loadHead]);
50111321Ssteve.reinhardt@amd.com
5029023Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
5034593Sgblack@eecs.umich.edu            loadQueue[loadHead]->readPC());
5049023Sgblack@eecs.umich.edu
5054377Sgblack@eecs.umich.edu    loadQueue[loadHead] = NULL;
5069023Sgblack@eecs.umich.edu
5074377Sgblack@eecs.umich.edu    incrLdIdx(loadHead);
5089023Sgblack@eecs.umich.edu
5099023Sgblack@eecs.umich.edu    --loads;
51011147Smitch.hayenga@arm.com}
5117720Sgblack@eecs.umich.edu
5124377Sgblack@eecs.umich.edutemplate <class Impl>
51311147Smitch.hayenga@arm.comvoid
51411147Smitch.hayenga@arm.comLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
5154377Sgblack@eecs.umich.edu{
5164181Sgblack@eecs.umich.edu    assert(loads == 0 || loadQueue[loadHead]);
5174181Sgblack@eecs.umich.edu
5184181Sgblack@eecs.umich.edu    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
5194539Sgblack@eecs.umich.edu        commitLoad();
5203276Sgblack@eecs.umich.edu    }
52111147Smitch.hayenga@arm.com}
52211147Smitch.hayenga@arm.com
5233280Sgblack@eecs.umich.edutemplate <class Impl>
5243280Sgblack@eecs.umich.eduvoid
5253276Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
5263276Sgblack@eecs.umich.edu{
5273276Sgblack@eecs.umich.edu    assert(stores == 0 || storeQueue[storeHead].inst);
5287720Sgblack@eecs.umich.edu
5293276Sgblack@eecs.umich.edu    int store_idx = storeHead;
5303276Sgblack@eecs.umich.edu
5314181Sgblack@eecs.umich.edu    while (store_idx != storeTail) {
5328955Sgblack@eecs.umich.edu        assert(storeQueue[store_idx].inst);
5334522Ssaidi@eecs.umich.edu        // Mark any stores that are now committed and have not yet
53411147Smitch.hayenga@arm.com        // been marked as able to write back.
5357720Sgblack@eecs.umich.edu        if (!storeQueue[store_idx].canWB) {
5362470SN/A            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
5378955Sgblack@eecs.umich.edu                break;
5384181Sgblack@eecs.umich.edu            }
5394522Ssaidi@eecs.umich.edu            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
5404181Sgblack@eecs.umich.edu                    "%#x [sn:%lli]\n",
54110061Sandreas@sandberg.pp.se                    storeQueue[store_idx].inst->readPC(),
54211147Smitch.hayenga@arm.com                    storeQueue[store_idx].inst->seqNum);
54311147Smitch.hayenga@arm.com
54410061Sandreas@sandberg.pp.se            storeQueue[store_idx].canWB = true;
54510061Sandreas@sandberg.pp.se
54610061Sandreas@sandberg.pp.se            ++storesToWB;
54711147Smitch.hayenga@arm.com        }
54810061Sandreas@sandberg.pp.se
54911147Smitch.hayenga@arm.com        incrStIdx(store_idx);
55011147Smitch.hayenga@arm.com    }
55110061Sandreas@sandberg.pp.se}
55210061Sandreas@sandberg.pp.se
55311147Smitch.hayenga@arm.comtemplate <class Impl>
55410061Sandreas@sandberg.pp.sevoid
5552623SN/ALSQUnit<Impl>::writebackStores()
5562623SN/A{
5572623SN/A    while (storesToWB > 0 &&
5582623SN/A           storeWBIdx != storeTail &&
5592623SN/A           storeQueue[storeWBIdx].inst &&
56011147Smitch.hayenga@arm.com           storeQueue[storeWBIdx].canWB &&
56111147Smitch.hayenga@arm.com           usedPorts < cachePorts) {
56211147Smitch.hayenga@arm.com
5637720Sgblack@eecs.umich.edu        if (isStoreBlocked || lsq->cacheBlocked()) {
5647720Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
56511147Smitch.hayenga@arm.com                    " is blocked!\n");
5667720Sgblack@eecs.umich.edu            break;
5678780Sgblack@eecs.umich.edu        }
56811147Smitch.hayenga@arm.com
5697720Sgblack@eecs.umich.edu        // Store didn't write any data so no need to write it back to
57011147Smitch.hayenga@arm.com        // memory.
57111147Smitch.hayenga@arm.com        if (storeQueue[storeWBIdx].size == 0) {
5722623SN/A            completeStore(storeWBIdx);
5732683Sktlim@umich.edu
5742623SN/A            incrStIdx(storeWBIdx);
5752SN/A
5762623SN/A            continue;
57711147Smitch.hayenga@arm.com        }
5782SN/A
5792SN/A        ++usedPorts;
5802623SN/A
58111147Smitch.hayenga@arm.com        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
58211147Smitch.hayenga@arm.com            incrStIdx(storeWBIdx);
5832623SN/A
5842SN/A            continue;
5855953Ssaidi@eecs.umich.edu        }
58611147Smitch.hayenga@arm.com
5875953Ssaidi@eecs.umich.edu        assert(storeQueue[storeWBIdx].req);
5885953Ssaidi@eecs.umich.edu        assert(!storeQueue[storeWBIdx].committed);
58910061Sandreas@sandberg.pp.se
59011147Smitch.hayenga@arm.com        DynInstPtr inst = storeQueue[storeWBIdx].inst;
59110061Sandreas@sandberg.pp.se
59210061Sandreas@sandberg.pp.se        Request *req = storeQueue[storeWBIdx].req;
5937897Shestness@cs.utexas.edu        storeQueue[storeWBIdx].committed = true;
5947897Shestness@cs.utexas.edu
5957897Shestness@cs.utexas.edu        assert(!inst->memData);
59611147Smitch.hayenga@arm.com        inst->memData = new uint8_t[64];
59711147Smitch.hayenga@arm.com        memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data,
5987897Shestness@cs.utexas.edu               req->getSize());
5997897Shestness@cs.utexas.edu
6007897Shestness@cs.utexas.edu        PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
6017897Shestness@cs.utexas.edu        data_pkt->dataStatic(inst->memData);
60211147Smitch.hayenga@arm.com
60311147Smitch.hayenga@arm.com        LSQSenderState *state = new LSQSenderState;
6047897Shestness@cs.utexas.edu        state->isLoad = false;
60511147Smitch.hayenga@arm.com        state->idx = storeWBIdx;
6067897Shestness@cs.utexas.edu        state->inst = inst;
6077897Shestness@cs.utexas.edu        data_pkt->senderState = state;
60811147Smitch.hayenga@arm.com
6097897Shestness@cs.utexas.edu        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
61011147Smitch.hayenga@arm.com                "to Addr:%#x, data:%#x [sn:%lli]\n",
6117897Shestness@cs.utexas.edu                storeWBIdx, inst->readPC(),
6127897Shestness@cs.utexas.edu                req->getPaddr(), *(inst->memData),
61311147Smitch.hayenga@arm.com                inst->seqNum);
6147897Shestness@cs.utexas.edu
61511147Smitch.hayenga@arm.com        // @todo: Remove this SC hack once the memory system handles it.
6167897Shestness@cs.utexas.edu        if (req->getFlags() & LOCKED) {
6177897Shestness@cs.utexas.edu            if (req->getFlags() & UNCACHEABLE) {
61811147Smitch.hayenga@arm.com                req->setScResult(2);
6197897Shestness@cs.utexas.edu            } else {
62011147Smitch.hayenga@arm.com                if (cpu->lockFlag) {
6217897Shestness@cs.utexas.edu                    req->setScResult(1);
62211147Smitch.hayenga@arm.com                    DPRINTF(LSQUnit, "Store conditional [sn:%lli] succeeded.",
6237897Shestness@cs.utexas.edu                            inst->seqNum);
6247897Shestness@cs.utexas.edu                } else {
6257897Shestness@cs.utexas.edu                    req->setScResult(0);
62611147Smitch.hayenga@arm.com                    // Hack: Instantly complete this store.
62710193SCurtis.Dunham@arm.com//                    completeDataAccess(data_pkt);
6288780Sgblack@eecs.umich.edu                    DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed.  "
6298780Sgblack@eecs.umich.edu                            "Instantly completing it.\n",
6302644Sstever@eecs.umich.edu                            inst->seqNum);
6312644Sstever@eecs.umich.edu                    WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
6324046Sbinkertn@umich.edu                    wb->schedule(curTick + 1);
6334046Sbinkertn@umich.edu                    delete state;
6344046Sbinkertn@umich.edu                    completeStore(storeWBIdx);
6352644Sstever@eecs.umich.edu                    incrStIdx(storeWBIdx);
63610464SAndreas.Sandberg@ARM.com                    continue;
63710464SAndreas.Sandberg@ARM.com                }
63810464SAndreas.Sandberg@ARM.com            }
6392623SN/A        } else {
6402SN/A            // Non-store conditionals do not need a writeback.
6412623SN/A            state->noWB = true;
64210379Sandreas.hansson@arm.com        }
6432623SN/A
64411147Smitch.hayenga@arm.com        if (!dcachePort->sendTiming(data_pkt)) {
64511147Smitch.hayenga@arm.com            if (data_pkt->result == Packet::BadAddress) {
64611147Smitch.hayenga@arm.com                panic("LSQ sent out a bad address for a completed store!");
64710061Sandreas@sandberg.pp.se            }
64810061Sandreas@sandberg.pp.se            // Need to handle becoming blocked on a store.
6494377Sgblack@eecs.umich.edu            DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will"
65011147Smitch.hayenga@arm.com                    "retry later\n",
6512090SN/A                    inst->seqNum);
6523905Ssaidi@eecs.umich.edu            isStoreBlocked = true;
65311147Smitch.hayenga@arm.com            ++lsqCacheBlocked;
6549023Sgblack@eecs.umich.edu            assert(retryPkt == NULL);
6554377Sgblack@eecs.umich.edu            retryPkt = data_pkt;
6567720Sgblack@eecs.umich.edu            lsq->setRetryTid(lsqID);
6577720Sgblack@eecs.umich.edu        } else {
6587720Sgblack@eecs.umich.edu            storePostSend(data_pkt);
6597720Sgblack@eecs.umich.edu        }
6607720Sgblack@eecs.umich.edu    }
6617720Sgblack@eecs.umich.edu
6623276Sgblack@eecs.umich.edu    // Not sure this should set it to 0.
6632SN/A    usedPorts = 0;
66410061Sandreas@sandberg.pp.se
66510061Sandreas@sandberg.pp.se    assert(stores >= 0 && storesToWB >= 0);
66610061Sandreas@sandberg.pp.se}
66710061Sandreas@sandberg.pp.se
66810061Sandreas@sandberg.pp.se/*template <class Impl>
66910061Sandreas@sandberg.pp.sevoid
67011147Smitch.hayenga@arm.comLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
67110061Sandreas@sandberg.pp.se{
67211147Smitch.hayenga@arm.com    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
67310061Sandreas@sandberg.pp.se                                              mshrSeqNums.end(),
67410061Sandreas@sandberg.pp.se                                              seqNum);
67511147Smitch.hayenga@arm.com
67611147Smitch.hayenga@arm.com    if (mshr_it != mshrSeqNums.end()) {
67710061Sandreas@sandberg.pp.se        mshrSeqNums.erase(mshr_it);
67810061Sandreas@sandberg.pp.se        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
6792SN/A    }
6802SN/A}*/
6819461Snilay@cs.wisc.edu
6829461Snilay@cs.wisc.edutemplate <class Impl>
6839461Snilay@cs.wisc.eduvoid
6849461Snilay@cs.wisc.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
68511147Smitch.hayenga@arm.com{
68611147Smitch.hayenga@arm.com    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
6879461Snilay@cs.wisc.edu            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
688
689    int load_idx = loadTail;
690    decrLdIdx(load_idx);
691
692    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
693        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
694                "[sn:%lli]\n",
695                loadQueue[load_idx]->readPC(),
696                loadQueue[load_idx]->seqNum);
697
698        if (isStalled() && load_idx == stallingLoadIdx) {
699            stalled = false;
700            stallingStoreIsn = 0;
701            stallingLoadIdx = 0;
702        }
703
704        // Clear the smart pointer to make sure it is decremented.
705        loadQueue[load_idx]->setSquashed();
706        loadQueue[load_idx] = NULL;
707        --loads;
708
709        // Inefficient!
710        loadTail = load_idx;
711
712        decrLdIdx(load_idx);
713        ++lsqSquashedLoads;
714    }
715
716    if (isLoadBlocked) {
717        if (squashed_num < blockedLoadSeqNum) {
718            isLoadBlocked = false;
719            loadBlockedHandled = false;
720            blockedLoadSeqNum = 0;
721        }
722    }
723
724    int store_idx = storeTail;
725    decrStIdx(store_idx);
726
727    while (stores != 0 &&
728           storeQueue[store_idx].inst->seqNum > squashed_num) {
729        // Instructions marked as can WB are already committed.
730        if (storeQueue[store_idx].canWB) {
731            break;
732        }
733
734        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
735                "idx:%i [sn:%lli]\n",
736                storeQueue[store_idx].inst->readPC(),
737                store_idx, storeQueue[store_idx].inst->seqNum);
738
739        // I don't think this can happen.  It should have been cleared
740        // by the stalling load.
741        if (isStalled() &&
742            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
743            panic("Is stalled should have been cleared by stalling load!\n");
744            stalled = false;
745            stallingStoreIsn = 0;
746        }
747
748        // Clear the smart pointer to make sure it is decremented.
749        storeQueue[store_idx].inst->setSquashed();
750        storeQueue[store_idx].inst = NULL;
751        storeQueue[store_idx].canWB = 0;
752
753        storeQueue[store_idx].req = NULL;
754        --stores;
755
756        // Inefficient!
757        storeTail = store_idx;
758
759        decrStIdx(store_idx);
760        ++lsqSquashedStores;
761    }
762}
763
764template <class Impl>
765void
766LSQUnit<Impl>::storePostSend(Packet *pkt)
767{
768    if (isStalled() &&
769        storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
770        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
771                "load idx:%i\n",
772                stallingStoreIsn, stallingLoadIdx);
773        stalled = false;
774        stallingStoreIsn = 0;
775        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
776    }
777
778    if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
779        // The store is basically completed at this time. This
780        // only works so long as the checker doesn't try to
781        // verify the value in memory for stores.
782        storeQueue[storeWBIdx].inst->setCompleted();
783#if USE_CHECKER
784        if (cpu->checker) {
785            cpu->checker->verify(storeQueue[storeWBIdx].inst);
786        }
787#endif
788    }
789
790    if (pkt->result != Packet::Success) {
791        DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
792                storeWBIdx);
793
794        DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
795                storeQueue[storeWBIdx].inst->seqNum);
796
797        //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
798
799        //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
800
801        // @todo: Increment stat here.
802    } else {
803        DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
804                storeWBIdx);
805
806        DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
807                storeQueue[storeWBIdx].inst->seqNum);
808    }
809
810    incrStIdx(storeWBIdx);
811}
812
813template <class Impl>
814void
815LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
816{
817    iewStage->wakeCPU();
818
819    // Squashed instructions do not need to complete their access.
820    if (inst->isSquashed()) {
821        iewStage->decrWb(inst->seqNum);
822        assert(!inst->isStore());
823        ++lsqIgnoredResponses;
824        return;
825    }
826
827    if (!inst->isExecuted()) {
828        inst->setExecuted();
829
830        // Complete access to copy data to proper place.
831        inst->completeAcc(pkt);
832    }
833
834    // Need to insert instruction into queue to commit
835    iewStage->instToCommit(inst);
836
837    iewStage->activityThisCycle();
838}
839
840template <class Impl>
841void
842LSQUnit<Impl>::completeStore(int store_idx)
843{
844    assert(storeQueue[store_idx].inst);
845    storeQueue[store_idx].completed = true;
846    --storesToWB;
847    // A bit conservative because a store completion may not free up entries,
848    // but hopefully avoids two store completions in one cycle from making
849    // the CPU tick twice.
850    cpu->wakeCPU();
851    cpu->activityThisCycle();
852
853    if (store_idx == storeHead) {
854        do {
855            incrStIdx(storeHead);
856
857            --stores;
858        } while (storeQueue[storeHead].completed &&
859                 storeHead != storeTail);
860
861        iewStage->updateLSQNextCycle = true;
862    }
863
864    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
865            "idx:%i\n",
866            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
867
868    if (isStalled() &&
869        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
870        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
871                "load idx:%i\n",
872                stallingStoreIsn, stallingLoadIdx);
873        stalled = false;
874        stallingStoreIsn = 0;
875        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
876    }
877
878    storeQueue[store_idx].inst->setCompleted();
879
880    // Tell the checker we've completed this instruction.  Some stores
881    // may get reported twice to the checker, but the checker can
882    // handle that case.
883#if USE_CHECKER
884    if (cpu->checker) {
885        cpu->checker->verify(storeQueue[store_idx].inst);
886    }
887#endif
888}
889
890template <class Impl>
891void
892LSQUnit<Impl>::recvRetry()
893{
894    if (isStoreBlocked) {
895        assert(retryPkt != NULL);
896
897        if (dcachePort->sendTiming(retryPkt)) {
898            if (retryPkt->result == Packet::BadAddress) {
899                panic("LSQ sent out a bad address for a completed store!");
900            }
901            storePostSend(retryPkt);
902            retryPkt = NULL;
903            isStoreBlocked = false;
904            lsq->setRetryTid(-1);
905        } else {
906            // Still blocked!
907            ++lsqCacheBlocked;
908            lsq->setRetryTid(lsqID);
909        }
910    } else if (isLoadBlocked) {
911        DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
912                "no need to resend packet.\n");
913    } else {
914        DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n");
915    }
916}
917
918template <class Impl>
919inline void
920LSQUnit<Impl>::incrStIdx(int &store_idx)
921{
922    if (++store_idx >= SQEntries)
923        store_idx = 0;
924}
925
926template <class Impl>
927inline void
928LSQUnit<Impl>::decrStIdx(int &store_idx)
929{
930    if (--store_idx < 0)
931        store_idx += SQEntries;
932}
933
934template <class Impl>
935inline void
936LSQUnit<Impl>::incrLdIdx(int &load_idx)
937{
938    if (++load_idx >= LQEntries)
939        load_idx = 0;
940}
941
942template <class Impl>
943inline void
944LSQUnit<Impl>::decrLdIdx(int &load_idx)
945{
946    if (--load_idx < 0)
947        load_idx += LQEntries;
948}
949
950template <class Impl>
951void
952LSQUnit<Impl>::dumpInsts()
953{
954    cprintf("Load store queue: Dumping instructions.\n");
955    cprintf("Load queue size: %i\n", loads);
956    cprintf("Load queue: ");
957
958    int load_idx = loadHead;
959
960    while (load_idx != loadTail && loadQueue[load_idx]) {
961        cprintf("%#x ", loadQueue[load_idx]->readPC());
962
963        incrLdIdx(load_idx);
964    }
965
966    cprintf("Store queue size: %i\n", stores);
967    cprintf("Store queue: ");
968
969    int store_idx = storeHead;
970
971    while (store_idx != storeTail && storeQueue[store_idx].inst) {
972        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
973
974        incrStIdx(store_idx);
975    }
976
977    cprintf("\n");
978}
979