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