lsq_unit_impl.hh revision 2329
12623SN/A/*
22623SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
32623SN/A * All rights reserved.
42623SN/A *
52623SN/A * Redistribution and use in source and binary forms, with or without
62623SN/A * modification, are permitted provided that the following conditions are
72623SN/A * met: redistributions of source code must retain the above copyright
82623SN/A * notice, this list of conditions and the following disclaimer;
92623SN/A * redistributions in binary form must reproduce the above copyright
102623SN/A * notice, this list of conditions and the following disclaimer in the
112623SN/A * documentation and/or other materials provided with the distribution;
122623SN/A * neither the name of the copyright holders nor the names of its
132623SN/A * contributors may be used to endorse or promote products derived from
142623SN/A * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292623SN/A#include "cpu/checker/cpu.hh"
302623SN/A#include "cpu/o3/lsq_unit.hh"
313170Sstever@eecs.umich.edu#include "base/str.hh"
322623SN/A
334040Ssaidi@eecs.umich.edutemplate <class Impl>
342623SN/ALSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
352623SN/A                                                          Event *wb_event,
363348Sbinkertn@umich.edu                                                          LSQUnit<Impl> *lsq_ptr)
373348Sbinkertn@umich.edu    : Event(&mainEventQueue),
384762Snate@binkert.org      wbEvent(wb_event),
392901Ssaidi@eecs.umich.edu      storeIdx(store_idx),
402623SN/A      lsqPtr(lsq_ptr)
412623SN/A{
422623SN/A    this->setFlags(Event::AutoDelete);
432623SN/A}
442856Srdreslin@umich.edu
452856Srdreslin@umich.edutemplate <class Impl>
462856Srdreslin@umich.eduvoid
472856Srdreslin@umich.eduLSQUnit<Impl>::StoreCompletionEvent::process()
482856Srdreslin@umich.edu{
492856Srdreslin@umich.edu    DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
502856Srdreslin@umich.edu    DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
512856Srdreslin@umich.edu
522856Srdreslin@umich.edu    //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
532856Srdreslin@umich.edu
542623SN/A    if (lsqPtr->isSwitchedOut())
552623SN/A        return;
562623SN/A
572623SN/A    lsqPtr->cpu->wakeCPU();
582623SN/A    if (wbEvent)
592623SN/A        wbEvent->process();
602680Sktlim@umich.edu    lsqPtr->completeStore(storeIdx);
612680Sktlim@umich.edu}
622623SN/A
632623SN/Atemplate <class Impl>
642680Sktlim@umich.educonst char *
652623SN/ALSQUnit<Impl>::StoreCompletionEvent::description()
662623SN/A{
672623SN/A    return "LSQ store completion event";
682623SN/A}
692623SN/A
703349Sbinkertn@umich.edutemplate <class Impl>
712623SN/ALSQUnit<Impl>::LSQUnit()
722623SN/A    : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
732623SN/A      loadBlockedHandled(false)
742623SN/A{
752623SN/A}
762623SN/A
773349Sbinkertn@umich.edutemplate<class Impl>
782623SN/Avoid
793184Srdreslin@umich.eduLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
803184Srdreslin@umich.edu                    unsigned maxSQEntries, unsigned id)
812623SN/A
822623SN/A{
832623SN/A    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
842623SN/A
852623SN/A    switchedOut = false;
863647Srdreslin@umich.edu
873647Srdreslin@umich.edu    lsqID = id;
883647Srdreslin@umich.edu
893647Srdreslin@umich.edu    // Add 1 for the sentinel entry (they are circular queues).
903647Srdreslin@umich.edu    LQEntries = maxLQEntries + 1;
912631SN/A    SQEntries = maxSQEntries + 1;
923647Srdreslin@umich.edu
932631SN/A    loadQueue.resize(LQEntries);
942623SN/A    storeQueue.resize(SQEntries);
952623SN/A
962623SN/A    loadHead = loadTail = 0;
972948Ssaidi@eecs.umich.edu
982948Ssaidi@eecs.umich.edu    storeHead = storeWBIdx = storeTail = 0;
993349Sbinkertn@umich.edu
1002948Ssaidi@eecs.umich.edu    usedPorts = 0;
1012948Ssaidi@eecs.umich.edu    cachePorts = params->cachePorts;
1022948Ssaidi@eecs.umich.edu
1032948Ssaidi@eecs.umich.edu    dcacheInterface = params->dcacheInterface;
1042948Ssaidi@eecs.umich.edu
1052623SN/A    memDepViolator = NULL;
1063170Sstever@eecs.umich.edu
1073170Sstever@eecs.umich.edu    blockedLoadSeqNum = 0;
1082623SN/A}
1092623SN/A
1103647Srdreslin@umich.edutemplate<class Impl>
1113647Srdreslin@umich.edustd::string
1123647Srdreslin@umich.eduLSQUnit<Impl>::name() const
1133647Srdreslin@umich.edu{
1142623SN/A    if (Impl::MaxThreads == 1) {
1152839Sktlim@umich.edu        return iewStage->name() + ".lsq";
1162867Sktlim@umich.edu    } else {
1173222Sktlim@umich.edu        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
1182901Ssaidi@eecs.umich.edu    }
1192623SN/A}
1202623SN/A
1212623SN/Atemplate<class Impl>
1222623SN/Avoid
1232623SN/ALSQUnit<Impl>::clearLQ()
1242623SN/A{
1252623SN/A    loadQueue.clear();
1262623SN/A}
1272623SN/A
1282623SN/Atemplate<class Impl>
1292915Sktlim@umich.eduvoid
1302915Sktlim@umich.eduLSQUnit<Impl>::clearSQ()
1312623SN/A{
1322623SN/A    storeQueue.clear();
1332623SN/A}
1342623SN/A
1352623SN/A#if 0
1362623SN/Atemplate<class Impl>
1372915Sktlim@umich.eduvoid
1382915Sktlim@umich.eduLSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
1392623SN/A{
1402798Sktlim@umich.edu    DPRINTF(LSQUnit, "Setting the page table pointer.\n");
1412798Sktlim@umich.edu    pTable = pt_ptr;
1422901Ssaidi@eecs.umich.edu}
1432839Sktlim@umich.edu#endif
1442798Sktlim@umich.edu
1452839Sktlim@umich.edutemplate<class Impl>
1462798Sktlim@umich.eduvoid
1472798Sktlim@umich.eduLSQUnit<Impl>::switchOut()
1482901Ssaidi@eecs.umich.edu{
1492901Ssaidi@eecs.umich.edu    switchedOut = true;
1502798Sktlim@umich.edu    for (int i = 0; i < loadQueue.size(); ++i)
1512839Sktlim@umich.edu        loadQueue[i] = NULL;
1522839Sktlim@umich.edu
1532901Ssaidi@eecs.umich.edu    assert(storesToWB == 0);
1542798Sktlim@umich.edu
1552623SN/A    while (storesToWB > 0 &&
1562623SN/A           storeWBIdx != storeTail &&
1572623SN/A           storeQueue[storeWBIdx].inst &&
1582798Sktlim@umich.edu           storeQueue[storeWBIdx].canWB) {
1592623SN/A
1602798Sktlim@umich.edu        if (storeQueue[storeWBIdx].size == 0 ||
1614762Snate@binkert.org            storeQueue[storeWBIdx].inst->isDataPrefetch() ||
1623201Shsul@eecs.umich.edu            storeQueue[storeWBIdx].committed ||
1632867Sktlim@umich.edu            storeQueue[storeWBIdx].req->flags & LOCKED) {
1642867Sktlim@umich.edu            incrStIdx(storeWBIdx);
1652915Sktlim@umich.edu
1662915Sktlim@umich.edu            continue;
1672915Sktlim@umich.edu        }
1682867Sktlim@umich.edu
1692867Sktlim@umich.edu        assert(storeQueue[storeWBIdx].req);
1702867Sktlim@umich.edu        assert(!storeQueue[storeWBIdx].committed);
1714471Sstever@eecs.umich.edu
1722623SN/A        MemReqPtr req = storeQueue[storeWBIdx].req;
1732798Sktlim@umich.edu        storeQueue[storeWBIdx].committed = true;
1742901Ssaidi@eecs.umich.edu
1753222Sktlim@umich.edu        req->cmd = Write;
1762798Sktlim@umich.edu        req->completionEvent = NULL;
1772798Sktlim@umich.edu        req->time = curTick;
1782798Sktlim@umich.edu        assert(!req->data);
1792798Sktlim@umich.edu        req->data = new uint8_t[64];
1802798Sktlim@umich.edu        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
1812798Sktlim@umich.edu
1822798Sktlim@umich.edu        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
1833222Sktlim@umich.edu                "to Addr:%#x, data:%#x [sn:%lli]\n",
1842867Sktlim@umich.edu                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
1852867Sktlim@umich.edu                req->paddr, *(req->data),
1862867Sktlim@umich.edu                storeQueue[storeWBIdx].inst->seqNum);
1872867Sktlim@umich.edu
1882867Sktlim@umich.edu        switch(storeQueue[storeWBIdx].size) {
1892623SN/A          case 1:
1902623SN/A            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
1912623SN/A            break;
1922623SN/A          case 2:
1932623SN/A            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
1942623SN/A            break;
1954192Sktlim@umich.edu          case 4:
1962623SN/A            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
1972680Sktlim@umich.edu            break;
1982623SN/A          case 8:
1992680Sktlim@umich.edu            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
2002680Sktlim@umich.edu            break;
2012680Sktlim@umich.edu          default:
2022623SN/A            panic("Unexpected store size!\n");
2032623SN/A        }
2042623SN/A        incrStIdx(storeWBIdx);
2052623SN/A    }
2063201Shsul@eecs.umich.edu}
2073201Shsul@eecs.umich.edu
2083201Shsul@eecs.umich.edutemplate<class Impl>
2093201Shsul@eecs.umich.eduvoid
2102623SN/ALSQUnit<Impl>::takeOverFrom()
2112623SN/A{
2122623SN/A    switchedOut = false;
2132623SN/A    loads = stores = storesToWB = 0;
2142623SN/A
2152623SN/A    loadHead = loadTail = 0;
2162623SN/A
2172683Sktlim@umich.edu    storeHead = storeWBIdx = storeTail = 0;
2182623SN/A
2192623SN/A    usedPorts = 0;
2202623SN/A
2212623SN/A    memDepViolator = NULL;
2222623SN/A
2233686Sktlim@umich.edu    blockedLoadSeqNum = 0;
2242623SN/A
2254471Sstever@eecs.umich.edu    stalled = false;
2262623SN/A    isLoadBlocked = false;
2272623SN/A    loadBlockedHandled = false;
2282623SN/A}
2292623SN/A
2302623SN/Atemplate<class Impl>
2312623SN/Avoid
2322623SN/ALSQUnit<Impl>::resizeLQ(unsigned size)
2332683Sktlim@umich.edu{
2342623SN/A    unsigned size_plus_sentinel = size + 1;
2352644Sstever@eecs.umich.edu    assert(size_plus_sentinel >= LQEntries);
2362623SN/A
2372644Sstever@eecs.umich.edu    if (size_plus_sentinel > LQEntries) {
2382644Sstever@eecs.umich.edu        while (size_plus_sentinel > loadQueue.size()) {
2392623SN/A            DynInstPtr dummy;
2402623SN/A            loadQueue.push_back(dummy);
2412623SN/A            LQEntries++;
2422623SN/A        }
2432623SN/A    } else {
2442623SN/A        LQEntries = size_plus_sentinel;
2452623SN/A    }
2462623SN/A
2472623SN/A}
2482623SN/A
2493169Sstever@eecs.umich.edutemplate<class Impl>
2503169Sstever@eecs.umich.eduvoid
2513170Sstever@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size)
2522623SN/A{
2532623SN/A    unsigned size_plus_sentinel = size + 1;
2543169Sstever@eecs.umich.edu    if (size_plus_sentinel > SQEntries) {
2552623SN/A        while (size_plus_sentinel > storeQueue.size()) {
2562623SN/A            SQEntry dummy;
2572623SN/A            storeQueue.push_back(dummy);
2583169Sstever@eecs.umich.edu            SQEntries++;
2592623SN/A        }
2602623SN/A    } else {
2612623SN/A        SQEntries = size_plus_sentinel;
2623349Sbinkertn@umich.edu    }
2634022Sstever@eecs.umich.edu}
2643169Sstever@eecs.umich.edu
2652623SN/Atemplate <class Impl>
2663169Sstever@eecs.umich.eduvoid
2672623SN/ALSQUnit<Impl>::insert(DynInstPtr &inst)
2683169Sstever@eecs.umich.edu{
2692623SN/A    assert(inst->isMemRef());
2702623SN/A
2713169Sstever@eecs.umich.edu    assert(inst->isLoad() || inst->isStore());
2722623SN/A
2732623SN/A    if (inst->isLoad()) {
2744200Ssaidi@eecs.umich.edu        insertLoad(inst);
2754200Ssaidi@eecs.umich.edu    } else {
2764200Ssaidi@eecs.umich.edu        insertStore(inst);
2774200Ssaidi@eecs.umich.edu    }
2783658Sktlim@umich.edu
2793658Sktlim@umich.edu    inst->setInLSQ();
2802623SN/A}
2812623SN/A
2822623SN/Atemplate <class Impl>
2832623SN/Avoid
2842623SN/ALSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
2852623SN/A{
2862623SN/A    assert((loadTail + 1) % LQEntries != loadHead);
2872623SN/A    assert(loads < LQEntries);
2882623SN/A
2894040Ssaidi@eecs.umich.edu    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
2904040Ssaidi@eecs.umich.edu            load_inst->readPC(), loadTail, load_inst->seqNum);
2914040Ssaidi@eecs.umich.edu
2924040Ssaidi@eecs.umich.edu    load_inst->lqIdx = loadTail;
2934115Ssaidi@eecs.umich.edu
2944115Ssaidi@eecs.umich.edu    if (stores == 0) {
2954115Ssaidi@eecs.umich.edu        load_inst->sqIdx = -1;
2964115Ssaidi@eecs.umich.edu    } else {
2972623SN/A        load_inst->sqIdx = storeTail;
2982623SN/A    }
2992623SN/A
3002623SN/A    loadQueue[loadTail] = load_inst;
3012623SN/A
3022623SN/A    incrLdIdx(loadTail);
3032623SN/A
3042623SN/A    ++loads;
3052623SN/A}
3062623SN/A
3072623SN/Atemplate <class Impl>
3082623SN/Avoid
3092623SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
3102623SN/A{
3112623SN/A    // Make sure it is not full before inserting an instruction.
3122623SN/A    assert((storeTail + 1) % SQEntries != storeHead);
3132623SN/A    assert(stores < SQEntries);
3142623SN/A
3152623SN/A    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
3162623SN/A            store_inst->readPC(), storeTail, store_inst->seqNum);
3172623SN/A
3182623SN/A    store_inst->sqIdx = storeTail;
3192623SN/A    store_inst->lqIdx = loadTail;
3202623SN/A
3212623SN/A    storeQueue[storeTail] = SQEntry(store_inst);
3222623SN/A
3232623SN/A    incrStIdx(storeTail);
3242623SN/A
3252623SN/A    ++stores;
3262623SN/A}
3272623SN/A
3282623SN/Atemplate <class Impl>
3292623SN/Atypename Impl::DynInstPtr
3302623SN/ALSQUnit<Impl>::getMemDepViolator()
3312623SN/A{
3322623SN/A    DynInstPtr temp = memDepViolator;
3332623SN/A
3342623SN/A    memDepViolator = NULL;
3352623SN/A
3362623SN/A    return temp;
3372623SN/A}
3382623SN/A
3392623SN/Atemplate <class Impl>
3403169Sstever@eecs.umich.eduunsigned
3413169Sstever@eecs.umich.eduLSQUnit<Impl>::numFreeEntries()
3423170Sstever@eecs.umich.edu{
3432623SN/A    unsigned free_lq_entries = LQEntries - loads;
3444040Ssaidi@eecs.umich.edu    unsigned free_sq_entries = SQEntries - stores;
3454040Ssaidi@eecs.umich.edu
3464040Ssaidi@eecs.umich.edu    // Both the LQ and SQ entries have an extra dummy entry to differentiate
3474040Ssaidi@eecs.umich.edu    // empty/full conditions.  Subtract 1 from the free entries.
3482623SN/A    if (free_lq_entries < free_sq_entries) {
3493169Sstever@eecs.umich.edu        return free_lq_entries - 1;
3503169Sstever@eecs.umich.edu    } else {
3512623SN/A        return free_sq_entries - 1;
3522623SN/A    }
3533169Sstever@eecs.umich.edu}
3544040Ssaidi@eecs.umich.edu
3554040Ssaidi@eecs.umich.edutemplate <class Impl>
3564040Ssaidi@eecs.umich.eduint
3574040Ssaidi@eecs.umich.eduLSQUnit<Impl>::numLoadsReady()
3583169Sstever@eecs.umich.edu{
3593169Sstever@eecs.umich.edu    int load_idx = loadHead;
3602623SN/A    int retval = 0;
3613170Sstever@eecs.umich.edu
3623170Sstever@eecs.umich.edu    while (load_idx != loadTail) {
3633170Sstever@eecs.umich.edu        assert(loadQueue[load_idx]);
3643170Sstever@eecs.umich.edu
3653170Sstever@eecs.umich.edu        if (loadQueue[load_idx]->readyToIssue()) {
3664040Ssaidi@eecs.umich.edu            ++retval;
3674040Ssaidi@eecs.umich.edu        }
3684040Ssaidi@eecs.umich.edu    }
3694040Ssaidi@eecs.umich.edu
3703170Sstever@eecs.umich.edu    return retval;
3713170Sstever@eecs.umich.edu}
3723170Sstever@eecs.umich.edu
3733170Sstever@eecs.umich.edutemplate <class Impl>
3743170Sstever@eecs.umich.eduFault
3753170Sstever@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst)
3763170Sstever@eecs.umich.edu{
3773170Sstever@eecs.umich.edu    // Execute a specific load.
3783170Sstever@eecs.umich.edu    Fault load_fault = NoFault;
3792623SN/A
3804200Ssaidi@eecs.umich.edu    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
3814200Ssaidi@eecs.umich.edu            inst->readPC(),inst->seqNum);
3824200Ssaidi@eecs.umich.edu
3833658Sktlim@umich.edu//    load_fault = inst->initiateAcc();
3843658Sktlim@umich.edu    load_fault = inst->execute();
3852623SN/A
3862623SN/A    // If the instruction faulted, then we need to send it along to commit
3872623SN/A    // without the instruction completing.
3882623SN/A    if (load_fault != NoFault) {
3892623SN/A        // Send this instruction to commit, also make sure iew stage
3902623SN/A        // realizes there is activity.
3912623SN/A        iewStage->instToCommit(inst);
3922623SN/A        iewStage->activityThisCycle();
3932623SN/A    }
3942623SN/A
3952623SN/A    return load_fault;
3962623SN/A}
3974224Sgblack@eecs.umich.edu
3984224Sgblack@eecs.umich.edutemplate <class Impl>
3994224Sgblack@eecs.umich.eduFault
4004224Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
4014224Sgblack@eecs.umich.edu{
4024224Sgblack@eecs.umich.edu    using namespace TheISA;
4034224Sgblack@eecs.umich.edu    // Make sure that a store exists.
4044224Sgblack@eecs.umich.edu    assert(stores != 0);
4054224Sgblack@eecs.umich.edu
4064224Sgblack@eecs.umich.edu    int store_idx = store_inst->sqIdx;
4072623SN/A
4082623SN/A    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
4092623SN/A            store_inst->readPC(), store_inst->seqNum);
4102623SN/A
4112623SN/A    // Check the recently completed loads to see if any match this store's
4122623SN/A    // address.  If so, then we have a memory ordering violation.
4132623SN/A    int load_idx = store_inst->lqIdx;
4142623SN/A
4152623SN/A    Fault store_fault = store_inst->initiateAcc();
4162623SN/A//    Fault store_fault = store_inst->execute();
4172623SN/A
4182623SN/A    if (storeQueue[store_idx].size == 0) {
4192623SN/A        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
4202623SN/A                store_inst->readPC(),store_inst->seqNum);
4212623SN/A
4222623SN/A        return store_fault;
4232623SN/A    }
4242623SN/A
4252623SN/A    assert(store_fault == NoFault);
4262623SN/A
4272623SN/A    if (store_inst->isNonSpeculative()) {
4282623SN/A        // Nonspeculative accesses (namely store conditionals)
4292623SN/A        // need to set themselves as able to writeback if we
4302623SN/A        // haven't had a fault by here.
4312623SN/A        storeQueue[store_idx].canWB = true;
4322623SN/A
4332623SN/A        ++storesToWB;
4342623SN/A    }
4352623SN/A
4362623SN/A    if (!memDepViolator) {
4372623SN/A        while (load_idx != loadTail) {
4382623SN/A            // Really only need to check loads that have actually executed
4392623SN/A            // It's safe to check all loads because effAddr is set to
4402623SN/A            // InvalAddr when the dyn inst is created.
4412623SN/A
4422623SN/A            // @todo: For now this is extra conservative, detecting a
4432623SN/A            // violation if the addresses match assuming all accesses
4442623SN/A            // are quad word accesses.
4452623SN/A
4462623SN/A            // @todo: Fix this, magic number being used here
4472623SN/A            if ((loadQueue[load_idx]->effAddr >> 8) ==
4482623SN/A                (store_inst->effAddr >> 8)) {
4492623SN/A                // A load incorrectly passed this store.  Squash and refetch.
4502623SN/A                // For now return a fault to show that it was unsuccessful.
4512623SN/A                memDepViolator = loadQueue[load_idx];
4522623SN/A
4533387Sgblack@eecs.umich.edu                return genMachineCheckFault();
4543387Sgblack@eecs.umich.edu            }
4552631SN/A
4562663Sstever@eecs.umich.edu            incrLdIdx(load_idx);
4573170Sstever@eecs.umich.edu        }
4582662Sstever@eecs.umich.edu
4592623SN/A        // If we've reached this point, there was no violation.
4604022Sstever@eecs.umich.edu        memDepViolator = NULL;
4612623SN/A    }
4622623SN/A
4632623SN/A    return store_fault;
4642630SN/A}
4652623SN/A
4662623SN/Atemplate <class Impl>
4672623SN/Avoid
4682623SN/ALSQUnit<Impl>::commitLoad()
4692623SN/A{
4702623SN/A    assert(loadQueue[loadHead]);
4712623SN/A
4722623SN/A    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
4732623SN/A            loadQueue[loadHead]->readPC());
4743658Sktlim@umich.edu
4753658Sktlim@umich.edu
4762644Sstever@eecs.umich.edu    loadQueue[loadHead] = NULL;
4772644Sstever@eecs.umich.edu
4782623SN/A    incrLdIdx(loadHead);
4793222Sktlim@umich.edu
4803222Sktlim@umich.edu    --loads;
4813222Sktlim@umich.edu}
4822623SN/A
4832623SN/Atemplate <class Impl>
4842623SN/Avoid
4852623SN/ALSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
4862644Sstever@eecs.umich.edu{
4872623SN/A    assert(loads == 0 || loadQueue[loadHead]);
4882623SN/A
4892623SN/A    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
4902631SN/A        commitLoad();
4912631SN/A    }
4922631SN/A}
4932631SN/A
4942631SN/Atemplate <class Impl>
4952631SN/Avoid
4962623SN/ALSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
4972623SN/A{
4982623SN/A    assert(stores == 0 || storeQueue[storeHead].inst);
4992623SN/A
5003349Sbinkertn@umich.edu    int store_idx = storeHead;
5012623SN/A
5022623SN/A    while (store_idx != storeTail) {
5032623SN/A        assert(storeQueue[store_idx].inst);
5042644Sstever@eecs.umich.edu        // Mark any stores that are now committed and have not yet
5052623SN/A        // been marked as able to write back.
5062798Sktlim@umich.edu        if (!storeQueue[store_idx].canWB) {
5072623SN/A            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
5082644Sstever@eecs.umich.edu                break;
5093222Sktlim@umich.edu            }
5103222Sktlim@umich.edu            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
5113222Sktlim@umich.edu                    "%#x [sn:%lli]\n",
5122839Sktlim@umich.edu                    storeQueue[store_idx].inst->readPC(),
5133658Sktlim@umich.edu                    storeQueue[store_idx].inst->seqNum);
5143658Sktlim@umich.edu
5153658Sktlim@umich.edu            storeQueue[store_idx].canWB = true;
5162839Sktlim@umich.edu
5172798Sktlim@umich.edu            ++storesToWB;
5182798Sktlim@umich.edu        }
5192798Sktlim@umich.edu
5202623SN/A        incrStIdx(store_idx);
5212644Sstever@eecs.umich.edu    }
5222623SN/A}
5232623SN/A
5243170Sstever@eecs.umich.edutemplate <class Impl>
5253170Sstever@eecs.umich.eduvoid
5263170Sstever@eecs.umich.eduLSQUnit<Impl>::writebackStores()
5273170Sstever@eecs.umich.edu{
5282644Sstever@eecs.umich.edu    while (storesToWB > 0 &&
5293170Sstever@eecs.umich.edu           storeWBIdx != storeTail &&
5303170Sstever@eecs.umich.edu           storeQueue[storeWBIdx].inst &&
5313170Sstever@eecs.umich.edu           storeQueue[storeWBIdx].canWB &&
5323170Sstever@eecs.umich.edu           usedPorts < cachePorts) {
5333170Sstever@eecs.umich.edu
5343170Sstever@eecs.umich.edu        // Store didn't write any data so no need to write it back to
5353170Sstever@eecs.umich.edu        // memory.
5363170Sstever@eecs.umich.edu        if (storeQueue[storeWBIdx].size == 0) {
5373170Sstever@eecs.umich.edu            completeStore(storeWBIdx);
5382644Sstever@eecs.umich.edu
5392644Sstever@eecs.umich.edu            incrStIdx(storeWBIdx);
5402644Sstever@eecs.umich.edu
5412623SN/A            continue;
5422623SN/A        }
5432623SN/A
5442644Sstever@eecs.umich.edu        if (dcacheInterface && dcacheInterface->isBlocked()) {
5452644Sstever@eecs.umich.edu            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
5462623SN/A                    " is blocked!\n");
5473658Sktlim@umich.edu            break;
5483658Sktlim@umich.edu        }
5493658Sktlim@umich.edu
5502623SN/A        ++usedPorts;
5512623SN/A
5522948Ssaidi@eecs.umich.edu        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
5532948Ssaidi@eecs.umich.edu            incrStIdx(storeWBIdx);
5542948Ssaidi@eecs.umich.edu
5552948Ssaidi@eecs.umich.edu            continue;
5562948Ssaidi@eecs.umich.edu        }
5572623SN/A
5582623SN/A        assert(storeQueue[storeWBIdx].req);
5593349Sbinkertn@umich.edu        assert(!storeQueue[storeWBIdx].committed);
5602623SN/A
5613310Srdreslin@umich.edu        MemReqPtr req = storeQueue[storeWBIdx].req;
5623310Srdreslin@umich.edu        storeQueue[storeWBIdx].committed = true;
5634584Ssaidi@eecs.umich.edu
5642948Ssaidi@eecs.umich.edu        req->cmd = Write;
5653495Sktlim@umich.edu        req->completionEvent = NULL;
5663310Srdreslin@umich.edu        req->time = curTick;
5673310Srdreslin@umich.edu        assert(!req->data);
5683495Sktlim@umich.edu        req->data = new uint8_t[64];
5692948Ssaidi@eecs.umich.edu        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
5703310Srdreslin@umich.edu
5713310Srdreslin@umich.edu        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
5724433Ssaidi@eecs.umich.edu                "to Addr:%#x, data:%#x [sn:%lli]\n",
5734433Ssaidi@eecs.umich.edu                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
5744433Ssaidi@eecs.umich.edu                req->paddr, *(req->data),
5754433Ssaidi@eecs.umich.edu                storeQueue[storeWBIdx].inst->seqNum);
5764433Ssaidi@eecs.umich.edu
5774433Ssaidi@eecs.umich.edu        switch(storeQueue[storeWBIdx].size) {
5784433Ssaidi@eecs.umich.edu          case 1:
5793310Srdreslin@umich.edu            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
5804433Ssaidi@eecs.umich.edu            break;
5814433Ssaidi@eecs.umich.edu          case 2:
5822623SN/A            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
5832623SN/A            break;
5842657Ssaidi@eecs.umich.edu          case 4:
5852623SN/A            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
5862623SN/A            break;
5872623SN/A          case 8:
5882623SN/A            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
5892623SN/A            break;
5902623SN/A          default:
5913349Sbinkertn@umich.edu            panic("Unexpected store size!\n");
5922657Ssaidi@eecs.umich.edu        }
5932657Ssaidi@eecs.umich.edu
5942657Ssaidi@eecs.umich.edu        // Stores other than store conditionals are completed at this
5952657Ssaidi@eecs.umich.edu        // time.  Mark them as completed and, if we have a checker,
5962623SN/A        // tell it that the instruction is completed.
5972623SN/A        // @todo: Figure out what time I can say stores are complete in
5982623SN/A        // the timing memory.
5993349Sbinkertn@umich.edu        if (!(req->flags & LOCKED)) {
6002623SN/A            storeQueue[storeWBIdx].inst->setCompleted();
6012623SN/A            if (cpu->checker) {
6022623SN/A                cpu->checker->tick(storeQueue[storeWBIdx].inst);
6032641Sstever@eecs.umich.edu            }
6042623SN/A        }
6052623SN/A
6062623SN/A        if (dcacheInterface) {
6073222Sktlim@umich.edu            assert(!req->completionEvent);
6083222Sktlim@umich.edu            StoreCompletionEvent *store_event = new
6093184Srdreslin@umich.edu                StoreCompletionEvent(storeWBIdx, NULL, this);
6102623SN/A            req->completionEvent = store_event;
6112623SN/A
6123170Sstever@eecs.umich.edu            MemAccessResult result = dcacheInterface->access(req);
6133170Sstever@eecs.umich.edu
6143170Sstever@eecs.umich.edu            if (isStalled() &&
6153170Sstever@eecs.umich.edu                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
6162644Sstever@eecs.umich.edu                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
6172644Sstever@eecs.umich.edu                        "load idx:%i\n",
6182644Sstever@eecs.umich.edu                        stallingStoreIsn, stallingLoadIdx);
6193184Srdreslin@umich.edu                stalled = false;
6203227Sktlim@umich.edu                stallingStoreIsn = 0;
6213201Shsul@eecs.umich.edu                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
6223201Shsul@eecs.umich.edu            }
6233201Shsul@eecs.umich.edu
6243201Shsul@eecs.umich.edu            typename IEW::LdWritebackEvent *wb = NULL;
6253201Shsul@eecs.umich.edu            if (req->flags & LOCKED) {
6263201Shsul@eecs.umich.edu                // Stx_C should not generate a system port transaction
6273201Shsul@eecs.umich.edu                // if it misses in the cache, but that might be hard
6282644Sstever@eecs.umich.edu                // to accomplish without explicit cache support.
6292623SN/A                wb = new typename
6302623SN/A                    IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
6312623SN/A                                              iewStage);
6322798Sktlim@umich.edu                store_event->wbEvent = wb;
6332839Sktlim@umich.edu            }
6342798Sktlim@umich.edu
6352839Sktlim@umich.edu            if (result != MA_HIT && dcacheInterface->doEvents()) {
6362901Ssaidi@eecs.umich.edu                DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
6372839Sktlim@umich.edu                        storeWBIdx);
6382798Sktlim@umich.edu
6392623SN/A                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
6404192Sktlim@umich.edu                        storeQueue[storeWBIdx].inst->seqNum);
6414192Sktlim@umich.edu
6424192Sktlim@umich.edu                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
6434192Sktlim@umich.edu
6444192Sktlim@umich.edu                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
6454192Sktlim@umich.edu
6464192Sktlim@umich.edu                // @todo: Increment stat here.
6474192Sktlim@umich.edu            } else {
6484192Sktlim@umich.edu                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
6494192Sktlim@umich.edu                        storeWBIdx);
6504192Sktlim@umich.edu
6514192Sktlim@umich.edu                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
6522623SN/A                        storeQueue[storeWBIdx].inst->seqNum);
6533349Sbinkertn@umich.edu            }
6542623SN/A
6553310Srdreslin@umich.edu            incrStIdx(storeWBIdx);
6563310Srdreslin@umich.edu        } else {
6574584Ssaidi@eecs.umich.edu            panic("Must HAVE DCACHE!!!!!\n");
6582948Ssaidi@eecs.umich.edu        }
6593495Sktlim@umich.edu    }
6603310Srdreslin@umich.edu
6613310Srdreslin@umich.edu    // Not sure this should set it to 0.
6623495Sktlim@umich.edu    usedPorts = 0;
6632948Ssaidi@eecs.umich.edu
6643310Srdreslin@umich.edu    assert(stores >= 0 && storesToWB >= 0);
6653310Srdreslin@umich.edu}
6664433Ssaidi@eecs.umich.edu
6674433Ssaidi@eecs.umich.edu/*template <class Impl>
6684433Ssaidi@eecs.umich.eduvoid
6694433Ssaidi@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
6704433Ssaidi@eecs.umich.edu{
6714433Ssaidi@eecs.umich.edu    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
6724433Ssaidi@eecs.umich.edu                                              mshrSeqNums.end(),
6733310Srdreslin@umich.edu                                              seqNum);
6744433Ssaidi@eecs.umich.edu
6754433Ssaidi@eecs.umich.edu    if (mshr_it != mshrSeqNums.end()) {
6762948Ssaidi@eecs.umich.edu        mshrSeqNums.erase(mshr_it);
6772948Ssaidi@eecs.umich.edu        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
6782948Ssaidi@eecs.umich.edu    }
6792948Ssaidi@eecs.umich.edu}*/
6802948Ssaidi@eecs.umich.edu
6812630SN/Atemplate <class Impl>
6822623SN/Avoid
6832623SN/ALSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
6842657Ssaidi@eecs.umich.edu{
6852623SN/A    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
6862623SN/A            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
6872623SN/A
6882623SN/A    int load_idx = loadTail;
6892623SN/A    decrLdIdx(load_idx);
6902623SN/A
6913349Sbinkertn@umich.edu    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
6922657Ssaidi@eecs.umich.edu        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
6932657Ssaidi@eecs.umich.edu                "[sn:%lli]\n",
6943170Sstever@eecs.umich.edu                loadQueue[load_idx]->readPC(),
6952657Ssaidi@eecs.umich.edu                loadQueue[load_idx]->seqNum);
6962657Ssaidi@eecs.umich.edu
6972623SN/A        if (isStalled() && load_idx == stallingLoadIdx) {
6982623SN/A            stalled = false;
6992623SN/A            stallingStoreIsn = 0;
7002623SN/A            stallingLoadIdx = 0;
7012623SN/A        }
7022623SN/A
7032623SN/A        // Clear the smart pointer to make sure it is decremented.
7044762Snate@binkert.org        loadQueue[load_idx]->squashed = true;
7054762Snate@binkert.org        loadQueue[load_idx] = NULL;
7062623SN/A        --loads;
7072623SN/A
7084762Snate@binkert.org        // Inefficient!
7092623SN/A        loadTail = load_idx;
7102623SN/A
7112623SN/A        decrLdIdx(load_idx);
7122623SN/A    }
7132623SN/A
7143119Sktlim@umich.edu    if (isLoadBlocked) {
7152623SN/A        if (squashed_num < blockedLoadSeqNum) {
7162623SN/A            isLoadBlocked = false;
7173661Srdreslin@umich.edu            loadBlockedHandled = false;
7182623SN/A            blockedLoadSeqNum = 0;
7192623SN/A        }
7202901Ssaidi@eecs.umich.edu    }
7213170Sstever@eecs.umich.edu
7222623SN/A    int store_idx = storeTail;
7232623SN/A    decrStIdx(store_idx);
7242623SN/A
7252623SN/A    while (stores != 0 &&
7262623SN/A           storeQueue[store_idx].inst->seqNum > squashed_num) {
7273617Sbinkertn@umich.edu        // Instructions marked as can WB are already committed.
7283617Sbinkertn@umich.edu        if (storeQueue[store_idx].canWB) {
7293617Sbinkertn@umich.edu            break;
7302623SN/A        }
7314762Snate@binkert.org
7324762Snate@binkert.org        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
7334762Snate@binkert.org                "idx:%i [sn:%lli]\n",
7342623SN/A                storeQueue[store_idx].inst->readPC(),
7352623SN/A                store_idx, storeQueue[store_idx].inst->seqNum);
7362623SN/A
7372623SN/A        // I don't think this can happen.  It should have been cleared
7382623SN/A        // by the stalling load.
739        if (isStalled() &&
740            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
741            panic("Is stalled should have been cleared by stalling load!\n");
742            stalled = false;
743            stallingStoreIsn = 0;
744        }
745
746        // Clear the smart pointer to make sure it is decremented.
747        storeQueue[store_idx].inst->squashed = true;
748        storeQueue[store_idx].inst = NULL;
749        storeQueue[store_idx].canWB = 0;
750
751        if (storeQueue[store_idx].req) {
752            // There should not be a completion event if the store has
753            // not yet committed.
754            assert(!storeQueue[store_idx].req->completionEvent);
755        }
756
757        storeQueue[store_idx].req = NULL;
758        --stores;
759
760        // Inefficient!
761        storeTail = store_idx;
762
763        decrStIdx(store_idx);
764    }
765}
766
767template <class Impl>
768void
769LSQUnit<Impl>::completeStore(int store_idx)
770{
771    assert(storeQueue[store_idx].inst);
772    storeQueue[store_idx].completed = true;
773    --storesToWB;
774    // A bit conservative because a store completion may not free up entries,
775    // but hopefully avoids two store completions in one cycle from making
776    // the CPU tick twice.
777    cpu->activityThisCycle();
778
779    if (store_idx == storeHead) {
780        do {
781            incrStIdx(storeHead);
782
783            --stores;
784        } while (storeQueue[storeHead].completed &&
785                 storeHead != storeTail);
786
787        iewStage->updateLSQNextCycle = true;
788    }
789
790    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
791            "idx:%i\n",
792            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
793
794    if (isStalled() &&
795        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
796        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
797                "load idx:%i\n",
798                stallingStoreIsn, stallingLoadIdx);
799        stalled = false;
800        stallingStoreIsn = 0;
801        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
802    }
803
804    storeQueue[store_idx].inst->setCompleted();
805
806    // Tell the checker we've completed this instruction.  Some stores
807    // may get reported twice to the checker, but the checker can
808    // handle that case.
809    if (cpu->checker) {
810        cpu->checker->tick(storeQueue[store_idx].inst);
811    }
812}
813
814template <class Impl>
815inline void
816LSQUnit<Impl>::incrStIdx(int &store_idx)
817{
818    if (++store_idx >= SQEntries)
819        store_idx = 0;
820}
821
822template <class Impl>
823inline void
824LSQUnit<Impl>::decrStIdx(int &store_idx)
825{
826    if (--store_idx < 0)
827        store_idx += SQEntries;
828}
829
830template <class Impl>
831inline void
832LSQUnit<Impl>::incrLdIdx(int &load_idx)
833{
834    if (++load_idx >= LQEntries)
835        load_idx = 0;
836}
837
838template <class Impl>
839inline void
840LSQUnit<Impl>::decrLdIdx(int &load_idx)
841{
842    if (--load_idx < 0)
843        load_idx += LQEntries;
844}
845
846template <class Impl>
847void
848LSQUnit<Impl>::dumpInsts()
849{
850    cprintf("Load store queue: Dumping instructions.\n");
851    cprintf("Load queue size: %i\n", loads);
852    cprintf("Load queue: ");
853
854    int load_idx = loadHead;
855
856    while (load_idx != loadTail && loadQueue[load_idx]) {
857        cprintf("%#x ", loadQueue[load_idx]->readPC());
858
859        incrLdIdx(load_idx);
860    }
861
862    cprintf("Store queue size: %i\n", stores);
863    cprintf("Store queue: ");
864
865    int store_idx = storeHead;
866
867    while (store_idx != storeTail && storeQueue[store_idx].inst) {
868        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
869
870        incrStIdx(store_idx);
871    }
872
873    cprintf("\n");
874}
875