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"
66 :
Event(Default_Pri, AutoDelete),
67 inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
69 assert(_inst->savedRequest);
70 _inst->savedRequest->writebackScheduled();
76 assert(!lsqPtr->cpu->switchedOut());
78 lsqPtr->writeback(inst, pkt);
80 assert(inst->savedRequest);
81 inst->savedRequest->writebackDone();
88 return "Store writeback";
95 assert(request !=
nullptr);
127 "store notification (ignored) of HTM transaction failure "
128 "in cache - addr=0x%lx - rc=%s - htmUid=%d\n",
145 panic(
"HTM error - unhandled return code from cache (%s)",
150 std::make_shared<GenericHtmFailureFault>(
151 inst->getHtmTransactionUid(),
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(),
166 if (!inst->isSquashed()) {
170 assert(inst->isLoad() || inst->isStoreConditional() ||
180 if (inst->isStore() || inst->isAtomic()) {
184 }
else if (inst->isStore()) {
204 LSQ *lsq_ptr,
unsigned id)
255 : statistics::
Group(parent),
257 "Number of loads that had data forwarded from stores"),
259 "Number of loads squashed"),
261 "Number of memory responses ignored because the instruction is "
264 "Number of memory ordering violations"),
266 "Number of stores squashed"),
268 "Number of loads that were rescheduled"),
270 "Number of times an access to memory failed due to the cache "
272 ADD_STAT(loadToUse,
"Distribution of cycle latency between the "
273 "first time a load is issued and its completion")
305 assert(inst->isMemRef());
307 assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
309 if (inst->isLoad()) {
335 assert(load_inst->lqIdx > 0);
341 if (load_inst->isHtmStart()) {
343 DPRINTF(HtmCpu,
">> htmStarts++ (%d) : htmStops (%d)\n",
348 auto htm_uid = htm_cpt->getHtmUid();
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) {
356 "unusual HTM transactional depth (%d)"
357 " possibly caused by mispeculation - htmUid=%u\n",
361 load_inst->setHtmTransactionalState(htm_uid, htm_depth);
364 if (load_inst->isHtmStop()) {
366 DPRINTF(HtmCpu,
">> htmStarts (%d) : htmStops++ (%d)\n",
371 "htmStops==1 && htmStarts==0. "
372 "This generally shouldn't happen "
373 "(unless due to misspeculation)\n");
393 assert(store_inst->lqIdx > 0);
436 bool no_squash =
cpu->
thread[
x]->noSquashFromTC;
454 if (ld_inst->effAddrValid() &&
457 ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit(ld_inst.
get());
460 bool force_squash =
false;
463 ld_inst = iter->instruction();
465 request = iter->request();
466 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered())
470 ld_inst->seqNum, invalidate_addr);
480 if (ld_inst->possibleLoadViolation() || force_squash) {
482 pkt->
getAddr(), ld_inst->seqNum);
485 ld_inst->fault = std::make_shared<ReExec>();
489 pkt->
getAddr(), ld_inst->seqNum);
495 ld_inst->tcBase()->getIsaPtr()->
496 handleLockedSnoopHit(ld_inst.
get());
502 ld_inst->hitExternalSnoop(
true);
523 if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
532 if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
533 if (inst->isLoad()) {
537 if (ld_inst->hitExternalSnoop()) {
541 "and [sn:%lli] at address %#x\n",
542 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
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);
556 ld_inst->possibleLoadViolation(
true);
558 " between instructions [sn:%lli] and [sn:%lli]\n",
559 inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
568 "[sn:%lli] at address %#x\n",
569 inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
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);
596 inst->pcState(), inst->seqNum);
598 assert(!inst->isSquashed());
600 load_fault = inst->initiateAcc();
602 if (load_fault ==
NoFault && !inst->readMemAccPredicate()) {
603 assert(inst->readPredicate());
605 inst->completeAcc(
nullptr);
611 if (inst->isTranslationDelayed() && load_fault ==
NoFault)
614 if (load_fault !=
NoFault && inst->translationCompleted() &&
615 inst->savedRequest->isPartialFault()
616 && !inst->savedRequest->isComplete()) {
617 assert(inst->savedRequest->isSplit());
627 if (load_fault !=
NoFault || !inst->readPredicate()) {
632 if (!inst->readPredicate())
633 inst->forwardOldRegs();
636 (load_fault !=
NoFault ?
"fault" :
"predication"));
637 if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
638 inst->isAtCommit()) {
644 if (inst->effAddrValid()) {
645 auto it = inst->lqIt;
662 ssize_t store_idx = store_inst->sqIdx;
665 store_inst->pcState(), store_inst->seqNum);
667 assert(!store_inst->isSquashed());
671 typename LoadQueue::iterator loadIt = store_inst->lqIt;
673 Fault store_fault = store_inst->initiateAcc();
675 if (store_inst->isTranslationDelayed() &&
679 if (!store_inst->readPredicate()) {
680 DPRINTF(
LSQUnit,
"Store [sn:%lli] not executed from predication\n",
682 store_inst->forwardOldRegs();
688 store_inst->pcState(), store_inst->seqNum);
690 if (store_inst->isAtomic()) {
693 if (!(store_inst->hasRequest() && store_inst->strictlyOrdered()) ||
694 store_inst->isAtCommit()) {
695 store_inst->setExecuted();
704 assert(store_fault ==
NoFault);
706 if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
730 if (!inst->isInstPrefetch() && !inst->isDataPrefetch()
731 && inst->firstIssue != -1
732 && inst->lastWakeDependents != -1) {
734 inst->lastWakeDependents - inst->firstIssue));
763 if (
x.instruction()->seqNum > youngest_inst) {
768 x.instruction()->pcState(),
769 x.instruction()->seqNum);
782 storeWBIt->request()->sendPacketToCache();
819 if (
storeWBIt->instruction()->isDataPrefetch()) {
832 if ((request->
mainReq()->isLLSC() ||
833 request->
mainReq()->isRelease()) &&
836 "[sn:%lli] is %s%s and not head of the queue\n",
838 request->
mainReq()->getPaddr(), inst->seqNum,
839 request->
mainReq()->isLLSC() ?
"SC" :
"",
840 request->
mainReq()->isRelease() ?
"/Release" :
"");
846 assert(!inst->memData);
847 inst->memData =
new uint8_t[request->
_size];
850 memset(inst->memData, 0, request->
_size);
857 "to Addr:%#x, data:%#x [sn:%lli]\n",
859 request->
mainReq()->getPaddr(), (
int)*(inst->memData),
863 if (inst->isStoreConditional()) {
867 inst->recordResult(
false);
868 bool success = inst->tcBase()->getIsaPtr()->handleLockedWrite(
870 inst->recordResult(
true);
877 "Instantly completing it.\n",
892 if (request->
mainReq()->isLocalAccess()) {
893 assert(!inst->isStoreConditional());
894 assert(!inst->inHtmTransactionalState());
899 request->
mainReq()->localAccessor(thread, main_pkt);
912 DPRINTF(
LSQUnit,
"D-Cache became blocked when writing [sn:%lli], "
913 "will retry later\n",
946 DPRINTF(HtmCpu,
">> htmStarts-- (%d) : htmStops (%d)\n",
952 DPRINTF(HtmCpu,
">> htmStarts (%d) : htmStops-- (%d)\n",
966 uint64_t in_flight_uid = 0;
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);
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;
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",
993 htm_cpt->setHtmUid(new_local_htm_uid);
1009 "idx:%i [sn:%lli]\n",
1017 panic(
"Is stalled should have been cleared by stalling load!\n");
1039 return htm_cpt->getHtmUid();
1055 if (!
storeWBIt->instruction()->isStoreConditional()) {
1059 storeWBIt->instruction()->setCompleted();
1079 if (inst->isSquashed()) {
1080 assert (!inst->isStore() || inst->isStoreConditional());
1085 if (!inst->isExecuted()) {
1086 inst->setExecuted();
1090 inst->completeAcc(pkt);
1100 auto htm_fault = std::dynamic_pointer_cast<
1104 assert(
dynamic_cast<ReExec*
>(inst->fault.
get()) !=
nullptr ||
1105 inst->savedRequest->isPartialFault());
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(),
1118 htm_fault->getHtmUid());
1122 "due to pending fault.\n", inst->seqNum);
1138 assert(store_idx->valid());
1139 store_idx->completed() =
true;
1149 DynInstPtr store_inst = store_idx->instruction();
1160 DPRINTF(
LSQUnit,
"Completing store [sn:%lli], idx:%i, store head "
1165 if (debug::O3PipeView) {
1166 store_inst->storeTick =
1167 curTick() - store_inst->fetchTick;
1181 store_inst->setCompleted();
1193 if (
cpu->
checker && !store_inst->isStoreConditional()) {
1202 bool cache_got_blocked =
false;
1210 cache_got_blocked =
true;
1223 if (cache_got_blocked) {
1228 assert(request ==
storeWBIt->request());
1233 DPRINTF(
LSQUnit,
"Memory request (pkt: %s) from inst [sn:%llu] was"
1234 " %ssent (cache is blocked: %d, cache_got_blocked: %d)\n",
1243 DPRINTF(
LSQUnit,
"Unit %p marking stale translations %d %d\n",
this,
1246 if (entry.valid() && entry.hasRequest())
1247 entry.request()->markAsStaleTranslation();
1250 if (entry.valid() && entry.hasRequest())
1251 entry.request()->markAsStaleTranslation();
1260 if (entry.valid() && entry.hasRequest()
1261 && entry.request()->hasStaleTranslation())
1265 if (entry.valid() && entry.hasRequest()
1266 && entry.request()->hasStaleTranslation())
1285 cprintf(
"Load store queue: Dumping instructions.\n");
1291 cprintf(
"%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1300 cprintf(
"%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1325 assert(!load_inst->isExecuted());
1332 if (request->
mainReq()->isStrictlyOrdered() &&
1333 (load_idx !=
loadQueue.
head() || !load_inst->isAtCommit())) {
1337 load_inst->clearIssued();
1338 load_inst->effAddrValid(
false);
1341 load_inst->seqNum, load_inst->pcState());
1348 return std::make_shared<GenericISA::M5PanicFault>(
1349 "Strictly ordered load [sn:%llx] PC %s\n",
1350 load_inst->seqNum, load_inst->pcState());
1354 "storeHead: %i addr: %#x%s\n",
1359 if (request->
mainReq()->isLLSC()) {
1363 load_inst->recordResult(
false);
1364 load_inst->tcBase()->getIsaPtr()->handleLockedRead(load_inst.
get(),
1366 load_inst->recordResult(
true);
1369 if (request->
mainReq()->isLocalAccess()) {
1370 assert(!load_inst->memData);
1378 Cycles delay = request->
mainReq()->localAccessor(thread, main_pkt);
1386 auto store_it = load_inst->sqIt;
1389 while (store_it !=
storeWBIt && !load_inst->isDataPrefetch()) {
1392 assert(store_it->valid());
1393 assert(store_it->instruction()->seqNum < load_inst->seqNum);
1394 int store_size = store_it->size();
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());
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;
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;
1422 if (!store_it->instruction()->isAtomic() &&
1423 store_has_lower_limit && store_has_upper_limit &&
1424 !request->
mainReq()->isLLSC()) {
1426 const auto& store_req = store_it->request()->mainReq();
1427 coverage = store_req->isMasked() ?
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))) ||
1439 (request->
mainReq()->isLLSC() &&
1440 ((store_has_lower_limit || upper_load_has_store_part) &&
1441 (store_has_upper_limit || lower_load_has_store_part))) ||
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)))) {
1453 int shift_amt = request->
mainReq()->getVaddr() -
1454 store_it->instruction()->effAddr;
1457 if (!load_inst->memData) {
1458 load_inst->memData =
1459 new uint8_t[request->
mainReq()->getSize()];
1461 if (store_it->isAllZeros())
1462 memset(load_inst->memData, 0,
1463 request->
mainReq()->getSize());
1465 memcpy(load_inst->memData,
1466 store_it->
data() + shift_amt,
1467 request->
mainReq()->getSize());
1470 "addr %#x\n", store_it._idx,
1471 request->
mainReq()->getVaddr());
1484 assert(!request->
mainReq()->isHTMCmd());
1485 if (load_inst->inHtmTransactionalState()) {
1486 assert (!
storeQueue[store_it._idx].completed());
1489 inHtmTransactionalState());
1491 load_inst->getHtmTransactionUid() ==
1493 getHtmTransactionUid());
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,
1503 load_inst->getHtmTransactionUid());
1531 if (store_it->completed()) {
1532 panic(
"Should not check one of these");
1550 load_inst->clearIssued();
1551 load_inst->effAddrValid(
false);
1557 "Store idx %i to load addr %#x\n",
1558 store_it._idx, request->
mainReq()->getVaddr());
1569 DPRINTF(
LSQUnit,
"Doing memory access for inst [sn:%lli] PC %s\n",
1570 load_inst->seqNum, load_inst->pcState());
1573 if (!load_inst->memData) {
1574 load_inst->memData =
new uint8_t[request->
mainReq()->getSize()];
1579 if (request->
mainReq()->isHTMCmd()) {
1583 *load_inst->memData = (uint64_t) 0x1ull;
1606 DPRINTF(
LSQUnit,
"Doing write to store idx %i, addr %#x | storeHead:%i "
1609 storeQueue[store_idx].instruction()->seqNum);
1612 unsigned size = request->
_size;
1614 bool store_no_data =
1616 storeQueue[store_idx].isAllZeros() = store_no_data;
1621 !request->
req()->isCacheMaintenance() &&
1622 !request->
req()->isAtomic())