lsq_unit_impl.hh revision 2692:e5b7553eff69
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 *          Korey Sewell
30 */
31
32#include "cpu/checker/cpu.hh"
33#include "cpu/o3/lsq_unit.hh"
34#include "base/str.hh"
35#include "mem/request.hh"
36
37template<class Impl>
38LSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
39                                              LSQUnit *lsq_ptr)
40    : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
41{
42    this->setFlags(Event::AutoDelete);
43}
44
45template<class Impl>
46void
47LSQUnit<Impl>::WritebackEvent::process()
48{
49    if (!lsqPtr->isSwitchedOut()) {
50        lsqPtr->writeback(inst, pkt);
51    }
52    delete pkt;
53}
54
55template<class Impl>
56const char *
57LSQUnit<Impl>::WritebackEvent::description()
58{
59    return "Store writeback event";
60}
61
62template<class Impl>
63void
64LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
65{
66    LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
67    DynInstPtr inst = state->inst;
68    DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum);
69//    DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
70
71    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
72
73    if (isSwitchedOut() || inst->isSquashed()) {
74        delete state;
75        delete pkt;
76        return;
77    } else {
78        if (!state->noWB) {
79            writeback(inst, pkt);
80        }
81
82        if (inst->isStore()) {
83            completeStore(state->idx);
84        }
85    }
86
87    delete state;
88    delete pkt;
89}
90
91template <class Impl>
92Tick
93LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
94{
95    panic("O3CPU model does not work with atomic mode!");
96    return curTick;
97}
98
99template <class Impl>
100void
101LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
102{
103    panic("O3CPU doesn't expect recvFunctional callback!");
104}
105
106template <class Impl>
107void
108LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
109{
110    if (status == RangeChange)
111        return;
112
113    panic("O3CPU doesn't expect recvStatusChange callback!");
114}
115
116template <class Impl>
117bool
118LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
119{
120    lsq->completeDataAccess(pkt);
121    return true;
122}
123
124template <class Impl>
125void
126LSQUnit<Impl>::DcachePort::recvRetry()
127{
128    panic("Retry unsupported for now!");
129    // we shouldn't get a retry unless we have a packet that we're
130    // waiting to transmit
131/*
132    assert(cpu->dcache_pkt != NULL);
133    assert(cpu->_status == DcacheRetry);
134    PacketPtr tmp = cpu->dcache_pkt;
135    if (sendTiming(tmp)) {
136        cpu->_status = DcacheWaitResponse;
137        cpu->dcache_pkt = NULL;
138    }
139*/
140}
141
142template <class Impl>
143LSQUnit<Impl>::LSQUnit()
144    : loads(0), stores(0), storesToWB(0), stalled(false),
145      isStoreBlocked(false), isLoadBlocked(false),
146      loadBlockedHandled(false)
147{
148}
149
150template<class Impl>
151void
152LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
153                    unsigned maxSQEntries, unsigned id)
154{
155    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
156
157    switchedOut = false;
158
159    lsqID = id;
160
161    // Add 1 for the sentinel entry (they are circular queues).
162    LQEntries = maxLQEntries + 1;
163    SQEntries = maxSQEntries + 1;
164
165    loadQueue.resize(LQEntries);
166    storeQueue.resize(SQEntries);
167
168    loadHead = loadTail = 0;
169
170    storeHead = storeWBIdx = storeTail = 0;
171
172    usedPorts = 0;
173    cachePorts = params->cachePorts;
174
175    mem = params->mem;
176
177    memDepViolator = NULL;
178
179    blockedLoadSeqNum = 0;
180}
181
182template<class Impl>
183void
184LSQUnit<Impl>::setCPU(FullCPU *cpu_ptr)
185{
186    cpu = cpu_ptr;
187    dcachePort = new DcachePort(cpu, this);
188
189    Port *mem_dport = mem->getPort("");
190    dcachePort->setPeer(mem_dport);
191    mem_dport->setPeer(dcachePort);
192
193    if (cpu->checker) {
194        cpu->checker->setDcachePort(dcachePort);
195    }
196}
197
198template<class Impl>
199std::string
200LSQUnit<Impl>::name() const
201{
202    if (Impl::MaxThreads == 1) {
203        return iewStage->name() + ".lsq";
204    } else {
205        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
206    }
207}
208
209template<class Impl>
210void
211LSQUnit<Impl>::clearLQ()
212{
213    loadQueue.clear();
214}
215
216template<class Impl>
217void
218LSQUnit<Impl>::clearSQ()
219{
220    storeQueue.clear();
221}
222
223#if 0
224template<class Impl>
225void
226LSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
227{
228    DPRINTF(LSQUnit, "Setting the page table pointer.\n");
229    pTable = pt_ptr;
230}
231#endif
232
233template<class Impl>
234void
235LSQUnit<Impl>::switchOut()
236{
237    switchedOut = true;
238    for (int i = 0; i < loadQueue.size(); ++i)
239        loadQueue[i] = NULL;
240
241    assert(storesToWB == 0);
242}
243
244template<class Impl>
245void
246LSQUnit<Impl>::takeOverFrom()
247{
248    switchedOut = false;
249    loads = stores = storesToWB = 0;
250
251    loadHead = loadTail = 0;
252
253    storeHead = storeWBIdx = storeTail = 0;
254
255    usedPorts = 0;
256
257    memDepViolator = NULL;
258
259    blockedLoadSeqNum = 0;
260
261    stalled = false;
262    isLoadBlocked = false;
263    loadBlockedHandled = false;
264}
265
266template<class Impl>
267void
268LSQUnit<Impl>::resizeLQ(unsigned size)
269{
270    unsigned size_plus_sentinel = size + 1;
271    assert(size_plus_sentinel >= LQEntries);
272
273    if (size_plus_sentinel > LQEntries) {
274        while (size_plus_sentinel > loadQueue.size()) {
275            DynInstPtr dummy;
276            loadQueue.push_back(dummy);
277            LQEntries++;
278        }
279    } else {
280        LQEntries = size_plus_sentinel;
281    }
282
283}
284
285template<class Impl>
286void
287LSQUnit<Impl>::resizeSQ(unsigned size)
288{
289    unsigned size_plus_sentinel = size + 1;
290    if (size_plus_sentinel > SQEntries) {
291        while (size_plus_sentinel > storeQueue.size()) {
292            SQEntry dummy;
293            storeQueue.push_back(dummy);
294            SQEntries++;
295        }
296    } else {
297        SQEntries = size_plus_sentinel;
298    }
299}
300
301template <class Impl>
302void
303LSQUnit<Impl>::insert(DynInstPtr &inst)
304{
305    assert(inst->isMemRef());
306
307    assert(inst->isLoad() || inst->isStore());
308
309    if (inst->isLoad()) {
310        insertLoad(inst);
311    } else {
312        insertStore(inst);
313    }
314
315    inst->setInLSQ();
316}
317
318template <class Impl>
319void
320LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
321{
322    assert((loadTail + 1) % LQEntries != loadHead);
323    assert(loads < LQEntries);
324
325    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
326            load_inst->readPC(), loadTail, load_inst->seqNum);
327
328    load_inst->lqIdx = loadTail;
329
330    if (stores == 0) {
331        load_inst->sqIdx = -1;
332    } else {
333        load_inst->sqIdx = storeTail;
334    }
335
336    loadQueue[loadTail] = load_inst;
337
338    incrLdIdx(loadTail);
339
340    ++loads;
341}
342
343template <class Impl>
344void
345LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
346{
347    // Make sure it is not full before inserting an instruction.
348    assert((storeTail + 1) % SQEntries != storeHead);
349    assert(stores < SQEntries);
350
351    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
352            store_inst->readPC(), storeTail, store_inst->seqNum);
353
354    store_inst->sqIdx = storeTail;
355    store_inst->lqIdx = loadTail;
356
357    storeQueue[storeTail] = SQEntry(store_inst);
358
359    incrStIdx(storeTail);
360
361    ++stores;
362}
363
364template <class Impl>
365typename Impl::DynInstPtr
366LSQUnit<Impl>::getMemDepViolator()
367{
368    DynInstPtr temp = memDepViolator;
369
370    memDepViolator = NULL;
371
372    return temp;
373}
374
375template <class Impl>
376unsigned
377LSQUnit<Impl>::numFreeEntries()
378{
379    unsigned free_lq_entries = LQEntries - loads;
380    unsigned free_sq_entries = SQEntries - stores;
381
382    // Both the LQ and SQ entries have an extra dummy entry to differentiate
383    // empty/full conditions.  Subtract 1 from the free entries.
384    if (free_lq_entries < free_sq_entries) {
385        return free_lq_entries - 1;
386    } else {
387        return free_sq_entries - 1;
388    }
389}
390
391template <class Impl>
392int
393LSQUnit<Impl>::numLoadsReady()
394{
395    int load_idx = loadHead;
396    int retval = 0;
397
398    while (load_idx != loadTail) {
399        assert(loadQueue[load_idx]);
400
401        if (loadQueue[load_idx]->readyToIssue()) {
402            ++retval;
403        }
404    }
405
406    return retval;
407}
408
409template <class Impl>
410Fault
411LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
412{
413    // Execute a specific load.
414    Fault load_fault = NoFault;
415
416    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
417            inst->readPC(),inst->seqNum);
418
419    load_fault = inst->initiateAcc();
420
421    // If the instruction faulted, then we need to send it along to commit
422    // without the instruction completing.
423    if (load_fault != NoFault) {
424        // Send this instruction to commit, also make sure iew stage
425        // realizes there is activity.
426        iewStage->instToCommit(inst);
427        iewStage->activityThisCycle();
428    }
429
430    return load_fault;
431}
432
433template <class Impl>
434Fault
435LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
436{
437    using namespace TheISA;
438    // Make sure that a store exists.
439    assert(stores != 0);
440
441    int store_idx = store_inst->sqIdx;
442
443    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
444            store_inst->readPC(), store_inst->seqNum);
445
446    // Check the recently completed loads to see if any match this store's
447    // address.  If so, then we have a memory ordering violation.
448    int load_idx = store_inst->lqIdx;
449
450    Fault store_fault = store_inst->initiateAcc();
451
452    if (storeQueue[store_idx].size == 0) {
453        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
454                store_inst->readPC(),store_inst->seqNum);
455
456        return store_fault;
457    }
458
459    assert(store_fault == NoFault);
460
461    if (store_inst->isStoreConditional()) {
462        // Store conditionals need to set themselves as able to
463        // writeback if we haven't had a fault by here.
464        storeQueue[store_idx].canWB = true;
465
466        ++storesToWB;
467    }
468
469    if (!memDepViolator) {
470        while (load_idx != loadTail) {
471            // Really only need to check loads that have actually executed
472            // It's safe to check all loads because effAddr is set to
473            // InvalAddr when the dyn inst is created.
474
475            // @todo: For now this is extra conservative, detecting a
476            // violation if the addresses match assuming all accesses
477            // are quad word accesses.
478
479            // @todo: Fix this, magic number being used here
480            if ((loadQueue[load_idx]->effAddr >> 8) ==
481                (store_inst->effAddr >> 8)) {
482                // A load incorrectly passed this store.  Squash and refetch.
483                // For now return a fault to show that it was unsuccessful.
484                memDepViolator = loadQueue[load_idx];
485
486                return genMachineCheckFault();
487            }
488
489            incrLdIdx(load_idx);
490        }
491
492        // If we've reached this point, there was no violation.
493        memDepViolator = NULL;
494    }
495
496    return store_fault;
497}
498
499template <class Impl>
500void
501LSQUnit<Impl>::commitLoad()
502{
503    assert(loadQueue[loadHead]);
504
505    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
506            loadQueue[loadHead]->readPC());
507
508    loadQueue[loadHead] = NULL;
509
510    incrLdIdx(loadHead);
511
512    --loads;
513}
514
515template <class Impl>
516void
517LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
518{
519    assert(loads == 0 || loadQueue[loadHead]);
520
521    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
522        commitLoad();
523    }
524}
525
526template <class Impl>
527void
528LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
529{
530    assert(stores == 0 || storeQueue[storeHead].inst);
531
532    int store_idx = storeHead;
533
534    while (store_idx != storeTail) {
535        assert(storeQueue[store_idx].inst);
536        // Mark any stores that are now committed and have not yet
537        // been marked as able to write back.
538        if (!storeQueue[store_idx].canWB) {
539            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
540                break;
541            }
542            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
543                    "%#x [sn:%lli]\n",
544                    storeQueue[store_idx].inst->readPC(),
545                    storeQueue[store_idx].inst->seqNum);
546
547            storeQueue[store_idx].canWB = true;
548
549            ++storesToWB;
550        }
551
552        incrStIdx(store_idx);
553    }
554}
555
556template <class Impl>
557void
558LSQUnit<Impl>::writebackStores()
559{
560    while (storesToWB > 0 &&
561           storeWBIdx != storeTail &&
562           storeQueue[storeWBIdx].inst &&
563           storeQueue[storeWBIdx].canWB &&
564           usedPorts < cachePorts) {
565
566        if (isStoreBlocked) {
567            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
568                    " is blocked!\n");
569            break;
570        }
571
572        // Store didn't write any data so no need to write it back to
573        // memory.
574        if (storeQueue[storeWBIdx].size == 0) {
575            completeStore(storeWBIdx);
576
577            incrStIdx(storeWBIdx);
578
579            continue;
580        }
581
582        ++usedPorts;
583
584        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
585            incrStIdx(storeWBIdx);
586
587            continue;
588        }
589
590        assert(storeQueue[storeWBIdx].req);
591        assert(!storeQueue[storeWBIdx].committed);
592
593        DynInstPtr inst = storeQueue[storeWBIdx].inst;
594
595        Request *req = storeQueue[storeWBIdx].req;
596        storeQueue[storeWBIdx].committed = true;
597
598        assert(!inst->memData);
599        inst->memData = new uint8_t[64];
600        memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data,
601               req->getSize());
602
603        PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
604        data_pkt->dataStatic(inst->memData);
605
606        LSQSenderState *state = new LSQSenderState;
607        state->isLoad = false;
608        state->idx = storeWBIdx;
609        state->inst = inst;
610        data_pkt->senderState = state;
611
612        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
613                "to Addr:%#x, data:%#x [sn:%lli]\n",
614                storeWBIdx, storeQueue[storeWBIdx].inst->readPC(),
615                req->getPaddr(), *(inst->memData),
616                storeQueue[storeWBIdx].inst->seqNum);
617
618        if (!dcachePort->sendTiming(data_pkt)) {
619            // Need to handle becoming blocked on a store.
620            isStoreBlocked = true;
621        } else {
622            if (isStalled() &&
623                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
624                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
625                        "load idx:%i\n",
626                        stallingStoreIsn, stallingLoadIdx);
627                stalled = false;
628                stallingStoreIsn = 0;
629                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
630            }
631
632            if (!(req->getFlags() & LOCKED)) {
633                assert(!storeQueue[storeWBIdx].inst->isStoreConditional());
634                // Non-store conditionals do not need a writeback.
635                state->noWB = true;
636
637                // The store is basically completed at this time. This
638                // only works so long as the checker doesn't try to
639                // verify the value in memory for stores.
640                storeQueue[storeWBIdx].inst->setCompleted();
641                if (cpu->checker) {
642                    cpu->checker->tick(storeQueue[storeWBIdx].inst);
643                }
644            }
645
646            if (data_pkt->result != Packet::Success) {
647                DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
648                        storeWBIdx);
649
650                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
651                        storeQueue[storeWBIdx].inst->seqNum);
652
653                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
654
655                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
656
657                // @todo: Increment stat here.
658            } else {
659                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
660                        storeWBIdx);
661
662                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
663                        storeQueue[storeWBIdx].inst->seqNum);
664            }
665
666            incrStIdx(storeWBIdx);
667        }
668    }
669
670    // Not sure this should set it to 0.
671    usedPorts = 0;
672
673    assert(stores >= 0 && storesToWB >= 0);
674}
675
676/*template <class Impl>
677void
678LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
679{
680    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
681                                              mshrSeqNums.end(),
682                                              seqNum);
683
684    if (mshr_it != mshrSeqNums.end()) {
685        mshrSeqNums.erase(mshr_it);
686        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
687    }
688}*/
689
690template <class Impl>
691void
692LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
693{
694    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
695            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
696
697    int load_idx = loadTail;
698    decrLdIdx(load_idx);
699
700    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
701        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
702                "[sn:%lli]\n",
703                loadQueue[load_idx]->readPC(),
704                loadQueue[load_idx]->seqNum);
705
706        if (isStalled() && load_idx == stallingLoadIdx) {
707            stalled = false;
708            stallingStoreIsn = 0;
709            stallingLoadIdx = 0;
710        }
711
712        // Clear the smart pointer to make sure it is decremented.
713        loadQueue[load_idx]->squashed = true;
714        loadQueue[load_idx] = NULL;
715        --loads;
716
717        // Inefficient!
718        loadTail = load_idx;
719
720        decrLdIdx(load_idx);
721    }
722
723    if (isLoadBlocked) {
724        if (squashed_num < blockedLoadSeqNum) {
725            isLoadBlocked = false;
726            loadBlockedHandled = false;
727            blockedLoadSeqNum = 0;
728        }
729    }
730
731    int store_idx = storeTail;
732    decrStIdx(store_idx);
733
734    while (stores != 0 &&
735           storeQueue[store_idx].inst->seqNum > squashed_num) {
736        // Instructions marked as can WB are already committed.
737        if (storeQueue[store_idx].canWB) {
738            break;
739        }
740
741        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
742                "idx:%i [sn:%lli]\n",
743                storeQueue[store_idx].inst->readPC(),
744                store_idx, storeQueue[store_idx].inst->seqNum);
745
746        // I don't think this can happen.  It should have been cleared
747        // by the stalling load.
748        if (isStalled() &&
749            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
750            panic("Is stalled should have been cleared by stalling load!\n");
751            stalled = false;
752            stallingStoreIsn = 0;
753        }
754
755        // Clear the smart pointer to make sure it is decremented.
756        storeQueue[store_idx].inst->squashed = true;
757        storeQueue[store_idx].inst = NULL;
758        storeQueue[store_idx].canWB = 0;
759
760        storeQueue[store_idx].req = NULL;
761        --stores;
762
763        // Inefficient!
764        storeTail = store_idx;
765
766        decrStIdx(store_idx);
767    }
768}
769
770template <class Impl>
771void
772LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
773{
774    iewStage->wakeCPU();
775
776    // Squashed instructions do not need to complete their access.
777    if (inst->isSquashed()) {
778        assert(!inst->isStore());
779        return;
780    }
781
782    if (!inst->isExecuted()) {
783        inst->setExecuted();
784
785        // Complete access to copy data to proper place.
786        inst->completeAcc(pkt);
787    }
788
789    // Need to insert instruction into queue to commit
790    iewStage->instToCommit(inst);
791
792    iewStage->activityThisCycle();
793}
794
795template <class Impl>
796void
797LSQUnit<Impl>::completeStore(int store_idx)
798{
799    assert(storeQueue[store_idx].inst);
800    storeQueue[store_idx].completed = true;
801    --storesToWB;
802    // A bit conservative because a store completion may not free up entries,
803    // but hopefully avoids two store completions in one cycle from making
804    // the CPU tick twice.
805    cpu->activityThisCycle();
806
807    if (store_idx == storeHead) {
808        do {
809            incrStIdx(storeHead);
810
811            --stores;
812        } while (storeQueue[storeHead].completed &&
813                 storeHead != storeTail);
814
815        iewStage->updateLSQNextCycle = true;
816    }
817
818    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
819            "idx:%i\n",
820            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
821
822    if (isStalled() &&
823        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
824        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
825                "load idx:%i\n",
826                stallingStoreIsn, stallingLoadIdx);
827        stalled = false;
828        stallingStoreIsn = 0;
829        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
830    }
831
832    storeQueue[store_idx].inst->setCompleted();
833
834    // Tell the checker we've completed this instruction.  Some stores
835    // may get reported twice to the checker, but the checker can
836    // handle that case.
837    if (cpu->checker) {
838        cpu->checker->tick(storeQueue[store_idx].inst);
839    }
840}
841
842template <class Impl>
843inline void
844LSQUnit<Impl>::incrStIdx(int &store_idx)
845{
846    if (++store_idx >= SQEntries)
847        store_idx = 0;
848}
849
850template <class Impl>
851inline void
852LSQUnit<Impl>::decrStIdx(int &store_idx)
853{
854    if (--store_idx < 0)
855        store_idx += SQEntries;
856}
857
858template <class Impl>
859inline void
860LSQUnit<Impl>::incrLdIdx(int &load_idx)
861{
862    if (++load_idx >= LQEntries)
863        load_idx = 0;
864}
865
866template <class Impl>
867inline void
868LSQUnit<Impl>::decrLdIdx(int &load_idx)
869{
870    if (--load_idx < 0)
871        load_idx += LQEntries;
872}
873
874template <class Impl>
875void
876LSQUnit<Impl>::dumpInsts()
877{
878    cprintf("Load store queue: Dumping instructions.\n");
879    cprintf("Load queue size: %i\n", loads);
880    cprintf("Load queue: ");
881
882    int load_idx = loadHead;
883
884    while (load_idx != loadTail && loadQueue[load_idx]) {
885        cprintf("%#x ", loadQueue[load_idx]->readPC());
886
887        incrLdIdx(load_idx);
888    }
889
890    cprintf("Store queue size: %i\n", stores);
891    cprintf("Store queue: ");
892
893    int store_idx = storeHead;
894
895    while (store_idx != storeTail && storeQueue[store_idx].inst) {
896        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
897
898        incrStIdx(store_idx);
899    }
900
901    cprintf("\n");
902}
903