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 M5_VAR_USED
Fault 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->isFullMemBarrier();
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();
305 port.numAccessesInDTLB++;
309 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request\n");
324 DPRINTFS(MinorMem, (&port),
"Retiring packet\n");
326 packetInFlight =
false;
334 port.numAccessesInDTLB--;
336 M5_VAR_USED
unsigned int expected_fragment_index =
337 numTranslatedFragments;
339 numInTranslationFragments--;
340 numTranslatedFragments++;
342 DPRINTFS(MinorMem, (&port),
"Received translation response for fragment"
343 " %d of request: %s delayed:%d %s\n", expected_fragment_index,
344 *inst, isTranslationDelayed,
345 fault_ !=
NoFault ? fault_->name() :
"");
347 assert(request_ == fragmentRequests[expected_fragment_index]);
355 inst->translationFault = fault_;
357 DPRINTFS(MinorMem, (&port),
"Faulting translation for fragment:"
358 " %d of request: %s\n",
359 expected_fragment_index, *inst);
361 if (expected_fragment_index > 0 || isTranslationDelayed)
362 tryToSuppressFault();
363 if (expected_fragment_index == 0) {
364 if (isTranslationDelayed && inst->translationFault ==
NoFault) {
365 completeDisabledMemAccess();
368 setState(Translated);
370 }
else if (inst->translationFault ==
NoFault) {
371 setState(Translated);
372 numTranslatedFragments--;
373 makeFragmentPackets();
375 setState(Translated);
377 port.tryToSendToTransfers(
this);
378 }
else if (numTranslatedFragments == numFragments) {
379 makeFragmentPackets();
380 setState(Translated);
381 port.tryToSendToTransfers(
this);
384 assert(!translationEvent.scheduled());
385 port.cpu.schedule(translationEvent,
curTick());
391 LSQRequest(port_, inst_, isLoad_, data_, res_),
395 numInTranslationFragments(0),
396 numTranslatedFragments(0),
397 numIssuedFragments(0),
398 numRetiredFragments(0),
408 for (
auto i = fragmentPackets.begin();
409 i != fragmentPackets.end();
i++)
418 Addr base_addr = request->getVaddr();
419 unsigned int whole_size = request->getSize();
420 unsigned int line_width = port.lineWidth;
422 unsigned int fragment_size;
439 unsigned int first_fragment_offset =
441 unsigned int last_fragment_size =
443 unsigned int first_fragment_size =
444 line_width - first_fragment_offset;
446 unsigned int middle_fragments_total_size =
447 whole_size - (first_fragment_size + last_fragment_size);
451 unsigned int middle_fragment_count =
452 middle_fragments_total_size / line_width;
454 numFragments = 1 + middle_fragment_count +
455 (last_fragment_size == 0 ? 0 : 1);
457 DPRINTFS(MinorMem, (&port),
"Dividing transfer into %d fragmentRequests."
458 " First fragment size: %d Last fragment size: %d\n",
459 numFragments, first_fragment_size,
460 (last_fragment_size == 0 ? line_width : last_fragment_size));
462 assert(((middle_fragment_count * line_width) +
463 first_fragment_size + last_fragment_size) == whole_size);
465 fragment_addr = base_addr;
466 fragment_size = first_fragment_size;
469 Addr end_addr = base_addr + whole_size;
471 auto& byte_enable = request->getByteEnable();
472 unsigned int num_disabled_fragments = 0;
474 for (
unsigned int fragment_index = 0; fragment_index < numFragments;
477 M5_VAR_USED
bool is_last_fragment =
false;
479 if (fragment_addr == base_addr) {
481 fragment_size = first_fragment_size;
483 if ((fragment_addr + line_width) > end_addr) {
485 fragment_size = end_addr - fragment_addr;
486 is_last_fragment =
true;
489 fragment_size = line_width;
493 RequestPtr fragment = std::make_shared<Request>();
494 bool disabled_fragment =
false;
496 fragment->setContext(request->contextId());
498 auto it_start = byte_enable.begin() +
499 (fragment_addr - base_addr);
500 auto it_end = byte_enable.begin() +
501 (fragment_addr - base_addr) + fragment_size;
504 fragment_addr, fragment_size, request->getFlags(),
505 request->requestorId(),
509 disabled_fragment =
true;
512 if (!disabled_fragment) {
513 DPRINTFS(MinorMem, (&port),
"Generating fragment addr: 0x%x"
514 " size: %d (whole request addr: 0x%x size: %d) %s\n",
515 fragment_addr, fragment_size, base_addr, whole_size,
516 (is_last_fragment ?
"last fragment" :
""));
518 fragmentRequests.push_back(fragment);
520 num_disabled_fragments++;
523 fragment_addr += fragment_size;
525 assert(numFragments >= num_disabled_fragments);
526 numFragments -= num_disabled_fragments;
532 assert(numTranslatedFragments > 0);
533 Addr base_addr = request->getVaddr();
535 DPRINTFS(MinorMem, (&port),
"Making packets for request: %s\n", *inst);
537 for (
unsigned int fragment_index = 0;
538 fragment_index < numTranslatedFragments;
541 RequestPtr fragment = fragmentRequests[fragment_index];
543 DPRINTFS(MinorMem, (&port),
"Making packet %d for request: %s"
545 fragment_index, *inst,
546 (fragment->hasPaddr() ?
"has paddr" :
"no paddr"),
547 (fragment->hasPaddr() ? fragment->getPaddr() : 0));
549 Addr fragment_addr = fragment->getVaddr();
550 unsigned int fragment_size = fragment->getSize();
552 uint8_t *request_data = NULL;
557 request_data =
new uint8_t[fragment_size];
558 std::memcpy(request_data,
data + (fragment_addr - base_addr),
562 assert(fragment->hasPaddr());
567 fragmentPackets.push_back(fragment_packet);
569 request->setFlags(fragment->getFlags());
575 request->setPaddr(fragmentRequests[0]->getPaddr());
582 makeFragmentRequests();
584 if (numFragments > 0) {
586 numInTranslationFragments = 0;
587 numTranslatedFragments = 0;
597 sendNextFragmentToTranslation();
607 assert(numIssuedFragments < numTranslatedFragments);
609 return fragmentPackets[numIssuedFragments];
615 assert(numIssuedFragments < numTranslatedFragments);
617 numIssuedFragments++;
623 assert(inst->translationFault ==
NoFault);
624 assert(numRetiredFragments < numTranslatedFragments);
626 DPRINTFS(MinorMem, (&port),
"Retiring fragment addr: 0x%x size: %d"
627 " offset: 0x%x (retired fragment num: %d)\n",
628 response->
req->getVaddr(), response->
req->getSize(),
629 request->getVaddr() - response->
req->getVaddr(),
630 numRetiredFragments);
632 numRetiredFragments++;
637 DPRINTFS(MinorMem, (&port),
"Skipping this fragment\n");
638 }
else if (response->
isError()) {
640 DPRINTFS(MinorMem, (&port),
"Fragment has an error, skipping\n");
642 packet->copyError(response);
649 data =
new uint8_t[request->getSize()];
655 data + (response->
req->getVaddr() - request->getVaddr()),
657 response->
req->getSize());
662 if (skipped && !hasPacketsInMemSystem()) {
663 DPRINTFS(MinorMem, (&port),
"Completed skipped burst\n");
665 if (packet->needsResponse())
666 packet->makeResponse();
669 if (numRetiredFragments == numTranslatedFragments)
672 if (!skipped && isComplete()) {
673 DPRINTFS(MinorMem, (&port),
"Completed burst %d\n", packet != NULL);
675 DPRINTFS(MinorMem, (&port),
"Retired packet isRead: %d isWrite: %d"
676 " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
677 " %s\n", packet->isRead(), packet->isWrite(),
678 packet->needsResponse(), packet->getSize(), request->getSize(),
684 data =
new uint8_t[request->getSize()];
688 DPRINTFS(MinorMem, (&port),
"Copying read data\n");
689 std::memcpy(packet->getPtr<uint8_t>(),
data, request->getSize());
691 packet->makeResponse();
700 unsigned int fragment_index = numTranslatedFragments;
705 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request for fragment: %d\n",
708 port.numAccessesInDTLB++;
709 numInTranslationFragments++;
712 fragmentRequests[fragment_index], thread,
this, (isLoad ?
720 return slots.size() < numSlots;
726 auto found = std::find(slots.begin(), slots.end(), request);
728 if (found != slots.end()) {
729 DPRINTF(MinorMem,
"Deleting request: %s %s %s from StoreBuffer\n",
730 request, *found, *(request->
inst));
741 warn(
"%s: store buffer insertion without space to insert from"
742 " inst: %s\n",
name(), *(request->
inst));
745 DPRINTF(MinorMem,
"Pushing store: %s into store buffer\n", request);
747 numUnissuedAccesses++;
752 slots.push_back(request);
761 unsigned int &found_slot)
763 unsigned int slot_index = slots.size() - 1;
764 auto i = slots.rbegin();
776 slot->
inst->id.threadId == request->
inst->id.threadId &&
777 !slot->
packet->
req->isCacheMaintenance()) {
781 DPRINTF(MinorMem,
"Forwarding: slot: %d result: %s thisAddr:"
782 " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
783 slot_index, coverage,
787 found_slot = slot_index;
802 unsigned int slot_number)
804 assert(slot_number < slots.size());
815 Addr addr_offset = load_addr - store_addr;
817 unsigned int load_size = load->
request->getSize();
819 DPRINTF(MinorMem,
"Forwarding %d bytes for addr: 0x%x from store buffer"
820 " slot: %d addr: 0x%x addressOffset: 0x%x\n",
821 load_size, load_addr, slot_number,
822 store_addr, addr_offset);
825 void *store_packet_data = store->
packet->
getPtr<uint8_t>() + addr_offset;
827 std::memcpy(load_packet_data, store_packet_data, load_size);
836 numUnissuedAccesses--;
842 DPRINTF(MinorMem,
"StoreBuffer step numUnissuedAccesses: %d\n",
843 numUnissuedAccesses);
847 while (!slots.empty() &&
848 slots.front()->isComplete() && slots.front()->isBarrier())
852 DPRINTF(MinorMem,
"Clearing barrier for inst: %s\n",
855 numUnissuedAccesses--;
856 lsq.clearMemBarrier(barrier->
inst);
862 auto i = slots.begin();
864 unsigned int issue_count = 0;
874 issue_count < storeLimitPerCycle &&
875 lsq.canSendToMemorySystem() &&
880 DPRINTF(MinorMem,
"Considering request: %s, sentAllPackets: %d"
891 DPRINTF(MinorMem,
"Trying to send request: %s to memory"
892 " system\n", *(request->
inst));
894 if (lsq.tryToSend(request)) {
895 countIssuedStore(request);
915 if (!inst->inStoreBuffer) {
929 unsigned int size = slots.size();
931 std::ostringstream
os;
943 while (
i < numSlots) {
951 MINORTRACE(
"addr=%s num_unissued_stores=%d\n",
os.str(),
952 numUnissuedAccesses);
959 DPRINTF(MinorMem,
"Request needs retry, not issuing to"
960 " memory until retry arrives\n");
965 DPRINTF(MinorMem,
"Request still in translation, not issuing to"
976 DPRINTF(MinorMem,
"Request not at front of requests queue, can't"
977 " issue to memory\n");
982 DPRINTF(MinorMem,
"No space to insert request into transfers"
988 DPRINTF(MinorMem,
"Passing a %s transfer on to transfers"
989 " queue\n", (request->
isComplete() ?
"completed" :
"failed"));
1000 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1001 " waiting for responses before aborting request\n");
1003 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1004 " aborting request\n");
1013 if (request->
inst->staticInst->isPrefetch()) {
1014 DPRINTF(MinorMem,
"Not signalling fault for faulting prefetch\n");
1016 DPRINTF(MinorMem,
"Moving faulting request into the transfers"
1024 bool is_load = request->
isLoad;
1025 bool is_llsc = request->
request->isLLSC();
1026 bool is_release = request->
request->isRelease();
1027 bool is_swap = request->
request->isSwap();
1028 bool is_atomic = request->
request->isAtomic();
1029 bool bufferable = !(request->
request->isStrictlyOrdered() ||
1030 is_llsc || is_swap || is_atomic || is_release);
1034 DPRINTF(MinorMem,
"Load request with stores still in transfers"
1035 " queue, stalling\n");
1040 if (bufferable && !request->
request->isLocalAccess()) {
1043 DPRINTF(MinorMem,
"Moving store into transfers queue\n");
1050 if (((!is_load && is_llsc) || is_release) &&
1052 DPRINTF(MinorMem,
"Memory access needs to wait for store buffer"
1062 DPRINTF(MinorMem,
"Memory access not the head inst., can't be"
1063 " sure it can be performed, not issuing\n");
1067 unsigned int forwarding_slot = 0;
1079 DPRINTF(MinorMem,
"Memory access can receive forwarded data"
1080 " from the store buffer, but need to wait for store buffer"
1090 bool do_access =
true;
1095 unsigned int forwarding_slot = 0;
1100 switch (forwarding_result) {
1111 DPRINTF(MinorMem,
"Load partly satisfied by store buffer"
1112 " data. Must wait for the store to complete\n");
1116 DPRINTF(MinorMem,
"No forwardable data from store buffer\n");
1123 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1140 DPRINTF(MinorMem,
"Not perfoming a memory "
1141 "access for store conditional\n");
1150 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1176 DPRINTF(MinorMem,
"Can't send request: %s yet, no space in memory\n",
1181 DPRINTF(MinorMem,
"Trying to send request: %s addr: 0x%x\n",
1182 *(request->
inst), packet->
req->getVaddr());
1188 if (request->
request->isLocalAccess()) {
1191 request->
request->contextId()));
1194 DPRINTF(MinorMem,
"IPR read inst: %s\n", *(request->
inst));
1196 DPRINTF(MinorMem,
"IPR write inst: %s\n", *(request->
inst));
1198 request->
request->localAccessor(thread, packet);
1204 DPRINTF(MinorMem,
"IPR access has another packet: %s\n",
1213 DPRINTF(MinorMem,
"Sent data memory request\n");
1221 switch (request->
state) {
1235 panic(
"Unrecognized LSQ request state %d.", request->
state);
1241 "Sending data memory request - needs retry\n");
1247 switch (request->
state) {
1257 panic(
"Unrecognized LSQ request state %d.", request->
state);
1298 DPRINTF(MinorMem,
"Received response packet inst: %s"
1299 " addr: 0x%x cmd: %s\n",
1306 DPRINTF(MinorMem,
"Received error response packet: %s\n",
1310 switch (request->
state) {
1316 DPRINTF(MinorMem,
"Has outstanding packets?: %d %d\n",
1331 DPRINTF(MinorMem,
"Completed transfer for barrier: %s"
1332 " leaving the request as it is also a barrier\n",
1338 panic(
"Shouldn't be allowed to receive a response from another state");
1355 DPRINTF(MinorMem,
"Received retry request\n");
1399 LSQ::LSQ(std::string name_, std::string dcache_port_name_,
1401 unsigned int in_memory_system_limit,
unsigned int line_width,
1402 unsigned int requests_queue_size,
unsigned int transfers_queue_size,
1403 unsigned int store_buffer_size,
1404 unsigned int store_buffer_cycle_store_limit) :
1412 lineWidth((line_width == 0 ?
cpu.cacheLineSize() : line_width)),
1413 requests(name_ +
".requests",
"addr", requests_queue_size),
1414 transfers(name_ +
".transfers",
"addr", transfers_queue_size),
1416 *this, store_buffer_size, store_buffer_cycle_store_limit),
1424 if (in_memory_system_limit < 1) {
1425 fatal(
"%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
1426 in_memory_system_limit);
1429 if (store_buffer_cycle_store_limit < 1) {
1430 fatal(
"%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1431 " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
1434 if (requests_queue_size < 1) {
1435 fatal(
"%s: executeLSQRequestsQueueSize must be"
1436 " >= 1 (%d)\n", name_, requests_queue_size);
1439 if (transfers_queue_size < 1) {
1440 fatal(
"%s: executeLSQTransfersQueueSize must be"
1441 " >= 1 (%d)\n", name_, transfers_queue_size);
1444 if (store_buffer_size < 1) {
1445 fatal(
"%s: executeLSQStoreBufferSize must be"
1446 " >= 1 (%d)\n", name_, store_buffer_size);
1492 if (request->
inst->id == inst->id) {
1495 bool to_store_buffer = request->
state ==
1498 if ((complete && !(request->
isBarrier() && !can_store)) ||
1499 (to_store_buffer && can_store))
1507 DPRINTF(MinorMem,
"Found matching memory response for inst: %s\n",
1510 DPRINTF(MinorMem,
"No matching memory response for inst: %s\n",
1531 DPRINTF(MinorMem,
"Deleting %s request: %s\n",
1532 (response->
isLoad ?
"load" :
"store"),
1544 DPRINTF(MinorMem,
"Sending store: %s to store buffer\n",
1547 request->
inst->inStoreBuffer =
true;
1569 ret = have_translated_requests ||
1574 DPRINTF(Activity,
"Need to tick\n");
1585 assert(inst->translationFault ==
NoFault || inst->inLSQ);
1588 return inst->translationFault;
1593 if (needs_burst && inst->staticInst->isAtomic()) {
1601 panic(
"Do not expect cross-cache-line atomic memory request\n");
1608 uint8_t *request_data = NULL;
1610 DPRINTF(MinorMem,
"Pushing request (%s) addr: 0x%x size: %d flags:"
1611 " 0x%x%s lineWidth : 0x%x\n",
1612 (isLoad ?
"load" :
"store/atomic"),
addr, size, flags,
1613 (needs_burst ?
" (needs burst)" :
""),
lineWidth);
1618 request_data =
new uint8_t[size];
1619 if (inst->staticInst->isAtomic() ||
1622 std::memset(request_data, 0, size);
1624 std::memcpy(request_data,
data, size);
1630 *
this, inst, isLoad, request_data, res);
1633 *
this, inst, isLoad, request_data, res);
1636 if (inst->traceData)
1637 inst->traceData->setMem(
addr, size, flags);
1639 int cid =
cpu.
threads[inst->id.threadId]->getTC()->contextId();
1640 request->
request->setContext(cid);
1644 inst->pc.instAddr(), std::move(amo_op));
1645 request->
request->setByteEnable(byte_enable);
1651 return inst->translationFault;
1664 MINORTRACE(
"state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
1665 " lastMemBarrier=%d\n",
1674 unsigned int store_buffer_size,
1675 unsigned int store_limit_per_cycle) :
1676 Named(name_), lsq(lsq_),
1677 numSlots(store_buffer_size),
1678 storeLimitPerCycle(store_limit_per_cycle),
1680 numUnissuedAccesses(0)
1696 }
else if (!request->isCacheMaintenance()) {
1708 assert(inst->isInst() && inst->staticInst->isFullMemBarrier());
1720 assert(inst->translationFault ==
NoFault);
1738 os <<
"MemoryRunning";
1741 os <<
"MemoryNeedsRetry";
1744 os <<
"MemoryState-" <<
static_cast<int>(
state);
1780 if (tid != req_tid) {