lsq_unit_impl.hh revision 2307
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//        if (fault != NoFault) {
676            //What should we do if there is a fault???
677            //for now panic
678//            panic("Page Table Fault!!!!!\n");
679//        }
680        switch(storeQueue[storeWBIdx].size) {
681          case 1:
682            cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
683            break;
684          case 2:
685            cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
686            break;
687          case 4:
688            cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
689            break;
690          case 8:
691            cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
692            break;
693          default:
694            panic("Unexpected store size!\n");
695        }
696
697        if (dcacheInterface) {
698            MemAccessResult result = dcacheInterface->access(req);
699
700            if (isStalled() &&
701                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
702                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
703                        "load idx:%i\n",
704                        stallingStoreIsn, stallingLoadIdx);
705                stalled = false;
706                stallingStoreIsn = 0;
707                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
708            }
709
710            if (result != MA_HIT && dcacheInterface->doEvents()) {
711                typename IEW::LdWritebackEvent *wb = NULL;
712                if (req->flags & LOCKED) {
713                    // Stx_C does not generate a system port transaction.
714/*
715                    if (cpu->lockFlag && cpu->lockAddr == req->paddr) {
716                        req->result=1;
717                    } else {
718                        req->result = 0;
719                    }
720*/
721                    wb = new typename IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
722                                                            iewStage);
723                }
724
725                DPRINTF(LSQUnit,"D-Cache Write Miss!\n");
726
727                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
728                        storeQueue[storeWBIdx].inst->seqNum);
729
730                // Will stores need their own kind of writeback events?
731                // Do stores even need writeback events?
732                assert(!req->completionEvent);
733                req->completionEvent = new
734                    StoreCompletionEvent(storeWBIdx, wb, this);
735
736                lastDcacheStall = curTick;
737
738//                _status = DcacheMissStall;
739
740                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
741
742                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
743
744                // Increment stat here or something
745            } else {
746                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
747                        storeWBIdx);
748
749                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
750                        storeQueue[storeWBIdx].inst->seqNum);
751
752
753                if (req->flags & LOCKED) {
754                    // Stx_C does not generate a system port transaction.
755/*
756                    if (req->flags & UNCACHEABLE) {
757                        req->result = 2;
758                    } else {
759                        if (cpu->lockFlag && cpu->lockAddr == req->paddr) {
760                            req->result=1;
761                        } else {
762                            req->result = 0;
763                        }
764                    }
765*/
766                    typename IEW::LdWritebackEvent *wb =
767                        new typename IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
768                                                           iewStage);
769                    wb->schedule(curTick);
770                }
771
772                completeStore(storeWBIdx);
773            }
774
775            incrStIdx(storeWBIdx);
776        } else {
777            panic("Must HAVE DCACHE!!!!!\n");
778        }
779    }
780
781    // Not sure this should set it to 0.
782    usedPorts = 0;
783
784    assert(stores >= 0 && storesToWB >= 0);
785}
786
787/*template <class Impl>
788void
789LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
790{
791    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
792                                              mshrSeqNums.end(),
793                                              seqNum);
794
795    if (mshr_it != mshrSeqNums.end()) {
796        mshrSeqNums.erase(mshr_it);
797        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
798    }
799}*/
800
801template <class Impl>
802void
803LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
804{
805    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
806            "(Loads:%i Stores:%i)\n",squashed_num,loads,stores);
807
808    int load_idx = loadTail;
809    decrLdIdx(load_idx);
810
811    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
812
813        // Clear the smart pointer to make sure it is decremented.
814        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
815                "[sn:%lli]\n",
816                loadQueue[load_idx]->readPC(),
817                loadQueue[load_idx]->seqNum);
818
819        if (isStalled() && load_idx == stallingLoadIdx) {
820            stalled = false;
821            stallingStoreIsn = 0;
822            stallingLoadIdx = 0;
823        }
824
825        loadQueue[load_idx]->squashed = true;
826        loadQueue[load_idx] = NULL;
827        --loads;
828
829        // Inefficient!
830        loadTail = load_idx;
831
832        decrLdIdx(load_idx);
833    }
834
835    if (isLoadBlocked) {
836        if (squashed_num < blockedLoadSeqNum) {
837            isLoadBlocked = false;
838            loadBlockedHandled = false;
839            blockedLoadSeqNum = 0;
840        }
841    }
842
843    int store_idx = storeTail;
844    decrStIdx(store_idx);
845
846    while (stores != 0 &&
847           storeQueue[store_idx].inst->seqNum > squashed_num) {
848
849        if (storeQueue[store_idx].canWB) {
850            break;
851        }
852
853        // Clear the smart pointer to make sure it is decremented.
854        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
855                "idx:%i [sn:%lli]\n",
856                storeQueue[store_idx].inst->readPC(),
857                store_idx, storeQueue[store_idx].inst->seqNum);
858
859        // I don't think this can happen.  It should have been cleared by the
860        // stalling load.
861        if (isStalled() &&
862            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
863            panic("Is stalled should have been cleared by stalling load!\n");
864            stalled = false;
865            stallingStoreIsn = 0;
866        }
867
868        storeQueue[store_idx].inst->squashed = true;
869        storeQueue[store_idx].inst = NULL;
870        storeQueue[store_idx].canWB = 0;
871
872        if (storeQueue[store_idx].req) {
873            assert(!storeQueue[store_idx].req->completionEvent);
874        }
875        storeQueue[store_idx].req = NULL;
876        --stores;
877
878        // Inefficient!
879        storeTail = store_idx;
880
881        decrStIdx(store_idx);
882    }
883}
884
885template <class Impl>
886void
887LSQUnit<Impl>::dumpInsts()
888{
889    cprintf("Load store queue: Dumping instructions.\n");
890    cprintf("Load queue size: %i\n", loads);
891    cprintf("Load queue: ");
892
893    int load_idx = loadHead;
894
895    while (load_idx != loadTail && loadQueue[load_idx]) {
896        cprintf("%#x ", loadQueue[load_idx]->readPC());
897
898        incrLdIdx(load_idx);
899    }
900
901    cprintf("Store queue size: %i\n", stores);
902    cprintf("Store queue: ");
903
904    int store_idx = storeHead;
905
906    while (store_idx != storeTail && storeQueue[store_idx].inst) {
907        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
908
909        incrStIdx(store_idx);
910    }
911
912    cprintf("\n");
913}
914
915template <class Impl>
916void
917LSQUnit<Impl>::completeStore(int store_idx)
918{
919    assert(storeQueue[store_idx].inst);
920    storeQueue[store_idx].completed = true;
921    --storesToWB;
922    // A bit conservative because a store completion may not free up entries,
923    // but hopefully avoids two store completions in one cycle from making
924    // the CPU tick twice.
925    cpu->activityThisCycle();
926
927    if (store_idx == storeHead) {
928        do {
929            incrStIdx(storeHead);
930
931            --stores;
932        } while (storeQueue[storeHead].completed &&
933                 storeHead != storeTail);
934
935        iewStage->updateLSQNextCycle = true;
936    }
937
938    DPRINTF(LSQUnit, "Store head idx:%i\n", storeHead);
939
940    if (isStalled() &&
941        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
942        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
943                "load idx:%i\n",
944                stallingStoreIsn, stallingLoadIdx);
945        stalled = false;
946        stallingStoreIsn = 0;
947        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
948    }
949}
950
951template <class Impl>
952inline void
953LSQUnit<Impl>::incrStIdx(int &store_idx)
954{
955    if (++store_idx >= SQEntries)
956        store_idx = 0;
957}
958
959template <class Impl>
960inline void
961LSQUnit<Impl>::decrStIdx(int &store_idx)
962{
963    if (--store_idx < 0)
964        store_idx += SQEntries;
965}
966
967template <class Impl>
968inline void
969LSQUnit<Impl>::incrLdIdx(int &load_idx)
970{
971    if (++load_idx >= LQEntries)
972        load_idx = 0;
973}
974
975template <class Impl>
976inline void
977LSQUnit<Impl>::decrLdIdx(int &load_idx)
978{
979    if (--load_idx < 0)
980        load_idx += LQEntries;
981}
982