gem5 v24.0.0.0
Loading...
Searching...
No Matches
lsq_unit.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2014, 2017-2021 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#include "cpu/o3/lsq_unit.hh"
43
45#include "base/str.hh"
46#include "cpu/checker/cpu.hh"
47#include "cpu/o3/dyn_inst.hh"
48#include "cpu/o3/limits.hh"
49#include "cpu/o3/lsq.hh"
50#include "debug/Activity.hh"
51#include "debug/HtmCpu.hh"
52#include "debug/IEW.hh"
53#include "debug/LSQUnit.hh"
54#include "debug/O3PipeView.hh"
55#include "mem/packet.hh"
56#include "mem/request.hh"
57
58namespace gem5
59{
60
61namespace o3
62{
63
65 PacketPtr _pkt, LSQUnit *lsq_ptr)
66 : Event(Default_Pri, AutoDelete),
67 inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
68{
69 assert(_inst->savedRequest);
70 _inst->savedRequest->writebackScheduled();
71}
72
73void
75{
76 assert(!lsqPtr->cpu->switchedOut());
77
78 lsqPtr->writeback(inst, pkt);
79
80 assert(inst->savedRequest);
81 inst->savedRequest->writebackDone();
82 delete pkt;
83}
84
85const char *
87{
88 return "Store writeback";
89}
90
91bool
93{
94 LSQRequest *request = dynamic_cast<LSQRequest*>(pkt->senderState);
95 assert(request != nullptr);
96 bool ret = true;
97 /* Check that the request is still alive before any further action. */
98 if (!request->isReleased()) {
99 ret = request->recvTimingResp(pkt);
100 }
101 return ret;
102}
103
104void
106{
107 LSQRequest *request = dynamic_cast<LSQRequest *>(pkt->senderState);
108 DynInstPtr inst = request->instruction();
109
110 // hardware transactional memory
111 // sanity check
112 if (pkt->isHtmTransactional() && !inst->isSquashed()) {
113 assert(inst->getHtmTransactionUid() == pkt->getHtmTransactionUid());
114 }
115
116 // if in a HTM transaction, it's possible
117 // to abort within the cache hierarchy.
118 // This is signalled back to the processor
119 // through responses to memory requests.
120 if (pkt->htmTransactionFailedInCache()) {
121 // cannot do this for write requests because
122 // they cannot tolerate faults
123 const HtmCacheFailure htm_rc =
125 if (pkt->isWrite()) {
126 DPRINTF(HtmCpu,
127 "store notification (ignored) of HTM transaction failure "
128 "in cache - addr=0x%lx - rc=%s - htmUid=%d\n",
129 pkt->getAddr(), htmFailureToStr(htm_rc),
130 pkt->getHtmTransactionUid());
131 } else {
132 HtmFailureFaultCause fail_reason =
134
135 if (htm_rc == HtmCacheFailure::FAIL_SELF) {
136 fail_reason = HtmFailureFaultCause::SIZE;
137 } else if (htm_rc == HtmCacheFailure::FAIL_REMOTE) {
138 fail_reason = HtmFailureFaultCause::MEMORY;
139 } else if (htm_rc == HtmCacheFailure::FAIL_OTHER) {
140 // these are likely loads that were issued out of order
141 // they are faulted here, but it's unlikely that these will
142 // ever reach the commit head.
143 fail_reason = HtmFailureFaultCause::OTHER;
144 } else {
145 panic("HTM error - unhandled return code from cache (%s)",
146 htmFailureToStr(htm_rc));
147 }
148
149 inst->fault =
150 std::make_shared<GenericHtmFailureFault>(
151 inst->getHtmTransactionUid(),
152 fail_reason);
153
154 DPRINTF(HtmCpu,
155 "load notification of HTM transaction failure "
156 "in cache - pc=%s - addr=0x%lx - "
157 "rc=%u - htmUid=%d\n",
158 inst->pcState(), pkt->getAddr(),
159 htmFailureToStr(htm_rc), pkt->getHtmTransactionUid());
160 }
161 }
162
163 cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
164
165 assert(!cpu->switchedOut());
166 if (!inst->isSquashed()) {
167 if (request->needWBToRegister()) {
168 // Only loads, store conditionals and atomics perform the writeback
169 // after receving the response from the memory
170 assert(inst->isLoad() || inst->isStoreConditional() ||
171 inst->isAtomic());
172
173 // hardware transactional memory
174 if (pkt->htmTransactionFailedInCache()) {
177 }
178
179 writeback(inst, request->mainPacket());
180 if (inst->isStore() || inst->isAtomic()) {
181 request->writebackDone();
182 completeStore(request->instruction()->sqIt);
183 }
184 } else if (inst->isStore()) {
185 // This is a regular store (i.e., not store conditionals and
186 // atomics), so it can complete without writing back
187 completeStore(request->instruction()->sqIt);
188 }
189 }
190}
191
192LSQUnit::LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
193 : lsqID(-1), storeQueue(sqEntries), loadQueue(lqEntries),
194 storesToWB(0),
195 htmStarts(0), htmStops(0),
197 cacheBlockMask(0), stalled(false),
198 isStoreBlocked(false), storeInFlight(false), stats(nullptr)
199{
200}
201
202void
203LSQUnit::init(CPU *cpu_ptr, IEW *iew_ptr, const BaseO3CPUParams &params,
204 LSQ *lsq_ptr, unsigned id)
205{
206 lsqID = id;
207
208 cpu = cpu_ptr;
209 iewStage = iew_ptr;
210
211 lsq = lsq_ptr;
212
213 cpu->addStatGroup(csprintf("lsq%i", lsqID).c_str(), &stats);
214
215 DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",lsqID);
216
217 depCheckShift = params.LSQDepCheckShift;
218 checkLoads = params.LSQCheckLoads;
219 needsTSO = params.needsTSO;
220
221 resetState();
222}
223
224
225void
227{
228 storesToWB = 0;
229
230 // hardware transactional memory
231 // nesting depth
232 htmStarts = htmStops = 0;
233
235
236 retryPkt = NULL;
237 memDepViolator = NULL;
238
239 stalled = false;
240
241 cacheBlockMask = ~(cpu->cacheLineSize() - 1);
242}
243
244std::string
246{
247 if (MaxThreads == 1) {
248 return iewStage->name() + ".lsq";
249 } else {
250 return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
251 }
252}
253
255 : statistics::Group(parent),
256 ADD_STAT(forwLoads, statistics::units::Count::get(),
257 "Number of loads that had data forwarded from stores"),
258 ADD_STAT(squashedLoads, statistics::units::Count::get(),
259 "Number of loads squashed"),
260 ADD_STAT(ignoredResponses, statistics::units::Count::get(),
261 "Number of memory responses ignored because the instruction is "
262 "squashed"),
263 ADD_STAT(memOrderViolation, statistics::units::Count::get(),
264 "Number of memory ordering violations"),
265 ADD_STAT(squashedStores, statistics::units::Count::get(),
266 "Number of stores squashed"),
267 ADD_STAT(rescheduledLoads, statistics::units::Count::get(),
268 "Number of loads that were rescheduled"),
269 ADD_STAT(blockedByCache, statistics::units::Count::get(),
270 "Number of times an access to memory failed due to the cache "
271 "being blocked"),
272 ADD_STAT(loadToUse, "Distribution of cycle latency between the "
273 "first time a load is issued and its completion")
274{
276 .init(0, 299, 10)
278}
279
280void
282{
283 dcachePort = dcache_port;
284}
285
286void
288{
289 for (int i = 0; i < loadQueue.capacity(); ++i)
290 assert(!loadQueue[i].valid());
291
292 assert(storesToWB == 0);
293 assert(!retryPkt);
294}
295
296void
301
302void
304{
305 assert(inst->isMemRef());
306
307 assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
308
309 if (inst->isLoad()) {
310 insertLoad(inst);
311 } else {
312 insertStore(inst);
313 }
314
315 inst->setInLSQ();
316}
317
318void
320{
321 assert(!loadQueue.full());
322 assert(loadQueue.size() < loadQueue.capacity());
323
324 DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
325 load_inst->pcState(), loadQueue.tail(), load_inst->seqNum);
326
327 /* Grow the queue. */
329
330 load_inst->sqIt = storeQueue.end();
331
332 assert(!loadQueue.back().valid());
333 loadQueue.back().set(load_inst);
334 load_inst->lqIdx = loadQueue.tail();
335 assert(load_inst->lqIdx > 0);
336 load_inst->lqIt = loadQueue.getIterator(load_inst->lqIdx);
337
338 // hardware transactional memory
339 // transactional state and nesting depth must be tracked
340 // in the in-order part of the core.
341 if (load_inst->isHtmStart()) {
342 htmStarts++;
343 DPRINTF(HtmCpu, ">> htmStarts++ (%d) : htmStops (%d)\n",
345
346 const int htm_depth = htmStarts - htmStops;
347 const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
348 auto htm_uid = htm_cpt->getHtmUid();
349
350 // for debugging purposes
351 if (!load_inst->inHtmTransactionalState()) {
352 htm_uid = htm_cpt->newHtmUid();
353 DPRINTF(HtmCpu, "generating new htmUid=%u\n", htm_uid);
354 if (htm_depth != 1) {
355 DPRINTF(HtmCpu,
356 "unusual HTM transactional depth (%d)"
357 " possibly caused by mispeculation - htmUid=%u\n",
358 htm_depth, htm_uid);
359 }
360 }
361 load_inst->setHtmTransactionalState(htm_uid, htm_depth);
362 }
363
364 if (load_inst->isHtmStop()) {
365 htmStops++;
366 DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops++ (%d)\n",
368
369 if (htmStops==1 && htmStarts==0) {
370 DPRINTF(HtmCpu,
371 "htmStops==1 && htmStarts==0. "
372 "This generally shouldn't happen "
373 "(unless due to misspeculation)\n");
374 }
375 }
376}
377
378void
380{
381 // Make sure it is not full before inserting an instruction.
382 assert(!storeQueue.full());
383 assert(storeQueue.size() < storeQueue.capacity());
384
385 DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
386 store_inst->pcState(), storeQueue.tail(), store_inst->seqNum);
388
389 store_inst->sqIdx = storeQueue.tail();
390 store_inst->sqIt = storeQueue.getIterator(store_inst->sqIdx);
391
392 store_inst->lqIdx = loadQueue.tail() + 1;
393 assert(store_inst->lqIdx > 0);
394 store_inst->lqIt = loadQueue.end();
395
396 storeQueue.back().set(store_inst);
397}
398
401{
403
404 memDepViolator = NULL;
405
406 return temp;
407}
408
409unsigned
411{
412 DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n",
414 return loadQueue.capacity() - loadQueue.size();
415}
416
417unsigned
419{
420 DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n",
422 return storeQueue.capacity() - storeQueue.size();
423
424 }
425
426void
428{
429 // Should only ever get invalidations in here
430 assert(pkt->isInvalidate());
431
432 DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
433
434 for (int x = 0; x < cpu->numContexts(); x++) {
436 bool no_squash = cpu->thread[x]->noSquashFromTC;
437 cpu->thread[x]->noSquashFromTC = true;
439 cpu->thread[x]->noSquashFromTC = no_squash;
440 }
441
442 if (loadQueue.empty())
443 return;
444
445 auto iter = loadQueue.begin();
446
447 Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
448
449 DynInstPtr ld_inst = iter->instruction();
450 assert(ld_inst);
451 LSQRequest *request = iter->request();
452
453 // Check that this snoop didn't just invalidate our lock flag
454 if (ld_inst->effAddrValid() && request &&
455 request->isCacheBlockHit(invalidate_addr, cacheBlockMask)
456 && ld_inst->memReqFlags & Request::LLSC) {
457 ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit(ld_inst.get());
458 }
459
460 bool force_squash = false;
461
462 while (++iter != loadQueue.end()) {
463 ld_inst = iter->instruction();
464 assert(ld_inst);
465 request = iter->request();
466 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered() || !request)
467 continue;
468
469 DPRINTF(LSQUnit, "-- inst [sn:%lli] to pktAddr:%#x\n",
470 ld_inst->seqNum, invalidate_addr);
471
472 if (force_squash ||
473 request->isCacheBlockHit(invalidate_addr, cacheBlockMask)) {
474 if (needsTSO) {
475 // If we have a TSO system, as all loads must be ordered with
476 // all other loads, this load as well as *all* subsequent loads
477 // need to be squashed to prevent possible load reordering.
478 force_squash = true;
479 }
480 if (ld_inst->possibleLoadViolation() || force_squash) {
481 DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
482 pkt->getAddr(), ld_inst->seqNum);
483
484 // Mark the load for re-execution
485 ld_inst->fault = std::make_shared<ReExec>();
486 request->setStateToFault();
487 } else {
488 DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
489 pkt->getAddr(), ld_inst->seqNum);
490
491 // Make sure that we don't lose a snoop hitting a LOCKED
492 // address since the LOCK* flags don't get updated until
493 // commit.
494 if (ld_inst->memReqFlags & Request::LLSC) {
495 ld_inst->tcBase()->getIsaPtr()->
496 handleLockedSnoopHit(ld_inst.get());
497 }
498
499 // If a older load checks this and it's true
500 // then we might have missed the snoop
501 // in which case we need to invalidate to be sure
502 ld_inst->hitExternalSnoop(true);
503 }
504 }
505 }
506 return;
507}
508
509Fault
510LSQUnit::checkViolations(typename LoadQueue::iterator& loadIt,
511 const DynInstPtr& inst)
512{
513 Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
514 Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
515
521 while (loadIt != loadQueue.end()) {
522 DynInstPtr ld_inst = loadIt->instruction();
523 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
524 ++loadIt;
525 continue;
526 }
527
528 Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
529 Addr ld_eff_addr2 =
530 (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
531
532 if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
533 if (inst->isLoad()) {
534 // If this load is to the same block as an external snoop
535 // invalidate that we've observed then the load needs to be
536 // squashed as it could have newer data
537 if (ld_inst->hitExternalSnoop()) {
538 if (!memDepViolator ||
539 ld_inst->seqNum < memDepViolator->seqNum) {
540 DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
541 "and [sn:%lli] at address %#x\n",
542 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
543 memDepViolator = ld_inst;
544
546
547 return std::make_shared<GenericISA::M5PanicFault>(
548 "Detected fault with inst [sn:%lli] and "
549 "[sn:%lli] at address %#x\n",
550 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
551 }
552 }
553
554 // Otherwise, mark the load has a possible load violation and
555 // if we see a snoop before it's commited, we need to squash
556 ld_inst->possibleLoadViolation(true);
557 DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
558 " between instructions [sn:%lli] and [sn:%lli]\n",
559 inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
560 } else {
561 // A load/store incorrectly passed this store.
562 // Check if we already have a violator, or if it's newer
563 // squash and refetch.
564 if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
565 break;
566
567 DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
568 "[sn:%lli] at address %#x\n",
569 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
570 memDepViolator = ld_inst;
571
573
574 return std::make_shared<GenericISA::M5PanicFault>(
575 "Detected fault with "
576 "inst [sn:%lli] and [sn:%lli] at address %#x\n",
577 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
578 }
579 }
580
581 ++loadIt;
582 }
583 return NoFault;
584}
585
586
587
588
589Fault
591{
592 // Execute a specific load.
593 Fault load_fault = NoFault;
594
595 DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
596 inst->pcState(), inst->seqNum);
597
598 assert(!inst->isSquashed());
599
600 load_fault = inst->initiateAcc();
601
602 if (load_fault == NoFault && !inst->readMemAccPredicate()) {
603 assert(inst->readPredicate());
604 inst->setExecuted();
605 inst->completeAcc(nullptr);
606 iewStage->instToCommit(inst);
608 return NoFault;
609 }
610
611 if (inst->isTranslationDelayed() && load_fault == NoFault)
612 return load_fault;
613
614 if (load_fault != NoFault && inst->translationCompleted() &&
615 inst->savedRequest->isPartialFault()
616 && !inst->savedRequest->isComplete()) {
617 assert(inst->savedRequest->isSplit());
618 // If we have a partial fault where the mem access is not complete yet
619 // then the cache must have been blocked. This load will be re-executed
620 // when the cache gets unblocked. We will handle the fault when the
621 // mem access is complete.
622 return NoFault;
623 }
624
625 // If the instruction faulted or predicated false, then we need to send it
626 // along to commit without the instruction completing.
627 if (load_fault != NoFault || !inst->readPredicate()) {
628 // Send this instruction to commit, also make sure iew stage
629 // realizes there is activity. Mark it as executed unless it
630 // is a strictly ordered load that needs to hit the head of
631 // commit.
632 if (!inst->readPredicate())
633 inst->forwardOldRegs();
634 DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
635 inst->seqNum,
636 (load_fault != NoFault ? "fault" : "predication"));
637 if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
638 inst->isAtCommit()) {
639 inst->setExecuted();
640 }
641 iewStage->instToCommit(inst);
643 } else {
644 if (inst->effAddrValid()) {
645 auto it = inst->lqIt;
646 ++it;
647
648 if (checkLoads)
649 return checkViolations(it, inst);
650 }
651 }
652
653 return load_fault;
654}
655
656Fault
658{
659 // Make sure that a store exists.
660 assert(storeQueue.size() != 0);
661
662 ssize_t store_idx = store_inst->sqIdx;
663
664 DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
665 store_inst->pcState(), store_inst->seqNum);
666
667 assert(!store_inst->isSquashed());
668
669 // Check the recently completed loads to see if any match this store's
670 // address. If so, then we have a memory ordering violation.
671 typename LoadQueue::iterator loadIt = store_inst->lqIt;
672
673 Fault store_fault = store_inst->initiateAcc();
674
675 if (store_inst->isTranslationDelayed() &&
676 store_fault == NoFault)
677 return store_fault;
678
679 if (!store_inst->readPredicate()) {
680 DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
681 store_inst->seqNum);
682 store_inst->forwardOldRegs();
683 return store_fault;
684 }
685
686 if (storeQueue[store_idx].size() == 0) {
687 DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
688 store_inst->pcState(), store_inst->seqNum);
689
690 if (store_inst->isAtomic()) {
691 // If the instruction faulted, then we need to send it along
692 // to commit without the instruction completing.
693 if (!(store_inst->hasRequest() && store_inst->strictlyOrdered()) ||
694 store_inst->isAtCommit()) {
695 store_inst->setExecuted();
696 }
697 iewStage->instToCommit(store_inst);
699 }
700
701 return store_fault;
702 }
703
704 assert(store_fault == NoFault);
705
706 if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
707 // Store conditionals and Atomics need to set themselves as able to
708 // writeback if we haven't had a fault by here.
709 storeQueue[store_idx].canWB() = true;
710
711 ++storesToWB;
712 }
713
714 return checkViolations(loadIt, store_inst);
715
716}
717
718void
720{
721 assert(loadQueue.front().valid());
722
723 DynInstPtr inst = loadQueue.front().instruction();
724
725 DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
726 inst->pcState());
727
728 // Update histogram with memory latency from load
729 // Only take latency from load demand that where issued and did not fault
730 if (!inst->isInstPrefetch() && !inst->isDataPrefetch()
731 && inst->firstIssue != -1
732 && inst->lastWakeDependents != -1) {
734 inst->lastWakeDependents - inst->firstIssue));
735 }
736
737 loadQueue.front().clear();
739}
740
741void
743{
744 assert(loadQueue.size() == 0 || loadQueue.front().valid());
745
746 while (loadQueue.size() != 0 && loadQueue.front().instruction()->seqNum
747 <= youngest_inst) {
748 commitLoad();
749 }
750}
751
752void
754{
755 assert(storeQueue.size() == 0 || storeQueue.front().valid());
756
757 /* Forward iterate the store queue (age order). */
758 for (auto& x : storeQueue) {
759 assert(x.valid());
760 // Mark any stores that are now committed and have not yet
761 // been marked as able to write back.
762 if (!x.canWB()) {
763 if (x.instruction()->seqNum > youngest_inst) {
764 break;
765 }
766 DPRINTF(LSQUnit, "Marking store as able to write back, PC "
767 "%s [sn:%lli]\n",
768 x.instruction()->pcState(),
769 x.instruction()->seqNum);
770
771 x.canWB() = true;
772
773 ++storesToWB;
774 }
775 }
776}
777
778void
780{
781 assert(isStoreBlocked);
782 storeWBIt->request()->sendPacketToCache();
783 if (storeWBIt->request()->isSent()){
785 }
786}
787
788void
790{
791 if (isStoreBlocked) {
792 DPRINTF(LSQUnit, "Writing back blocked store\n");
794 }
795
796 while (storesToWB > 0 &&
797 storeWBIt.dereferenceable() &&
798 storeWBIt->valid() &&
799 storeWBIt->canWB() &&
800 ((!needsTSO) || (!storeInFlight)) &&
801 lsq->cachePortAvailable(false)) {
802
803 if (isStoreBlocked) {
804 DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
805 " is blocked!\n");
806 break;
807 }
808
809 // Store didn't write any data so no need to write it back to
810 // memory.
811 if (storeWBIt->size() == 0) {
812 /* It is important that the preincrement happens at (or before)
813 * the call, as the the code of completeStore checks
814 * storeWBIt. */
816 continue;
817 }
818
819 if (storeWBIt->instruction()->isDataPrefetch()) {
820 storeWBIt++;
821 continue;
822 }
823
824 assert(storeWBIt->hasRequest());
825 assert(!storeWBIt->committed());
826
827 DynInstPtr inst = storeWBIt->instruction();
828 LSQRequest* request = storeWBIt->request();
829
830 // Process store conditionals or store release after all previous
831 // stores are completed
832 if ((request->mainReq()->isLLSC() ||
833 request->mainReq()->isRelease()) &&
834 (storeWBIt.idx() != storeQueue.head())) {
835 DPRINTF(LSQUnit, "Store idx:%i PC:%s to Addr:%#x "
836 "[sn:%lli] is %s%s and not head of the queue\n",
837 storeWBIt.idx(), inst->pcState(),
838 request->mainReq()->getPaddr(), inst->seqNum,
839 request->mainReq()->isLLSC() ? "SC" : "",
840 request->mainReq()->isRelease() ? "/Release" : "");
841 break;
842 }
843
844 storeWBIt->committed() = true;
845
846 assert(!inst->memData);
847 inst->memData = new uint8_t[request->_size];
848
849 if (storeWBIt->isAllZeros())
850 memset(inst->memData, 0, request->_size);
851 else
852 memcpy(inst->memData, storeWBIt->data(), request->_size);
853
854 request->buildPackets();
855
856 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
857 "to Addr:%#x, data:%#x [sn:%lli]\n",
858 storeWBIt.idx(), inst->pcState(),
859 request->mainReq()->getPaddr(), (int)*(inst->memData),
860 inst->seqNum);
861
862 // @todo: Remove this SC hack once the memory system handles it.
863 if (inst->isStoreConditional()) {
864 // Disable recording the result temporarily. Writing to
865 // misc regs normally updates the result, but this is not
866 // the desired behavior when handling store conditionals.
867 inst->recordResult(false);
868 bool success = inst->tcBase()->getIsaPtr()->handleLockedWrite(
869 inst.get(), request->mainReq(), cacheBlockMask);
870 inst->recordResult(true);
871 request->packetSent();
872
873 if (!success) {
874 request->complete();
875 // Instantly complete this store.
876 DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
877 "Instantly completing it.\n",
878 inst->seqNum);
879 PacketPtr new_pkt = new Packet(*request->packet());
880 WritebackEvent *wb = new WritebackEvent(inst,
881 new_pkt, this);
882 cpu->schedule(wb, curTick() + 1);
884 if (!storeQueue.empty())
885 storeWBIt++;
886 else
888 continue;
889 }
890 }
891
892 if (request->mainReq()->isLocalAccess()) {
893 assert(!inst->isStoreConditional());
894 assert(!inst->inHtmTransactionalState());
896 PacketPtr main_pkt = new Packet(request->mainReq(),
898 main_pkt->dataStatic(inst->memData);
899 request->mainReq()->localAccessor(thread, main_pkt);
900 delete main_pkt;
902 storeWBIt++;
903 continue;
904 }
905 /* Send to cache */
906 request->sendPacketToCache();
907
908 /* If successful, do the post send */
909 if (request->isSent()) {
911 } else {
912 DPRINTF(LSQUnit, "D-Cache became blocked when writing [sn:%lli], "
913 "will retry later\n",
914 inst->seqNum);
915 }
916 }
917 assert(storesToWB >= 0);
918}
919
920void
921LSQUnit::squash(const InstSeqNum &squashed_num)
922{
923 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
924 "(Loads:%i Stores:%i)\n", squashed_num, loadQueue.size(),
925 storeQueue.size());
926
927 while (loadQueue.size() != 0 &&
928 loadQueue.back().instruction()->seqNum > squashed_num) {
929 DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
930 "[sn:%lli]\n",
931 loadQueue.back().instruction()->pcState(),
932 loadQueue.back().instruction()->seqNum);
933
934 if (isStalled() && loadQueue.tail() == stallingLoadIdx) {
935 stalled = false;
937 stallingLoadIdx = 0;
938 }
939
940 // hardware transactional memory
941 // Squashing instructions can alter the transaction nesting depth
942 // and must be corrected before fetching resumes.
943 if (loadQueue.back().instruction()->isHtmStart())
944 {
945 htmStarts = (--htmStarts < 0) ? 0 : htmStarts;
946 DPRINTF(HtmCpu, ">> htmStarts-- (%d) : htmStops (%d)\n",
948 }
949 if (loadQueue.back().instruction()->isHtmStop())
950 {
951 htmStops = (--htmStops < 0) ? 0 : htmStops;
952 DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops-- (%d)\n",
954 }
955 // Clear the smart pointer to make sure it is decremented.
956 loadQueue.back().instruction()->setSquashed();
957 loadQueue.back().clear();
958
961 }
962
963 // hardware transactional memory
964 // scan load queue (from oldest to youngest) for most recent valid htmUid
965 auto scan_it = loadQueue.begin();
966 uint64_t in_flight_uid = 0;
967 while (scan_it != loadQueue.end()) {
968 if (scan_it->instruction()->isHtmStart() &&
969 !scan_it->instruction()->isSquashed()) {
970 in_flight_uid = scan_it->instruction()->getHtmTransactionUid();
971 DPRINTF(HtmCpu, "loadQueue[%d]: found valid HtmStart htmUid=%u\n",
972 scan_it._idx, in_flight_uid);
973 }
974 scan_it++;
975 }
976 // If there's a HtmStart in the pipeline then use its htmUid,
977 // otherwise use the most recently committed uid
978 const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
979 if (htm_cpt) {
980 const uint64_t old_local_htm_uid = htm_cpt->getHtmUid();
981 uint64_t new_local_htm_uid;
982 if (in_flight_uid > 0)
983 new_local_htm_uid = in_flight_uid;
984 else
985 new_local_htm_uid = lastRetiredHtmUid;
986
987 if (old_local_htm_uid != new_local_htm_uid) {
988 DPRINTF(HtmCpu, "flush: lastRetiredHtmUid=%u\n",
990 DPRINTF(HtmCpu, "flush: resetting localHtmUid=%u\n",
991 new_local_htm_uid);
992
993 htm_cpt->setHtmUid(new_local_htm_uid);
994 }
995 }
996
997 if (memDepViolator && squashed_num < memDepViolator->seqNum) {
998 memDepViolator = NULL;
999 }
1000
1001 while (storeQueue.size() != 0 &&
1002 storeQueue.back().instruction()->seqNum > squashed_num) {
1003 // Instructions marked as can WB are already committed.
1004 if (storeQueue.back().canWB()) {
1005 break;
1006 }
1007
1008 DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1009 "idx:%i [sn:%lli]\n",
1010 storeQueue.back().instruction()->pcState(),
1011 storeQueue.tail(), storeQueue.back().instruction()->seqNum);
1012
1013 // I don't think this can happen. It should have been cleared
1014 // by the stalling load.
1015 if (isStalled() &&
1016 storeQueue.back().instruction()->seqNum == stallingStoreIsn) {
1017 panic("Is stalled should have been cleared by stalling load!\n");
1018 stalled = false;
1019 stallingStoreIsn = 0;
1020 }
1021
1022 // Clear the smart pointer to make sure it is decremented.
1023 storeQueue.back().instruction()->setSquashed();
1024
1025 // Must delete request now that it wasn't handed off to
1026 // memory. This is quite ugly. @todo: Figure out the proper
1027 // place to really handle request deletes.
1028 storeQueue.back().clear();
1029
1032 }
1033}
1034
1035uint64_t
1037{
1038 const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
1039 return htm_cpt->getHtmUid();
1040}
1041
1042void
1044{
1045 if (isStalled() &&
1046 storeWBIt->instruction()->seqNum == stallingStoreIsn) {
1047 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1048 "load idx:%li\n",
1050 stalled = false;
1051 stallingStoreIsn = 0;
1053 }
1054
1055 if (!storeWBIt->instruction()->isStoreConditional()) {
1056 // The store is basically completed at this time. This
1057 // only works so long as the checker doesn't try to
1058 // verify the value in memory for stores.
1059 storeWBIt->instruction()->setCompleted();
1060
1061 if (cpu->checker) {
1062 cpu->checker->verify(storeWBIt->instruction());
1063 }
1064 }
1065
1066 if (needsTSO) {
1067 storeInFlight = true;
1068 }
1069
1070 storeWBIt++;
1071}
1072
1073void
1075{
1076 iewStage->wakeCPU();
1077
1078 // Squashed instructions do not need to complete their access.
1079 if (inst->isSquashed()) {
1080 assert (!inst->isStore() || inst->isStoreConditional());
1082 return;
1083 }
1084
1085 if (!inst->isExecuted()) {
1086 inst->setExecuted();
1087
1088 if (inst->fault == NoFault) {
1089 // Complete access to copy data to proper place.
1090 inst->completeAcc(pkt);
1091 } else {
1092 // If the instruction has an outstanding fault, we cannot complete
1093 // the access as this discards the current fault.
1094
1095 // If we have an outstanding fault, the fault should only be of
1096 // type ReExec or - in case of a SplitRequest - a partial
1097 // translation fault
1098
1099 // Unless it's a hardware transactional memory fault
1100 auto htm_fault = std::dynamic_pointer_cast<
1101 GenericHtmFailureFault>(inst->fault);
1102
1103 if (!htm_fault) {
1104 assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr ||
1105 inst->savedRequest->isPartialFault());
1106
1107 } else if (!pkt->htmTransactionFailedInCache()) {
1108 // Situation in which the instruction has a hardware
1109 // transactional memory fault but not the packet itself. This
1110 // can occur with ldp_uop microops since access is spread over
1111 // multiple packets.
1112 DPRINTF(HtmCpu,
1113 "%s writeback with HTM failure fault, "
1114 "however, completing packet is not aware of "
1115 "transaction failure. cause=%s htmUid=%u\n",
1116 inst->staticInst->getName(),
1117 htmFailureToStr(htm_fault->getHtmFailureFaultCause()),
1118 htm_fault->getHtmUid());
1119 }
1120
1121 DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1122 "due to pending fault.\n", inst->seqNum);
1123 }
1124 }
1125
1126 // Need to insert instruction into queue to commit
1127 iewStage->instToCommit(inst);
1128
1130
1131 // see if this load changed the PC
1133}
1134
1135void
1136LSQUnit::completeStore(typename StoreQueue::iterator store_idx)
1137{
1138 assert(store_idx->valid());
1139 store_idx->completed() = true;
1140 --storesToWB;
1141 // A bit conservative because a store completion may not free up entries,
1142 // but hopefully avoids two store completions in one cycle from making
1143 // the CPU tick twice.
1144 cpu->wakeCPU();
1146
1147 /* We 'need' a copy here because we may clear the entry from the
1148 * store queue. */
1149 DynInstPtr store_inst = store_idx->instruction();
1150 if (store_idx == storeQueue.begin()) {
1151 do {
1152 storeQueue.front().clear();
1154 } while (storeQueue.front().completed() &&
1155 !storeQueue.empty());
1156
1158 }
1159
1160 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1161 "idx:%i\n",
1162 store_inst->seqNum, store_idx.idx() - 1, storeQueue.head() - 1);
1163
1164#if TRACING_ON
1165 if (debug::O3PipeView) {
1166 store_inst->storeTick =
1167 curTick() - store_inst->fetchTick;
1168 }
1169#endif
1170
1171 if (isStalled() &&
1172 store_inst->seqNum == stallingStoreIsn) {
1173 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1174 "load idx:%li\n",
1176 stalled = false;
1177 stallingStoreIsn = 0;
1179 }
1180
1181 store_inst->setCompleted();
1182
1183 if (needsTSO) {
1184 storeInFlight = false;
1185 }
1186
1187 // Tell the checker we've completed this instruction. Some stores
1188 // may get reported twice to the checker, but the checker can
1189 // handle that case.
1190 // Store conditionals cannot be sent to the checker yet, they have
1191 // to update the misc registers first which should take place
1192 // when they commit
1193 if (cpu->checker && !store_inst->isStoreConditional()) {
1194 cpu->checker->verify(store_inst);
1195 }
1196}
1197
1198bool
1199LSQUnit::trySendPacket(bool isLoad, PacketPtr data_pkt)
1200{
1201 bool ret = true;
1202 bool cache_got_blocked = false;
1203
1204 LSQRequest *request = dynamic_cast<LSQRequest*>(data_pkt->senderState);
1205
1206 if (!lsq->cacheBlocked() &&
1207 lsq->cachePortAvailable(isLoad)) {
1208 if (!dcachePort->sendTimingReq(data_pkt)) {
1209 ret = false;
1210 cache_got_blocked = true;
1211 }
1212 } else {
1213 ret = false;
1214 }
1215
1216 if (ret) {
1217 if (!isLoad) {
1218 isStoreBlocked = false;
1219 }
1220 lsq->cachePortBusy(isLoad);
1221 request->packetSent();
1222 } else {
1223 if (cache_got_blocked) {
1224 lsq->cacheBlocked(true);
1226 }
1227 if (!isLoad) {
1228 assert(request == storeWBIt->request());
1229 isStoreBlocked = true;
1230 }
1231 request->packetNotSent();
1232 }
1233 DPRINTF(LSQUnit, "Memory request (pkt: %s) from inst [sn:%llu] was"
1234 " %ssent (cache is blocked: %d, cache_got_blocked: %d)\n",
1235 data_pkt->print(), request->instruction()->seqNum,
1236 ret ? "": "not ", lsq->cacheBlocked(), cache_got_blocked);
1237 return ret;
1238}
1239
1240void
1242{
1243 DPRINTF(LSQUnit, "Unit %p marking stale translations %d %d\n", this,
1245 for (auto& entry : storeQueue) {
1246 if (entry.valid() && entry.hasRequest())
1247 entry.request()->markAsStaleTranslation();
1248 }
1249 for (auto& entry : loadQueue) {
1250 if (entry.valid() && entry.hasRequest())
1251 entry.request()->markAsStaleTranslation();
1252 }
1253}
1254
1255bool
1257{
1258 DPRINTF(LSQUnit, "Unit %p checking stale translations\n", this);
1259 for (auto& entry : storeQueue) {
1260 if (entry.valid() && entry.hasRequest()
1261 && entry.request()->hasStaleTranslation())
1262 return true;
1263 }
1264 for (auto& entry : loadQueue) {
1265 if (entry.valid() && entry.hasRequest()
1266 && entry.request()->hasStaleTranslation())
1267 return true;
1268 }
1269 DPRINTF(LSQUnit, "Unit %p found no stale translations\n", this);
1270 return false;
1271}
1272
1273void
1275{
1276 if (isStoreBlocked) {
1277 DPRINTF(LSQUnit, "Receiving retry: blocked store\n");
1279 }
1280}
1281
1282void
1284{
1285 cprintf("Load store queue: Dumping instructions.\n");
1286 cprintf("Load queue size: %i\n", loadQueue.size());
1287 cprintf("Load queue: ");
1288
1289 for (const auto& e: loadQueue) {
1290 const DynInstPtr &inst(e.instruction());
1291 cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1292 }
1293 cprintf("\n");
1294
1295 cprintf("Store queue size: %i\n", storeQueue.size());
1296 cprintf("Store queue: ");
1297
1298 for (const auto& e: storeQueue) {
1299 const DynInstPtr &inst(e.instruction());
1300 cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1301 }
1302
1303 cprintf("\n");
1304}
1305
1306void LSQUnit::schedule(Event& ev, Tick when) { cpu->schedule(ev, when); }
1307
1309
1310unsigned int
1312{
1313 return cpu->cacheLineSize();
1314}
1315
1316Fault
1317LSQUnit::read(LSQRequest *request, ssize_t load_idx)
1318{
1319 LQEntry& load_entry = loadQueue[load_idx];
1320 const DynInstPtr& load_inst = load_entry.instruction();
1321
1322 load_entry.setRequest(request);
1323 assert(load_inst);
1324
1325 assert(!load_inst->isExecuted());
1326
1327 // Make sure this isn't a strictly ordered load
1328 // A bit of a hackish way to get strictly ordered accesses to work
1329 // only if they're at the head of the LSQ and are ready to commit
1330 // (at the head of the ROB too).
1331
1332 if (request->mainReq()->isStrictlyOrdered() &&
1333 (load_idx != loadQueue.head() || !load_inst->isAtCommit())) {
1334 // Tell IQ/mem dep unit that this instruction will need to be
1335 // rescheduled eventually
1336 iewStage->rescheduleMemInst(load_inst);
1337 load_inst->clearIssued();
1338 load_inst->effAddrValid(false);
1340 DPRINTF(LSQUnit, "Strictly ordered load [sn:%lli] PC %s\n",
1341 load_inst->seqNum, load_inst->pcState());
1342
1343 // Must delete request now that it wasn't handed off to
1344 // memory. This is quite ugly. @todo: Figure out the proper
1345 // place to really handle request deletes.
1346 load_entry.setRequest(nullptr);
1347 request->discard();
1348 return std::make_shared<GenericISA::M5PanicFault>(
1349 "Strictly ordered load [sn:%llx] PC %s\n",
1350 load_inst->seqNum, load_inst->pcState());
1351 }
1352
1353 DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
1354 "storeHead: %i addr: %#x%s\n",
1355 load_idx - 1, load_inst->sqIt._idx, storeQueue.head() - 1,
1356 request->mainReq()->getPaddr(), request->isSplit() ? " split" :
1357 "");
1358
1359 if (request->mainReq()->isLLSC()) {
1360 // Disable recording the result temporarily. Writing to misc
1361 // regs normally updates the result, but this is not the
1362 // desired behavior when handling store conditionals.
1363 load_inst->recordResult(false);
1364 load_inst->tcBase()->getIsaPtr()->handleLockedRead(load_inst.get(),
1365 request->mainReq());
1366 load_inst->recordResult(true);
1367 }
1368
1369 if (request->mainReq()->isLocalAccess()) {
1370 assert(!load_inst->memData);
1371 load_inst->memData = new uint8_t[MaxDataBytes];
1372
1373 gem5::ThreadContext *thread = cpu->tcBase(lsqID);
1374 PacketPtr main_pkt = new Packet(request->mainReq(), MemCmd::ReadReq);
1375
1376 main_pkt->dataStatic(load_inst->memData);
1377
1378 Cycles delay = request->mainReq()->localAccessor(thread, main_pkt);
1379
1380 WritebackEvent *wb = new WritebackEvent(load_inst, main_pkt, this);
1381 cpu->schedule(wb, cpu->clockEdge(delay));
1382 return NoFault;
1383 }
1384
1385 // Check the SQ for any previous stores that might lead to forwarding
1386 auto store_it = load_inst->sqIt;
1387 assert (store_it >= storeWBIt);
1388 // End once we've reached the top of the LSQ
1389 while (store_it != storeWBIt && !load_inst->isDataPrefetch()) {
1390 // Move the index to one younger
1391 store_it--;
1392 assert(store_it->valid());
1393 assert(store_it->instruction()->seqNum < load_inst->seqNum);
1394 int store_size = store_it->size();
1395
1396 // Cache maintenance instructions go down via the store
1397 // path but they carry no data and they shouldn't be
1398 // considered for forwarding
1399 if (store_size != 0 && !store_it->instruction()->strictlyOrdered() &&
1400 !(store_it->request()->mainReq() &&
1401 store_it->request()->mainReq()->isCacheMaintenance())) {
1402 assert(store_it->instruction()->effAddrValid());
1403
1404 // Check if the store data is within the lower and upper bounds of
1405 // addresses that the request needs.
1406 auto req_s = request->mainReq()->getVaddr();
1407 auto req_e = req_s + request->mainReq()->getSize();
1408 auto st_s = store_it->instruction()->effAddr;
1409 auto st_e = st_s + store_size;
1410
1411 bool store_has_lower_limit = req_s >= st_s;
1412 bool store_has_upper_limit = req_e <= st_e;
1413 bool lower_load_has_store_part = req_s < st_e;
1414 bool upper_load_has_store_part = req_e > st_s;
1415
1417
1418 // If the store entry is not atomic (atomic does not have valid
1419 // data), the store has all of the data needed, and
1420 // the load is not LLSC, then
1421 // we can forward data from the store to the load
1422 if (!store_it->instruction()->isAtomic() &&
1423 store_has_lower_limit && store_has_upper_limit &&
1424 !request->mainReq()->isLLSC()) {
1425
1426 const auto& store_req = store_it->request()->mainReq();
1427 coverage = store_req->isMasked() ?
1430 } else if (
1431 // This is the partial store-load forwarding case where a store
1432 // has only part of the load's data and the load isn't LLSC
1433 (!request->mainReq()->isLLSC() &&
1434 ((store_has_lower_limit && lower_load_has_store_part) ||
1435 (store_has_upper_limit && upper_load_has_store_part) ||
1436 (lower_load_has_store_part && upper_load_has_store_part))) ||
1437 // The load is LLSC, and the store has all or part of the
1438 // load's data
1439 (request->mainReq()->isLLSC() &&
1440 ((store_has_lower_limit || upper_load_has_store_part) &&
1441 (store_has_upper_limit || lower_load_has_store_part))) ||
1442 // The store entry is atomic and has all or part of the load's
1443 // data
1444 (store_it->instruction()->isAtomic() &&
1445 ((store_has_lower_limit || upper_load_has_store_part) &&
1446 (store_has_upper_limit || lower_load_has_store_part)))) {
1447
1449 }
1450
1452 // Get shift amount for offset into the store's data.
1453 int shift_amt = request->mainReq()->getVaddr() -
1454 store_it->instruction()->effAddr;
1455
1456 // Allocate memory if this is the first time a load is issued.
1457 if (!load_inst->memData) {
1458 load_inst->memData =
1459 new uint8_t[request->mainReq()->getSize()];
1460 }
1461 if (store_it->isAllZeros())
1462 memset(load_inst->memData, 0,
1463 request->mainReq()->getSize());
1464 else
1465 memcpy(load_inst->memData,
1466 store_it->data() + shift_amt,
1467 request->mainReq()->getSize());
1468
1469 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
1470 "addr %#x\n", store_it._idx,
1471 request->mainReq()->getVaddr());
1472
1473 PacketPtr data_pkt = new Packet(request->mainReq(),
1475 data_pkt->dataStatic(load_inst->memData);
1476
1477 // hardware transactional memory
1478 // Store to load forwarding within a transaction
1479 // This should be okay because the store will be sent to
1480 // the memory subsystem and subsequently get added to the
1481 // write set of the transaction. The write set has a stronger
1482 // property than the read set, so the load doesn't necessarily
1483 // have to be there.
1484 assert(!request->mainReq()->isHTMCmd());
1485 if (load_inst->inHtmTransactionalState()) {
1486 assert (!storeQueue[store_it._idx].completed());
1487 assert (
1488 storeQueue[store_it._idx].instruction()->
1489 inHtmTransactionalState());
1490 assert (
1491 load_inst->getHtmTransactionUid() ==
1492 storeQueue[store_it._idx].instruction()->
1493 getHtmTransactionUid());
1494 data_pkt->setHtmTransactional(
1495 load_inst->getHtmTransactionUid());
1496 DPRINTF(HtmCpu, "HTM LD (ST2LDF) "
1497 "pc=0x%lx - vaddr=0x%lx - "
1498 "paddr=0x%lx - htmUid=%u\n",
1499 load_inst->pcState().instAddr(),
1500 data_pkt->req->hasVaddr() ?
1501 data_pkt->req->getVaddr() : 0lu,
1502 data_pkt->getAddr(),
1503 load_inst->getHtmTransactionUid());
1504 }
1505
1506 if (request->isAnyOutstandingRequest()) {
1507 assert(request->_numOutstandingPackets > 0);
1508 // There are memory requests packets in flight already.
1509 // This may happen if the store was not complete the
1510 // first time this load got executed. Signal the senderSate
1511 // that response packets should be discarded.
1512 request->discard();
1513 // Avoid checking snoops on this discarded request.
1514 load_entry.setRequest(nullptr);
1515 }
1516
1517 WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt,
1518 this);
1519
1520 // We'll say this has a 1 cycle load-store forwarding latency
1521 // for now.
1522 // @todo: Need to make this a parameter.
1523 cpu->schedule(wb, curTick());
1524
1525 // Don't need to do anything special for split loads.
1526 ++stats.forwLoads;
1527
1528 return NoFault;
1529 } else if (
1531 // If it's already been written back, then don't worry about
1532 // stalling on it.
1533 if (store_it->completed()) {
1534 panic("Should not check one of these");
1535 continue;
1536 }
1537
1538 // Must stall load and force it to retry, so long as it's the
1539 // oldest load that needs to do so.
1540 if (!stalled ||
1541 (stalled &&
1542 load_inst->seqNum <
1543 loadQueue[stallingLoadIdx].instruction()->seqNum)) {
1544 stalled = true;
1545 stallingStoreIsn = store_it->instruction()->seqNum;
1546 stallingLoadIdx = load_idx;
1547 }
1548
1549 // Tell IQ/mem dep unit that this instruction will need to be
1550 // rescheduled eventually
1551 iewStage->rescheduleMemInst(load_inst);
1552 load_inst->clearIssued();
1553 load_inst->effAddrValid(false);
1555
1556 // Do not generate a writeback event as this instruction is not
1557 // complete.
1558 DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
1559 "Store idx %i to load addr %#x\n",
1560 store_it._idx, request->mainReq()->getVaddr());
1561
1562 // Must discard the request.
1563 request->discard();
1564 load_entry.setRequest(nullptr);
1565 return NoFault;
1566 }
1567 }
1568 }
1569
1570 // If there's no forwarding case, then go access memory
1571 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n",
1572 load_inst->seqNum, load_inst->pcState());
1573
1574 // Allocate memory if this is the first time a load is issued.
1575 if (!load_inst->memData) {
1576 load_inst->memData = new uint8_t[request->mainReq()->getSize()];
1577 }
1578
1579
1580 // hardware transactional memory
1581 if (request->mainReq()->isHTMCmd()) {
1582 // this is a simple sanity check
1583 // the Ruby cache controller will set
1584 // memData to 0x0ul if successful.
1585 *load_inst->memData = (uint64_t) 0x1ull;
1586 }
1587
1588 // For now, load throughput is constrained by the number of
1589 // load FUs only, and loads do not consume a cache port (only
1590 // stores do).
1591 // @todo We should account for cache port contention
1592 // and arbitrate between loads and stores.
1593
1594 // if we the cache is not blocked, do cache access
1595 request->buildPackets();
1596 request->sendPacketToCache();
1597 if (!request->isSent())
1598 iewStage->blockMemInst(load_inst);
1599
1600 return NoFault;
1601}
1602
1603Fault
1604LSQUnit::write(LSQRequest *request, uint8_t *data, ssize_t store_idx)
1605{
1606 assert(storeQueue[store_idx].valid());
1607
1608 DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x | storeHead:%i "
1609 "[sn:%llu]\n",
1610 store_idx - 1, request->req()->getPaddr(), storeQueue.head() - 1,
1611 storeQueue[store_idx].instruction()->seqNum);
1612
1613 storeQueue[store_idx].setRequest(request);
1614 unsigned size = request->_size;
1615 storeQueue[store_idx].size() = size;
1616 bool store_no_data =
1617 request->mainReq()->getFlags() & Request::STORE_NO_DATA;
1618 storeQueue[store_idx].isAllZeros() = store_no_data;
1619 assert(size <= SQEntry::DataSize || store_no_data);
1620
1621 // copy data into the storeQueue only if the store request has valid data
1622 if (!(request->req()->getFlags() & Request::CACHE_BLOCK_ZERO) &&
1623 !request->req()->isCacheMaintenance() &&
1624 !request->req()->isAtomic())
1625 memcpy(storeQueue[store_idx].data(), data, size);
1626
1627 // This function only writes the data to the store queue, so no fault
1628 // can happen here.
1629 return NoFault;
1630}
1631
1634{
1635 if (loadQueue.front().valid())
1636 return loadQueue.front().instruction()->seqNum;
1637 else
1638 return 0;
1639}
1640
1643{
1644 if (storeQueue.front().valid())
1645 return storeQueue.front().instruction()->seqNum;
1646 else
1647 return 0;
1648}
1649
1650} // namespace o3
1651} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
Addr cacheLineSize() const
Get the cache line size of the system.
Definition base.hh:397
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition base.hh:288
unsigned numContexts()
Get the number of thread contexts available.
Definition base.hh:292
bool switchedOut() const
Determine if the CPU is switched out.
Definition base.hh:373
virtual void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
Definition isa.hh:115
void verify(const DynInstPtr &inst)
Definition cpu_impl.hh:119
iterator getIterator(size_t idx)
Return an iterator to an index in the queue.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles ticksToCycles(Tick t) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setHtmTransactionFailedInCache(const HtmCacheFailure ret_code)
Stipulates that this packet/request has returned from the cache hierarchy in a failed transaction.
Definition packet.cc:493
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition packet.cc:368
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition packet.hh:1175
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
HtmCacheFailure getHtmTransactionFailedInCacheRC() const
If a packet/request has returned from the cache hierarchy in a failed transaction,...
Definition packet.cc:509
bool isHtmTransactional() const
Returns whether or not this packet/request originates in the CPU executing in transactional mode,...
Definition packet.cc:523
bool isWrite() const
Definition packet.hh:594
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition packet.cc:529
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
void setHtmTransactional(uint64_t val)
Stipulates that this packet/request originates in the CPU executing in transactional mode,...
Definition packet.cc:516
bool isInvalidate() const
Definition packet.hh:609
bool htmTransactionFailedInCache() const
Returns whether or not this packet/request has returned from the cache hierarchy in a failed transact...
Definition packet.cc:503
T * data
The stored pointer.
Definition refcnt.hh:146
T * get() const
Directly access the pointer itself without taking a reference.
Definition refcnt.hh:227
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition port.hh:136
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
@ LLSC
The request is a Load locked/store conditional.
Definition request.hh:156
@ CACHE_BLOCK_ZERO
This is a write that is targeted and zeroing an entire cache block.
Definition request.hh:143
static const FlagsType STORE_NO_DATA
Definition request.hh:260
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual BaseISA * getIsaPtr() const =0
virtual BaseHTMCheckpointPtr & getHtmCheckpointPtr()=0
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition cpu.hh:94
gem5::Checker< DynInstPtr > * checker
Pointer to the checker, which can dynamically verify instruction results at run time.
Definition cpu.hh:527
std::vector< ThreadState * > thread
Pointers to all of the threads in the CPU.
Definition cpu.hh:533
void activityThisCycle()
Records that there was time buffer activity this cycle.
Definition cpu.hh:488
ProbePointArg< std::pair< DynInstPtr, PacketPtr > > * ppDataAccessComplete
Definition cpu.hh:177
BaseMMU * mmu
Definition cpu.hh:110
gem5::ThreadContext * tcBase(ThreadID tid)
Returns a pointer to a thread context.
Definition cpu.hh:515
void wakeCPU()
Wakes the CPU, rescheduling the CPU if it's not already active.
Definition cpu.cc:1316
IEW handles both single threaded and SMT IEW (issue/execute/writeback).
Definition iew.hh:88
void instToCommit(const DynInstPtr &inst)
Sends an instruction to commit through the time buffer.
Definition iew.cc:529
void blockMemInst(const DynInstPtr &inst)
Moves memory instruction onto the list of cache blocked instructions.
Definition iew.cc:517
void activityThisCycle()
Reports to the CPU that there is activity this cycle.
Definition iew.cc:771
void wakeCPU()
Tells the CPU to wakeup if it has descheduled itself due to no activity.
Definition iew.cc:765
void rescheduleMemInst(const DynInstPtr &inst)
Tells memory dependence unit that a memory instruction needs to be rescheduled.
Definition iew.cc:505
std::string name() const
Returns the name of the IEW stage.
Definition iew.cc:118
void checkMisprediction(const DynInstPtr &inst)
Check misprediction
Definition iew.cc:1554
bool updateLSQNextCycle
Records if the LSQ needs to be updated on the next cycle, so that IEW knows if there will be activity...
Definition iew.hh:365
void replayMemInst(const DynInstPtr &inst)
Re-executes all rescheduled memory instructions.
Definition iew.cc:511
void setRequest(LSQRequest *r)
Definition lsq_unit.hh:138
const DynInstPtr & instruction() const
Definition lsq_unit.hh:145
static constexpr size_t DataSize
Definition lsq_unit.hh:167
Writeback event, specifically for when stores forward data to loads.
Definition lsq_unit.hh:412
WritebackEvent(const DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr)
Constructs a writeback event.
Definition lsq_unit.cc:64
const char * description() const
Returns the description of this event.
Definition lsq_unit.cc:86
void process()
Processes the writeback event.
Definition lsq_unit.cc:74
Class that implements the actual LQ and SQ for each specific thread.
Definition lsq_unit.hh:89
void insertStore(const DynInstPtr &store_inst)
Inserts a store instruction.
Definition lsq_unit.cc:379
Fault write(LSQRequest *requst, uint8_t *data, ssize_t store_idx)
Executes the store at the given index.
Definition lsq_unit.cc:1604
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition lsq_unit.hh:479
IEW * iewStage
Pointer to the IEW stage.
Definition lsq_unit.hh:402
bool isStoreBlocked
Whehter or not a store is blocked due to the memory system.
Definition lsq_unit.hh:497
void takeOverFrom()
Takes over from another CPU's thread.
Definition lsq_unit.cc:297
bool checkLoads
Should loads be checked for dependency issues.
Definition lsq_unit.hh:461
Fault read(LSQRequest *request, ssize_t load_idx)
Executes the load at the given index.
Definition lsq_unit.cc:1317
bool storeInFlight
Whether or not a store is in flight.
Definition lsq_unit.hh:500
CPU * cpu
Pointer to the CPU.
Definition lsq_unit.hh:399
InstSeqNum getStoreHeadSeqNum()
Returns the sequence number of the head store instruction.
Definition lsq_unit.cc:1642
InstSeqNum getLoadHeadSeqNum()
Returns the sequence number of the head load instruction.
Definition lsq_unit.cc:1633
unsigned depCheckShift
The number of places to shift addresses in the LSQ before checking for dependency violations.
Definition lsq_unit.hh:458
void storePostSend()
Handles completing the send of a store to memory.
Definition lsq_unit.cc:1043
RequestPort * dcachePort
Pointer to the dcache port.
Definition lsq_unit.hh:408
InstSeqNum stallingStoreIsn
The store that causes the stall due to partial store to load forwarding.
Definition lsq_unit.hh:489
bool isStalled()
Returns whether or not the LSQ unit is stalled.
Definition lsq_unit.hh:562
void insertLoad(const DynInstPtr &load_inst)
Inserts a load instruction.
Definition lsq_unit.cc:319
Fault executeStore(const DynInstPtr &inst)
Executes a store instruction.
Definition lsq_unit.cc:657
void insert(const DynInstPtr &inst)
Inserts an instruction.
Definition lsq_unit.cc:303
bool checkStaleTranslations() const
Definition lsq_unit.cc:1256
uint64_t getLatestHtmUid() const
Definition lsq_unit.cc:1036
void schedule(Event &ev, Tick when)
Schedule event for the cpu.
Definition lsq_unit.cc:1306
void writebackStores()
Writes back stores.
Definition lsq_unit.cc:789
Fault checkViolations(typename LoadQueue::iterator &loadIt, const DynInstPtr &inst)
Check for ordering violations in the LSQ.
Definition lsq_unit.cc:510
StoreQueue storeQueue
The store queue.
Definition lsq_unit.hh:449
Fault executeLoad(const DynInstPtr &inst)
Executes a load instruction.
Definition lsq_unit.cc:590
void commitLoad()
Commits the head load.
Definition lsq_unit.cc:719
LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
Constructs an LSQ unit.
Definition lsq_unit.cc:192
void completeStore(typename StoreQueue::iterator store_idx)
Completes the store at the specified index.
Definition lsq_unit.cc:1136
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition lsq_unit.cc:287
void setDcachePort(RequestPort *dcache_port)
Sets the pointer to the dcache port.
Definition lsq_unit.cc:281
unsigned int cacheLineSize()
Definition lsq_unit.cc:1311
void resetState()
Reset the LSQ state.
Definition lsq_unit.cc:226
unsigned numFreeStoreEntries()
Returns the number of free SQ entries.
Definition lsq_unit.cc:418
uint64_t lastRetiredHtmUid
Definition lsq_unit.hh:471
void dumpInsts() const
Debugging function to dump instructions in the LSQ.
Definition lsq_unit.cc:1283
bool stalled
Whether or not the LSQ is stalled.
Definition lsq_unit.hh:485
ssize_t stallingLoadIdx
The index of the above store.
Definition lsq_unit.hh:491
LoadQueue loadQueue
The load queue.
Definition lsq_unit.hh:452
PacketPtr retryPkt
The packet that needs to be retried.
Definition lsq_unit.hh:494
void init(CPU *cpu_ptr, IEW *iew_ptr, const BaseO3CPUParams &params, LSQ *lsq_ptr, unsigned id)
Initializes the LSQ unit with the specified number of entries.
Definition lsq_unit.cc:203
DynInstPtr getMemDepViolator()
Returns the memory ordering violator.
Definition lsq_unit.cc:400
DynInstPtr memDepViolator
The oldest load that caused a memory ordering violation.
Definition lsq_unit.hh:503
void squash(const InstSeqNum &squashed_num)
Squashes all instructions younger than a specific sequence number.
Definition lsq_unit.cc:921
std::string name() const
Returns the name of the LSQ unit.
Definition lsq_unit.cc:245
void checkSnoop(PacketPtr pkt)
Check if an incoming invalidate hits in the lsq on a load that might have issued out of order wrt ano...
Definition lsq_unit.cc:427
static constexpr auto MaxDataBytes
Definition lsq_unit.hh:91
void recvRetry()
Handles doing the retry.
Definition lsq_unit.cc:1274
int storesToWB
The number of store instructions in the SQ waiting to writeback.
Definition lsq_unit.hh:464
unsigned numFreeLoadEntries()
Returns the number of free LQ entries.
Definition lsq_unit.cc:410
bool trySendPacket(bool isLoad, PacketPtr data_pkt)
Attempts to send a packet to the cache.
Definition lsq_unit.cc:1199
void writeback(const DynInstPtr &inst, PacketPtr pkt)
Writes back the instruction, sending it to IEW.
Definition lsq_unit.cc:1074
StoreQueue::iterator storeWBIt
The index of the first instruction that may be ready to be written back, and has not yet been written...
Definition lsq_unit.hh:476
BaseMMU * getMMUPtr()
Definition lsq_unit.cc:1308
void writebackBlockedStore()
Try to finish a previously blocked write back attempt.
Definition lsq_unit.cc:779
void commitLoads(InstSeqNum &youngest_inst)
Commits loads older than a specific sequence number.
Definition lsq_unit.cc:742
gem5::o3::LSQUnit::LSQUnitStats stats
void completeDataAccess(PacketPtr pkt)
Completes the data access that has been returned from the memory system.
Definition lsq_unit.cc:105
void startStaleTranslationFlush()
Definition lsq_unit.cc:1241
LSQ * lsq
Pointer to the LSQ.
Definition lsq_unit.hh:405
bool needsTSO
Flag for memory model.
Definition lsq_unit.hh:506
void commitStores(InstSeqNum &youngest_inst)
Commits stores older than a specific sequence number.
Definition lsq_unit.cc:753
ThreadID lsqID
The LSQUnit thread id.
Definition lsq_unit.hh:446
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
Definition lsq_unit.cc:92
Memory operation metadata.
Definition lsq.hh:190
virtual bool recvTimingResp(PacketPtr pkt)=0
virtual void buildPackets()=0
virtual RequestPtr mainReq()
Definition lsq.hh:378
virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask)=0
Test if the request accesses a particular cache line.
void discard()
The request is discarded (e.g.
Definition lsq.hh:518
PacketPtr packet(int idx=0)
Definition lsq.hh:368
uint32_t _numOutstandingPackets
Definition lsq.hh:258
void packetNotSent()
Update the status to reflect that a packet was not sent.
Definition lsq.hh:446
const uint32_t _size
Definition lsq.hh:255
bool isReleased()
Test if the LSQRequest has been released, i.e.
Definition lsq.hh:402
bool isAnyOutstandingRequest()
Test if there is any in-flight translation or mem access request.
Definition lsq.hh:388
virtual void sendPacketToCache()=0
bool isSplit() const
Definition lsq.hh:409
void packetSent()
Update the status to reflect that a packet was sent.
Definition lsq.hh:437
bool needWBToRegister() const
Definition lsq.hh:415
RequestPtr req(int idx=0)
Definition lsq.hh:362
virtual PacketPtr mainPacket()
Definition lsq.hh:371
const DynInstPtr & instruction()
Definition lsq.hh:334
bool cacheBlocked() const
Is D-cache blocked?
Definition lsq.cc:186
void cachePortBusy(bool is_load)
Another store port is in use.
Definition lsq.cc:210
bool cachePortAvailable(bool is_load) const
Is any store port available to use?
Definition lsq.cc:198
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
void pop_front(size_t num_elem=1)
Circularly increase the head pointer.
bool empty() const
Is the queue empty?
void pop_back()
Circularly decrease the tail pointer.
void advance_tail()
Increases the tail by one.
bool full() const
Is the queue full? A queue is full if the head is the 0^{th} element and the tail is the (size-1)^{th...
iterator begin()
Iterators.
size_t capacity() const
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
void addStatGroup(const char *name, Group *block)
Add a stat block as a child of this block.
Definition group.cc:117
Bitfield< 21 > writeback
Definition types.hh:126
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9 > e
Definition misc_types.hh:65
Bitfield< 33 > id
Bitfield< 3 > x
Definition pagetable.hh:73
static constexpr int MaxThreads
Definition limits.hh:38
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
void cprintf(const char *format, const Args &...args)
Definition cprintf.hh:155
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
std::string htmFailureToStr(HtmFailureFaultCause cause)
Convert enum into string to be used for debug purposes.
Definition htm.cc:44
uint64_t Tick
Tick count type.
Definition types.hh:58
HtmCacheFailure
Definition htm.hh:60
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
constexpr decltype(nullptr) NoFault
Definition types.hh:253
HtmFailureFaultCause
Definition htm.hh:48
uint64_t InstSeqNum
Definition inst_seq.hh:40
Declaration of the Packet class.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
statistics::Scalar blockedByCache
Number of times the LSQ is blocked due to the cache.
Definition lsq_unit.hh:536
statistics::Scalar forwLoads
Total number of loads forwaded from LSQ stores.
Definition lsq_unit.hh:517
LSQUnitStats(statistics::Group *parent)
Definition lsq_unit.cc:254
statistics::Scalar ignoredResponses
Total number of responses from the memory system that are ignored due to the instruction already bein...
Definition lsq_unit.hh:524
statistics::Distribution loadToUse
Distribution of cycle latency between the first time a load is issued and its completion.
Definition lsq_unit.hh:540
statistics::Scalar rescheduledLoads
Number of loads that were rescheduled.
Definition lsq_unit.hh:533
statistics::Scalar squashedStores
Total number of squashed stores.
Definition lsq_unit.hh:530
statistics::Scalar squashedLoads
Total number of squashed loads.
Definition lsq_unit.hh:520
statistics::Scalar memOrderViolation
Tota number of memory ordering violations.
Definition lsq_unit.hh:527

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0