43 #ifndef __CPU_O3_LSQ_UNIT_IMPL_HH__
44 #define __CPU_O3_LSQ_UNIT_IMPL_HH__
47 #include "arch/locked_mem.hh"
49 #include "config/the_isa.hh"
53 #include "debug/Activity.hh"
54 #include "debug/HtmCpu.hh"
55 #include "debug/IEW.hh"
56 #include "debug/LSQUnit.hh"
57 #include "debug/O3PipeView.hh"
64 :
Event(Default_Pri, AutoDelete),
65 inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
67 assert(_inst->savedReq);
68 _inst->savedReq->writebackScheduled();
75 assert(!lsqPtr->cpu->switchedOut());
77 lsqPtr->writeback(inst, pkt);
79 assert(inst->savedReq);
80 inst->savedReq->writebackDone();
88 return "Store writeback";
97 assert(req !=
nullptr);
100 if (senderState->alive()) {
101 ret = req->recvTimingResp(pkt);
103 senderState->outstanding--;
133 "store notification (ignored) of HTM transaction failure "
134 "in cache - addr=0x%lx - rc=%s - htmUid=%d\n",
151 panic(
"HTM error - unhandled return code from cache (%s)",
156 std::make_shared<GenericHtmFailureFault>(
157 inst->getHtmTransactionUid(),
161 "load notification of HTM transaction failure "
162 "in cache - pc=%s - addr=0x%lx - "
163 "rc=%u - htmUid=%d\n",
164 inst->pcState(), pkt->
getAddr(),
169 cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
175 assert(!
cpu->switchedOut());
176 if (!inst->isSquashed()) {
180 assert(inst->isLoad() || inst->isStoreConditional() ||
185 state->request()->mainPacket()->setHtmTransactionFailedInCache(
189 writeback(inst, state->request()->mainPacket());
190 if (inst->isStore() || inst->isAtomic()) {
195 }
else if (inst->isStore()) {
203 template <
class Impl>
218 LSQ *lsq_ptr,
unsigned id)
227 cpu->addStatGroup(
csprintf(
"lsq%i", lsqID).c_str(), &stats);
231 depCheckShift = params->LSQDepCheckShift;
232 checkLoads = params->LSQCheckLoads;
233 needsTSO = params->needsTSO;
243 loads = stores = storesToWB = 0;
247 htmStarts = htmStops = 0;
249 storeWBIt = storeQueue.begin();
252 memDepViolator = NULL;
256 cacheBlockMask = ~(cpu->cacheLineSize() - 1);
263 if (Impl::MaxThreads == 1) {
264 return iewStage->name() +
".lsq";
270 template <
class Impl>
272 :
Stats::Group(parent),
273 ADD_STAT(forwLoads,
"Number of loads that had data forwarded from"
275 ADD_STAT(squashedLoads,
"Number of loads squashed"),
276 ADD_STAT(ignoredResponses,
"Number of memory responses ignored"
277 " because the instruction is squashed"),
278 ADD_STAT(memOrderViolation,
"Number of memory ordering violations"),
279 ADD_STAT(squashedStores,
"Number of stores squashed"),
280 ADD_STAT(rescheduledLoads,
"Number of loads that were rescheduled"),
281 ADD_STAT(blockedByCache,
"Number of times an access to memory failed"
282 " due to the cache being blocked")
311 template <
class Impl>
315 assert(inst->isMemRef());
317 assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
319 if (inst->isLoad()) {
328 template <
class Impl>
353 if (load_inst->isHtmStart()) {
355 DPRINTF(HtmCpu,
">> htmStarts++ (%d) : htmStops (%d)\n",
359 const auto& htm_cpt =
cpu->tcBase(
lsqID)->getHtmCheckpointPtr();
360 auto htm_uid = htm_cpt->getHtmUid();
363 if (!load_inst->inHtmTransactionalState()) {
364 htm_uid = htm_cpt->newHtmUid();
365 DPRINTF(HtmCpu,
"generating new htmUid=%u\n", htm_uid);
366 if (htm_depth != 1) {
368 "unusual HTM transactional depth (%d)"
369 " possibly caused by mispeculation - htmUid=%u\n",
373 load_inst->setHtmTransactionalState(htm_uid, htm_depth);
376 if (load_inst->isHtmStop()) {
378 DPRINTF(HtmCpu,
">> htmStarts (%d) : htmStops++ (%d)\n",
383 "htmStops==1 && htmStarts==0. "
384 "This generally shouldn't happen "
385 "(unless due to misspeculation)\n");
390 template <
class Impl>
399 store_inst->pcState(),
storeQueue.tail(), store_inst->seqNum);
411 template <
class Impl>
412 typename Impl::DynInstPtr
422 template <
class Impl>
433 template <
class Impl>
445 template <
class Impl>
454 for (
int x = 0;
x <
cpu->numContexts();
x++) {
456 bool no_squash =
cpu->thread[
x]->noSquashFromTC;
457 cpu->thread[
x]->noSquashFromTC =
true;
459 cpu->thread[
x]->noSquashFromTC = no_squash;
474 if (ld_inst->effAddrValid() &&
479 bool force_squash =
false;
482 ld_inst = iter->instruction();
484 req = iter->request();
485 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered())
489 ld_inst->seqNum, invalidate_addr);
499 if (ld_inst->possibleLoadViolation() || force_squash) {
501 pkt->
getAddr(), ld_inst->seqNum);
504 ld_inst->fault = std::make_shared<ReExec>();
505 req->setStateToFault();
508 pkt->
getAddr(), ld_inst->seqNum);
519 ld_inst->hitExternalSnoop(
true);
526 template <
class Impl>
541 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
550 if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
551 if (inst->isLoad()) {
555 if (ld_inst->hitExternalSnoop()) {
559 "and [sn:%lli] at address %#x\n",
560 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
565 return std::make_shared<GenericISA::M5PanicFault>(
566 "Detected fault with inst [sn:%lli] and "
567 "[sn:%lli] at address %#x\n",
568 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
574 ld_inst->possibleLoadViolation(
true);
576 " between instructions [sn:%lli] and [sn:%lli]\n",
577 inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
586 "[sn:%lli] at address %#x\n",
587 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
592 return std::make_shared<GenericISA::M5PanicFault>(
593 "Detected fault with "
594 "inst [sn:%lli] and [sn:%lli] at address %#x\n",
595 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
607 template <
class Impl>
616 inst->pcState(), inst->seqNum);
618 assert(!inst->isSquashed());
620 load_fault = inst->initiateAcc();
622 if (load_fault ==
NoFault && !inst->readMemAccPredicate()) {
623 assert(inst->readPredicate());
625 inst->completeAcc(
nullptr);
631 if (inst->isTranslationDelayed() && load_fault ==
NoFault)
634 if (load_fault !=
NoFault && inst->translationCompleted() &&
635 inst->savedReq->isPartialFault() && !inst->savedReq->isComplete()) {
636 assert(inst->savedReq->isSplit());
646 if (load_fault !=
NoFault || !inst->readPredicate()) {
651 if (!inst->readPredicate())
652 inst->forwardOldRegs();
655 (load_fault !=
NoFault ?
"fault" :
"predication"));
656 if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
657 inst->isAtCommit()) {
663 if (inst->effAddrValid()) {
664 auto it = inst->lqIt;
675 template <
class Impl>
683 int store_idx = store_inst->sqIdx;
686 store_inst->pcState(), store_inst->seqNum);
688 assert(!store_inst->isSquashed());
692 typename LoadQueue::iterator loadIt = store_inst->lqIt;
694 Fault store_fault = store_inst->initiateAcc();
696 if (store_inst->isTranslationDelayed() &&
700 if (!store_inst->readPredicate()) {
701 DPRINTF(
LSQUnit,
"Store [sn:%lli] not executed from predication\n",
703 store_inst->forwardOldRegs();
709 store_inst->pcState(), store_inst->seqNum);
714 assert(store_fault ==
NoFault);
716 if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
728 template <
class Impl>
743 template <
class Impl>
755 template <
class Impl>
767 if (
x.instruction()->seqNum > youngest_inst) {
772 x.instruction()->pcState(),
773 x.instruction()->seqNum);
782 template <
class Impl>
787 storeWBIt->request()->sendPacketToCache();
793 template <
class Impl>
825 if (
storeWBIt->instruction()->isDataPrefetch()) {
838 if ((req->mainRequest()->isLLSC() ||
839 req->mainRequest()->isRelease()) &&
842 "[sn:%lli] is %s%s and not head of the queue\n",
844 req->request()->getPaddr(), inst->seqNum,
845 req->mainRequest()->isLLSC() ?
"SC" :
"",
846 req->mainRequest()->isRelease() ?
"/Release" :
"");
852 assert(!inst->memData);
853 inst->memData =
new uint8_t[req->_size];
856 memset(inst->memData, 0, req->_size);
858 memcpy(inst->memData,
storeWBIt->data(), req->_size);
861 if (req->senderState() ==
nullptr) {
863 state->isLoad =
false;
864 state->needWB =
false;
867 req->senderState(state);
868 if (inst->isStoreConditional() || inst->isAtomic()) {
870 state->needWB =
true;
876 "to Addr:%#x, data:%#x [sn:%lli]\n",
878 req->request()->getPaddr(), (
int)*(inst->memData),
882 if (inst->isStoreConditional()) {
886 inst->recordResult(
false);
889 inst->recordResult(
true);
896 "Instantly completing it.\n",
911 if (req->request()->isLocalAccess()) {
912 assert(!inst->isStoreConditional());
913 assert(!inst->inHtmTransactionalState());
918 req->request()->localAccessor(thread, main_pkt);
925 req->sendPacketToCache();
931 DPRINTF(
LSQUnit,
"D-Cache became blocked when writing [sn:%lli], "
932 "will retry later\n",
939 template <
class Impl>
944 "(Loads:%i Stores:%i)\n", squashed_num,
loads,
stores);
965 DPRINTF(HtmCpu,
">> htmStarts-- (%d) : htmStops (%d)\n",
971 DPRINTF(HtmCpu,
">> htmStarts (%d) : htmStops-- (%d)\n",
987 uint64_t in_flight_uid = 0;
989 if (scan_it->instruction()->isHtmStart() &&
990 !scan_it->instruction()->isSquashed()) {
991 in_flight_uid = scan_it->instruction()->getHtmTransactionUid();
992 DPRINTF(HtmCpu,
"loadQueue[%d]: found valid HtmStart htmUid=%u\n",
993 scan_it._idx, in_flight_uid);
999 const auto& htm_cpt =
cpu->tcBase(
lsqID)->getHtmCheckpointPtr();
1001 const uint64_t old_local_htm_uid = htm_cpt->getHtmUid();
1002 uint64_t new_local_htm_uid;
1003 if (in_flight_uid > 0)
1004 new_local_htm_uid = in_flight_uid;
1008 if (old_local_htm_uid != new_local_htm_uid) {
1009 DPRINTF(HtmCpu,
"flush: lastRetiredHtmUid=%u\n",
1011 DPRINTF(HtmCpu,
"flush: resetting localHtmUid=%u\n",
1014 htm_cpt->setHtmUid(new_local_htm_uid);
1023 storeQueue.back().instruction()->seqNum > squashed_num) {
1030 "idx:%i [sn:%lli]\n",
1038 panic(
"Is stalled should have been cleared by stalling load!\n");
1044 storeQueue.back().instruction()->setSquashed();
1057 template <
class Impl>
1071 if (!
storeWBIt->instruction()->isStoreConditional()) {
1075 storeWBIt->instruction()->setCompleted();
1089 template <
class Impl>
1096 if (inst->isSquashed()) {
1097 assert (!inst->isStore() || inst->isStoreConditional());
1102 if (!inst->isExecuted()) {
1103 inst->setExecuted();
1107 inst->completeAcc(pkt);
1117 auto htm_fault = std::dynamic_pointer_cast<
1121 assert(
dynamic_cast<ReExec*
>(inst->fault.get()) !=
nullptr ||
1122 inst->savedReq->isPartialFault());
1129 "%s writeback with HTM failure fault, "
1130 "however, completing packet is not aware of "
1131 "transaction failure. cause=%s htmUid=%u\n",
1132 inst->staticInst->getName(),
1134 htm_fault->getHtmUid());
1138 "due to pending fault.\n", inst->seqNum);
1148 iewStage->checkMisprediction(inst);
1151 template <
class Impl>
1155 assert(store_idx->valid());
1156 store_idx->completed() =
true;
1162 cpu->activityThisCycle();
1166 DynInstPtr store_inst = store_idx->instruction();
1175 iewStage->updateLSQNextCycle =
true;
1178 DPRINTF(
LSQUnit,
"Completing store [sn:%lli], idx:%i, store head "
1180 store_inst->seqNum, store_idx.
idx() - 1,
storeQueue.head() - 1);
1183 if (
DTRACE(O3PipeView)) {
1184 store_inst->storeTick =
1185 curTick() - store_inst->fetchTick;
1199 store_inst->setCompleted();
1211 if (
cpu->checker && !store_inst->isStoreConditional()) {
1212 cpu->checker->verify(store_inst);
1216 template <
class Impl>
1221 bool cache_got_blocked =
false;
1229 cache_got_blocked =
true;
1240 state->outstanding++;
1241 state->request()->packetSent();
1243 if (cache_got_blocked) {
1248 assert(state->request() ==
storeWBIt->request());
1251 state->request()->packetNotSent();
1256 template <
class Impl>
1266 template <
class Impl>
1270 cprintf(
"Load store queue: Dumping instructions.\n");
1276 cprintf(
"%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1285 cprintf(
"%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1291 template <
class Impl>
1295 return cpu->cacheLineSize();
1298 #endif//__CPU_O3_LSQ_UNIT_IMPL_HH__