lsq_unit_impl.hh revision 2310
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
29#include "cpu/o3/lsq_unit.hh"
30#include "base/str.hh"
31
32template <class Impl>
33LSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
34                                                          Event *wb_event,
35                                                          LSQUnit<Impl> *lsq_ptr)
36    : Event(&mainEventQueue),
37      storeIdx(store_idx),
38      wbEvent(wb_event),
39      lsqPtr(lsq_ptr)
40{
41    this->setFlags(Event::AutoDelete);
42}
43
44template <class Impl>
45void
46LSQUnit<Impl>::StoreCompletionEvent::process()
47{
48    DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
49    DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
50
51    //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
52
53    if (lsqPtr->isSwitchedOut())
54        return;
55
56    lsqPtr->cpu->wakeCPU();
57    if (wbEvent)
58        wbEvent->process();
59    lsqPtr->completeStore(storeIdx);
60}
61
62template <class Impl>
63const char *
64LSQUnit<Impl>::StoreCompletionEvent::description()
65{
66    return "LSQ store completion event";
67}
68
69template <class Impl>
70LSQUnit<Impl>::LSQUnit()
71    : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
72      loadBlockedHandled(false)
73{
74}
75
76template<class Impl>
77void
78LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
79                    unsigned maxSQEntries, unsigned id)
80
81{
82    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
83
84    switchedOut = false;
85
86    lsqID = id;
87
88    LQEntries = maxLQEntries;
89    SQEntries = maxSQEntries;
90
91    loadQueue.resize(LQEntries);
92    storeQueue.resize(SQEntries);
93
94
95    // May want to initialize these entries to NULL
96
97    loadHead = loadTail = 0;
98
99    storeHead = storeWBIdx = storeTail = 0;
100
101    usedPorts = 0;
102    cachePorts = params->cachePorts;
103
104    dcacheInterface = params->dcacheInterface;
105
106    loadFaultInst = storeFaultInst = memDepViolator = NULL;
107
108    blockedLoadSeqNum = 0;
109}
110
111template<class Impl>
112std::string
113LSQUnit<Impl>::name() const
114{
115    if (Impl::MaxThreads == 1) {
116        return iewStage->name() + ".lsq";
117    } else {
118        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
119    }
120}
121
122template<class Impl>
123void
124LSQUnit<Impl>::clearLQ()
125{
126    loadQueue.clear();
127}
128
129template<class Impl>
130void
131LSQUnit<Impl>::clearSQ()
132{
133    storeQueue.clear();
134}
135
136#if 0
137template<class Impl>
138void
139LSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
140{
141    DPRINTF(LSQUnit, "Setting the page table pointer.\n");
142    pTable = pt_ptr;
143}
144#endif
145
146template<class Impl>
147void
148LSQUnit<Impl>::switchOut()
149{
150    switchedOut = true;
151    for (int i = 0; i < loadQueue.size(); ++i)
152        loadQueue[i] = NULL;
153
154    while (storesToWB > 0 &&
155           storeWBIdx != storeTail &&
156           storeQueue[storeWBIdx].inst &&
157           storeQueue[storeWBIdx].canWB) {
158
159        if (storeQueue[storeWBIdx].size == 0 ||
160            storeQueue[storeWBIdx].inst->isDataPrefetch() ||
161            storeQueue[storeWBIdx].committed ||
162            storeQueue[storeWBIdx].req->flags & LOCKED) {
163            incrStIdx(storeWBIdx);
164
165            continue;
166        }
167
168        assert(storeQueue[storeWBIdx].req);
169        assert(!storeQueue[storeWBIdx].committed);
170
171        MemReqPtr req = storeQueue[storeWBIdx].req;
172        storeQueue[storeWBIdx].committed = true;
173
174        req->cmd = Write;
175        req->completionEvent = NULL;
176        req->time = curTick;
177        assert(!req->data);
178        req->data = new uint8_t[64];
179        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
180
181        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
182                "to Addr:%#x, data:%#x [sn:%lli]\n",
183                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
184                req->paddr, *(req->data),
185                storeQueue[storeWBIdx].inst->seqNum);
186
187        switch(storeQueue[storeWBIdx].size) {
188          case 1:
189            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
190            break;
191          case 2:
192            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
193            break;
194          case 4:
195            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
196            break;
197          case 8:
198            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
199            break;
200          default:
201            panic("Unexpected store size!\n");
202        }
203        incrStIdx(storeWBIdx);
204    }
205}
206
207template<class Impl>
208void
209LSQUnit<Impl>::takeOverFrom()
210{
211    switchedOut = false;
212    loads = stores = storesToWB = 0;
213
214    loadHead = loadTail = 0;
215
216    storeHead = storeWBIdx = storeTail = 0;
217
218    usedPorts = 0;
219
220    loadFaultInst = storeFaultInst = memDepViolator = NULL;
221
222    blockedLoadSeqNum = 0;
223
224    stalled = false;
225    isLoadBlocked = false;
226    loadBlockedHandled = false;
227}
228
229template<class Impl>
230void
231LSQUnit<Impl>::resizeLQ(unsigned size)
232{
233    assert( size >= LQEntries);
234
235    if (size > LQEntries) {
236        while (size > loadQueue.size()) {
237            DynInstPtr dummy;
238            loadQueue.push_back(dummy);
239            LQEntries++;
240        }
241    } else {
242        LQEntries = size;
243    }
244
245}
246
247template<class Impl>
248void
249LSQUnit<Impl>::resizeSQ(unsigned size)
250{
251    if (size > SQEntries) {
252        while (size > storeQueue.size()) {
253            SQEntry dummy;
254            storeQueue.push_back(dummy);
255            SQEntries++;
256        }
257    } else {
258        SQEntries = size;
259    }
260}
261
262template <class Impl>
263void
264LSQUnit<Impl>::insert(DynInstPtr &inst)
265{
266    // Make sure we really have a memory reference.
267    assert(inst->isMemRef());
268
269    // Make sure it's one of the two classes of memory references.
270    assert(inst->isLoad() || inst->isStore());
271
272    if (inst->isLoad()) {
273        insertLoad(inst);
274    } else {
275        insertStore(inst);
276    }
277
278    inst->setInLSQ();
279}
280
281template <class Impl>
282void
283LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
284{
285    assert((loadTail + 1) % LQEntries != loadHead && loads < LQEntries);
286
287    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
288            load_inst->readPC(), loadTail, load_inst->seqNum);
289
290    load_inst->lqIdx = loadTail;
291
292    if (stores == 0) {
293        load_inst->sqIdx = -1;
294    } else {
295        load_inst->sqIdx = storeTail;
296    }
297
298    loadQueue[loadTail] = load_inst;
299
300    incrLdIdx(loadTail);
301
302    ++loads;
303}
304
305template <class Impl>
306void
307LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
308{
309    // Make sure it is not full before inserting an instruction.
310    assert((storeTail + 1) % SQEntries != storeHead);
311    assert(stores < SQEntries);
312
313    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
314            store_inst->readPC(), storeTail, store_inst->seqNum);
315
316    store_inst->sqIdx = storeTail;
317    store_inst->lqIdx = loadTail;
318
319    storeQueue[storeTail] = SQEntry(store_inst);
320
321    incrStIdx(storeTail);
322
323    ++stores;
324
325}
326
327template <class Impl>
328typename Impl::DynInstPtr
329LSQUnit<Impl>::getMemDepViolator()
330{
331    DynInstPtr temp = memDepViolator;
332
333    memDepViolator = NULL;
334
335    return temp;
336}
337
338template <class Impl>
339unsigned
340LSQUnit<Impl>::numFreeEntries()
341{
342    unsigned free_lq_entries = LQEntries - loads;
343    unsigned free_sq_entries = SQEntries - stores;
344
345    // Both the LQ and SQ entries have an extra dummy entry to differentiate
346    // empty/full conditions.  Subtract 1 from the free entries.
347    if (free_lq_entries < free_sq_entries) {
348        return free_lq_entries - 1;
349    } else {
350        return free_sq_entries - 1;
351    }
352}
353
354template <class Impl>
355int
356LSQUnit<Impl>::numLoadsReady()
357{
358    int load_idx = loadHead;
359    int retval = 0;
360
361    while (load_idx != loadTail) {
362        assert(loadQueue[load_idx]);
363
364        if (loadQueue[load_idx]->readyToIssue()) {
365            ++retval;
366        }
367    }
368
369    return retval;
370}
371
372#if 0
373template <class Impl>
374Fault
375LSQUnit<Impl>::executeLoad()
376{
377    Fault load_fault = NoFault;
378    DynInstPtr load_inst;
379
380    assert(readyLoads.size() != 0);
381
382    // Execute a ready load.
383    LdMapIt ready_it = readyLoads.begin();
384
385    load_inst = (*ready_it).second;
386
387    // Execute the instruction, which is held in the data portion of the
388    // iterator.
389    load_fault = load_inst->execute();
390
391    // If it executed successfully, then switch it over to the executed
392    // loads list.
393    if (load_fault == NoFault) {
394        executedLoads[load_inst->seqNum] = load_inst;
395
396        readyLoads.erase(ready_it);
397    } else {
398        loadFaultInst = load_inst;
399    }
400
401    return load_fault;
402}
403#endif
404
405template <class Impl>
406Fault
407LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
408{
409    // Execute a specific load.
410    Fault load_fault = NoFault;
411
412    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
413            inst->readPC(),inst->seqNum);
414
415    // Make sure it's really in the list.
416    // Normally it should always be in the list.  However,
417    /* due to a syscall it may not be the list.
418#ifdef DEBUG
419    int i = loadHead;
420    while (1) {
421        if (i == loadTail && !find(inst)) {
422            assert(0 && "Load not in the queue!");
423        } else if (loadQueue[i] == inst) {
424            break;
425        }
426
427        i = i + 1;
428        if (i >= LQEntries) {
429            i = 0;
430        }
431    }
432#endif // DEBUG*/
433
434//    load_fault = inst->initiateAcc();
435    load_fault = inst->execute();
436
437    // If the instruction faulted, then we need to send it along to commit
438    // without the instruction completing.
439    if (load_fault != NoFault) {
440        // Maybe just set it as can commit here, although that might cause
441        // some other problems with sending traps to the ROB too quickly.
442        iewStage->instToCommit(inst);
443        iewStage->activityThisCycle();
444    }
445
446    return load_fault;
447}
448
449template <class Impl>
450Fault
451LSQUnit<Impl>::executeLoad(int lq_idx)
452{
453    // Very hackish.  Not sure the best way to check that this
454    // instruction is at the head of the ROB.  I should have some sort
455    // of extra information here so that I'm not overloading the
456    // canCommit signal for 15 different things.
457    loadQueue[lq_idx]->setCanCommit();
458    Fault ret_fault = executeLoad(loadQueue[lq_idx]);
459    loadQueue[lq_idx]->clearCanCommit();
460    return ret_fault;
461}
462
463template <class Impl>
464Fault
465LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
466{
467    using namespace TheISA;
468    // Make sure that a store exists.
469    assert(stores != 0);
470
471    int store_idx = store_inst->sqIdx;
472
473    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
474            store_inst->readPC(), store_inst->seqNum);
475
476    // Check the recently completed loads to see if any match this store's
477    // address.  If so, then we have a memory ordering violation.
478    int load_idx = store_inst->lqIdx;
479
480    Fault store_fault = store_inst->initiateAcc();
481//    Fault store_fault = store_inst->execute();
482
483    // Store size should now be available.  Use it to get proper offset for
484    // addr comparisons.
485    int size = storeQueue[store_idx].size;
486
487    if (size == 0) {
488        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
489                store_inst->readPC(),store_inst->seqNum);
490
491        return store_fault;
492    }
493
494    assert(store_fault == NoFault);
495
496    if (!storeFaultInst) {
497        if (store_fault != NoFault) {
498            panic("Fault in a store instruction!");
499            storeFaultInst = store_inst;
500        } else if (store_inst->isNonSpeculative()) {
501            // Nonspeculative accesses (namely store conditionals)
502            // need to set themselves as able to writeback if we
503            // haven't had a fault by here.
504            storeQueue[store_idx].canWB = true;
505
506            ++storesToWB;
507        }
508    }
509
510    if (!memDepViolator) {
511        while (load_idx != loadTail) {
512            // Actually should only check loads that have actually executed
513            // Might be safe because effAddr is set to InvalAddr when the
514            // dyn inst is created.
515
516            // Must actually check all addrs in the proper size range
517            // Which is more correct than needs to be.  What if for now we just
518            // assume all loads are quad-word loads, and do the addr based
519            // on that.
520            // @todo: Fix this, magic number being used here
521            if ((loadQueue[load_idx]->effAddr >> 8) ==
522                (store_inst->effAddr >> 8)) {
523                // A load incorrectly passed this store.  Squash and refetch.
524                // For now return a fault to show that it was unsuccessful.
525                memDepViolator = loadQueue[load_idx];
526
527                return genMachineCheckFault();
528            }
529
530            incrLdIdx(load_idx);
531        }
532
533        // If we've reached this point, there was no violation.
534        memDepViolator = NULL;
535    }
536
537    return store_fault;
538}
539
540template <class Impl>
541void
542LSQUnit<Impl>::commitLoad()
543{
544    assert(loadQueue[loadHead]);
545
546    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
547            loadQueue[loadHead]->readPC());
548
549
550    loadQueue[loadHead] = NULL;
551
552    incrLdIdx(loadHead);
553
554    --loads;
555}
556
557template <class Impl>
558void
559LSQUnit<Impl>::commitLoad(InstSeqNum &inst)
560{
561    // Hopefully I don't use this function too much
562    panic("Don't use this function!");
563
564    int i = loadHead;
565    while (1) {
566        if (i == loadTail) {
567            assert(0 && "Load not in the queue!");
568        } else if (loadQueue[i]->seqNum == inst) {
569            break;
570        }
571
572        ++i;
573        if (i >= LQEntries) {
574            i = 0;
575        }
576    }
577
578    loadQueue[i]->removeInLSQ();
579    loadQueue[i] = NULL;
580    --loads;
581}
582
583template <class Impl>
584void
585LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
586{
587    assert(loads == 0 || loadQueue[loadHead]);
588
589    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
590        commitLoad();
591    }
592}
593
594template <class Impl>
595void
596LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
597{
598    assert(stores == 0 || storeQueue[storeHead].inst);
599
600    int store_idx = storeHead;
601
602    while (store_idx != storeTail) {
603        assert(storeQueue[store_idx].inst);
604        if (!storeQueue[store_idx].canWB) {
605            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
606                break;
607            }
608            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
609                    "%#x [sn:%lli]\n",
610                    storeQueue[store_idx].inst->readPC(),
611                    storeQueue[store_idx].inst->seqNum);
612
613            storeQueue[store_idx].canWB = true;
614
615//            --stores;
616            ++storesToWB;
617        }
618
619        incrStIdx(store_idx);
620    }
621}
622
623template <class Impl>
624void
625LSQUnit<Impl>::writebackStores()
626{
627    while (storesToWB > 0 &&
628           storeWBIdx != storeTail &&
629           storeQueue[storeWBIdx].inst &&
630           storeQueue[storeWBIdx].canWB &&
631           usedPorts < cachePorts) {
632
633        if (storeQueue[storeWBIdx].size == 0) {
634            completeStore(storeWBIdx);
635
636            incrStIdx(storeWBIdx);
637
638            continue;
639        }
640
641        if (dcacheInterface && dcacheInterface->isBlocked()) {
642            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
643                    " is blocked!\n");
644            break;
645        }
646
647        ++usedPorts;
648
649        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
650            incrStIdx(storeWBIdx);
651
652            continue;
653        }
654
655        assert(storeQueue[storeWBIdx].req);
656        assert(!storeQueue[storeWBIdx].committed);
657
658        MemReqPtr req = storeQueue[storeWBIdx].req;
659        storeQueue[storeWBIdx].committed = true;
660
661//	Fault fault = cpu->translateDataWriteReq(req);
662        req->cmd = Write;
663        req->completionEvent = NULL;
664        req->time = curTick;
665        assert(!req->data);
666        req->data = new uint8_t[64];
667        memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
668
669        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
670                "to Addr:%#x, data:%#x [sn:%lli]\n",
671                storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
672                req->paddr, *(req->data),
673                storeQueue[storeWBIdx].inst->seqNum);
674
675        switch(storeQueue[storeWBIdx].size) {
676          case 1:
677            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
678            break;
679          case 2:
680            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
681            break;
682          case 4:
683            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
684            break;
685          case 8:
686            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
687            break;
688          default:
689            panic("Unexpected store size!\n");
690        }
691        if (!(req->flags & LOCKED)) {
692            storeQueue[storeWBIdx].inst->setCompleted();
693        }
694
695        if (dcacheInterface) {
696            assert(!req->completionEvent);
697            StoreCompletionEvent *store_event = new
698                StoreCompletionEvent(storeWBIdx, NULL, this);
699            req->completionEvent = store_event;
700
701            MemAccessResult result = dcacheInterface->access(req);
702
703            if (isStalled() &&
704                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
705                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
706                        "load idx:%i\n",
707                        stallingStoreIsn, stallingLoadIdx);
708                stalled = false;
709                stallingStoreIsn = 0;
710                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
711            }
712
713            if (result != MA_HIT && dcacheInterface->doEvents()) {
714                typename IEW::LdWritebackEvent *wb = NULL;
715                if (req->flags & LOCKED) {
716                    // Stx_C should not generate a system port transaction,
717                    // but that might be hard to accomplish.
718                    wb = new typename
719                        IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
720                                              iewStage);
721                    store_event->wbEvent = wb;
722                }
723
724                DPRINTF(LSQUnit,"D-Cache Write Miss!\n");
725
726                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
727                        storeQueue[storeWBIdx].inst->seqNum);
728
729                lastDcacheStall = curTick;
730
731//                _status = DcacheMissStall;
732
733                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
734
735                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
736
737                // Increment stat here or something
738            } else {
739                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
740                        storeWBIdx);
741
742                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
743                        storeQueue[storeWBIdx].inst->seqNum);
744
745
746                if (req->flags & LOCKED) {
747                    // Stx_C does not generate a system port transaction.
748/*
749                    if (req->flags & UNCACHEABLE) {
750                        req->result = 2;
751                    } else {
752                        if (cpu->lockFlag && cpu->lockAddr == req->paddr) {
753                            req->result=1;
754                        } else {
755                            req->result = 0;
756                        }
757                    }
758*/
759                    typename IEW::LdWritebackEvent *wb =
760                        new typename IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
761                                                           iewStage);
762                    store_event->wbEvent = wb;
763                }
764            }
765
766            incrStIdx(storeWBIdx);
767        } else {
768            panic("Must HAVE DCACHE!!!!!\n");
769        }
770    }
771
772    // Not sure this should set it to 0.
773    usedPorts = 0;
774
775    assert(stores >= 0 && storesToWB >= 0);
776}
777
778/*template <class Impl>
779void
780LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
781{
782    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
783                                              mshrSeqNums.end(),
784                                              seqNum);
785
786    if (mshr_it != mshrSeqNums.end()) {
787        mshrSeqNums.erase(mshr_it);
788        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
789    }
790}*/
791
792template <class Impl>
793void
794LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
795{
796    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
797            "(Loads:%i Stores:%i)\n",squashed_num,loads,stores);
798
799    int load_idx = loadTail;
800    decrLdIdx(load_idx);
801
802    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
803
804        // Clear the smart pointer to make sure it is decremented.
805        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
806                "[sn:%lli]\n",
807                loadQueue[load_idx]->readPC(),
808                loadQueue[load_idx]->seqNum);
809
810        if (isStalled() && load_idx == stallingLoadIdx) {
811            stalled = false;
812            stallingStoreIsn = 0;
813            stallingLoadIdx = 0;
814        }
815
816        loadQueue[load_idx]->squashed = true;
817        loadQueue[load_idx] = NULL;
818        --loads;
819
820        // Inefficient!
821        loadTail = load_idx;
822
823        decrLdIdx(load_idx);
824    }
825
826    if (isLoadBlocked) {
827        if (squashed_num < blockedLoadSeqNum) {
828            isLoadBlocked = false;
829            loadBlockedHandled = false;
830            blockedLoadSeqNum = 0;
831        }
832    }
833
834    int store_idx = storeTail;
835    decrStIdx(store_idx);
836
837    while (stores != 0 &&
838           storeQueue[store_idx].inst->seqNum > squashed_num) {
839
840        if (storeQueue[store_idx].canWB) {
841            break;
842        }
843
844        // Clear the smart pointer to make sure it is decremented.
845        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
846                "idx:%i [sn:%lli]\n",
847                storeQueue[store_idx].inst->readPC(),
848                store_idx, storeQueue[store_idx].inst->seqNum);
849
850        // I don't think this can happen.  It should have been cleared by the
851        // stalling load.
852        if (isStalled() &&
853            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
854            panic("Is stalled should have been cleared by stalling load!\n");
855            stalled = false;
856            stallingStoreIsn = 0;
857        }
858
859        storeQueue[store_idx].inst->squashed = true;
860        storeQueue[store_idx].inst = NULL;
861        storeQueue[store_idx].canWB = 0;
862
863        if (storeQueue[store_idx].req) {
864            assert(!storeQueue[store_idx].req->completionEvent);
865        }
866        storeQueue[store_idx].req = NULL;
867        --stores;
868
869        // Inefficient!
870        storeTail = store_idx;
871
872        decrStIdx(store_idx);
873    }
874}
875
876template <class Impl>
877void
878LSQUnit<Impl>::dumpInsts()
879{
880    cprintf("Load store queue: Dumping instructions.\n");
881    cprintf("Load queue size: %i\n", loads);
882    cprintf("Load queue: ");
883
884    int load_idx = loadHead;
885
886    while (load_idx != loadTail && loadQueue[load_idx]) {
887        cprintf("%#x ", loadQueue[load_idx]->readPC());
888
889        incrLdIdx(load_idx);
890    }
891
892    cprintf("Store queue size: %i\n", stores);
893    cprintf("Store queue: ");
894
895    int store_idx = storeHead;
896
897    while (store_idx != storeTail && storeQueue[store_idx].inst) {
898        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
899
900        incrStIdx(store_idx);
901    }
902
903    cprintf("\n");
904}
905
906template <class Impl>
907void
908LSQUnit<Impl>::completeStore(int store_idx)
909{
910    assert(storeQueue[store_idx].inst);
911    storeQueue[store_idx].completed = true;
912    --storesToWB;
913    // A bit conservative because a store completion may not free up entries,
914    // but hopefully avoids two store completions in one cycle from making
915    // the CPU tick twice.
916    cpu->activityThisCycle();
917
918    if (store_idx == storeHead) {
919        do {
920            incrStIdx(storeHead);
921
922            --stores;
923        } while (storeQueue[storeHead].completed &&
924                 storeHead != storeTail);
925
926        iewStage->updateLSQNextCycle = true;
927    }
928
929    DPRINTF(LSQUnit, "Store head idx:%i\n", storeHead);
930
931    if (isStalled() &&
932        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
933        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
934                "load idx:%i\n",
935                stallingStoreIsn, stallingLoadIdx);
936        stalled = false;
937        stallingStoreIsn = 0;
938        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
939    }
940}
941
942template <class Impl>
943inline void
944LSQUnit<Impl>::incrStIdx(int &store_idx)
945{
946    if (++store_idx >= SQEntries)
947        store_idx = 0;
948}
949
950template <class Impl>
951inline void
952LSQUnit<Impl>::decrStIdx(int &store_idx)
953{
954    if (--store_idx < 0)
955        store_idx += SQEntries;
956}
957
958template <class Impl>
959inline void
960LSQUnit<Impl>::incrLdIdx(int &load_idx)
961{
962    if (++load_idx >= LQEntries)
963        load_idx = 0;
964}
965
966template <class Impl>
967inline void
968LSQUnit<Impl>::decrLdIdx(int &load_idx)
969{
970    if (--load_idx < 0)
971        load_idx += LQEntries;
972}
973