43 #include "arch/locked_mem.hh"
50 #include "debug/Activity.hh"
51 #include "debug/MinorMem.hh"
67 issuedToMemory(false),
68 isTranslationDelayed(false),
71 request = std::make_shared<Request>();
77 SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
79 ExecContext context(port.cpu, thread, port.execute, inst);
80 Fault M5_VAR_USED fault = inst->translationFault;
83 inst->translationFault = inst->staticInst->initiateAcc(&context,
nullptr);
84 if (inst->translationFault ==
NoFault) {
86 "Translation fault suppressed for inst:%s\n", *inst);
88 assert(inst->translationFault == fault);
96 DPRINTFS(MinorMem, (&port),
"Complete disabled mem access for inst:%s\n",
99 SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
102 ExecContext context(port.cpu, thread, port.execute, inst);
105 inst->staticInst->completeAcc(
nullptr, &context, inst->traceData);
113 port.cpu.threads[inst->id.threadId]->setMemAccPredicate(
false);
114 DPRINTFS(MinorMem, (&port),
"Disable mem access for inst:%s\n", *inst);
119 Addr req1_addr,
unsigned int req1_size,
120 Addr req2_addr,
unsigned int req2_size)
124 Addr req2_end_addr = req2_addr + req2_size;
125 Addr req1_end_addr = req1_addr + req1_size;
129 if (req1_addr >= req2_end_addr || req1_end_addr <= req2_addr)
131 else if (req1_addr <= req2_addr && req1_end_addr >= req2_end_addr)
143 request->getPaddr(), request->getSize(),
144 other_request->
request->getPaddr(), other_request->
request->getSize());
157 return inst->isInst() && inst->staticInst->isMemBarrier();
163 return state == StoreToStoreBuffer;
169 DPRINTFS(MinorMem, (&port),
"Setting state from %d to %d for request:"
170 " %s\n",
state, new_state, *inst);
185 os << (isLoad ?
'R' :
'W') <<
';';
186 inst->reportData(
os);
195 os <<
"PartialAddrRangeCoverage";
198 os <<
"FullAddrRangeCoverage";
201 os <<
"NoAddrRangeCoverage";
204 os <<
"AddrRangeCoverage-" <<
static_cast<int>(coverage);
218 os <<
"InTranslation";
227 os <<
"RequestIssuing";
230 os <<
"StoreToStoreBuffer";
233 os <<
"StoreInStoreBuffer";
236 os <<
"StoreBufferIssuing";
239 os <<
"RequestNeedsRetry";
242 os <<
"StoreBufferNeedsRetry";
248 os <<
"LSQRequestState-" <<
static_cast<int>(
state);
257 bool is_last_barrier =
260 DPRINTF(MinorMem,
"Moving %s barrier out of store buffer inst: %s\n",
261 (is_last_barrier ?
"last" :
"a"), *inst);
271 port.numAccessesInDTLB--;
273 DPRINTFS(MinorMem, (&port),
"Received translation response for"
274 " request: %s delayed:%d %s\n", *inst, isTranslationDelayed,
275 fault_ !=
NoFault ? fault_->name() :
"");
278 inst->translationFault = fault_;
279 if (isTranslationDelayed) {
280 tryToSuppressFault();
281 if (inst->translationFault ==
NoFault) {
282 completeDisabledMemAccess();
286 setState(Translated);
288 setState(Translated);
291 port.tryToSendToTransfers(
this);
303 const auto &byte_enable = request->getByteEnable();
304 if (byte_enable.size() == 0 ||
306 port.numAccessesInDTLB++;
310 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request\n");
325 DPRINTFS(MinorMem, (&port),
"Retiring packet\n");
327 packetInFlight =
false;
335 port.numAccessesInDTLB--;
337 unsigned int M5_VAR_USED expected_fragment_index =
338 numTranslatedFragments;
340 numInTranslationFragments--;
341 numTranslatedFragments++;
343 DPRINTFS(MinorMem, (&port),
"Received translation response for fragment"
344 " %d of request: %s delayed:%d %s\n", expected_fragment_index,
345 *inst, isTranslationDelayed,
346 fault_ !=
NoFault ? fault_->name() :
"");
348 assert(request_ == fragmentRequests[expected_fragment_index]);
356 inst->translationFault = fault_;
358 DPRINTFS(MinorMem, (&port),
"Faulting translation for fragment:"
359 " %d of request: %s\n",
360 expected_fragment_index, *inst);
362 if (expected_fragment_index > 0 || isTranslationDelayed)
363 tryToSuppressFault();
364 if (expected_fragment_index == 0) {
365 if (isTranslationDelayed && inst->translationFault ==
NoFault) {
366 completeDisabledMemAccess();
369 setState(Translated);
371 }
else if (inst->translationFault ==
NoFault) {
372 setState(Translated);
373 numTranslatedFragments--;
374 makeFragmentPackets();
376 setState(Translated);
378 port.tryToSendToTransfers(
this);
379 }
else if (numTranslatedFragments == numFragments) {
380 makeFragmentPackets();
381 setState(Translated);
382 port.tryToSendToTransfers(
this);
385 assert(!translationEvent.scheduled());
386 port.cpu.schedule(translationEvent,
curTick());
392 LSQRequest(port_, inst_, isLoad_, data_, res_),
396 numInTranslationFragments(0),
397 numTranslatedFragments(0),
398 numIssuedFragments(0),
399 numRetiredFragments(0),
409 for (
auto i = fragmentPackets.begin();
410 i != fragmentPackets.end();
i++)
419 Addr base_addr = request->getVaddr();
420 unsigned int whole_size = request->getSize();
421 unsigned int line_width = port.lineWidth;
423 unsigned int fragment_size;
440 unsigned int first_fragment_offset =
442 unsigned int last_fragment_size =
444 unsigned int first_fragment_size =
445 line_width - first_fragment_offset;
447 unsigned int middle_fragments_total_size =
448 whole_size - (first_fragment_size + last_fragment_size);
452 unsigned int middle_fragment_count =
453 middle_fragments_total_size / line_width;
455 numFragments = 1 + middle_fragment_count +
456 (last_fragment_size == 0 ? 0 : 1);
458 DPRINTFS(MinorMem, (&port),
"Dividing transfer into %d fragmentRequests."
459 " First fragment size: %d Last fragment size: %d\n",
460 numFragments, first_fragment_size,
461 (last_fragment_size == 0 ? line_width : last_fragment_size));
463 assert(((middle_fragment_count * line_width) +
464 first_fragment_size + last_fragment_size) == whole_size);
466 fragment_addr = base_addr;
467 fragment_size = first_fragment_size;
470 Addr end_addr = base_addr + whole_size;
472 auto& byte_enable = request->getByteEnable();
473 unsigned int num_disabled_fragments = 0;
475 for (
unsigned int fragment_index = 0; fragment_index < numFragments;
478 bool M5_VAR_USED is_last_fragment =
false;
480 if (fragment_addr == base_addr) {
482 fragment_size = first_fragment_size;
484 if ((fragment_addr + line_width) > end_addr) {
486 fragment_size = end_addr - fragment_addr;
487 is_last_fragment =
true;
490 fragment_size = line_width;
495 bool disabled_fragment =
false;
497 fragment->setContext(request->contextId());
498 if (byte_enable.empty()) {
500 fragment_addr, fragment_size, request->getFlags(),
501 request->requestorId(), request->getPC());
504 auto it_start = byte_enable.begin() +
505 (fragment_addr - base_addr);
506 auto it_end = byte_enable.begin() +
507 (fragment_addr - base_addr) + fragment_size;
510 fragment_addr, fragment_size, request->getFlags(),
511 request->requestorId(), request->getPC());
514 disabled_fragment =
true;
518 if (!disabled_fragment) {
519 DPRINTFS(MinorMem, (&port),
"Generating fragment addr: 0x%x"
520 " size: %d (whole request addr: 0x%x size: %d) %s\n",
521 fragment_addr, fragment_size, base_addr, whole_size,
522 (is_last_fragment ?
"last fragment" :
""));
524 fragmentRequests.push_back(
fragment);
526 num_disabled_fragments++;
529 fragment_addr += fragment_size;
531 assert(numFragments >= num_disabled_fragments);
532 numFragments -= num_disabled_fragments;
538 assert(numTranslatedFragments > 0);
539 Addr base_addr = request->getVaddr();
541 DPRINTFS(MinorMem, (&port),
"Making packets for request: %s\n", *inst);
543 for (
unsigned int fragment_index = 0;
544 fragment_index < numTranslatedFragments;
549 DPRINTFS(MinorMem, (&port),
"Making packet %d for request: %s"
551 fragment_index, *inst,
552 (
fragment->hasPaddr() ?
"has paddr" :
"no paddr"),
556 unsigned int fragment_size =
fragment->getSize();
558 uint8_t *request_data = NULL;
563 request_data =
new uint8_t[fragment_size];
564 std::memcpy(request_data,
data + (fragment_addr - base_addr),
573 fragmentPackets.push_back(fragment_packet);
575 request->setFlags(
fragment->getFlags());
581 request->setPaddr(fragmentRequests[0]->getPaddr());
588 makeFragmentRequests();
590 if (numFragments > 0) {
592 numInTranslationFragments = 0;
593 numTranslatedFragments = 0;
603 sendNextFragmentToTranslation();
613 assert(numIssuedFragments < numTranslatedFragments);
615 return fragmentPackets[numIssuedFragments];
621 assert(numIssuedFragments < numTranslatedFragments);
623 numIssuedFragments++;
629 assert(inst->translationFault ==
NoFault);
630 assert(numRetiredFragments < numTranslatedFragments);
632 DPRINTFS(MinorMem, (&port),
"Retiring fragment addr: 0x%x size: %d"
633 " offset: 0x%x (retired fragment num: %d)\n",
634 response->
req->getVaddr(), response->
req->getSize(),
635 request->getVaddr() - response->
req->getVaddr(),
636 numRetiredFragments);
638 numRetiredFragments++;
643 DPRINTFS(MinorMem, (&port),
"Skipping this fragment\n");
644 }
else if (response->
isError()) {
646 DPRINTFS(MinorMem, (&port),
"Fragment has an error, skipping\n");
648 packet->copyError(response);
655 data =
new uint8_t[request->getSize()];
661 data + (response->
req->getVaddr() - request->getVaddr()),
663 response->
req->getSize());
668 if (skipped && !hasPacketsInMemSystem()) {
669 DPRINTFS(MinorMem, (&port),
"Completed skipped burst\n");
671 if (packet->needsResponse())
672 packet->makeResponse();
675 if (numRetiredFragments == numTranslatedFragments)
678 if (!skipped && isComplete()) {
679 DPRINTFS(MinorMem, (&port),
"Completed burst %d\n", packet != NULL);
681 DPRINTFS(MinorMem, (&port),
"Retired packet isRead: %d isWrite: %d"
682 " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
683 " %s\n", packet->isRead(), packet->isWrite(),
684 packet->needsResponse(), packet->getSize(), request->getSize(),
690 data =
new uint8_t[request->getSize()];
694 DPRINTFS(MinorMem, (&port),
"Copying read data\n");
695 std::memcpy(packet->getPtr<uint8_t>(),
data, request->getSize());
697 packet->makeResponse();
706 unsigned int fragment_index = numTranslatedFragments;
711 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request for fragment: %d\n",
714 port.numAccessesInDTLB++;
715 numInTranslationFragments++;
718 fragmentRequests[fragment_index], thread,
this, (isLoad ?
726 return slots.size() < numSlots;
732 auto found = std::find(slots.begin(), slots.end(), request);
734 if (found != slots.end()) {
735 DPRINTF(MinorMem,
"Deleting request: %s %s %s from StoreBuffer\n",
736 request, *found, *(request->
inst));
747 warn(
"%s: store buffer insertion without space to insert from"
748 " inst: %s\n",
name(), *(request->
inst));
751 DPRINTF(MinorMem,
"Pushing store: %s into store buffer\n", request);
753 numUnissuedAccesses++;
758 slots.push_back(request);
767 unsigned int &found_slot)
769 unsigned int slot_index = slots.size() - 1;
770 auto i = slots.rbegin();
782 slot->
inst->id.threadId == request->
inst->id.threadId &&
783 !slot->
packet->
req->isCacheMaintenance()) {
787 DPRINTF(MinorMem,
"Forwarding: slot: %d result: %s thisAddr:"
788 " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
789 slot_index, coverage,
793 found_slot = slot_index;
808 unsigned int slot_number)
810 assert(slot_number < slots.size());
821 Addr addr_offset = load_addr - store_addr;
823 unsigned int load_size = load->
request->getSize();
825 DPRINTF(MinorMem,
"Forwarding %d bytes for addr: 0x%x from store buffer"
826 " slot: %d addr: 0x%x addressOffset: 0x%x\n",
827 load_size, load_addr, slot_number,
828 store_addr, addr_offset);
831 void *store_packet_data = store->
packet->
getPtr<uint8_t>() + addr_offset;
833 std::memcpy(load_packet_data, store_packet_data, load_size);
842 numUnissuedAccesses--;
848 DPRINTF(MinorMem,
"StoreBuffer step numUnissuedAccesses: %d\n",
849 numUnissuedAccesses);
853 while (!slots.empty() &&
854 slots.front()->isComplete() && slots.front()->isBarrier())
858 DPRINTF(MinorMem,
"Clearing barrier for inst: %s\n",
861 numUnissuedAccesses--;
862 lsq.clearMemBarrier(barrier->
inst);
868 auto i = slots.begin();
870 unsigned int issue_count = 0;
880 issue_count < storeLimitPerCycle &&
881 lsq.canSendToMemorySystem() &&
886 DPRINTF(MinorMem,
"Considering request: %s, sentAllPackets: %d"
897 DPRINTF(MinorMem,
"Trying to send request: %s to memory"
898 " system\n", *(request->
inst));
900 if (lsq.tryToSend(request)) {
901 countIssuedStore(request);
921 if (!inst->inStoreBuffer) {
935 unsigned int size = slots.size();
937 std::ostringstream
os;
949 while (
i < numSlots) {
957 MINORTRACE(
"addr=%s num_unissued_stores=%d\n",
os.str(),
958 numUnissuedAccesses);
965 DPRINTF(MinorMem,
"Request needs retry, not issuing to"
966 " memory until retry arrives\n");
971 DPRINTF(MinorMem,
"Request still in translation, not issuing to"
982 DPRINTF(MinorMem,
"Request not at front of requests queue, can't"
983 " issue to memory\n");
988 DPRINTF(MinorMem,
"No space to insert request into transfers"
994 DPRINTF(MinorMem,
"Passing a %s transfer on to transfers"
995 " queue\n", (request->
isComplete() ?
"completed" :
"failed"));
1006 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1007 " waiting for responses before aborting request\n");
1009 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1010 " aborting request\n");
1019 if (request->
inst->staticInst->isPrefetch()) {
1020 DPRINTF(MinorMem,
"Not signalling fault for faulting prefetch\n");
1022 DPRINTF(MinorMem,
"Moving faulting request into the transfers"
1030 bool is_load = request->
isLoad;
1031 bool is_llsc = request->
request->isLLSC();
1032 bool is_release = request->
request->isRelease();
1033 bool is_swap = request->
request->isSwap();
1034 bool is_atomic = request->
request->isAtomic();
1035 bool bufferable = !(request->
request->isStrictlyOrdered() ||
1036 is_llsc || is_swap || is_atomic || is_release);
1040 DPRINTF(MinorMem,
"Load request with stores still in transfers"
1041 " queue, stalling\n");
1046 if (bufferable && !request->
request->isLocalAccess()) {
1049 DPRINTF(MinorMem,
"Moving store into transfers queue\n");
1056 if (((!is_load && is_llsc) || is_release) &&
1058 DPRINTF(MinorMem,
"Memory access needs to wait for store buffer"
1068 DPRINTF(MinorMem,
"Memory access not the head inst., can't be"
1069 " sure it can be performed, not issuing\n");
1073 unsigned int forwarding_slot = 0;
1085 DPRINTF(MinorMem,
"Memory access can receive forwarded data"
1086 " from the store buffer, but need to wait for store buffer"
1096 bool do_access =
true;
1101 unsigned int forwarding_slot = 0;
1106 switch (forwarding_result) {
1117 DPRINTF(MinorMem,
"Load partly satisfied by store buffer"
1118 " data. Must wait for the store to complete\n");
1122 DPRINTF(MinorMem,
"No forwardable data from store buffer\n");
1129 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1146 DPRINTF(MinorMem,
"Not perfoming a memory "
1147 "access for store conditional\n");
1156 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1182 DPRINTF(MinorMem,
"Can't send request: %s yet, no space in memory\n",
1187 DPRINTF(MinorMem,
"Trying to send request: %s addr: 0x%x\n",
1188 *(request->
inst), packet->
req->getVaddr());
1194 if (request->
request->isLocalAccess()) {
1197 request->
request->contextId()));
1200 DPRINTF(MinorMem,
"IPR read inst: %s\n", *(request->
inst));
1202 DPRINTF(MinorMem,
"IPR write inst: %s\n", *(request->
inst));
1204 request->
request->localAccessor(thread, packet);
1210 DPRINTF(MinorMem,
"IPR access has another packet: %s\n",
1219 DPRINTF(MinorMem,
"Sent data memory request\n");
1227 switch (request->
state) {
1241 panic(
"Unrecognized LSQ request state %d.", request->
state);
1247 "Sending data memory request - needs retry\n");
1253 switch (request->
state) {
1263 panic(
"Unrecognized LSQ request state %d.", request->
state);
1304 DPRINTF(MinorMem,
"Received response packet inst: %s"
1305 " addr: 0x%x cmd: %s\n",
1312 DPRINTF(MinorMem,
"Received error response packet: %s\n",
1316 switch (request->
state) {
1322 DPRINTF(MinorMem,
"Has outstanding packets?: %d %d\n",
1337 DPRINTF(MinorMem,
"Completed transfer for barrier: %s"
1338 " leaving the request as it is also a barrier\n",
1344 panic(
"Shouldn't be allowed to receive a response from another state");
1361 DPRINTF(MinorMem,
"Received retry request\n");
1405 LSQ::LSQ(std::string name_, std::string dcache_port_name_,
1407 unsigned int in_memory_system_limit,
unsigned int line_width,
1408 unsigned int requests_queue_size,
unsigned int transfers_queue_size,
1409 unsigned int store_buffer_size,
1410 unsigned int store_buffer_cycle_store_limit) :
1418 lineWidth((line_width == 0 ?
cpu.cacheLineSize() : line_width)),
1419 requests(name_ +
".requests",
"addr", requests_queue_size),
1420 transfers(name_ +
".transfers",
"addr", transfers_queue_size),
1422 *this, store_buffer_size, store_buffer_cycle_store_limit),
1430 if (in_memory_system_limit < 1) {
1431 fatal(
"%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
1432 in_memory_system_limit);
1435 if (store_buffer_cycle_store_limit < 1) {
1436 fatal(
"%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1437 " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
1440 if (requests_queue_size < 1) {
1441 fatal(
"%s: executeLSQRequestsQueueSize must be"
1442 " >= 1 (%d)\n", name_, requests_queue_size);
1445 if (transfers_queue_size < 1) {
1446 fatal(
"%s: executeLSQTransfersQueueSize must be"
1447 " >= 1 (%d)\n", name_, transfers_queue_size);
1450 if (store_buffer_size < 1) {
1451 fatal(
"%s: executeLSQStoreBufferSize must be"
1452 " >= 1 (%d)\n", name_, store_buffer_size);
1498 if (request->
inst->id == inst->id) {
1501 bool to_store_buffer = request->
state ==
1504 if ((complete && !(request->
isBarrier() && !can_store)) ||
1505 (to_store_buffer && can_store))
1513 DPRINTF(MinorMem,
"Found matching memory response for inst: %s\n",
1516 DPRINTF(MinorMem,
"No matching memory response for inst: %s\n",
1537 DPRINTF(MinorMem,
"Deleting %s request: %s\n",
1538 (response->
isLoad ?
"load" :
"store"),
1550 DPRINTF(MinorMem,
"Sending store: %s to store buffer\n",
1553 request->
inst->inStoreBuffer =
true;
1575 ret = have_translated_requests ||
1580 DPRINTF(Activity,
"Need to tick\n");
1591 assert(inst->translationFault ==
NoFault || inst->inLSQ);
1594 return inst->translationFault;
1599 if (needs_burst && inst->staticInst->isAtomic()) {
1607 panic(
"Do not expect cross-cache-line atomic memory request\n");
1614 uint8_t *request_data = NULL;
1616 DPRINTF(MinorMem,
"Pushing request (%s) addr: 0x%x size: %d flags:"
1617 " 0x%x%s lineWidth : 0x%x\n",
1618 (isLoad ?
"load" :
"store/atomic"),
addr, size, flags,
1619 (needs_burst ?
" (needs burst)" :
""),
lineWidth);
1624 request_data =
new uint8_t[size];
1625 if (inst->staticInst->isAtomic() ||
1628 std::memset(request_data, 0, size);
1630 std::memcpy(request_data,
data, size);
1636 *
this, inst, isLoad, request_data, res);
1639 *
this, inst, isLoad, request_data, res);
1642 if (inst->traceData)
1643 inst->traceData->setMem(
addr, size, flags);
1645 int cid =
cpu.
threads[inst->id.threadId]->getTC()->contextId();
1646 request->
request->setContext(cid);
1650 inst->pc.instAddr(), std::move(amo_op));
1651 request->
request->setByteEnable(byte_enable);
1657 return inst->translationFault;
1670 MINORTRACE(
"state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
1671 " lastMemBarrier=%d\n",
1680 unsigned int store_buffer_size,
1681 unsigned int store_limit_per_cycle) :
1682 Named(name_), lsq(lsq_),
1683 numSlots(store_buffer_size),
1684 storeLimitPerCycle(store_limit_per_cycle),
1686 numUnissuedAccesses(0)
1702 }
else if (!request->isCacheMaintenance()) {
1714 assert(inst->isInst() && inst->staticInst->isMemBarrier());
1726 assert(inst->translationFault ==
NoFault);
1744 os <<
"MemoryRunning";
1747 os <<
"MemoryNeedsRetry";
1750 os <<
"MemoryState-" <<
static_cast<int>(
state);
1786 if (tid != req_tid) {