gem5  v20.1.0.0
Sequencer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2020 ARM Limited
3  * All rights reserved.
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
15  * Copyright (c) 2013 Advanced Micro Devices, Inc.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
43 
44 #include "arch/x86/ldstflags.hh"
45 #include "base/logging.hh"
46 #include "base/str.hh"
48 #include "debug/LLSC.hh"
49 #include "debug/MemoryAccess.hh"
50 #include "debug/ProtocolTrace.hh"
51 #include "debug/RubySequencer.hh"
52 #include "debug/RubyStats.hh"
53 #include "mem/packet.hh"
55 #include "mem/ruby/protocol/PrefetchBit.hh"
56 #include "mem/ruby/protocol/RubyAccessMode.hh"
60 #include "sim/system.hh"
61 
62 using namespace std;
63 
64 Sequencer *
65 RubySequencerParams::create()
66 {
67  return new Sequencer(this);
68 }
69 
71  : RubyPort(p), m_IncompleteTimes(MachineType_NUM),
72  deadlockCheckEvent([this]{ wakeup(); }, "Sequencer deadlock check")
73 {
74  m_outstanding_count = 0;
75 
76  m_instCache_ptr = p->icache;
77  m_dataCache_ptr = p->dcache;
78  m_max_outstanding_requests = p->max_outstanding_requests;
79  m_deadlock_threshold = p->deadlock_threshold;
80 
81  m_coreId = p->coreid; // for tracking the two CorePair sequencers
82  assert(m_max_outstanding_requests > 0);
83  assert(m_deadlock_threshold > 0);
84  assert(m_instCache_ptr != NULL);
85  assert(m_dataCache_ptr != NULL);
86 
87  m_runningGarnetStandalone = p->garnet_standalone;
88 }
89 
91 {
92 }
93 
94 void
96 {
97  AbstractCacheEntry *line = m_dataCache_ptr->lookup(claddr);
98  if (line) {
99  line->setLocked(m_version);
100  DPRINTF(LLSC, "LLSC Monitor - inserting load linked - "
101  "addr=0x%lx - cpu=%u\n", claddr, m_version);
102  }
103 }
104 
105 void
107 {
108  AbstractCacheEntry *line = m_dataCache_ptr->lookup(claddr);
109  if (line && line->isLocked(m_version)) {
110  line->clearLocked();
111  DPRINTF(LLSC, "LLSC Monitor - clearing due to store - "
112  "addr=0x%lx - cpu=%u\n", claddr, m_version);
113  }
114 }
115 
116 bool
118 {
119  AbstractCacheEntry *line = m_dataCache_ptr->lookup(claddr);
120  if (!line)
121  return false;
122 
123  DPRINTF(LLSC, "LLSC Monitor - clearing due to "
124  "store conditional - "
125  "addr=0x%lx - cpu=%u\n",
126  claddr, m_version);
127 
128  if (line->isLocked(m_version)) {
129  line->clearLocked();
130  return true;
131  } else {
132  line->clearLocked();
133  return false;
134  }
135 }
136 
137 bool
139 {
140  const Addr claddr = makeLineAddress(address);
141  AbstractCacheEntry *line = m_dataCache_ptr->lookup(claddr);
142  if (!line)
143  return false;
144 
145  if (line->isLocked(m_version)) {
146  return true;
147  } else {
148  return false;
149  }
150 }
151 
152 void
154 {
156 }
157 
158 void
160 {
161  assert(drainState() != DrainState::Draining);
162 
163  // Check for deadlock of any of the requests
164  Cycles current_time = curCycle();
165 
166  // Check across all outstanding requests
167  int total_outstanding = 0;
168 
169  for (const auto &table_entry : m_RequestTable) {
170  for (const auto &seq_req : table_entry.second) {
171  if (current_time - seq_req.issue_time < m_deadlock_threshold)
172  continue;
173 
174  panic("Possible Deadlock detected. Aborting!\n version: %d "
175  "request.paddr: 0x%x m_readRequestTable: %d current time: "
176  "%u issue_time: %d difference: %d\n", m_version,
177  seq_req.pkt->getAddr(), table_entry.second.size(),
178  current_time * clockPeriod(), seq_req.issue_time
179  * clockPeriod(), (current_time * clockPeriod())
180  - (seq_req.issue_time * clockPeriod()));
181  }
182  total_outstanding += table_entry.second.size();
183  }
184 
185  assert(m_outstanding_count == total_outstanding);
186 
187  if (m_outstanding_count > 0) {
188  // If there are still outstanding requests, keep checking
190  }
191 }
192 
193 int
195 {
196  int num_written = RubyPort::functionalWrite(func_pkt);
197 
198  for (const auto &table_entry : m_RequestTable) {
199  for (const auto& seq_req : table_entry.second) {
200  if (seq_req.functionalWrite(func_pkt))
201  ++num_written;
202  }
203  }
204 
205  return num_written;
206 }
207 
209 {
214  for (int i = 0; i < RubyRequestType_NUM; i++) {
215  m_typeLatencyHist[i]->reset();
216  m_hitTypeLatencyHist[i]->reset();
217  m_missTypeLatencyHist[i]->reset();
218  for (int j = 0; j < MachineType_NUM; j++) {
219  m_hitTypeMachLatencyHist[i][j]->reset();
220  m_missTypeMachLatencyHist[i][j]->reset();
221  }
222  }
223 
224  for (int i = 0; i < MachineType_NUM; i++) {
225  m_missMachLatencyHist[i]->reset();
226  m_hitMachLatencyHist[i]->reset();
227 
228  m_IssueToInitialDelayHist[i]->reset();
229  m_InitialToForwardDelayHist[i]->reset();
232 
233  m_IncompleteTimes[i] = 0;
234  }
235 }
236 
237 // Insert the request in the request table. Return RequestStatus_Aliased
238 // if the entry was already present.
239 RequestStatus
240 Sequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type,
241  RubyRequestType secondary_type)
242 {
243  // See if we should schedule a deadlock check
244  if (!deadlockCheckEvent.scheduled() &&
247  }
248 
249  Addr line_addr = makeLineAddress(pkt->getAddr());
250  // Check if there is any outstanding request for the same cache line.
251  auto &seq_req_list = m_RequestTable[line_addr];
252  // Create a default entry
253  seq_req_list.emplace_back(pkt, primary_type,
254  secondary_type, curCycle());
256 
257  if (seq_req_list.size() > 1) {
258  return RequestStatus_Aliased;
259  }
260 
262 
263  return RequestStatus_Ready;
264 }
265 
266 void
268 {
270 }
271 
272 void
273 Sequencer::recordMissLatency(SequencerRequest* srequest, bool llscSuccess,
274  const MachineType respondingMach,
275  bool isExternalHit, Cycles initialRequestTime,
276  Cycles forwardRequestTime,
277  Cycles firstResponseTime)
278 {
279  RubyRequestType type = srequest->m_type;
280  Cycles issued_time = srequest->issue_time;
281  Cycles completion_time = curCycle();
282 
283  assert(curCycle() >= issued_time);
284  Cycles total_lat = completion_time - issued_time;
285 
286  if (initialRequestTime < issued_time) {
287  // if the request was combined in the protocol with an earlier request
288  // for the same address, it is possible that it will return an
289  // initialRequestTime corresponding the earlier request. Since Cycles
290  // is unsigned, we can't let this request get profiled below.
291 
292  total_lat = Cycles(0);
293  }
294 
295  DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n",
296  curTick(), m_version, "Seq", llscSuccess ? "Done" : "SC_Failed",
297  "", "", printAddress(srequest->pkt->getAddr()), total_lat);
298 
299  m_latencyHist.sample(total_lat);
300  m_typeLatencyHist[type]->sample(total_lat);
301 
302  if (isExternalHit) {
303  m_missLatencyHist.sample(total_lat);
304  m_missTypeLatencyHist[type]->sample(total_lat);
305 
306  if (respondingMach != MachineType_NUM) {
307  m_missMachLatencyHist[respondingMach]->sample(total_lat);
308  m_missTypeMachLatencyHist[type][respondingMach]->sample(total_lat);
309 
310  if ((issued_time <= initialRequestTime) &&
311  (initialRequestTime <= forwardRequestTime) &&
312  (forwardRequestTime <= firstResponseTime) &&
313  (firstResponseTime <= completion_time)) {
314 
315  m_IssueToInitialDelayHist[respondingMach]->sample(
316  initialRequestTime - issued_time);
317  m_InitialToForwardDelayHist[respondingMach]->sample(
318  forwardRequestTime - initialRequestTime);
319  m_ForwardToFirstResponseDelayHist[respondingMach]->sample(
320  firstResponseTime - forwardRequestTime);
321  m_FirstResponseToCompletionDelayHist[respondingMach]->sample(
322  completion_time - firstResponseTime);
323  } else {
324  m_IncompleteTimes[respondingMach]++;
325  }
326  }
327  } else {
328  m_hitLatencyHist.sample(total_lat);
329  m_hitTypeLatencyHist[type]->sample(total_lat);
330 
331  if (respondingMach != MachineType_NUM) {
332  m_hitMachLatencyHist[respondingMach]->sample(total_lat);
333  m_hitTypeMachLatencyHist[type][respondingMach]->sample(total_lat);
334  }
335  }
336 }
337 
338 void
340 {
341  llscClearMonitor(address);
342  writeCallback(address, data);
343 }
344 
345 void
347  const bool externalHit, const MachineType mach,
348  const Cycles initialRequestTime,
349  const Cycles forwardRequestTime,
350  const Cycles firstResponseTime)
351 {
352  //
353  // Free the whole list as we assume we have had the exclusive access
354  // to this cache line when response for the write comes back
355  //
356  assert(address == makeLineAddress(address));
357  assert(m_RequestTable.find(address) != m_RequestTable.end());
358  auto &seq_req_list = m_RequestTable[address];
359 
360  // Perform hitCallback on every cpu request made to this cache block while
361  // ruby request was outstanding. Since only 1 ruby request was made,
362  // profile the ruby latency once.
363  bool ruby_request = true;
364  int aliased_stores = 0;
365  int aliased_loads = 0;
366  while (!seq_req_list.empty()) {
367  SequencerRequest &seq_req = seq_req_list.front();
368  if (ruby_request) {
369  assert(seq_req.m_type != RubyRequestType_LD);
370  assert(seq_req.m_type != RubyRequestType_Load_Linked);
371  assert(seq_req.m_type != RubyRequestType_IFETCH);
372  }
373 
374  // handle write request
375  if ((seq_req.m_type != RubyRequestType_LD) &&
376  (seq_req.m_type != RubyRequestType_Load_Linked) &&
377  (seq_req.m_type != RubyRequestType_IFETCH)) {
378  // LL/SC support (tested with ARMv8)
379  bool success = true;
380 
381  if (seq_req.m_type != RubyRequestType_Store_Conditional) {
382  // Regular stores to addresses being monitored
383  // will fail (remove) the monitor entry.
384  llscClearMonitor(address);
385  } else {
386  // Store conditionals must first check the monitor
387  // if they will succeed or not
388  success = llscStoreConditional(address);
389  seq_req.pkt->req->setExtraData(success ? 1 : 0);
390  }
391 
392  // Handle SLICC block_on behavior for Locked_RMW accesses. NOTE: the
393  // address variable here is assumed to be a line address, so when
394  // blocking buffers, must check line addresses.
395  if (seq_req.m_type == RubyRequestType_Locked_RMW_Read) {
396  // blockOnQueue blocks all first-level cache controller queues
397  // waiting on memory accesses for the specified address that go
398  // to the specified queue. In this case, a Locked_RMW_Write must
399  // go to the mandatory_q before unblocking the first-level
400  // controller. This will block standard loads, stores, ifetches,
401  // etc.
403  } else if (seq_req.m_type == RubyRequestType_Locked_RMW_Write) {
404  m_controller->unblock(address);
405  }
406 
407  if (ruby_request) {
408  recordMissLatency(&seq_req, success, mach, externalHit,
409  initialRequestTime, forwardRequestTime,
410  firstResponseTime);
411  } else {
412  aliased_stores++;
413  }
414  markRemoved();
415  ruby_request = false;
416  hitCallback(&seq_req, data, success, mach, externalHit,
417  initialRequestTime, forwardRequestTime,
418  firstResponseTime);
419  } else {
420  // handle read request
421  assert(!ruby_request);
422  markRemoved();
423  ruby_request = false;
424  aliased_loads++;
425  hitCallback(&seq_req, data, true, mach, externalHit,
426  initialRequestTime, forwardRequestTime,
427  firstResponseTime);
428  }
429  seq_req_list.pop_front();
430  }
431 
432  // free all outstanding requests corresponding to this address
433  if (seq_req_list.empty()) {
434  m_RequestTable.erase(address);
435  }
436 }
437 
438 void
440  bool externalHit, const MachineType mach,
441  Cycles initialRequestTime,
442  Cycles forwardRequestTime,
443  Cycles firstResponseTime)
444 {
445  //
446  // Free up read requests until we hit the first Write request
447  // or end of the corresponding list.
448  //
449  assert(address == makeLineAddress(address));
450  assert(m_RequestTable.find(address) != m_RequestTable.end());
451  auto &seq_req_list = m_RequestTable[address];
452 
453  // Perform hitCallback on every cpu request made to this cache block while
454  // ruby request was outstanding. Since only 1 ruby request was made,
455  // profile the ruby latency once.
456  bool ruby_request = true;
457  int aliased_loads = 0;
458  while (!seq_req_list.empty()) {
459  SequencerRequest &seq_req = seq_req_list.front();
460  if (ruby_request) {
461  assert((seq_req.m_type == RubyRequestType_LD) ||
462  (seq_req.m_type == RubyRequestType_Load_Linked) ||
463  (seq_req.m_type == RubyRequestType_IFETCH));
464  } else {
465  aliased_loads++;
466  }
467  if ((seq_req.m_type != RubyRequestType_LD) &&
468  (seq_req.m_type != RubyRequestType_Load_Linked) &&
469  (seq_req.m_type != RubyRequestType_IFETCH)) {
470  // Write request: reissue request to the cache hierarchy
471  issueRequest(seq_req.pkt, seq_req.m_second_type);
472  break;
473  }
474  if (ruby_request) {
475  recordMissLatency(&seq_req, true, mach, externalHit,
476  initialRequestTime, forwardRequestTime,
477  firstResponseTime);
478  }
479  markRemoved();
480  ruby_request = false;
481  hitCallback(&seq_req, data, true, mach, externalHit,
482  initialRequestTime, forwardRequestTime,
483  firstResponseTime);
484  seq_req_list.pop_front();
485  }
486 
487  // free all outstanding requests corresponding to this address
488  if (seq_req_list.empty()) {
489  m_RequestTable.erase(address);
490  }
491 }
492 
493 void
495  bool llscSuccess,
496  const MachineType mach, const bool externalHit,
497  const Cycles initialRequestTime,
498  const Cycles forwardRequestTime,
499  const Cycles firstResponseTime)
500 {
501  warn_once("Replacement policy updates recently became the responsibility "
502  "of SLICC state machines. Make sure to setMRU() near callbacks "
503  "in .sm files!");
504 
505  PacketPtr pkt = srequest->pkt;
506  Addr request_address(pkt->getAddr());
507  RubyRequestType type = srequest->m_type;
508 
509  // Load-linked handling
510  if (type == RubyRequestType_Load_Linked) {
511  Addr line_addr = makeLineAddress(request_address);
512  llscLoadLinked(line_addr);
513  }
514 
515  // update the data unless it is a non-data-carrying flush
517  data.setData(pkt->getConstPtr<uint8_t>(),
518  getOffset(request_address), pkt->getSize());
519  } else if (!pkt->isFlush()) {
520  if ((type == RubyRequestType_LD) ||
521  (type == RubyRequestType_IFETCH) ||
522  (type == RubyRequestType_RMW_Read) ||
523  (type == RubyRequestType_Locked_RMW_Read) ||
524  (type == RubyRequestType_Load_Linked)) {
525  pkt->setData(
526  data.getData(getOffset(request_address), pkt->getSize()));
527  DPRINTF(RubySequencer, "read data %s\n", data);
528  } else if (pkt->req->isSwap()) {
529  std::vector<uint8_t> overwrite_val(pkt->getSize());
530  pkt->writeData(&overwrite_val[0]);
531  pkt->setData(
532  data.getData(getOffset(request_address), pkt->getSize()));
533  data.setData(&overwrite_val[0],
534  getOffset(request_address), pkt->getSize());
535  DPRINTF(RubySequencer, "swap data %s\n", data);
536  } else if (type != RubyRequestType_Store_Conditional || llscSuccess) {
537  // Types of stores set the actual data here, apart from
538  // failed Store Conditional requests
539  data.setData(pkt->getConstPtr<uint8_t>(),
540  getOffset(request_address), pkt->getSize());
541  DPRINTF(RubySequencer, "set data %s\n", data);
542  }
543  }
544 
545  // If using the RubyTester, update the RubyTester sender state's
546  // subBlock with the recieved data. The tester will later access
547  // this state.
548  if (m_usingRubyTester) {
549  DPRINTF(RubySequencer, "hitCallback %s 0x%x using RubyTester\n",
550  pkt->cmdString(), pkt->getAddr());
551  RubyTester::SenderState* testerSenderState =
553  assert(testerSenderState);
554  testerSenderState->subBlock.mergeFrom(data);
555  }
556 
559  assert(pkt->req);
560  delete pkt;
561  rs->m_cache_recorder->enqueueNextFetchRequest();
562  } else if (RubySystem::getCooldownEnabled()) {
563  delete pkt;
564  rs->m_cache_recorder->enqueueNextFlushRequest();
565  } else {
566  ruby_hit_callback(pkt);
568  }
569 }
570 
571 bool
573 {
574  return m_RequestTable.empty();
575 }
576 
577 RequestStatus
579 {
580  // HTM abort signals must be allowed to reach the Sequencer
581  // the same cycle they are issued. They cannot be retried.
583  !pkt->req->isHTMAbort()) {
584  return RequestStatus_BufferFull;
585  }
586 
587  RubyRequestType primary_type = RubyRequestType_NULL;
588  RubyRequestType secondary_type = RubyRequestType_NULL;
589 
590  if (pkt->isLLSC()) {
591  // LL/SC instructions need to be handled carefully by the cache
592  // coherence protocol to ensure they follow the proper semantics. In
593  // particular, by identifying the operations as atomic, the protocol
594  // should understand that migratory sharing optimizations should not
595  // be performed (i.e. a load between the LL and SC should not steal
596  // away exclusive permission).
597  //
598  // The following logic works correctly with the semantics
599  // of armV8 LDEX/STEX instructions.
600 
601  if (pkt->isWrite()) {
602  DPRINTF(RubySequencer, "Issuing SC\n");
603  primary_type = RubyRequestType_Store_Conditional;
604 #if defined (PROTOCOL_MESI_Three_Level) || defined (PROTOCOL_MESI_Three_Level_HTM)
605  secondary_type = RubyRequestType_Store_Conditional;
606 #else
607  secondary_type = RubyRequestType_ST;
608 #endif
609  } else {
610  DPRINTF(RubySequencer, "Issuing LL\n");
611  assert(pkt->isRead());
612  primary_type = RubyRequestType_Load_Linked;
613  secondary_type = RubyRequestType_LD;
614  }
615  } else if (pkt->req->isLockedRMW()) {
616  //
617  // x86 locked instructions are translated to store cache coherence
618  // requests because these requests should always be treated as read
619  // exclusive operations and should leverage any migratory sharing
620  // optimization built into the protocol.
621  //
622  if (pkt->isWrite()) {
623  DPRINTF(RubySequencer, "Issuing Locked RMW Write\n");
624  primary_type = RubyRequestType_Locked_RMW_Write;
625  } else {
626  DPRINTF(RubySequencer, "Issuing Locked RMW Read\n");
627  assert(pkt->isRead());
628  primary_type = RubyRequestType_Locked_RMW_Read;
629  }
630  secondary_type = RubyRequestType_ST;
631  } else {
632  //
633  // To support SwapReq, we need to check isWrite() first: a SwapReq
634  // should always be treated like a write, but since a SwapReq implies
635  // both isWrite() and isRead() are true, check isWrite() first here.
636  //
637  if (pkt->isWrite()) {
638  //
639  // Note: M5 packets do not differentiate ST from RMW_Write
640  //
641  primary_type = secondary_type = RubyRequestType_ST;
642  } else if (pkt->isRead()) {
643  // hardware transactional memory commands
644  if (pkt->req->isHTMCmd()) {
645  primary_type = secondary_type = htmCmdToRubyRequestType(pkt);
646  } else if (pkt->req->isInstFetch()) {
647  primary_type = secondary_type = RubyRequestType_IFETCH;
648  } else {
649  bool storeCheck = false;
650  // only X86 need the store check
651  if (system->getArch() == Arch::X86ISA) {
652  uint32_t flags = pkt->req->getFlags();
653  storeCheck = flags &
655  }
656  if (storeCheck) {
657  primary_type = RubyRequestType_RMW_Read;
658  secondary_type = RubyRequestType_ST;
659  } else {
660  primary_type = secondary_type = RubyRequestType_LD;
661  }
662  }
663  } else if (pkt->isFlush()) {
664  primary_type = secondary_type = RubyRequestType_FLUSH;
665  } else {
666  panic("Unsupported ruby packet type\n");
667  }
668  }
669 
670  // Check if the line is blocked for a Locked_RMW
672  (primary_type != RubyRequestType_Locked_RMW_Write)) {
673  // Return that this request's cache line address aliases with
674  // a prior request that locked the cache line. The request cannot
675  // proceed until the cache line is unlocked by a Locked_RMW_Write
676  return RequestStatus_Aliased;
677  }
678 
679  RequestStatus status = insertRequest(pkt, primary_type, secondary_type);
680 
681  // It is OK to receive RequestStatus_Aliased, it can be considered Issued
682  if (status != RequestStatus_Ready && status != RequestStatus_Aliased)
683  return status;
684  // non-aliased with any existing request in the request table, just issue
685  // to the cache
686  if (status != RequestStatus_Aliased)
687  issueRequest(pkt, secondary_type);
688 
689  // TODO: issue hardware prefetches here
690  return RequestStatus_Issued;
691 }
692 
693 void
694 Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type)
695 {
696  assert(pkt != NULL);
697  ContextID proc_id = pkt->req->hasContextId() ?
698  pkt->req->contextId() : InvalidContextID;
699 
700  ContextID core_id = coreId();
701 
702  // If valid, copy the pc to the ruby request
703  Addr pc = 0;
704  if (pkt->req->hasPC()) {
705  pc = pkt->req->getPC();
706  }
707 
708  // check if the packet has data as for example prefetch and flush
709  // requests do not
710  std::shared_ptr<RubyRequest> msg =
711  std::make_shared<RubyRequest>(clockEdge(), pkt->getAddr(),
712  pkt->isFlush() ?
713  nullptr : pkt->getPtr<uint8_t>(),
714  pkt->getSize(), pc, secondary_type,
715  RubyAccessMode_Supervisor, pkt,
716  PrefetchBit_No, proc_id, core_id);
717 
718  DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\n",
719  curTick(), m_version, "Seq", "Begin", "", "",
720  printAddress(msg->getPhysicalAddress()),
721  RubyRequestType_to_string(secondary_type));
722 
723  // hardware transactional memory
724  // If the request originates in a transaction,
725  // then mark the Ruby message as such.
726  if (pkt->isHtmTransactional()) {
727  msg->m_htmFromTransaction = true;
728  msg->m_htmTransactionUid = pkt->getHtmTransactionUid();
729  }
730 
731  Tick latency = cyclesToTicks(
732  m_controller->mandatoryQueueLatency(secondary_type));
733  assert(latency > 0);
734 
735  assert(m_mandatory_q_ptr != NULL);
736  m_mandatory_q_ptr->enqueue(msg, clockEdge(), latency);
737 }
738 
739 template <class KEY, class VALUE>
740 std::ostream &
741 operator<<(ostream &out, const std::unordered_map<KEY, VALUE> &map)
742 {
743  for (const auto &table_entry : map) {
744  out << "[ " << table_entry.first << " =";
745  for (const auto &seq_req : table_entry.second) {
746  out << " " << RubyRequestType_to_string(seq_req.m_second_type);
747  }
748  }
749  out << " ]";
750 
751  return out;
752 }
753 
754 void
755 Sequencer::print(ostream& out) const
756 {
757  out << "[Sequencer: " << m_version
758  << ", outstanding requests: " << m_outstanding_count
759  << ", request table: " << m_RequestTable
760  << "]";
761 }
762 
763 void
764 Sequencer::recordRequestType(SequencerRequestType requestType) {
765  DPRINTF(RubyStats, "Recorded statistic: %s\n",
766  SequencerRequestType_to_string(requestType));
767 }
768 
769 void
771 {
772  llscClearMonitor(address);
773  ruby_eviction_callback(address);
774 }
775 
776 void
778 {
780 
781  // These statistical variables are not for display.
782  // The profiler will collate these across different
783  // sequencers and display those collated statistics.
785  m_latencyHist.init(10);
788 
789  for (int i = 0; i < RubyRequestType_NUM; i++) {
790  m_typeLatencyHist.push_back(new Stats::Histogram());
791  m_typeLatencyHist[i]->init(10);
792 
793  m_hitTypeLatencyHist.push_back(new Stats::Histogram());
794  m_hitTypeLatencyHist[i]->init(10);
795 
796  m_missTypeLatencyHist.push_back(new Stats::Histogram());
797  m_missTypeLatencyHist[i]->init(10);
798  }
799 
800  for (int i = 0; i < MachineType_NUM; i++) {
801  m_hitMachLatencyHist.push_back(new Stats::Histogram());
802  m_hitMachLatencyHist[i]->init(10);
803 
804  m_missMachLatencyHist.push_back(new Stats::Histogram());
805  m_missMachLatencyHist[i]->init(10);
806 
808  m_IssueToInitialDelayHist[i]->init(10);
809 
811  m_InitialToForwardDelayHist[i]->init(10);
812 
815 
818  }
819 
820  for (int i = 0; i < RubyRequestType_NUM; i++) {
823 
824  for (int j = 0; j < MachineType_NUM; j++) {
825  m_hitTypeMachLatencyHist[i].push_back(new Stats::Histogram());
826  m_hitTypeMachLatencyHist[i][j]->init(10);
827 
828  m_missTypeMachLatencyHist[i].push_back(new Stats::Histogram());
829  m_missTypeMachLatencyHist[i][j]->init(10);
830  }
831  }
832 }
AbstractCacheEntry
Definition: AbstractCacheEntry.hh:57
ArmISA::status
Bitfield< 5, 0 > status
Definition: miscregs_types.hh:417
AbstractController::blockOnQueue
void blockOnQueue(Addr, MessageBuffer *)
Definition: AbstractController.cc:265
X86ISA::FlagShift
const int FlagShift
Definition: ldstflags.hh:50
Stats::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:64
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
Sequencer::m_ForwardToFirstResponseDelayHist
std::vector< Stats::Histogram * > m_ForwardToFirstResponseDelayHist
Definition: Sequencer.hh:262
RubyPort::m_usingRubyTester
bool m_usingRubyTester
Definition: RubyPort.hh:192
RubyPort::ruby_hit_callback
void ruby_hit_callback(PacketPtr pkt)
Definition: RubyPort.cc:432
Sequencer::m_outstanding_count
int m_outstanding_count
Definition: Sequencer.hh:225
Sequencer::functionalWrite
virtual int functionalWrite(Packet *func_pkt) override
Definition: Sequencer.cc:194
Sequencer::m_outstandReqHist
Stats::Histogram m_outstandReqHist
Histogram for number of outstanding requests per cycle.
Definition: Sequencer.hh:233
system.hh
SequencerRequest::pkt
PacketPtr pkt
Definition: Sequencer.hh:58
Sequencer::empty
virtual bool empty() const
Definition: Sequencer.cc:572
Profiler.hh
Sequencer::m_missMachLatencyHist
std::vector< Stats::Histogram * > m_missMachLatencyHist
Histograms for profiling the latencies for requests that required external messages.
Definition: Sequencer.hh:256
CacheMemory::lookup
AbstractCacheEntry * lookup(Addr address)
Definition: CacheMemory.cc:342
data
const char data[]
Definition: circlebuf.test.cc:42
Sequencer::resetStats
void resetStats() override
Callback to reset stats.
Definition: Sequencer.cc:208
htmCmdToRubyRequestType
RubyRequestType htmCmdToRubyRequestType(const Packet *pkt)
Definition: RubySlicc_Util.hh:153
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
Sequencer::m_max_outstanding_requests
int m_max_outstanding_requests
Definition: Sequencer.hh:212
makeLineAddress
Addr makeLineAddress(Addr addr)
Definition: Address.cc:54
Sequencer
Definition: Sequencer.hh:80
AbstractCacheEntry::setLocked
void setLocked(int context)
Definition: AbstractCacheEntry.cc:78
Packet::writeData
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1254
Packet::isHtmTransactional
bool isHtmTransactional() const
Returns whether or not this packet/request originates in the CPU executing in transactional mode,...
Definition: packet.cc:544
Sequencer::writeCallbackScFail
void writeCallbackScFail(Addr address, DataBlock &data)
Proxy function to writeCallback that first invalidates the line address in the local monitor.
Definition: Sequencer.cc:339
RubyPort::Params
RubyPortParams Params
Definition: RubyPort.hh:146
warn_once
#define warn_once(...)
Definition: logging.hh:243
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
Sequencer::m_hitTypeLatencyHist
std::vector< Stats::Histogram * > m_hitTypeLatencyHist
Definition: Sequencer.hh:242
Sequencer::m_IssueToInitialDelayHist
std::vector< Stats::Histogram * > m_IssueToInitialDelayHist
Histograms for recording the breakdown of miss latency.
Definition: Sequencer.hh:260
ContextID
int ContextID
Globally unique thread context ID.
Definition: types.hh:231
RubyPort::testDrainComplete
void testDrainComplete()
Definition: RubyPort.cc:481
SequencerRequest::m_type
RubyRequestType m_type
Definition: Sequencer.hh:59
Packet::isRead
bool isRead() const
Definition: packet.hh:556
type
uint8_t type
Definition: inet.hh:421
Sequencer::m_dataCache_ptr
CacheMemory * m_dataCache_ptr
Definition: Sequencer.hh:214
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
Sequencer::wakeup
virtual void wakeup()
Definition: Sequencer.cc:159
Sequencer::~Sequencer
~Sequencer()
Definition: Sequencer.cc:90
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
Sequencer::makeRequest
RequestStatus makeRequest(PacketPtr pkt) override
Definition: Sequencer.cc:578
RubyRequest.hh
ldstflags.hh
Packet::isLLSC
bool isLLSC() const
Definition: packet.hh:582
std::vector< uint8_t >
InvalidContextID
const ContextID InvalidContextID
Definition: types.hh:232
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
MessageBuffer::enqueue
void enqueue(MsgPtr message, Tick curTime, Tick delta)
Definition: MessageBuffer.cc:162
Sequencer::coreId
int coreId() const
Definition: Sequencer.hh:130
Sequencer::m_RequestTable
std::unordered_map< Addr, std::list< SequencerRequest > > m_RequestTable
Definition: Sequencer.hh:203
Sequencer::m_hitLatencyHist
Stats::Histogram m_hitLatencyHist
Histogram for holding latency profile of all requests that hit in the controller connected to this se...
Definition: Sequencer.hh:241
AbstractController::isBlocked
bool isBlocked(Addr) const
Definition: AbstractController.cc:272
Sequencer::m_latencyHist
Stats::Histogram m_latencyHist
Histogram for holding latency profile of all requests.
Definition: Sequencer.hh:236
Sequencer::m_missTypeMachLatencyHist
std::vector< std::vector< Stats::Histogram * > > m_missTypeMachLatencyHist
Definition: Sequencer.hh:257
Packet::setData
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1225
DataBlock
Definition: DataBlock.hh:40
packet.hh
RubyPort::m_mandatory_q_ptr
MessageBuffer * m_mandatory_q_ptr
Definition: RubyPort.hh:191
Stats::Histogram
A simple histogram stat.
Definition: statistics.hh:2654
SequencerRequest::issue_time
Cycles issue_time
Definition: Sequencer.hh:61
SequencerRequest::m_second_type
RubyRequestType m_second_type
Definition: Sequencer.hh:60
str.hh
System::getArch
Arch getArch() const
Get the architecture.
Definition: system.hh:382
RubyPort::m_controller
AbstractController * m_controller
Definition: RubyPort.hh:190
Sequencer::print
virtual void print(std::ostream &out) const
Definition: Sequencer.cc:755
ArmISA::j
Bitfield< 24 > j
Definition: miscregs_types.hh:54
AbstractController::unblock
void unblock(Addr)
Definition: AbstractController.cc:278
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
Clocked::cyclesToTicks
Tick cyclesToTicks(Cycles c) const
Definition: clocked_object.hh:224
Sequencer::insertRequest
virtual RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type)
Definition: Sequencer.cc:240
Sequencer::hitCallback
void hitCallback(SequencerRequest *srequest, DataBlock &data, bool llscSuccess, const MachineType mach, const bool externalHit, const Cycles initialRequestTime, const Cycles forwardRequestTime, const Cycles firstResponseTime)
Definition: Sequencer.cc:494
Sequencer::recordMissLatency
void recordMissLatency(SequencerRequest *srequest, bool llscSuccess, const MachineType respondingMach, bool isExternalHit, Cycles initialRequestTime, Cycles forwardRequestTime, Cycles firstResponseTime)
Definition: Sequencer.cc:273
Sequencer::llscStoreConditional
bool llscStoreConditional(const Addr)
Searches for cache line address in the global monitor tagged with this Sequencer object's version id.
Definition: Sequencer.cc:117
Sequencer::readCallback
void readCallback(Addr address, DataBlock &data, const bool externalHit=false, const MachineType mach=MachineType_NUM, const Cycles initialRequestTime=Cycles(0), const Cycles forwardRequestTime=Cycles(0), const Cycles firstResponseTime=Cycles(0))
Definition: Sequencer.cc:439
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
RubySystem
Definition: RubySystem.hh:52
Packet::cmdString
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:551
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
RubyPort
Definition: RubyPort.hh:58
Sequencer::markRemoved
void markRemoved()
Definition: Sequencer.cc:267
Packet::findNextSenderState
T * findNextSenderState() const
Go through the sender state stack and return the first instance that is of type T (as determined by a...
Definition: packet.hh:538
RubyTester.hh
Sequencer::m_missLatencyHist
Stats::Histogram m_missLatencyHist
Histogram for holding latency profile of all requests that miss in the controller connected to this s...
Definition: Sequencer.hh:251
Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:192
Sequencer::llscLoadLinked
void llscLoadLinked(const Addr)
Places the cache line address into the global monitor tagged with this Sequencer object's version id.
Definition: Sequencer.cc:95
Clocked::clockEdge
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Definition: clocked_object.hh:174
Sequencer::deadlockCheckEvent
EventFunctionWrapper deadlockCheckEvent
Definition: Sequencer.hh:266
RubyTester::SenderState
Definition: RubyTester.hh:86
DPRINTFR
#define DPRINTFR(...)
Definition: trace.hh:236
RubySlicc_Util.hh
Sequencer::evictionCallback
void evictionCallback(Addr address)
Definition: Sequencer.cc:770
Sequencer::m_IncompleteTimes
std::vector< Stats::Counter > m_IncompleteTimes
Definition: Sequencer.hh:264
AbstractCacheEntry::clearLocked
void clearLocked()
Definition: AbstractCacheEntry.cc:85
Sequencer::writeCallback
void writeCallback(Addr address, DataBlock &data, const bool externalHit=false, const MachineType mach=MachineType_NUM, const Cycles initialRequestTime=Cycles(0), const Cycles forwardRequestTime=Cycles(0), const Cycles firstResponseTime=Cycles(0))
Definition: Sequencer.cc:346
Sequencer::llscClearMonitor
void llscClearMonitor(const Addr)
Removes the cache line address from the global monitor.
Definition: Sequencer.cc:106
RubyPort::system
System * system
Definition: RubyPort.hh:193
Sequencer::recordRequestType
void recordRequestType(SequencerRequestType requestType)
Definition: Sequencer.cc:764
RubySystem.hh
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Sequencer::m_hitTypeMachLatencyHist
std::vector< std::vector< Stats::Histogram * > > m_hitTypeMachLatencyHist
Definition: Sequencer.hh:247
RubySystem::getCooldownEnabled
static bool getCooldownEnabled()
Definition: RubySystem.hh:66
AbstractCacheEntry::isLocked
bool isLocked(int context) const
Definition: AbstractCacheEntry.cc:92
Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:214
Sequencer::llscCheckMonitor
bool llscCheckMonitor(const Addr)
Searches for cache line address in the global monitor tagged with this Sequencer object's version id.
Definition: Sequencer.cc:138
CacheMemory::clearLockedAll
void clearLockedAll(int context)
Definition: CacheMemory.cc:496
operator<<
std::ostream & operator<<(ostream &out, const std::unordered_map< KEY, VALUE > &map)
Definition: Sequencer.cc:741
RubyPort::functionalWrite
virtual int functionalWrite(Packet *func_pkt)
Definition: RubyPort.cc:648
Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:320
Packet::getHtmTransactionUid
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition: packet.cc:550
RubyTester::SenderState::subBlock
SubBlock subBlock
Definition: RubyTester.hh:88
Sequencer::m_hitMachLatencyHist
std::vector< Stats::Histogram * > m_hitMachLatencyHist
Histograms for profiling the latencies for requests that did not required external messages.
Definition: Sequencer.hh:246
Sequencer::regStats
void regStats() override
Callback to set stat parameters.
Definition: Sequencer.cc:777
X86ISA::StoreCheck
@ StoreCheck
Definition: ldstflags.hh:54
Sequencer::m_InitialToForwardDelayHist
std::vector< Stats::Histogram * > m_InitialToForwardDelayHist
Definition: Sequencer.hh:261
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
Sequencer::m_deadlock_threshold
Cycles m_deadlock_threshold
Definition: Sequencer.hh:205
RubySystem::getWarmupEnabled
static bool getWarmupEnabled()
Definition: RubySystem.hh:65
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
getOffset
Addr getOffset(Addr addr)
Definition: Address.cc:48
Sequencer::m_typeLatencyHist
std::vector< Stats::Histogram * > m_typeLatencyHist
Definition: Sequencer.hh:237
Stats::DistBase::reset
void reset()
Reset stat value to default.
Definition: statistics.hh:1948
ArmISA::rs
Bitfield< 9, 8 > rs
Definition: miscregs_types.hh:372
Stats::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1924
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
Packet::isWrite
bool isWrite() const
Definition: packet.hh:557
Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1157
SequencerRequest
Definition: Sequencer.hh:56
Sequencer::issueRequest
void issueRequest(PacketPtr pkt, RubyRequestType type)
Definition: Sequencer.cc:694
Stats::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2669
Packet::isFlush
bool isFlush() const
Definition: packet.hh:585
Sequencer::Sequencer
Sequencer(const Params *)
Definition: Sequencer.cc:70
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
SubBlock::mergeFrom
void mergeFrom(const DataBlock &data)
Definition: SubBlock.hh:60
AbstractController::mandatoryQueueLatency
virtual Cycles mandatoryQueueLatency(const RubyRequestType &param_type)
Definition: AbstractController.hh:112
RubyPort::m_ruby_system
RubySystem * m_ruby_system
Definition: RubyPort.hh:188
RubyPort::m_version
uint32_t m_version
Definition: RubyPort.hh:189
Packet::getConstPtr
const T * getConstPtr() const
Definition: packet.hh:1166
printAddress
std::string printAddress(Addr addr)
Definition: Address.cc:74
Sequencer::llscClearLocalMonitor
void llscClearLocalMonitor()
Removes all addresses from the local monitor.
Definition: Sequencer.cc:153
RubyPort::ruby_eviction_callback
void ruby_eviction_callback(Addr address)
Definition: RubyPort.cc:614
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
Sequencer::m_FirstResponseToCompletionDelayHist
std::vector< Stats::Histogram * > m_FirstResponseToCompletionDelayHist
Definition: Sequencer.hh:263
Sequencer::m_missTypeLatencyHist
std::vector< Stats::Histogram * > m_missTypeLatencyHist
Definition: Sequencer.hh:252
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
Sequencer.hh

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17