lsq_unit_impl.hh revision 2699:c255fef3daaa
12SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/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.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim
292665Ssaidi@eecs.umich.edu *          Korey Sewell
302SN/A */
312SN/A
322SN/A#include "cpu/checker/cpu.hh"
332SN/A#include "cpu/o3/lsq_unit.hh"
342SN/A#include "base/str.hh"
352SN/A#include "mem/request.hh"
361354SN/A
371354SN/Atemplate<class Impl>
382SN/ALSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
392SN/A                                              LSQUnit *lsq_ptr)
405501Snate@binkert.org    : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
415546Snate@binkert.org{
422SN/A    this->setFlags(Event::AutoDelete);
432SN/A}
442SN/A
452SN/Atemplate<class Impl>
4656SN/Avoid
475769Snate@binkert.orgLSQUnit<Impl>::WritebackEvent::process()
482361SN/A{
491354SN/A    if (!lsqPtr->isSwitchedOut()) {
506216Snate@binkert.org        lsqPtr->writeback(inst, pkt);
5156SN/A    }
522SN/A    delete pkt;
535543Ssaidi@eecs.umich.edu}
542SN/A
551354SN/Atemplate<class Impl>
561354SN/Aconst char *
572SN/ALSQUnit<Impl>::WritebackEvent::description()
582SN/A{
592SN/A    return "Store writeback event";
602SN/A}
615501Snate@binkert.org
625501Snate@binkert.orgtemplate<class Impl>
632SN/Avoid
64395SN/ALSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
652SN/A{
662SN/A    LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
672SN/A    DynInstPtr inst = state->inst;
685769Snate@binkert.org    DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum);
695769Snate@binkert.org    DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum);
705769Snate@binkert.org
715769Snate@binkert.org    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
725769Snate@binkert.org
735769Snate@binkert.org    if (isSwitchedOut() || inst->isSquashed()) {
745769Snate@binkert.org        delete state;
755769Snate@binkert.org        delete pkt;
765769Snate@binkert.org        return;
775769Snate@binkert.org    } else {
785769Snate@binkert.org        if (!state->noWB) {
795769Snate@binkert.org            writeback(inst, pkt);
805774Snate@binkert.org        }
815774Snate@binkert.org
825774Snate@binkert.org        if (inst->isStore()) {
835769Snate@binkert.org            completeStore(state->idx);
842SN/A        }
855502Snate@binkert.org    }
865502Snate@binkert.org
875502Snate@binkert.org    delete state;
885503Snate@binkert.org    delete pkt;
895503Snate@binkert.org}
905502Snate@binkert.org
915502Snate@binkert.orgtemplate <class Impl>
925502Snate@binkert.orgTick
935502Snate@binkert.orgLSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
945502Snate@binkert.org{
955502Snate@binkert.org    panic("O3CPU model does not work with atomic mode!");
965502Snate@binkert.org    return curTick;
975602Snate@binkert.org}
985602Snate@binkert.org
995501Snate@binkert.orgtemplate <class Impl>
1005543Ssaidi@eecs.umich.eduvoid
1015543Ssaidi@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
1025769Snate@binkert.org{
1034016Sstever@eecs.umich.edu    panic("O3CPU doesn't expect recvFunctional callback!");
1044016Sstever@eecs.umich.edu}
1054016Sstever@eecs.umich.edu
1064016Sstever@eecs.umich.edutemplate <class Impl>
1074016Sstever@eecs.umich.eduvoid
1084016Sstever@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
1094016Sstever@eecs.umich.edu{
1104016Sstever@eecs.umich.edu    if (status == RangeChange)
1114016Sstever@eecs.umich.edu        return;
1125501Snate@binkert.org
1135605Snate@binkert.org    panic("O3CPU doesn't expect recvStatusChange callback!");
1145605Snate@binkert.org}
1155605Snate@binkert.org
1165605Snate@binkert.orgtemplate <class Impl>
1175501Snate@binkert.orgbool
1184016Sstever@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
1195577SSteve.Reinhardt@amd.com{
1205501Snate@binkert.org    lsq->completeDataAccess(pkt);
1215501Snate@binkert.org    return true;
1225501Snate@binkert.org}
1235502Snate@binkert.org
1245502Snate@binkert.orgtemplate <class Impl>
1255605Snate@binkert.orgvoid
1265502Snate@binkert.orgLSQUnit<Impl>::DcachePort::recvRetry()
1275502Snate@binkert.org{
1285605Snate@binkert.org    lsq->recvRetry();
1295605Snate@binkert.org}
1305605Snate@binkert.org
1315577SSteve.Reinhardt@amd.comtemplate <class Impl>
1325502Snate@binkert.orgLSQUnit<Impl>::LSQUnit()
1335502Snate@binkert.org    : loads(0), stores(0), storesToWB(0), stalled(false),
1345502Snate@binkert.org      isStoreBlocked(false), isLoadBlocked(false),
1355502Snate@binkert.org      loadBlockedHandled(false)
1362SN/A{
1375769Snate@binkert.org}
1385769Snate@binkert.org
1395769Snate@binkert.orgtemplate<class Impl>
1405769Snate@binkert.orgvoid
1415769Snate@binkert.orgLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
1425769Snate@binkert.org                    unsigned maxSQEntries, unsigned id)
1432SN/A{
1445769Snate@binkert.org    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
1455769Snate@binkert.org
1465769Snate@binkert.org    switchedOut = false;
1475769Snate@binkert.org
1485769Snate@binkert.org    lsqID = id;
1495769Snate@binkert.org
1502SN/A    // Add 1 for the sentinel entry (they are circular queues).
1515769Snate@binkert.org    LQEntries = maxLQEntries + 1;
1525769Snate@binkert.org    SQEntries = maxSQEntries + 1;
1535769Snate@binkert.org
1545769Snate@binkert.org    loadQueue.resize(LQEntries);
1555769Snate@binkert.org    storeQueue.resize(SQEntries);
1565769Snate@binkert.org
1575769Snate@binkert.org    loadHead = loadTail = 0;
1585769Snate@binkert.org
1595769Snate@binkert.org    storeHead = storeWBIdx = storeTail = 0;
1605769Snate@binkert.org
1615769Snate@binkert.org    usedPorts = 0;
1625769Snate@binkert.org    cachePorts = params->cachePorts;
1635769Snate@binkert.org
1645769Snate@binkert.org    mem = params->mem;
1655769Snate@binkert.org
1665769Snate@binkert.org    memDepViolator = NULL;
1675769Snate@binkert.org
1685769Snate@binkert.org    blockedLoadSeqNum = 0;
1695769Snate@binkert.org}
1705769Snate@binkert.org
1715769Snate@binkert.orgtemplate<class Impl>
1725769Snate@binkert.orgvoid
1735769Snate@binkert.orgLSQUnit<Impl>::setCPU(FullCPU *cpu_ptr)
1745769Snate@binkert.org{
1755769Snate@binkert.org    cpu = cpu_ptr;
1765769Snate@binkert.org    dcachePort = new DcachePort(cpu, this);
1775769Snate@binkert.org
1785769Snate@binkert.org    Port *mem_dport = mem->getPort("");
1795501Snate@binkert.org    dcachePort->setPeer(mem_dport);
1805543Ssaidi@eecs.umich.edu    mem_dport->setPeer(dcachePort);
1812SN/A
1822SN/A    if (cpu->checker) {
183396SN/A        cpu->checker->setDcachePort(dcachePort);
184396SN/A    }
185396SN/A}
186396SN/A
187396SN/Atemplate<class Impl>
1885501Snate@binkert.orgstd::string
1895543Ssaidi@eecs.umich.eduLSQUnit<Impl>::name() const
1905501Snate@binkert.org{
1913329Sstever@eecs.umich.edu    if (Impl::MaxThreads == 1) {
1923329Sstever@eecs.umich.edu        return iewStage->name() + ".lsq";
1933329Sstever@eecs.umich.edu    } else {
1943329Sstever@eecs.umich.edu        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
1953329Sstever@eecs.umich.edu    }
1963329Sstever@eecs.umich.edu}
1973329Sstever@eecs.umich.edu
1983329Sstever@eecs.umich.edutemplate<class Impl>
1995543Ssaidi@eecs.umich.eduvoid
200396SN/ALSQUnit<Impl>::clearLQ()
2013329Sstever@eecs.umich.edu{
2023329Sstever@eecs.umich.edu    loadQueue.clear();
2033329Sstever@eecs.umich.edu}
2043329Sstever@eecs.umich.edu
2055543Ssaidi@eecs.umich.edutemplate<class Impl>
2063329Sstever@eecs.umich.eduvoid
207396SN/ALSQUnit<Impl>::clearSQ()
208396SN/A{
209396SN/A    storeQueue.clear();
2105543Ssaidi@eecs.umich.edu}
211396SN/A
212396SN/Atemplate<class Impl>
2135543Ssaidi@eecs.umich.eduvoid
214396SN/ALSQUnit<Impl>::switchOut()
215396SN/A{
216396SN/A    switchedOut = true;
217396SN/A    for (int i = 0; i < loadQueue.size(); ++i)
2185543Ssaidi@eecs.umich.edu        loadQueue[i] = NULL;
219396SN/A
220396SN/A    assert(storesToWB == 0);
221396SN/A}
2225543Ssaidi@eecs.umich.edu
223396SN/Atemplate<class Impl>
224396SN/Avoid
225396SN/ALSQUnit<Impl>::takeOverFrom()
2265543Ssaidi@eecs.umich.edu{
227396SN/A    switchedOut = false;
2284075Sbinkertn@umich.edu    loads = stores = storesToWB = 0;
2294075Sbinkertn@umich.edu
2304075Sbinkertn@umich.edu    loadHead = loadTail = 0;
231396SN/A
232396SN/A    storeHead = storeWBIdx = storeTail = 0;
2335543Ssaidi@eecs.umich.edu
2345501Snate@binkert.org    usedPorts = 0;
2355501Snate@binkert.org
2365543Ssaidi@eecs.umich.edu    memDepViolator = NULL;
237396SN/A
238396SN/A    blockedLoadSeqNum = 0;
2392SN/A
2402SN/A    stalled = false;
2412SN/A    isLoadBlocked = false;
2422SN/A    loadBlockedHandled = false;
2435605Snate@binkert.org}
2445769Snate@binkert.org
245224SN/Atemplate<class Impl>
2464016Sstever@eecs.umich.eduvoid
2475501Snate@binkert.orgLSQUnit<Impl>::resizeLQ(unsigned size)
2485605Snate@binkert.org{
2495501Snate@binkert.org    unsigned size_plus_sentinel = size + 1;
2505501Snate@binkert.org    assert(size_plus_sentinel >= LQEntries);
2515774Snate@binkert.org
2525501Snate@binkert.org    if (size_plus_sentinel > LQEntries) {
2535501Snate@binkert.org        while (size_plus_sentinel > loadQueue.size()) {
2544016Sstever@eecs.umich.edu            DynInstPtr dummy;
255224SN/A            loadQueue.push_back(dummy);
256224SN/A            LQEntries++;
2575768Snate@binkert.org        }
2585768Snate@binkert.org    } else {
259265SN/A        LQEntries = size_plus_sentinel;
2605501Snate@binkert.org    }
2615501Snate@binkert.org
2625501Snate@binkert.org}
2635501Snate@binkert.org
2645501Snate@binkert.orgtemplate<class Impl>
2655501Snate@binkert.orgvoid
2665501Snate@binkert.orgLSQUnit<Impl>::resizeSQ(unsigned size)
2675501Snate@binkert.org{
2685501Snate@binkert.org    unsigned size_plus_sentinel = size + 1;
2695501Snate@binkert.org    if (size_plus_sentinel > SQEntries) {
2705501Snate@binkert.org        while (size_plus_sentinel > storeQueue.size()) {
2715501Snate@binkert.org            SQEntry dummy;
2725501Snate@binkert.org            storeQueue.push_back(dummy);
2735501Snate@binkert.org            SQEntries++;
2745501Snate@binkert.org        }
2755501Snate@binkert.org    } else {
2765501Snate@binkert.org        SQEntries = size_plus_sentinel;
2775501Snate@binkert.org    }
2785501Snate@binkert.org}
2795501Snate@binkert.org
2805501Snate@binkert.orgtemplate <class Impl>
2812SN/Avoid
2825769Snate@binkert.orgLSQUnit<Impl>::insert(DynInstPtr &inst)
2832SN/A{
2842SN/A    assert(inst->isMemRef());
2855769Snate@binkert.org
2862SN/A    assert(inst->isLoad() || inst->isStore());
2872SN/A
2885769Snate@binkert.org    if (inst->isLoad()) {
2892SN/A        insertLoad(inst);
2902667Sstever@eecs.umich.edu    } else {
2915769Snate@binkert.org        insertStore(inst);
2922667Sstever@eecs.umich.edu    }
2932SN/A
2942SN/A    inst->setInLSQ();
2952SN/A}
2962SN/A
2972SN/Atemplate <class Impl>
2982SN/Avoid
2995605Snate@binkert.orgLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
3005501Snate@binkert.org{
3015501Snate@binkert.org    assert((loadTail + 1) % LQEntries != loadHead);
3022SN/A    assert(loads < LQEntries);
3035501Snate@binkert.org
3045501Snate@binkert.org    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
3055501Snate@binkert.org            load_inst->readPC(), loadTail, load_inst->seqNum);
3062SN/A
3072SN/A    load_inst->lqIdx = loadTail;
3082SN/A
309224SN/A    if (stores == 0) {
310224SN/A        load_inst->sqIdx = -1;
311237SN/A    } else {
3125605Snate@binkert.org        load_inst->sqIdx = storeTail;
313571SN/A    }
314571SN/A
3152SN/A    loadQueue[loadTail] = load_inst;
3162SN/A
3172SN/A    incrLdIdx(loadTail);
318395SN/A
3192SN/A    ++loads;
3205605Snate@binkert.org}
321265SN/A
3222SN/Atemplate <class Impl>
3232SN/Avoid
3242SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
3252SN/A{
3262SN/A    // Make sure it is not full before inserting an instruction.
3272SN/A    assert((storeTail + 1) % SQEntries != storeHead);
3282SN/A    assert(stores < SQEntries);
329265SN/A
3302SN/A    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
3312SN/A            store_inst->readPC(), storeTail, store_inst->seqNum);
332512SN/A
333265SN/A    store_inst->sqIdx = storeTail;
3342SN/A    store_inst->lqIdx = loadTail;
3355738Snate@binkert.org
3365738Snate@binkert.org    storeQueue[storeTail] = SQEntry(store_inst);
3375738Snate@binkert.org
3382SN/A    incrStIdx(storeTail);
3395501Snate@binkert.org
3402667Sstever@eecs.umich.edu    ++stores;
3412SN/A}
3422SN/A
3432SN/Atemplate <class Impl>
3442SN/Atypename Impl::DynInstPtr
3455501Snate@binkert.orgLSQUnit<Impl>::getMemDepViolator()
3465501Snate@binkert.org{
3475501Snate@binkert.org    DynInstPtr temp = memDepViolator;
3482SN/A
3492SN/A    memDepViolator = NULL;
3502SN/A
3512SN/A    return temp;
3521634SN/A}
3531634SN/A
3541634SN/Atemplate <class Impl>
3551634SN/Aunsigned
3561634SN/ALSQUnit<Impl>::numFreeEntries()
3572SN/A{
3582SN/A    unsigned free_lq_entries = LQEntries - loads;
3592SN/A    unsigned free_sq_entries = SQEntries - stores;
3602SN/A
3612SN/A    // Both the LQ and SQ entries have an extra dummy entry to differentiate
3622SN/A    // empty/full conditions.  Subtract 1 from the free entries.
3632SN/A    if (free_lq_entries < free_sq_entries) {
3642SN/A        return free_lq_entries - 1;
3655501Snate@binkert.org    } else {
3662SN/A        return free_sq_entries - 1;
3675501Snate@binkert.org    }
3682SN/A}
3692SN/A
3702SN/Atemplate <class Impl>
3715502Snate@binkert.orgint
3725502Snate@binkert.orgLSQUnit<Impl>::numLoadsReady()
3735605Snate@binkert.org{
374217SN/A    int load_idx = loadHead;
375237SN/A    int retval = 0;
3765605Snate@binkert.org
3772SN/A    while (load_idx != loadTail) {
3782SN/A        assert(loadQueue[load_idx]);
3795605Snate@binkert.org
3805605Snate@binkert.org        if (loadQueue[load_idx]->readyToIssue()) {
3815605Snate@binkert.org            ++retval;
3825605Snate@binkert.org        }
3835605Snate@binkert.org    }
3845605Snate@binkert.org
3852SN/A    return retval;
3865605Snate@binkert.org}
3875605Snate@binkert.org
3885605Snate@binkert.orgtemplate <class Impl>
3895605Snate@binkert.orgFault
3902SN/ALSQUnit<Impl>::executeLoad(DynInstPtr &inst)
3915605Snate@binkert.org{
3925605Snate@binkert.org    // Execute a specific load.
3935605Snate@binkert.org    Fault load_fault = NoFault;
3945605Snate@binkert.org
3955605Snate@binkert.org    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
3965605Snate@binkert.org            inst->readPC(),inst->seqNum);
3975605Snate@binkert.org
3985605Snate@binkert.org    load_fault = inst->initiateAcc();
3995605Snate@binkert.org
4005605Snate@binkert.org    // If the instruction faulted, then we need to send it along to commit
4015605Snate@binkert.org    // without the instruction completing.
4025605Snate@binkert.org    if (load_fault != NoFault) {
4035605Snate@binkert.org        // Send this instruction to commit, also make sure iew stage
4045605Snate@binkert.org        // realizes there is activity.
4055605Snate@binkert.org        iewStage->instToCommit(inst);
4065605Snate@binkert.org        iewStage->activityThisCycle();
4075605Snate@binkert.org    }
4085605Snate@binkert.org
4095605Snate@binkert.org    return load_fault;
4105605Snate@binkert.org}
4115605Snate@binkert.org
4125605Snate@binkert.orgtemplate <class Impl>
4135605Snate@binkert.orgFault
4145605Snate@binkert.orgLSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
4155605Snate@binkert.org{
4165605Snate@binkert.org    using namespace TheISA;
4175605Snate@binkert.org    // Make sure that a store exists.
4185605Snate@binkert.org    assert(stores != 0);
4195605Snate@binkert.org
4205605Snate@binkert.org    int store_idx = store_inst->sqIdx;
4215605Snate@binkert.org
4225605Snate@binkert.org    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
4235605Snate@binkert.org            store_inst->readPC(), store_inst->seqNum);
4245605Snate@binkert.org
4255605Snate@binkert.org    // Check the recently completed loads to see if any match this store's
4265605Snate@binkert.org    // address.  If so, then we have a memory ordering violation.
4275605Snate@binkert.org    int load_idx = store_inst->lqIdx;
4285605Snate@binkert.org
4295605Snate@binkert.org    Fault store_fault = store_inst->initiateAcc();
4305605Snate@binkert.org
4315605Snate@binkert.org    if (storeQueue[store_idx].size == 0) {
4325605Snate@binkert.org        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
4335605Snate@binkert.org                store_inst->readPC(),store_inst->seqNum);
4345605Snate@binkert.org
4355605Snate@binkert.org        return store_fault;
4365605Snate@binkert.org    }
4375605Snate@binkert.org
4385605Snate@binkert.org    assert(store_fault == NoFault);
4395605Snate@binkert.org
4405605Snate@binkert.org    if (store_inst->isStoreConditional()) {
4415605Snate@binkert.org        // Store conditionals need to set themselves as able to
4425605Snate@binkert.org        // writeback if we haven't had a fault by here.
4435605Snate@binkert.org        storeQueue[store_idx].canWB = true;
4445605Snate@binkert.org
4455605Snate@binkert.org        ++storesToWB;
4465769Snate@binkert.org    }
4475605Snate@binkert.org
4485605Snate@binkert.org    if (!memDepViolator) {
4495605Snate@binkert.org        while (load_idx != loadTail) {
4505605Snate@binkert.org            // Really only need to check loads that have actually executed
4515605Snate@binkert.org            // It's safe to check all loads because effAddr is set to
4525605Snate@binkert.org            // InvalAddr when the dyn inst is created.
4535605Snate@binkert.org
4545605Snate@binkert.org            // @todo: For now this is extra conservative, detecting a
4555605Snate@binkert.org            // violation if the addresses match assuming all accesses
4565605Snate@binkert.org            // are quad word accesses.
4575605Snate@binkert.org
4585605Snate@binkert.org            // @todo: Fix this, magic number being used here
4595605Snate@binkert.org            if ((loadQueue[load_idx]->effAddr >> 8) ==
4605605Snate@binkert.org                (store_inst->effAddr >> 8)) {
4615605Snate@binkert.org                // A load incorrectly passed this store.  Squash and refetch.
4625605Snate@binkert.org                // For now return a fault to show that it was unsuccessful.
4635605Snate@binkert.org                memDepViolator = loadQueue[load_idx];
4645605Snate@binkert.org
4655605Snate@binkert.org                return genMachineCheckFault();
4665605Snate@binkert.org            }
4675605Snate@binkert.org
4685605Snate@binkert.org            incrLdIdx(load_idx);
4695605Snate@binkert.org        }
4705605Snate@binkert.org
4712SN/A        // If we've reached this point, there was no violation.
4725605Snate@binkert.org        memDepViolator = NULL;
4732SN/A    }
4745605Snate@binkert.org
4755605Snate@binkert.org    return store_fault;
4765774Snate@binkert.org}
4775774Snate@binkert.org
4785774Snate@binkert.orgtemplate <class Impl>
4795605Snate@binkert.orgvoid
4805605Snate@binkert.orgLSQUnit<Impl>::commitLoad()
4815605Snate@binkert.org{
4825769Snate@binkert.org    assert(loadQueue[loadHead]);
4835605Snate@binkert.org
4845769Snate@binkert.org    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
4855605Snate@binkert.org            loadQueue[loadHead]->readPC());
4865769Snate@binkert.org
4875605Snate@binkert.org    loadQueue[loadHead] = NULL;
4885605Snate@binkert.org
4895605Snate@binkert.org    incrLdIdx(loadHead);
4902SN/A
4912SN/A    --loads;
4922SN/A}
4935605Snate@binkert.org
4942SN/Atemplate <class Impl>
4955605Snate@binkert.orgvoid
4965774Snate@binkert.orgLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
4975774Snate@binkert.org{
4985774Snate@binkert.org    assert(loads == 0 || loadQueue[loadHead]);
4995605Snate@binkert.org
5005605Snate@binkert.org    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
5015605Snate@binkert.org        commitLoad();
5025769Snate@binkert.org    }
5035769Snate@binkert.org}
5045605Snate@binkert.org
5055769Snate@binkert.orgtemplate <class Impl>
5065605Snate@binkert.orgvoid
5075605Snate@binkert.orgLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
5085605Snate@binkert.org{
5095605Snate@binkert.org    assert(stores == 0 || storeQueue[storeHead].inst);
5102SN/A
5112SN/A    int store_idx = storeHead;
5122SN/A
5135605Snate@binkert.org    while (store_idx != storeTail) {
5142SN/A        assert(storeQueue[store_idx].inst);
5155605Snate@binkert.org        // Mark any stores that are now committed and have not yet
5165605Snate@binkert.org        // been marked as able to write back.
5175774Snate@binkert.org        if (!storeQueue[store_idx].canWB) {
5185774Snate@binkert.org            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
5195774Snate@binkert.org                break;
5205605Snate@binkert.org            }
5215605Snate@binkert.org            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
5225605Snate@binkert.org                    "%#x [sn:%lli]\n",
5235605Snate@binkert.org                    storeQueue[store_idx].inst->readPC(),
5245605Snate@binkert.org                    storeQueue[store_idx].inst->seqNum);
5255605Snate@binkert.org
5265769Snate@binkert.org            storeQueue[store_idx].canWB = true;
5275769Snate@binkert.org
5285605Snate@binkert.org            ++storesToWB;
5295769Snate@binkert.org        }
5305605Snate@binkert.org
5315769Snate@binkert.org        incrStIdx(store_idx);
5325605Snate@binkert.org    }
5335605Snate@binkert.org}
5345605Snate@binkert.org
5352SN/Atemplate <class Impl>
5362SN/Avoid
5375502Snate@binkert.orgLSQUnit<Impl>::writebackStores()
5385502Snate@binkert.org{
5395502Snate@binkert.org    while (storesToWB > 0 &&
5405502Snate@binkert.org           storeWBIdx != storeTail &&
5415502Snate@binkert.org           storeQueue[storeWBIdx].inst &&
5425502Snate@binkert.org           storeQueue[storeWBIdx].canWB &&
5435502Snate@binkert.org           usedPorts < cachePorts) {
5445502Snate@binkert.org
5455502Snate@binkert.org        if (isStoreBlocked) {
5465502Snate@binkert.org            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
5475502Snate@binkert.org                    " is blocked!\n");
5485502Snate@binkert.org            break;
5495502Snate@binkert.org        }
5505502Snate@binkert.org
5515502Snate@binkert.org        // Store didn't write any data so no need to write it back to
5525502Snate@binkert.org        // memory.
5535502Snate@binkert.org        if (storeQueue[storeWBIdx].size == 0) {
5545502Snate@binkert.org            completeStore(storeWBIdx);
5555502Snate@binkert.org
5565502Snate@binkert.org            incrStIdx(storeWBIdx);
5575502Snate@binkert.org
5585502Snate@binkert.org            continue;
5595502Snate@binkert.org        }
5605502Snate@binkert.org
5615502Snate@binkert.org        ++usedPorts;
5625502Snate@binkert.org
5635502Snate@binkert.org        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
5645502Snate@binkert.org            incrStIdx(storeWBIdx);
5655502Snate@binkert.org
5665502Snate@binkert.org            continue;
5675502Snate@binkert.org        }
5685502Snate@binkert.org
5695502Snate@binkert.org        assert(storeQueue[storeWBIdx].req);
5705502Snate@binkert.org        assert(!storeQueue[storeWBIdx].committed);
5715502Snate@binkert.org
5725502Snate@binkert.org        DynInstPtr inst = storeQueue[storeWBIdx].inst;
5735502Snate@binkert.org
5745502Snate@binkert.org        Request *req = storeQueue[storeWBIdx].req;
5755605Snate@binkert.org        storeQueue[storeWBIdx].committed = true;
5762SN/A
5771354SN/A        assert(!inst->memData);
578        inst->memData = new uint8_t[64];
579        memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data,
580               req->getSize());
581
582        PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
583        data_pkt->dataStatic(inst->memData);
584
585        LSQSenderState *state = new LSQSenderState;
586        state->isLoad = false;
587        state->idx = storeWBIdx;
588        state->inst = inst;
589        data_pkt->senderState = state;
590
591        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
592                "to Addr:%#x, data:%#x [sn:%lli]\n",
593                storeWBIdx, storeQueue[storeWBIdx].inst->readPC(),
594                req->getPaddr(), *(inst->memData),
595                storeQueue[storeWBIdx].inst->seqNum);
596
597        // @todo: Remove this SC hack once the memory system handles it.
598        if (req->getFlags() & LOCKED) {
599            if (req->getFlags() & UNCACHEABLE) {
600                req->setScResult(2);
601            } else {
602                if (cpu->lockFlag) {
603                    req->setScResult(1);
604                } else {
605                    req->setScResult(0);
606                    // Hack: Instantly complete this store.
607                    completeDataAccess(data_pkt);
608                    incrStIdx(storeWBIdx);
609                    continue;
610                }
611            }
612        } else {
613            // Non-store conditionals do not need a writeback.
614            state->noWB = true;
615        }
616
617        if (!dcachePort->sendTiming(data_pkt)) {
618            // Need to handle becoming blocked on a store.
619            isStoreBlocked = true;
620
621            assert(retryPkt == NULL);
622            retryPkt = data_pkt;
623        } else {
624            storePostSend(data_pkt);
625        }
626    }
627
628    // Not sure this should set it to 0.
629    usedPorts = 0;
630
631    assert(stores >= 0 && storesToWB >= 0);
632}
633
634/*template <class Impl>
635void
636LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
637{
638    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
639                                              mshrSeqNums.end(),
640                                              seqNum);
641
642    if (mshr_it != mshrSeqNums.end()) {
643        mshrSeqNums.erase(mshr_it);
644        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
645    }
646}*/
647
648template <class Impl>
649void
650LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
651{
652    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
653            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
654
655    int load_idx = loadTail;
656    decrLdIdx(load_idx);
657
658    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
659        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
660                "[sn:%lli]\n",
661                loadQueue[load_idx]->readPC(),
662                loadQueue[load_idx]->seqNum);
663
664        if (isStalled() && load_idx == stallingLoadIdx) {
665            stalled = false;
666            stallingStoreIsn = 0;
667            stallingLoadIdx = 0;
668        }
669
670        // Clear the smart pointer to make sure it is decremented.
671        loadQueue[load_idx]->squashed = true;
672        loadQueue[load_idx] = NULL;
673        --loads;
674
675        // Inefficient!
676        loadTail = load_idx;
677
678        decrLdIdx(load_idx);
679    }
680
681    if (isLoadBlocked) {
682        if (squashed_num < blockedLoadSeqNum) {
683            isLoadBlocked = false;
684            loadBlockedHandled = false;
685            blockedLoadSeqNum = 0;
686        }
687    }
688
689    int store_idx = storeTail;
690    decrStIdx(store_idx);
691
692    while (stores != 0 &&
693           storeQueue[store_idx].inst->seqNum > squashed_num) {
694        // Instructions marked as can WB are already committed.
695        if (storeQueue[store_idx].canWB) {
696            break;
697        }
698
699        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
700                "idx:%i [sn:%lli]\n",
701                storeQueue[store_idx].inst->readPC(),
702                store_idx, storeQueue[store_idx].inst->seqNum);
703
704        // I don't think this can happen.  It should have been cleared
705        // by the stalling load.
706        if (isStalled() &&
707            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
708            panic("Is stalled should have been cleared by stalling load!\n");
709            stalled = false;
710            stallingStoreIsn = 0;
711        }
712
713        // Clear the smart pointer to make sure it is decremented.
714        storeQueue[store_idx].inst->squashed = true;
715        storeQueue[store_idx].inst = NULL;
716        storeQueue[store_idx].canWB = 0;
717
718        storeQueue[store_idx].req = NULL;
719        --stores;
720
721        // Inefficient!
722        storeTail = store_idx;
723
724        decrStIdx(store_idx);
725    }
726}
727
728template <class Impl>
729void
730LSQUnit<Impl>::storePostSend(Packet *pkt)
731{
732    if (isStalled() &&
733        storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
734        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
735                "load idx:%i\n",
736                stallingStoreIsn, stallingLoadIdx);
737        stalled = false;
738        stallingStoreIsn = 0;
739        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
740    }
741
742    if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
743        // The store is basically completed at this time. This
744        // only works so long as the checker doesn't try to
745        // verify the value in memory for stores.
746        storeQueue[storeWBIdx].inst->setCompleted();
747        if (cpu->checker) {
748            cpu->checker->tick(storeQueue[storeWBIdx].inst);
749        }
750    }
751
752    if (pkt->result != Packet::Success) {
753        DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
754                storeWBIdx);
755
756        DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
757                storeQueue[storeWBIdx].inst->seqNum);
758
759        //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
760
761        //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
762
763        // @todo: Increment stat here.
764    } else {
765        DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
766                storeWBIdx);
767
768        DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
769                storeQueue[storeWBIdx].inst->seqNum);
770    }
771
772    incrStIdx(storeWBIdx);
773}
774
775template <class Impl>
776void
777LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
778{
779    iewStage->wakeCPU();
780
781    // Squashed instructions do not need to complete their access.
782    if (inst->isSquashed()) {
783        assert(!inst->isStore());
784        return;
785    }
786
787    if (!inst->isExecuted()) {
788        inst->setExecuted();
789
790        // Complete access to copy data to proper place.
791        inst->completeAcc(pkt);
792    }
793
794    // Need to insert instruction into queue to commit
795    iewStage->instToCommit(inst);
796
797    iewStage->activityThisCycle();
798}
799
800template <class Impl>
801void
802LSQUnit<Impl>::completeStore(int store_idx)
803{
804    assert(storeQueue[store_idx].inst);
805    storeQueue[store_idx].completed = true;
806    --storesToWB;
807    // A bit conservative because a store completion may not free up entries,
808    // but hopefully avoids two store completions in one cycle from making
809    // the CPU tick twice.
810    cpu->activityThisCycle();
811
812    if (store_idx == storeHead) {
813        do {
814            incrStIdx(storeHead);
815
816            --stores;
817        } while (storeQueue[storeHead].completed &&
818                 storeHead != storeTail);
819
820        iewStage->updateLSQNextCycle = true;
821    }
822
823    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
824            "idx:%i\n",
825            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
826
827    if (isStalled() &&
828        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
829        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
830                "load idx:%i\n",
831                stallingStoreIsn, stallingLoadIdx);
832        stalled = false;
833        stallingStoreIsn = 0;
834        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
835    }
836
837    storeQueue[store_idx].inst->setCompleted();
838
839    // Tell the checker we've completed this instruction.  Some stores
840    // may get reported twice to the checker, but the checker can
841    // handle that case.
842    if (cpu->checker) {
843        cpu->checker->tick(storeQueue[store_idx].inst);
844    }
845}
846
847template <class Impl>
848void
849LSQUnit<Impl>::recvRetry()
850{
851    if (isStoreBlocked) {
852        assert(retryPkt != NULL);
853
854        if (dcachePort->sendTiming(retryPkt)) {
855            storePostSend(retryPkt);
856            retryPkt = NULL;
857            isStoreBlocked = false;
858        } else {
859            // Still blocked!
860        }
861    } else if (isLoadBlocked) {
862        DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
863                "no need to resend packet.\n");
864    } else {
865        DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n");
866    }
867}
868
869template <class Impl>
870inline void
871LSQUnit<Impl>::incrStIdx(int &store_idx)
872{
873    if (++store_idx >= SQEntries)
874        store_idx = 0;
875}
876
877template <class Impl>
878inline void
879LSQUnit<Impl>::decrStIdx(int &store_idx)
880{
881    if (--store_idx < 0)
882        store_idx += SQEntries;
883}
884
885template <class Impl>
886inline void
887LSQUnit<Impl>::incrLdIdx(int &load_idx)
888{
889    if (++load_idx >= LQEntries)
890        load_idx = 0;
891}
892
893template <class Impl>
894inline void
895LSQUnit<Impl>::decrLdIdx(int &load_idx)
896{
897    if (--load_idx < 0)
898        load_idx += LQEntries;
899}
900
901template <class Impl>
902void
903LSQUnit<Impl>::dumpInsts()
904{
905    cprintf("Load store queue: Dumping instructions.\n");
906    cprintf("Load queue size: %i\n", loads);
907    cprintf("Load queue: ");
908
909    int load_idx = loadHead;
910
911    while (load_idx != loadTail && loadQueue[load_idx]) {
912        cprintf("%#x ", loadQueue[load_idx]->readPC());
913
914        incrLdIdx(load_idx);
915    }
916
917    cprintf("Store queue size: %i\n", stores);
918    cprintf("Store queue: ");
919
920    int store_idx = storeHead;
921
922    while (store_idx != storeTail && storeQueue[store_idx].inst) {
923        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
924
925        incrStIdx(store_idx);
926    }
927
928    cprintf("\n");
929}
930