lsq_unit_impl.hh revision 2361
16657Snate@binkert.org/*
26657Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan
36657Snate@binkert.org * All rights reserved.
46657Snate@binkert.org *
56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without
66657Snate@binkert.org * modification, are permitted provided that the following conditions are
76657Snate@binkert.org * met: redistributions of source code must retain the above copyright
86657Snate@binkert.org * notice, this list of conditions and the following disclaimer;
96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright
106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
116657Snate@binkert.org * documentation and/or other materials provided with the distribution;
126657Snate@binkert.org * neither the name of the copyright holders nor the names of its
136657Snate@binkert.org * contributors may be used to endorse or promote products derived from
146657Snate@binkert.org * this software without specific prior written permission.
156657Snate@binkert.org *
166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276657Snate@binkert.org */
286999Snate@binkert.org
296657Snate@binkert.org#include "cpu/checker/cpu.hh"
306657Snate@binkert.org#include "cpu/o3/lsq_unit.hh"
316657Snate@binkert.org#include "base/str.hh"
329302Snilay@cs.wisc.edu
336657Snate@binkert.orgtemplate <class Impl>
346657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
356657Snate@binkert.org                                                          Event *wb_event,
366657Snate@binkert.org                                                          LSQUnit<Impl> *lsq_ptr)
376657Snate@binkert.org    : Event(&mainEventQueue),
386657Snate@binkert.org      wbEvent(wb_event),
396657Snate@binkert.org      storeIdx(store_idx),
406657Snate@binkert.org      lsqPtr(lsq_ptr)
416657Snate@binkert.org{
426657Snate@binkert.org    this->setFlags(Event::AutoDelete);
436657Snate@binkert.org}
446657Snate@binkert.org
456657Snate@binkert.orgtemplate <class Impl>
466657Snate@binkert.orgvoid
476657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::process()
486657Snate@binkert.org{
496657Snate@binkert.org    DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
506657Snate@binkert.org    DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
516657Snate@binkert.org
526657Snate@binkert.org    //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
536657Snate@binkert.org
546657Snate@binkert.org    if (lsqPtr->isSwitchedOut()) {
556882SBrad.Beckmann@amd.com        if (wbEvent)
566657Snate@binkert.org            delete wbEvent;
576657Snate@binkert.org
586657Snate@binkert.org        return;
596657Snate@binkert.org    }
606657Snate@binkert.org
616657Snate@binkert.org    lsqPtr->cpu->wakeCPU();
626657Snate@binkert.org    if (wbEvent) {
636657Snate@binkert.org        wbEvent->process();
646657Snate@binkert.org        delete wbEvent;
656657Snate@binkert.org    }
666657Snate@binkert.org    lsqPtr->completeStore(storeIdx);
676657Snate@binkert.org}
686657Snate@binkert.org
696657Snate@binkert.orgtemplate <class Impl>
706657Snate@binkert.orgconst char *
716657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::description()
726657Snate@binkert.org{
736657Snate@binkert.org    return "LSQ store completion event";
746657Snate@binkert.org}
756657Snate@binkert.org
766657Snate@binkert.orgtemplate <class Impl>
776657Snate@binkert.orgLSQUnit<Impl>::LSQUnit()
786657Snate@binkert.org    : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
796657Snate@binkert.org      loadBlockedHandled(false)
806657Snate@binkert.org{
816657Snate@binkert.org}
826657Snate@binkert.org
836657Snate@binkert.orgtemplate<class Impl>
846657Snate@binkert.orgvoid
856657Snate@binkert.orgLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
866657Snate@binkert.org                    unsigned maxSQEntries, unsigned id)
876657Snate@binkert.org
886657Snate@binkert.org{
896657Snate@binkert.org    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
906657Snate@binkert.org
916657Snate@binkert.org    switchedOut = false;
926657Snate@binkert.org
936657Snate@binkert.org    lsqID = id;
946657Snate@binkert.org
956657Snate@binkert.org    // Add 1 for the sentinel entry (they are circular queues).
966657Snate@binkert.org    LQEntries = maxLQEntries + 1;
976657Snate@binkert.org    SQEntries = maxSQEntries + 1;
986657Snate@binkert.org
996657Snate@binkert.org    loadQueue.resize(LQEntries);
1006657Snate@binkert.org    storeQueue.resize(SQEntries);
1016657Snate@binkert.org
1026657Snate@binkert.org    loadHead = loadTail = 0;
1036657Snate@binkert.org
1048086SBrad.Beckmann@amd.com    storeHead = storeWBIdx = storeTail = 0;
1058086SBrad.Beckmann@amd.com
1068086SBrad.Beckmann@amd.com    usedPorts = 0;
1076657Snate@binkert.org    cachePorts = params->cachePorts;
1086657Snate@binkert.org
1096657Snate@binkert.org    dcacheInterface = params->dcacheInterface;
1106657Snate@binkert.org
1119298Snilay@cs.wisc.edu    memDepViolator = NULL;
1126657Snate@binkert.org
1136657Snate@binkert.org    blockedLoadSeqNum = 0;
1146657Snate@binkert.org}
1156657Snate@binkert.org
1166657Snate@binkert.orgtemplate<class Impl>
1176657Snate@binkert.orgstd::string
1186657Snate@binkert.orgLSQUnit<Impl>::name() const
1196657Snate@binkert.org{
1206657Snate@binkert.org    if (Impl::MaxThreads == 1) {
1216657Snate@binkert.org        return iewStage->name() + ".lsq";
1226657Snate@binkert.org    } else {
1236657Snate@binkert.org        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
1246657Snate@binkert.org    }
1256657Snate@binkert.org}
1266657Snate@binkert.org
1276657Snate@binkert.orgtemplate<class Impl>
1286657Snate@binkert.orgvoid
1296657Snate@binkert.orgLSQUnit<Impl>::regStats()
1306657Snate@binkert.org{
1316657Snate@binkert.org    lsqForwLoads
1326657Snate@binkert.org        .name(name() + ".forwLoads")
1336657Snate@binkert.org        .desc("Number of loads that had data forwarded from stores");
1346657Snate@binkert.org
1356657Snate@binkert.org    invAddrLoads
1366657Snate@binkert.org        .name(name() + ".invAddrLoads")
1376657Snate@binkert.org        .desc("Number of loads ignored due to an invalid address");
1386657Snate@binkert.org
1396657Snate@binkert.org    lsqSquashedLoads
1406657Snate@binkert.org        .name(name() + ".squashedLoads")
1416657Snate@binkert.org        .desc("Number of loads squashed");
1426657Snate@binkert.org
1436657Snate@binkert.org    lsqIgnoredResponses
1446657Snate@binkert.org        .name(name() + ".ignoredResponses")
1456657Snate@binkert.org        .desc("Number of memory responses ignored because the instruction is squashed");
1466657Snate@binkert.org
1476657Snate@binkert.org    lsqMemOrderViolation
1489298Snilay@cs.wisc.edu        .name(name() + ".memOrderViolation")
1496657Snate@binkert.org        .desc("Number of memory ordering violations");
1506657Snate@binkert.org
1516657Snate@binkert.org    lsqSquashedStores
1526657Snate@binkert.org        .name(name() + ".squashedStores")
1536657Snate@binkert.org        .desc("Number of stores squashed");
1546657Snate@binkert.org
1559302Snilay@cs.wisc.edu    invAddrSwpfs
1569302Snilay@cs.wisc.edu        .name(name() + ".invAddrSwpfs")
1579302Snilay@cs.wisc.edu        .desc("Number of software prefetches ignored due to an invalid address");
1586657Snate@binkert.org
1596657Snate@binkert.org    lsqBlockedLoads
1606657Snate@binkert.org        .name(name() + ".blockedLoads")
1616657Snate@binkert.org        .desc("Number of blocked loads due to partial load-store forwarding");
1626657Snate@binkert.org
1636657Snate@binkert.org    lsqRescheduledLoads
1646657Snate@binkert.org        .name(name() + ".rescheduledLoads")
1656657Snate@binkert.org        .desc("Number of loads that were rescheduled");
1666882SBrad.Beckmann@amd.com
1676882SBrad.Beckmann@amd.com    lsqCacheBlocked
1686882SBrad.Beckmann@amd.com        .name(name() + ".cacheBlocked")
1698086SBrad.Beckmann@amd.com        .desc("Number of times an access to memory failed due to the cache being blocked");
1708086SBrad.Beckmann@amd.com}
1718086SBrad.Beckmann@amd.com
1729298Snilay@cs.wisc.edutemplate<class Impl>
1736657Snate@binkert.orgvoid
1746657Snate@binkert.orgLSQUnit<Impl>::clearLQ()
1756657Snate@binkert.org{
1766657Snate@binkert.org    loadQueue.clear();
1776657Snate@binkert.org}
1786657Snate@binkert.org
1796657Snate@binkert.orgtemplate<class Impl>
1809298Snilay@cs.wisc.eduvoid
1819298Snilay@cs.wisc.eduLSQUnit<Impl>::clearSQ()
1829298Snilay@cs.wisc.edu{
1839298Snilay@cs.wisc.edu    storeQueue.clear();
1849298Snilay@cs.wisc.edu}
1859298Snilay@cs.wisc.edu
1869298Snilay@cs.wisc.edu#if 0
1879298Snilay@cs.wisc.edutemplate<class Impl>
1889298Snilay@cs.wisc.eduvoid
1899298Snilay@cs.wisc.eduLSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
1909298Snilay@cs.wisc.edu{
1919298Snilay@cs.wisc.edu    DPRINTF(LSQUnit, "Setting the page table pointer.\n");
1926657Snate@binkert.org    pTable = pt_ptr;
1936657Snate@binkert.org}
1946657Snate@binkert.org#endif
1956657Snate@binkert.org
1966657Snate@binkert.orgtemplate<class Impl>
1976657Snate@binkert.orgvoid
1986657Snate@binkert.orgLSQUnit<Impl>::switchOut()
1996657Snate@binkert.org{
2006657Snate@binkert.org    switchedOut = true;
2016657Snate@binkert.org    for (int i = 0; i < loadQueue.size(); ++i)
2026657Snate@binkert.org        loadQueue[i] = NULL;
2039219Spower.jg@gmail.com
2046657Snate@binkert.org    assert(storesToWB == 0);
2056657Snate@binkert.org
2066657Snate@binkert.org    while (storesToWB > 0 &&
2076657Snate@binkert.org           storeWBIdx != storeTail &&
2086657Snate@binkert.org           storeQueue[storeWBIdx].inst &&
2096657Snate@binkert.org           storeQueue[storeWBIdx].canWB) {
2106657Snate@binkert.org
2116657Snate@binkert.org        if (storeQueue[storeWBIdx].size == 0 ||
2126657Snate@binkert.org            storeQueue[storeWBIdx].inst->isDataPrefetch() ||
2136657Snate@binkert.org            storeQueue[storeWBIdx].committed ||
2146657Snate@binkert.org            storeQueue[storeWBIdx].req->flags & LOCKED) {
2156657Snate@binkert.org            incrStIdx(storeWBIdx);
2166999Snate@binkert.org
2176657Snate@binkert.org            continue;
2186657Snate@binkert.org        }
2196657Snate@binkert.org
2206657Snate@binkert.org        assert(storeQueue[storeWBIdx].req);
2216657Snate@binkert.org        assert(!storeQueue[storeWBIdx].committed);
2226657Snate@binkert.org
2236657Snate@binkert.org        MemReqPtr req = storeQueue[storeWBIdx].req;
2247007Snate@binkert.org        storeQueue[storeWBIdx].committed = true;
2257007Snate@binkert.org
2266657Snate@binkert.org        req->cmd = Write;
2277002Snate@binkert.org        req->completionEvent = NULL;
2287002Snate@binkert.org        req->time = curTick;
2299466Snilay@cs.wisc.edu        assert(!req->data);
2306657Snate@binkert.org        req->data = new uint8_t[64];
2316657Snate@binkert.org        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
2326657Snate@binkert.org
2336657Snate@binkert.org        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
2346657Snate@binkert.org                "to Addr:%#x, data:%#x [sn:%lli]\n",
2356657Snate@binkert.org                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
2366657Snate@binkert.org                req->paddr, *(req->data),
2376657Snate@binkert.org                storeQueue[storeWBIdx].inst->seqNum);
2386657Snate@binkert.org
2396657Snate@binkert.org        switch(storeQueue[storeWBIdx].size) {
2406657Snate@binkert.org          case 1:
2416657Snate@binkert.org            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
2427007Snate@binkert.org            break;
2437007Snate@binkert.org          case 2:
2446657Snate@binkert.org            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
2459466Snilay@cs.wisc.edu            break;
2466657Snate@binkert.org          case 4:
2476657Snate@binkert.org            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
2489466Snilay@cs.wisc.edu            break;
2499508Snilay@cs.wisc.edu          case 8:
2509466Snilay@cs.wisc.edu            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
2519466Snilay@cs.wisc.edu            break;
2529466Snilay@cs.wisc.edu          default:
2536657Snate@binkert.org            panic("Unexpected store size!\n");
2546657Snate@binkert.org        }
2556657Snate@binkert.org        incrStIdx(storeWBIdx);
2566657Snate@binkert.org    }
2576657Snate@binkert.org}
2586657Snate@binkert.org
2596657Snate@binkert.orgtemplate<class Impl>
2606657Snate@binkert.orgvoid
2616657Snate@binkert.orgLSQUnit<Impl>::takeOverFrom()
2626657Snate@binkert.org{
2636657Snate@binkert.org    switchedOut = false;
2646657Snate@binkert.org    loads = stores = storesToWB = 0;
2656657Snate@binkert.org
2666657Snate@binkert.org    loadHead = loadTail = 0;
2676657Snate@binkert.org
2686657Snate@binkert.org    storeHead = storeWBIdx = storeTail = 0;
2696657Snate@binkert.org
2707453Snate@binkert.org    usedPorts = 0;
2717453Snate@binkert.org
2727453Snate@binkert.org    memDepViolator = NULL;
2737453Snate@binkert.org
2747453Snate@binkert.org    blockedLoadSeqNum = 0;
2757453Snate@binkert.org
2767453Snate@binkert.org    stalled = false;
2777453Snate@binkert.org    isLoadBlocked = false;
2787453Snate@binkert.org    loadBlockedHandled = false;
2797453Snate@binkert.org}
2807453Snate@binkert.org
2817453Snate@binkert.orgtemplate<class Impl>
2827453Snate@binkert.orgvoid
2837453Snate@binkert.orgLSQUnit<Impl>::resizeLQ(unsigned size)
2847453Snate@binkert.org{
2857453Snate@binkert.org    unsigned size_plus_sentinel = size + 1;
2867453Snate@binkert.org    assert(size_plus_sentinel >= LQEntries);
2876657Snate@binkert.org
2886657Snate@binkert.org    if (size_plus_sentinel > LQEntries) {
2896657Snate@binkert.org        while (size_plus_sentinel > loadQueue.size()) {
2906657Snate@binkert.org            DynInstPtr dummy;
2919466Snilay@cs.wisc.edu            loadQueue.push_back(dummy);
2926657Snate@binkert.org            LQEntries++;
2939466Snilay@cs.wisc.edu        }
2949508Snilay@cs.wisc.edu    } else {
2959466Snilay@cs.wisc.edu        LQEntries = size_plus_sentinel;
2966657Snate@binkert.org    }
2976657Snate@binkert.org
2986657Snate@binkert.org}
2996657Snate@binkert.org
3009466Snilay@cs.wisc.edutemplate<class Impl>
3019466Snilay@cs.wisc.eduvoid
3029466Snilay@cs.wisc.eduLSQUnit<Impl>::resizeSQ(unsigned size)
3039466Snilay@cs.wisc.edu{
3046657Snate@binkert.org    unsigned size_plus_sentinel = size + 1;
3056657Snate@binkert.org    if (size_plus_sentinel > SQEntries) {
3066657Snate@binkert.org        while (size_plus_sentinel > storeQueue.size()) {
3076657Snate@binkert.org            SQEntry dummy;
3086657Snate@binkert.org            storeQueue.push_back(dummy);
3096657Snate@binkert.org            SQEntries++;
3106657Snate@binkert.org        }
3116657Snate@binkert.org    } else {
3126657Snate@binkert.org        SQEntries = size_plus_sentinel;
3136657Snate@binkert.org    }
3146657Snate@binkert.org}
3159466Snilay@cs.wisc.edu
3167453Snate@binkert.orgtemplate <class Impl>
3177453Snate@binkert.orgvoid
3187007Snate@binkert.orgLSQUnit<Impl>::insert(DynInstPtr &inst)
3197007Snate@binkert.org{
3207453Snate@binkert.org    assert(inst->isMemRef());
3217007Snate@binkert.org
3226657Snate@binkert.org    assert(inst->isLoad() || inst->isStore());
3236657Snate@binkert.org
3246657Snate@binkert.org    if (inst->isLoad()) {
3256657Snate@binkert.org        insertLoad(inst);
3266657Snate@binkert.org    } else {
3276657Snate@binkert.org        insertStore(inst);
3286657Snate@binkert.org    }
3296657Snate@binkert.org
3306657Snate@binkert.org    inst->setInLSQ();
3316657Snate@binkert.org}
3327007Snate@binkert.org
3337007Snate@binkert.orgtemplate <class Impl>
3347007Snate@binkert.orgvoid
3357007Snate@binkert.orgLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
3367007Snate@binkert.org{
3376657Snate@binkert.org    assert((loadTail + 1) % LQEntries != loadHead);
3386657Snate@binkert.org    assert(loads < LQEntries);
3396657Snate@binkert.org
3406657Snate@binkert.org    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
3416657Snate@binkert.org            load_inst->readPC(), loadTail, load_inst->seqNum);
3426657Snate@binkert.org
3436657Snate@binkert.org    load_inst->lqIdx = loadTail;
3446657Snate@binkert.org
3456657Snate@binkert.org    if (stores == 0) {
3467007Snate@binkert.org        load_inst->sqIdx = -1;
3477007Snate@binkert.org    } else {
3487007Snate@binkert.org        load_inst->sqIdx = storeTail;
3497007Snate@binkert.org    }
3507007Snate@binkert.org
3516657Snate@binkert.org    loadQueue[loadTail] = load_inst;
3526657Snate@binkert.org
3536657Snate@binkert.org    incrLdIdx(loadTail);
3546657Snate@binkert.org
3556657Snate@binkert.org    ++loads;
3566657Snate@binkert.org}
3576657Snate@binkert.org
3587007Snate@binkert.orgtemplate <class Impl>
3597007Snate@binkert.orgvoid
3607007Snate@binkert.orgLSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
3617007Snate@binkert.org{
3627007Snate@binkert.org    // Make sure it is not full before inserting an instruction.
3636657Snate@binkert.org    assert((storeTail + 1) % SQEntries != storeHead);
3646657Snate@binkert.org    assert(stores < SQEntries);
3657002Snate@binkert.org
3666657Snate@binkert.org    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
3676657Snate@binkert.org            store_inst->readPC(), storeTail, store_inst->seqNum);
3686657Snate@binkert.org
3696657Snate@binkert.org    store_inst->sqIdx = storeTail;
3706657Snate@binkert.org    store_inst->lqIdx = loadTail;
3716657Snate@binkert.org
3726657Snate@binkert.org    storeQueue[storeTail] = SQEntry(store_inst);
3736657Snate@binkert.org
3746657Snate@binkert.org    incrStIdx(storeTail);
3756657Snate@binkert.org
3766657Snate@binkert.org    ++stores;
3776657Snate@binkert.org}
3786657Snate@binkert.org
3796657Snate@binkert.orgtemplate <class Impl>
3806657Snate@binkert.orgtypename Impl::DynInstPtr
3816657Snate@binkert.orgLSQUnit<Impl>::getMemDepViolator()
3826657Snate@binkert.org{
3836657Snate@binkert.org    DynInstPtr temp = memDepViolator;
3846657Snate@binkert.org
3856657Snate@binkert.org    memDepViolator = NULL;
3866657Snate@binkert.org
3877007Snate@binkert.org    return temp;
3886657Snate@binkert.org}
3897007Snate@binkert.org
3906657Snate@binkert.orgtemplate <class Impl>
3919298Snilay@cs.wisc.eduunsigned
3929298Snilay@cs.wisc.eduLSQUnit<Impl>::numFreeEntries()
3939298Snilay@cs.wisc.edu{
3949298Snilay@cs.wisc.edu    unsigned free_lq_entries = LQEntries - loads;
3959298Snilay@cs.wisc.edu    unsigned free_sq_entries = SQEntries - stores;
3969298Snilay@cs.wisc.edu
3976657Snate@binkert.org    // Both the LQ and SQ entries have an extra dummy entry to differentiate
3986657Snate@binkert.org    // empty/full conditions.  Subtract 1 from the free entries.
3996657Snate@binkert.org    if (free_lq_entries < free_sq_entries) {
4006657Snate@binkert.org        return free_lq_entries - 1;
4017055Snate@binkert.org    } else {
4027007Snate@binkert.org        return free_sq_entries - 1;
4036657Snate@binkert.org    }
4046657Snate@binkert.org}
4057002Snate@binkert.org
4066657Snate@binkert.orgtemplate <class Impl>
4076657Snate@binkert.orgint
4086657Snate@binkert.orgLSQUnit<Impl>::numLoadsReady()
4097007Snate@binkert.org{
4106657Snate@binkert.org    int load_idx = loadHead;
4116657Snate@binkert.org    int retval = 0;
4126657Snate@binkert.org
4136657Snate@binkert.org    while (load_idx != loadTail) {
4146657Snate@binkert.org        assert(loadQueue[load_idx]);
4156999Snate@binkert.org
4166657Snate@binkert.org        if (loadQueue[load_idx]->readyToIssue()) {
4176657Snate@binkert.org            ++retval;
4186657Snate@binkert.org        }
4196657Snate@binkert.org    }
4206657Snate@binkert.org
4216657Snate@binkert.org    return retval;
4226657Snate@binkert.org}
4237002Snate@binkert.org
4247002Snate@binkert.orgtemplate <class Impl>
4256657Snate@binkert.orgFault
4269499Snilay@cs.wisc.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst)
4279499Snilay@cs.wisc.edu{
4287002Snate@binkert.org    // Execute a specific load.
4297002Snate@binkert.org    Fault load_fault = NoFault;
4306657Snate@binkert.org
4316657Snate@binkert.org    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
4326657Snate@binkert.org            inst->readPC(),inst->seqNum);
4336657Snate@binkert.org
4347007Snate@binkert.org//    load_fault = inst->initiateAcc();
4357007Snate@binkert.org    load_fault = inst->execute();
4366657Snate@binkert.org
4376657Snate@binkert.org    // If the instruction faulted, then we need to send it along to commit
4386657Snate@binkert.org    // without the instruction completing.
4396657Snate@binkert.org    if (load_fault != NoFault) {
4406657Snate@binkert.org        // Send this instruction to commit, also make sure iew stage
4416657Snate@binkert.org        // realizes there is activity.
4426657Snate@binkert.org        iewStage->instToCommit(inst);
4436657Snate@binkert.org        iewStage->activityThisCycle();
4446657Snate@binkert.org    }
4456657Snate@binkert.org
4469206Snilay@cs.wisc.edu    return load_fault;
4476657Snate@binkert.org}
4486657Snate@binkert.org
4496657Snate@binkert.orgtemplate <class Impl>
4506657Snate@binkert.orgFault
4516657Snate@binkert.orgLSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
4526657Snate@binkert.org{
4536657Snate@binkert.org    using namespace TheISA;
4549298Snilay@cs.wisc.edu    // Make sure that a store exists.
4559298Snilay@cs.wisc.edu    assert(stores != 0);
4569298Snilay@cs.wisc.edu
4579298Snilay@cs.wisc.edu    int store_idx = store_inst->sqIdx;
4586657Snate@binkert.org
4596657Snate@binkert.org    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
4606657Snate@binkert.org            store_inst->readPC(), store_inst->seqNum);
4616999Snate@binkert.org
4626657Snate@binkert.org    // Check the recently completed loads to see if any match this store's
4636657Snate@binkert.org    // address.  If so, then we have a memory ordering violation.
4646657Snate@binkert.org    int load_idx = store_inst->lqIdx;
4656657Snate@binkert.org
4666657Snate@binkert.org    Fault store_fault = store_inst->initiateAcc();
4677007Snate@binkert.org//    Fault store_fault = store_inst->execute();
4687007Snate@binkert.org
4697007Snate@binkert.org    if (storeQueue[store_idx].size == 0) {
4706657Snate@binkert.org        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
4717002Snate@binkert.org                store_inst->readPC(),store_inst->seqNum);
4727002Snate@binkert.org
4737002Snate@binkert.org        return store_fault;
4748086SBrad.Beckmann@amd.com    }
4758086SBrad.Beckmann@amd.com
4768086SBrad.Beckmann@amd.com    assert(store_fault == NoFault);
4778086SBrad.Beckmann@amd.com
4788602Snilay@cs.wisc.edu    if (store_inst->isStoreConditional()) {
4798602Snilay@cs.wisc.edu        // Store conditionals need to set themselves as able to
4808602Snilay@cs.wisc.edu        // writeback if we haven't had a fault by here.
4818602Snilay@cs.wisc.edu        storeQueue[store_idx].canWB = true;
4828602Snilay@cs.wisc.edu
4838602Snilay@cs.wisc.edu        ++storesToWB;
4848086SBrad.Beckmann@amd.com    }
4856657Snate@binkert.org
4867007Snate@binkert.org    if (!memDepViolator) {
4876657Snate@binkert.org        while (load_idx != loadTail) {
4886657Snate@binkert.org            // Really only need to check loads that have actually executed
4896657Snate@binkert.org            // It's safe to check all loads because effAddr is set to
4906657Snate@binkert.org            // InvalAddr when the dyn inst is created.
4916657Snate@binkert.org
4926657Snate@binkert.org            // @todo: For now this is extra conservative, detecting a
4936657Snate@binkert.org            // violation if the addresses match assuming all accesses
4946657Snate@binkert.org            // are quad word accesses.
4956657Snate@binkert.org
4966657Snate@binkert.org            // @todo: Fix this, magic number being used here
4976657Snate@binkert.org            if ((loadQueue[load_idx]->effAddr >> 8) ==
4986862Sdrh5@cs.wisc.edu                (store_inst->effAddr >> 8)) {
4996862Sdrh5@cs.wisc.edu                // A load incorrectly passed this store.  Squash and refetch.
5006862Sdrh5@cs.wisc.edu                // For now return a fault to show that it was unsuccessful.
5016862Sdrh5@cs.wisc.edu                memDepViolator = loadQueue[load_idx];
5026657Snate@binkert.org                ++lsqMemOrderViolation;
5036657Snate@binkert.org
5046657Snate@binkert.org                return genMachineCheckFault();
5056657Snate@binkert.org            }
5066657Snate@binkert.org
5077007Snate@binkert.org            incrLdIdx(load_idx);
5087007Snate@binkert.org        }
5097002Snate@binkert.org
5107007Snate@binkert.org        // If we've reached this point, there was no violation.
5117007Snate@binkert.org        memDepViolator = NULL;
5127002Snate@binkert.org    }
5137007Snate@binkert.org
5147007Snate@binkert.org    return store_fault;
5156657Snate@binkert.org}
5166657Snate@binkert.org
5176657Snate@binkert.orgtemplate <class Impl>
5186657Snate@binkert.orgvoid
5196657Snate@binkert.orgLSQUnit<Impl>::commitLoad()
5206657Snate@binkert.org{
5216657Snate@binkert.org    assert(loadQueue[loadHead]);
5226657Snate@binkert.org
5236657Snate@binkert.org    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
5246657Snate@binkert.org            loadQueue[loadHead]->readPC());
5256657Snate@binkert.org
5266657Snate@binkert.org    loadQueue[loadHead] = NULL;
5276657Snate@binkert.org
5288602Snilay@cs.wisc.edu    incrLdIdx(loadHead);
5298602Snilay@cs.wisc.edu
5308602Snilay@cs.wisc.edu    --loads;
5318602Snilay@cs.wisc.edu}
5328602Snilay@cs.wisc.edu
5338602Snilay@cs.wisc.edutemplate <class Impl>
5348602Snilay@cs.wisc.eduvoid
5358602Snilay@cs.wisc.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
5368602Snilay@cs.wisc.edu{
5378602Snilay@cs.wisc.edu    assert(loads == 0 || loadQueue[loadHead]);
5388602Snilay@cs.wisc.edu
5398602Snilay@cs.wisc.edu    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
5408602Snilay@cs.wisc.edu        commitLoad();
5418602Snilay@cs.wisc.edu    }
5428602Snilay@cs.wisc.edu}
5438602Snilay@cs.wisc.edu
5448602Snilay@cs.wisc.edutemplate <class Impl>
5458602Snilay@cs.wisc.eduvoid
5468602Snilay@cs.wisc.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
5478602Snilay@cs.wisc.edu{
5488602Snilay@cs.wisc.edu    assert(stores == 0 || storeQueue[storeHead].inst);
5498602Snilay@cs.wisc.edu
5508602Snilay@cs.wisc.edu    int store_idx = storeHead;
5516657Snate@binkert.org
5528086SBrad.Beckmann@amd.com    while (store_idx != storeTail) {
5538086SBrad.Beckmann@amd.com        assert(storeQueue[store_idx].inst);
5548086SBrad.Beckmann@amd.com        // Mark any stores that are now committed and have not yet
5558086SBrad.Beckmann@amd.com        // been marked as able to write back.
5568086SBrad.Beckmann@amd.com        if (!storeQueue[store_idx].canWB) {
5578086SBrad.Beckmann@amd.com            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
5588086SBrad.Beckmann@amd.com                break;
5598086SBrad.Beckmann@amd.com            }
5606657Snate@binkert.org            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
5616657Snate@binkert.org                    "%#x [sn:%lli]\n",
5627002Snate@binkert.org                    storeQueue[store_idx].inst->readPC(),
5636657Snate@binkert.org                    storeQueue[store_idx].inst->seqNum);
5647007Snate@binkert.org
5656657Snate@binkert.org            storeQueue[store_idx].canWB = true;
5666657Snate@binkert.org
5676657Snate@binkert.org            ++storesToWB;
5686657Snate@binkert.org        }
5696657Snate@binkert.org
5706999Snate@binkert.org        incrStIdx(store_idx);
5716657Snate@binkert.org    }
5726657Snate@binkert.org}
5736657Snate@binkert.org
5746657Snate@binkert.orgtemplate <class Impl>
5756657Snate@binkert.orgvoid
5766657Snate@binkert.orgLSQUnit<Impl>::writebackStores()
5777832Snate@binkert.org{
5787002Snate@binkert.org    while (storesToWB > 0 &&
5797002Snate@binkert.org           storeWBIdx != storeTail &&
5807002Snate@binkert.org           storeQueue[storeWBIdx].inst &&
5817805Snilay@cs.wisc.edu           storeQueue[storeWBIdx].canWB &&
5826657Snate@binkert.org           usedPorts < cachePorts) {
5836657Snate@binkert.org
5847002Snate@binkert.org        // Store didn't write any data so no need to write it back to
5857002Snate@binkert.org        // memory.
5866657Snate@binkert.org        if (storeQueue[storeWBIdx].size == 0) {
5876657Snate@binkert.org            completeStore(storeWBIdx);
5888086SBrad.Beckmann@amd.com
5898086SBrad.Beckmann@amd.com            incrStIdx(storeWBIdx);
5908086SBrad.Beckmann@amd.com
5918086SBrad.Beckmann@amd.com            continue;
5928086SBrad.Beckmann@amd.com        }
5938086SBrad.Beckmann@amd.com
5948086SBrad.Beckmann@amd.com        if (dcacheInterface && dcacheInterface->isBlocked()) {
5958086SBrad.Beckmann@amd.com            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
5968086SBrad.Beckmann@amd.com                    " is blocked!\n");
5978086SBrad.Beckmann@amd.com            ++lsqCacheBlocked;
5988086SBrad.Beckmann@amd.com            break;
5998086SBrad.Beckmann@amd.com        }
6008086SBrad.Beckmann@amd.com
6018086SBrad.Beckmann@amd.com        ++usedPorts;
6028086SBrad.Beckmann@amd.com
6038086SBrad.Beckmann@amd.com        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
6048086SBrad.Beckmann@amd.com            incrStIdx(storeWBIdx);
6058086SBrad.Beckmann@amd.com
6068086SBrad.Beckmann@amd.com            continue;
6078086SBrad.Beckmann@amd.com        }
6088086SBrad.Beckmann@amd.com
6096657Snate@binkert.org        assert(storeQueue[storeWBIdx].req);
6106657Snate@binkert.org        assert(!storeQueue[storeWBIdx].committed);
6116657Snate@binkert.org
6128602Snilay@cs.wisc.edu        MemReqPtr req = storeQueue[storeWBIdx].req;
6136657Snate@binkert.org        storeQueue[storeWBIdx].committed = true;
6146657Snate@binkert.org
6157007Snate@binkert.org        req->cmd = Write;
6167007Snate@binkert.org        req->completionEvent = NULL;
6177007Snate@binkert.org        req->time = curTick;
6186657Snate@binkert.org        assert(!req->data);
6196657Snate@binkert.org        req->data = new uint8_t[64];
6206657Snate@binkert.org        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
6216657Snate@binkert.org
6226657Snate@binkert.org        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
6236657Snate@binkert.org                "to Addr:%#x, data:%#x [sn:%lli]\n",
6247007Snate@binkert.org                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
6257007Snate@binkert.org                req->paddr, *(req->data),
6267007Snate@binkert.org                storeQueue[storeWBIdx].inst->seqNum);
6276657Snate@binkert.org
6286657Snate@binkert.org        switch(storeQueue[storeWBIdx].size) {
6296657Snate@binkert.org          case 1:
6306657Snate@binkert.org            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
6316657Snate@binkert.org            break;
6326657Snate@binkert.org          case 2:
6336657Snate@binkert.org            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
6346657Snate@binkert.org            break;
6356657Snate@binkert.org          case 4:
6366657Snate@binkert.org            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
6376657Snate@binkert.org            break;
6386657Snate@binkert.org          case 8:
6396657Snate@binkert.org            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
6406657Snate@binkert.org            break;
6417805Snilay@cs.wisc.edu          default:
6426657Snate@binkert.org            panic("Unexpected store size!\n");
6436657Snate@binkert.org        }
6446657Snate@binkert.org
6457007Snate@binkert.org        // Stores other than store conditionals are completed at this
6467007Snate@binkert.org        // time.  Mark them as completed and, if we have a checker,
6477007Snate@binkert.org        // tell it that the instruction is completed.
6486657Snate@binkert.org        // @todo: Figure out what time I can say stores are complete in
6496657Snate@binkert.org        // the timing memory.
6506657Snate@binkert.org        if (!(req->flags & LOCKED)) {
6516657Snate@binkert.org            storeQueue[storeWBIdx].inst->setCompleted();
6527007Snate@binkert.org            if (cpu->checker) {
6536657Snate@binkert.org                cpu->checker->tick(storeQueue[storeWBIdx].inst);
6546657Snate@binkert.org            }
6556657Snate@binkert.org        }
6566657Snate@binkert.org
6577007Snate@binkert.org        if (dcacheInterface) {
6586657Snate@binkert.org            assert(!req->completionEvent);
6596657Snate@binkert.org            StoreCompletionEvent *store_event = new
6606657Snate@binkert.org                StoreCompletionEvent(storeWBIdx, NULL, this);
6616657Snate@binkert.org            req->completionEvent = store_event;
6627805Snilay@cs.wisc.edu
6636657Snate@binkert.org            MemAccessResult result = dcacheInterface->access(req);
6646657Snate@binkert.org
6656657Snate@binkert.org            if (isStalled() &&
6667007Snate@binkert.org                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
6677007Snate@binkert.org                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
6687007Snate@binkert.org                        "load idx:%i\n",
6697007Snate@binkert.org                        stallingStoreIsn, stallingLoadIdx);
6706657Snate@binkert.org                stalled = false;
6716657Snate@binkert.org                stallingStoreIsn = 0;
6726657Snate@binkert.org                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
6736657Snate@binkert.org            }
6746657Snate@binkert.org
6756657Snate@binkert.org            typename IEW::LdWritebackEvent *wb = NULL;
6766657Snate@binkert.org            if (req->flags & LOCKED) {
6776657Snate@binkert.org                // Stx_C should not generate a system port transaction
6786657Snate@binkert.org                // if it misses in the cache, but that might be hard
6797007Snate@binkert.org                // to accomplish without explicit cache support.
6807007Snate@binkert.org                wb = new typename
6816657Snate@binkert.org                    IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
6826657Snate@binkert.org                                              iewStage);
6836657Snate@binkert.org                store_event->wbEvent = wb;
6846657Snate@binkert.org            }
6857007Snate@binkert.org
6867007Snate@binkert.org            if (result != MA_HIT && dcacheInterface->doEvents()) {
6876657Snate@binkert.org                DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
6886657Snate@binkert.org                        storeWBIdx);
6896657Snate@binkert.org
6906657Snate@binkert.org                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
6916657Snate@binkert.org                        storeQueue[storeWBIdx].inst->seqNum);
6926657Snate@binkert.org
6936657Snate@binkert.org                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
6946657Snate@binkert.org
6956657Snate@binkert.org                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
6966657Snate@binkert.org
6976657Snate@binkert.org                // @todo: Increment stat here.
6986657Snate@binkert.org            } else {
6996657Snate@binkert.org                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
7006657Snate@binkert.org                        storeWBIdx);
7016657Snate@binkert.org
7026657Snate@binkert.org                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
7036657Snate@binkert.org                        storeQueue[storeWBIdx].inst->seqNum);
7047805Snilay@cs.wisc.edu            }
7056657Snate@binkert.org
7066657Snate@binkert.org            incrStIdx(storeWBIdx);
7076657Snate@binkert.org        } else {
7086657Snate@binkert.org            panic("Must HAVE DCACHE!!!!!\n");
7096657Snate@binkert.org        }
7107007Snate@binkert.org    }
7116657Snate@binkert.org
7127007Snate@binkert.org    // Not sure this should set it to 0.
7137007Snate@binkert.org    usedPorts = 0;
7146657Snate@binkert.org
7156657Snate@binkert.org    assert(stores >= 0 && storesToWB >= 0);
7166657Snate@binkert.org}
7176657Snate@binkert.org
7186657Snate@binkert.org/*template <class Impl>
7196657Snate@binkert.orgvoid
7206657Snate@binkert.orgLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
7216657Snate@binkert.org{
7226657Snate@binkert.org    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
7236657Snate@binkert.org                                              mshrSeqNums.end(),
7246657Snate@binkert.org                                              seqNum);
7256657Snate@binkert.org
7266657Snate@binkert.org    if (mshr_it != mshrSeqNums.end()) {
7276657Snate@binkert.org        mshrSeqNums.erase(mshr_it);
7287805Snilay@cs.wisc.edu        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
7296657Snate@binkert.org    }
7306657Snate@binkert.org}*/
7316657Snate@binkert.org
7326657Snate@binkert.orgtemplate <class Impl>
7336657Snate@binkert.orgvoid
7346657Snate@binkert.orgLSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
7356657Snate@binkert.org{
7366657Snate@binkert.org    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
7377007Snate@binkert.org            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
7387007Snate@binkert.org
7396657Snate@binkert.org    int load_idx = loadTail;
7406657Snate@binkert.org    decrLdIdx(load_idx);
7416657Snate@binkert.org
7426657Snate@binkert.org    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
7436657Snate@binkert.org        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
7446657Snate@binkert.org                "[sn:%lli]\n",
7456657Snate@binkert.org                loadQueue[load_idx]->readPC(),
7466657Snate@binkert.org                loadQueue[load_idx]->seqNum);
7476657Snate@binkert.org
7486657Snate@binkert.org        if (isStalled() && load_idx == stallingLoadIdx) {
7496657Snate@binkert.org            stalled = false;
7506657Snate@binkert.org            stallingStoreIsn = 0;
7516657Snate@binkert.org            stallingLoadIdx = 0;
7526657Snate@binkert.org        }
7536657Snate@binkert.org
7546657Snate@binkert.org        // Clear the smart pointer to make sure it is decremented.
7557805Snilay@cs.wisc.edu        loadQueue[load_idx]->setSquashed();
7566657Snate@binkert.org        loadQueue[load_idx] = NULL;
7576657Snate@binkert.org        --loads;
7586657Snate@binkert.org
7596657Snate@binkert.org        // Inefficient!
7606657Snate@binkert.org        loadTail = load_idx;
7616657Snate@binkert.org
7626657Snate@binkert.org        decrLdIdx(load_idx);
7636657Snate@binkert.org    }
7647007Snate@binkert.org
7657007Snate@binkert.org    if (isLoadBlocked) {
7666657Snate@binkert.org        if (squashed_num < blockedLoadSeqNum) {
7676657Snate@binkert.org            isLoadBlocked = false;
7686657Snate@binkert.org            loadBlockedHandled = false;
7696657Snate@binkert.org            blockedLoadSeqNum = 0;
7706657Snate@binkert.org        }
7716657Snate@binkert.org    }
7726657Snate@binkert.org
7736657Snate@binkert.org    int store_idx = storeTail;
7746657Snate@binkert.org    decrStIdx(store_idx);
7756657Snate@binkert.org
7766657Snate@binkert.org    while (stores != 0 &&
7776657Snate@binkert.org           storeQueue[store_idx].inst->seqNum > squashed_num) {
7786657Snate@binkert.org        // Instructions marked as can WB are already committed.
7796657Snate@binkert.org        if (storeQueue[store_idx].canWB) {
7806657Snate@binkert.org            break;
7817805Snilay@cs.wisc.edu        }
7826657Snate@binkert.org
7836657Snate@binkert.org        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
7846657Snate@binkert.org                "idx:%i [sn:%lli]\n",
7856657Snate@binkert.org                storeQueue[store_idx].inst->readPC(),
7868602Snilay@cs.wisc.edu                store_idx, storeQueue[store_idx].inst->seqNum);
7878602Snilay@cs.wisc.edu
7888602Snilay@cs.wisc.edu        // I don't think this can happen.  It should have been cleared
7898602Snilay@cs.wisc.edu        // by the stalling load.
7908602Snilay@cs.wisc.edu        if (isStalled() &&
7918602Snilay@cs.wisc.edu            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
7928602Snilay@cs.wisc.edu            panic("Is stalled should have been cleared by stalling load!\n");
7938602Snilay@cs.wisc.edu            stalled = false;
7948602Snilay@cs.wisc.edu            stallingStoreIsn = 0;
7958602Snilay@cs.wisc.edu        }
7968602Snilay@cs.wisc.edu
7978602Snilay@cs.wisc.edu        // Clear the smart pointer to make sure it is decremented.
7988602Snilay@cs.wisc.edu        storeQueue[store_idx].inst->setSquashed();
7998602Snilay@cs.wisc.edu        storeQueue[store_idx].inst = NULL;
8008602Snilay@cs.wisc.edu        storeQueue[store_idx].canWB = 0;
8018602Snilay@cs.wisc.edu
8028602Snilay@cs.wisc.edu        if (storeQueue[store_idx].req) {
8038602Snilay@cs.wisc.edu            // There should not be a completion event if the store has
8048602Snilay@cs.wisc.edu            // not yet committed.
8058602Snilay@cs.wisc.edu            assert(!storeQueue[store_idx].req->completionEvent);
8068602Snilay@cs.wisc.edu        }
8076657Snate@binkert.org
8086657Snate@binkert.org        storeQueue[store_idx].req = NULL;
8096657Snate@binkert.org        --stores;
8106657Snate@binkert.org
811        // Inefficient!
812        storeTail = store_idx;
813
814        decrStIdx(store_idx);
815        ++lsqSquashedStores;
816    }
817}
818
819template <class Impl>
820void
821LSQUnit<Impl>::completeStore(int store_idx)
822{
823    assert(storeQueue[store_idx].inst);
824    storeQueue[store_idx].completed = true;
825    --storesToWB;
826    // A bit conservative because a store completion may not free up entries,
827    // but hopefully avoids two store completions in one cycle from making
828    // the CPU tick twice.
829    cpu->activityThisCycle();
830
831    if (store_idx == storeHead) {
832        do {
833            incrStIdx(storeHead);
834
835            --stores;
836        } while (storeQueue[storeHead].completed &&
837                 storeHead != storeTail);
838
839        iewStage->updateLSQNextCycle = true;
840    }
841
842    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
843            "idx:%i\n",
844            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
845
846    if (isStalled() &&
847        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
848        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
849                "load idx:%i\n",
850                stallingStoreIsn, stallingLoadIdx);
851        stalled = false;
852        stallingStoreIsn = 0;
853        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
854    }
855
856    storeQueue[store_idx].inst->setCompleted();
857
858    // Tell the checker we've completed this instruction.  Some stores
859    // may get reported twice to the checker, but the checker can
860    // handle that case.
861    if (cpu->checker) {
862        cpu->checker->tick(storeQueue[store_idx].inst);
863    }
864}
865
866template <class Impl>
867inline void
868LSQUnit<Impl>::incrStIdx(int &store_idx)
869{
870    if (++store_idx >= SQEntries)
871        store_idx = 0;
872}
873
874template <class Impl>
875inline void
876LSQUnit<Impl>::decrStIdx(int &store_idx)
877{
878    if (--store_idx < 0)
879        store_idx += SQEntries;
880}
881
882template <class Impl>
883inline void
884LSQUnit<Impl>::incrLdIdx(int &load_idx)
885{
886    if (++load_idx >= LQEntries)
887        load_idx = 0;
888}
889
890template <class Impl>
891inline void
892LSQUnit<Impl>::decrLdIdx(int &load_idx)
893{
894    if (--load_idx < 0)
895        load_idx += LQEntries;
896}
897
898template <class Impl>
899void
900LSQUnit<Impl>::dumpInsts()
901{
902    cprintf("Load store queue: Dumping instructions.\n");
903    cprintf("Load queue size: %i\n", loads);
904    cprintf("Load queue: ");
905
906    int load_idx = loadHead;
907
908    while (load_idx != loadTail && loadQueue[load_idx]) {
909        cprintf("%#x ", loadQueue[load_idx]->readPC());
910
911        incrLdIdx(load_idx);
912    }
913
914    cprintf("Store queue size: %i\n", stores);
915    cprintf("Store queue: ");
916
917    int store_idx = storeHead;
918
919    while (store_idx != storeTail && storeQueue[store_idx].inst) {
920        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
921
922        incrStIdx(store_idx);
923    }
924
925    cprintf("\n");
926}
927