49 #include "debug/LLSC.hh"
50 #include "debug/MemoryAccess.hh"
51 #include "debug/ProtocolTrace.hh"
52 #include "debug/RubyHitMiss.hh"
53 #include "debug/RubySequencer.hh"
54 #include "debug/RubyStats.hh"
57 #include "mem/ruby/protocol/PrefetchBit.hh"
58 #include "mem/ruby/protocol/RubyAccessMode.hh"
71 :
RubyPort(
p), m_IncompleteTimes(MachineType_NUM),
72 deadlockCheckEvent([this]{
wakeup(); },
"Sequencer deadlock check")
74 m_outstanding_count = 0;
76 m_dataCache_ptr =
p.dcache;
77 m_max_outstanding_requests =
p.max_outstanding_requests;
78 m_deadlock_threshold =
p.deadlock_threshold;
81 assert(m_max_outstanding_requests > 0);
82 assert(m_deadlock_threshold > 0);
84 m_unaddressedTransactionCnt = 0;
86 m_runningGarnetStandalone =
p.garnet_standalone;
92 m_outstandReqHist.init(10);
93 m_latencyHist.init(10);
94 m_hitLatencyHist.init(10);
95 m_missLatencyHist.init(10);
97 for (
int i = 0;
i < RubyRequestType_NUM;
i++) {
99 m_typeLatencyHist[
i]->init(10);
102 m_hitTypeLatencyHist[
i]->init(10);
105 m_missTypeLatencyHist[
i]->init(10);
108 for (
int i = 0;
i < MachineType_NUM;
i++) {
110 m_hitMachLatencyHist[
i]->init(10);
113 m_missMachLatencyHist[
i]->init(10);
116 m_IssueToInitialDelayHist[
i]->init(10);
119 m_InitialToForwardDelayHist[
i]->init(10);
121 m_ForwardToFirstResponseDelayHist.push_back(
123 m_ForwardToFirstResponseDelayHist[
i]->init(10);
125 m_FirstResponseToCompletionDelayHist.push_back(
127 m_FirstResponseToCompletionDelayHist[
i]->init(10);
130 for (
int i = 0;
i < RubyRequestType_NUM;
i++) {
131 m_hitTypeMachLatencyHist.push_back(
133 m_missTypeMachLatencyHist.push_back(
136 for (
int j = 0;
j < MachineType_NUM;
j++) {
137 m_hitTypeMachLatencyHist[
i].push_back(
new statistics::Histogram());
138 m_hitTypeMachLatencyHist[
i][
j]->init(10);
140 m_missTypeMachLatencyHist[
i].push_back(
141 new statistics::Histogram());
142 m_missTypeMachLatencyHist[
i][
j]->init(10);
156 "%s must have a dcache object to support LLSC requests.",
name());
160 DPRINTF(LLSC,
"LLSC Monitor - inserting load linked - "
161 "addr=0x%lx - cpu=%u\n", claddr,
m_version);
174 DPRINTF(LLSC,
"LLSC Monitor - clearing due to store - "
175 "addr=0x%lx - cpu=%u\n", claddr,
m_version);
183 "%s must have a dcache object to support LLSC requests.",
name());
188 DPRINTF(LLSC,
"LLSC Monitor - clearing due to "
189 "store conditional - "
190 "addr=0x%lx - cpu=%u\n",
233 [[maybe_unused]]
int total_outstanding = 0;
236 for (
const auto &seq_req : table_entry.second) {
240 panic(
"Possible Deadlock detected. Aborting!\n version: %d "
241 "request.paddr: 0x%x m_readRequestTable: %d current time: "
242 "%u issue_time: %d difference: %d\n",
m_version,
243 seq_req.pkt->getAddr(), table_entry.second.size(),
248 total_outstanding += table_entry.second.size();
265 for (
const auto& seq_req : table_entry.second) {
266 if (seq_req.functionalWrite(func_pkt))
280 for (
int i = 0;
i < RubyRequestType_NUM;
i++) {
284 for (
int j = 0;
j < MachineType_NUM;
j++) {
290 for (
int i = 0;
i < MachineType_NUM;
i++) {
307 RubyRequestType secondary_type)
316 assert(primary_type == secondary_type);
318 switch (primary_type) {
319 case RubyRequestType_TLBI_EXT_SYNC_COMP:
322 case RubyRequestType_TLBI:
323 case RubyRequestType_TLBI_SYNC:
328 [[maybe_unused]]
auto insert_data = \
329 m_UnaddressedRequestTable.emplace(
332 pkt, primary_type, secondary_type,
curCycle()));
335 assert(insert_data.second &&
336 "Another TLBI request with the same ID exists");
338 DPRINTF(RubySequencer,
"Inserting TLBI request %016x\n",
345 panic(
"Unexpected TLBI RubyRequestType");
348 return RequestStatus_Ready;
355 seq_req_list.emplace_back(pkt, primary_type,
359 if (seq_req_list.size() > 1) {
360 return RequestStatus_Aliased;
365 return RequestStatus_Ready;
376 const MachineType respondingMach,
377 bool isExternalHit,
Cycles initialRequestTime,
378 Cycles forwardRequestTime,
386 Cycles total_lat = completion_time - issued_time;
388 if ((initialRequestTime != 0) && (initialRequestTime < issued_time)) {
397 DPRINTFR(ProtocolTrace,
"%15s %3s %10s%20s %6s>%-6s %s %d cycles\n",
408 if (respondingMach != MachineType_NUM) {
412 if ((issued_time <= initialRequestTime) &&
413 (initialRequestTime <= forwardRequestTime) &&
414 (forwardRequestTime <= firstResponseTime) &&
415 (firstResponseTime <= completion_time)) {
418 initialRequestTime - issued_time);
420 forwardRequestTime - initialRequestTime);
422 firstResponseTime - forwardRequestTime);
424 completion_time - firstResponseTime);
433 if (respondingMach != MachineType_NUM) {
449 const bool externalHit,
const MachineType mach,
450 const Cycles initialRequestTime,
451 const Cycles forwardRequestTime,
452 const Cycles firstResponseTime,
466 bool ruby_request =
true;
467 while (!seq_req_list.empty()) {
470 if (noCoales && !ruby_request) {
479 assert(seq_req.
m_type != RubyRequestType_LD);
480 assert(seq_req.
m_type != RubyRequestType_Load_Linked);
481 assert(seq_req.
m_type != RubyRequestType_IFETCH);
485 if ((seq_req.
m_type != RubyRequestType_LD) &&
486 (seq_req.
m_type != RubyRequestType_Load_Linked) &&
487 (seq_req.
m_type != RubyRequestType_IFETCH)) {
491 if (seq_req.
m_type != RubyRequestType_Store_Conditional) {
499 seq_req.
pkt->
req->setExtraData(success ? 1 : 0);
505 if (seq_req.
m_type == RubyRequestType_Locked_RMW_Read) {
513 }
else if (seq_req.
m_type == RubyRequestType_Locked_RMW_Write) {
519 initialRequestTime, forwardRequestTime,
525 initialRequestTime, forwardRequestTime,
526 firstResponseTime, !ruby_request);
527 ruby_request =
false;
530 assert(!ruby_request);
533 initialRequestTime, forwardRequestTime,
534 firstResponseTime, !ruby_request);
536 seq_req_list.pop_front();
540 if (seq_req_list.empty()) {
547 bool externalHit,
const MachineType mach,
548 Cycles initialRequestTime,
549 Cycles forwardRequestTime,
563 bool ruby_request =
true;
564 while (!seq_req_list.empty()) {
567 assert((seq_req.
m_type == RubyRequestType_LD) ||
568 (seq_req.
m_type == RubyRequestType_Load_Linked) ||
569 (seq_req.
m_type == RubyRequestType_IFETCH));
571 if ((seq_req.
m_type != RubyRequestType_LD) &&
572 (seq_req.
m_type != RubyRequestType_Load_Linked) &&
573 (seq_req.
m_type != RubyRequestType_IFETCH)) {
580 initialRequestTime, forwardRequestTime,
585 initialRequestTime, forwardRequestTime,
586 firstResponseTime, !ruby_request);
587 ruby_request =
false;
588 seq_req_list.pop_front();
592 if (seq_req_list.empty()) {
600 const MachineType mach,
const bool externalHit,
601 const Cycles initialRequestTime,
602 const Cycles forwardRequestTime,
603 const Cycles firstResponseTime,
604 const bool was_coalesced)
606 warn_once(
"Replacement policy updates recently became the responsibility "
607 "of SLICC state machines. Make sure to setMRU() near callbacks "
623 if (
type == RubyRequestType_Load_Linked) {
628 DPRINTF(RubyHitMiss,
"Cache %s at %#x\n",
629 externalHit ?
"miss" :
"hit",
636 if ((
type == RubyRequestType_LD) ||
637 (
type == RubyRequestType_IFETCH) ||
638 (
type == RubyRequestType_RMW_Read) ||
639 (
type == RubyRequestType_Locked_RMW_Read) ||
640 (
type == RubyRequestType_Load_Linked)) {
644 }
else if (pkt->
req->isSwap()) {
650 data.setData(&overwrite_val[0],
657 DPRINTF(RubySequencer,
"AMO original data %s\n",
data);
662 }
else if (
type != RubyRequestType_Store_Conditional || llscSuccess) {
674 DPRINTF(RubySequencer,
"hitCallback %s 0x%x using RubyTester\n",
678 assert(testerSenderState);
686 rs->m_cache_recorder->enqueueNextFetchRequest();
689 rs->m_cache_recorder->enqueueNextFlushRequest();
698 RubyRequestType reqType,
699 const MachineType mach,
700 const Cycles initialRequestTime,
701 const Cycles forwardRequestTime,
702 const Cycles firstResponseTime)
704 DPRINTF(RubySequencer,
"unaddressedCallback ID:%08x type:%d\n",
705 unaddressedReqId, reqType);
708 case RubyRequestType_TLBI_EXT_SYNC:
718 case RubyRequestType_TLBI:
719 case RubyRequestType_TLBI_SYNC:
730 assert(seq_req.
m_type == reqType);
742 panic(
"Unexpected TLBI RubyRequestType");
759 !pkt->
req->isHTMAbort()) {
760 return RequestStatus_BufferFull;
763 RubyRequestType primary_type = RubyRequestType_NULL;
764 RubyRequestType secondary_type = RubyRequestType_NULL;
778 DPRINTF(RubySequencer,
"Issuing SC\n");
779 primary_type = RubyRequestType_Store_Conditional;
780 #if defined (PROTOCOL_MESI_Three_Level) || defined (PROTOCOL_MESI_Three_Level_HTM)
781 secondary_type = RubyRequestType_Store_Conditional;
783 secondary_type = RubyRequestType_ST;
786 DPRINTF(RubySequencer,
"Issuing LL\n");
788 primary_type = RubyRequestType_Load_Linked;
789 secondary_type = RubyRequestType_LD;
791 }
else if (pkt->
req->isLockedRMW()) {
799 DPRINTF(RubySequencer,
"Issuing Locked RMW Write\n");
800 primary_type = RubyRequestType_Locked_RMW_Write;
802 DPRINTF(RubySequencer,
"Issuing Locked RMW Read\n");
804 primary_type = RubyRequestType_Locked_RMW_Read;
806 secondary_type = RubyRequestType_ST;
807 }
else if (pkt->
req->isTlbiCmd()) {
809 DPRINTF(RubySequencer,
"Issuing TLBI\n");
820 primary_type = secondary_type = RubyRequestType_ST;
821 }
else if (pkt->
isRead()) {
823 if (pkt->
req->isHTMCmd()) {
825 }
else if (pkt->
req->isInstFetch()) {
826 primary_type = secondary_type = RubyRequestType_IFETCH;
828 if (pkt->
req->isReadModifyWrite()) {
829 primary_type = RubyRequestType_RMW_Read;
830 secondary_type = RubyRequestType_ST;
832 primary_type = secondary_type = RubyRequestType_LD;
836 primary_type = secondary_type = RubyRequestType_FLUSH;
838 panic(
"Unsupported ruby packet type\n");
843 if (!pkt->
req->isMemMgmt() &&
845 (primary_type != RubyRequestType_Locked_RMW_Write)) {
849 return RequestStatus_Aliased;
855 if (
status != RequestStatus_Ready &&
status != RequestStatus_Aliased)
859 if (
status != RequestStatus_Aliased)
863 return RequestStatus_Issued;
877 if (pkt->
req->hasPC()) {
878 pc = pkt->
req->getPC();
883 std::shared_ptr<RubyRequest> msg;
884 if (pkt->
req->isMemMgmt()) {
885 msg = std::make_shared<RubyRequest>(
clockEdge(),
887 RubyAccessMode_Supervisor, pkt,
890 DPRINTFR(ProtocolTrace,
"%15s %3s %10s%20s %6s>%-6s %s\n",
892 RubyRequestType_to_string(secondary_type));
894 if (pkt->
req->isTlbiCmd()) {
895 msg->m_isTlbi =
true;
896 switch (secondary_type) {
897 case RubyRequestType_TLBI_EXT_SYNC_COMP:
898 msg->m_tlbiTransactionUid = pkt->
req->getExtraData();
900 case RubyRequestType_TLBI:
901 case RubyRequestType_TLBI_SYNC:
902 msg->m_tlbiTransactionUid = \
903 getCurrentUnaddressedTransactionID();
906 panic(
"Unexpected TLBI RubyRequestType");
908 DPRINTF(RubySequencer,
"Issuing TLBI %016x\n",
909 msg->m_tlbiTransactionUid);
914 RubyAccessMode_Supervisor, pkt,
915 PrefetchBit_No, proc_id, core_id);
917 DPRINTFR(ProtocolTrace,
"%15s %3s %10s%20s %6s>%-6s %#x %s\n",
920 RubyRequestType_to_string(secondary_type));
927 msg->m_htmFromTransaction =
true;
939 template <
class KEY,
class VALUE>
941 operator<<(std::ostream &out,
const std::unordered_map<KEY, VALUE> &map)
943 for (
const auto &table_entry : map) {
944 out <<
"[ " << table_entry.first <<
" =";
945 for (
const auto &seq_req : table_entry.second) {
946 out <<
" " << RubyRequestType_to_string(seq_req.m_second_type);
965 DPRINTF(RubyStats,
"Recorded statistic: %s\n",
966 SequencerRequestType_to_string(requestType));
982 uint64_t aligned_txid = \
985 if (aligned_txid > 0xFFFFFFFFull) {
994 uint64_t(
m_version & 0xFFFFFFFF) << 32) |