gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sequencer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
30 
31 #include "arch/x86/ldstflags.hh"
32 #include "base/misc.hh"
33 #include "base/str.hh"
35 #include "debug/MemoryAccess.hh"
36 #include "debug/ProtocolTrace.hh"
37 #include "debug/RubySequencer.hh"
38 #include "debug/RubyStats.hh"
39 #include "mem/packet.hh"
40 #include "mem/protocol/PrefetchBit.hh"
41 #include "mem/protocol/RubyAccessMode.hh"
45 #include "sim/system.hh"
46 
47 using namespace std;
48 
49 Sequencer *
50 RubySequencerParams::create()
51 {
52  return new Sequencer(this);
53 }
54 
56  : RubyPort(p), m_IncompleteTimes(MachineType_NUM), deadlockCheckEvent(this)
57 {
59 
60  m_instCache_ptr = p->icache;
61  m_dataCache_ptr = p->dcache;
62  m_data_cache_hit_latency = p->dcache_hit_latency;
63  m_inst_cache_hit_latency = p->icache_hit_latency;
64  m_max_outstanding_requests = p->max_outstanding_requests;
65  m_deadlock_threshold = p->deadlock_threshold;
66 
67  m_coreId = p->coreid; // for tracking the two CorePair sequencers
68  assert(m_max_outstanding_requests > 0);
69  assert(m_deadlock_threshold > 0);
70  assert(m_instCache_ptr != NULL);
71  assert(m_dataCache_ptr != NULL);
72  assert(m_data_cache_hit_latency > 0);
73  assert(m_inst_cache_hit_latency > 0);
74 
75  m_runningGarnetStandalone = p->garnet_standalone;
76 }
77 
79 {
80 }
81 
82 void
84 {
85  assert(drainState() != DrainState::Draining);
86 
87  // Check for deadlock of any of the requests
88  Cycles current_time = curCycle();
89 
90  // Check across all outstanding requests
91  int total_outstanding = 0;
92 
93  RequestTable::iterator read = m_readRequestTable.begin();
94  RequestTable::iterator read_end = m_readRequestTable.end();
95  for (; read != read_end; ++read) {
96  SequencerRequest* request = read->second;
97  if (current_time - request->issue_time < m_deadlock_threshold)
98  continue;
99 
100  panic("Possible Deadlock detected. Aborting!\n"
101  "version: %d request.paddr: 0x%x m_readRequestTable: %d "
102  "current time: %u issue_time: %d difference: %d\n", m_version,
103  request->pkt->getAddr(), m_readRequestTable.size(),
104  current_time * clockPeriod(), request->issue_time * clockPeriod(),
105  (current_time * clockPeriod()) - (request->issue_time * clockPeriod()));
106  }
107 
108  RequestTable::iterator write = m_writeRequestTable.begin();
109  RequestTable::iterator write_end = m_writeRequestTable.end();
110  for (; write != write_end; ++write) {
111  SequencerRequest* request = write->second;
112  if (current_time - request->issue_time < m_deadlock_threshold)
113  continue;
114 
115  panic("Possible Deadlock detected. Aborting!\n"
116  "version: %d request.paddr: 0x%x m_writeRequestTable: %d "
117  "current time: %u issue_time: %d difference: %d\n", m_version,
118  request->pkt->getAddr(), m_writeRequestTable.size(),
119  current_time * clockPeriod(), request->issue_time * clockPeriod(),
120  (current_time * clockPeriod()) - (request->issue_time * clockPeriod()));
121  }
122 
123  total_outstanding += m_writeRequestTable.size();
124  total_outstanding += m_readRequestTable.size();
125 
126  assert(m_outstanding_count == total_outstanding);
127 
128  if (m_outstanding_count > 0) {
129  // If there are still outstanding requests, keep checking
131  }
132 }
133 
135 {
139  for (int i = 0; i < RubyRequestType_NUM; i++) {
140  m_typeLatencyHist[i]->reset();
141  m_hitTypeLatencyHist[i]->reset();
142  m_missTypeLatencyHist[i]->reset();
143  for (int j = 0; j < MachineType_NUM; j++) {
144  m_hitTypeMachLatencyHist[i][j]->reset();
145  m_missTypeMachLatencyHist[i][j]->reset();
146  }
147  }
148 
149  for (int i = 0; i < MachineType_NUM; i++) {
150  m_missMachLatencyHist[i]->reset();
151  m_hitMachLatencyHist[i]->reset();
152 
153  m_IssueToInitialDelayHist[i]->reset();
154  m_InitialToForwardDelayHist[i]->reset();
157 
158  m_IncompleteTimes[i] = 0;
159  }
160 }
161 
162 // Insert the request on the correct request table. Return true if
163 // the entry was already present.
164 RequestStatus
165 Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type)
166 {
167  assert(m_outstanding_count ==
168  (m_writeRequestTable.size() + m_readRequestTable.size()));
169 
170  // See if we should schedule a deadlock check
171  if (!deadlockCheckEvent.scheduled() &&
174  }
175 
176  Addr line_addr = makeLineAddress(pkt->getAddr());
177 
178  // Check if the line is blocked for a Locked_RMW
179  if (m_controller->isBlocked(line_addr) &&
180  (request_type != RubyRequestType_Locked_RMW_Write)) {
181  // Return that this request's cache line address aliases with
182  // a prior request that locked the cache line. The request cannot
183  // proceed until the cache line is unlocked by a Locked_RMW_Write
184  return RequestStatus_Aliased;
185  }
186 
187  // Create a default entry, mapping the address to NULL, the cast is
188  // there to make gcc 4.4 happy
189  RequestTable::value_type default_entry(line_addr,
190  (SequencerRequest*) NULL);
191 
192  if ((request_type == RubyRequestType_ST) ||
193  (request_type == RubyRequestType_RMW_Read) ||
194  (request_type == RubyRequestType_RMW_Write) ||
195  (request_type == RubyRequestType_Load_Linked) ||
196  (request_type == RubyRequestType_Store_Conditional) ||
197  (request_type == RubyRequestType_Locked_RMW_Read) ||
198  (request_type == RubyRequestType_Locked_RMW_Write) ||
199  (request_type == RubyRequestType_FLUSH)) {
200 
201  // Check if there is any outstanding read request for the same
202  // cache line.
203  if (m_readRequestTable.count(line_addr) > 0) {
205  return RequestStatus_Aliased;
206  }
207 
209  m_writeRequestTable.insert(default_entry);
210  if (r.second) {
211  RequestTable::iterator i = r.first;
212  i->second = new SequencerRequest(pkt, request_type, curCycle());
214  } else {
215  // There is an outstanding write request for the cache line
217  return RequestStatus_Aliased;
218  }
219  } else {
220  // Check if there is any outstanding write request for the same
221  // cache line.
222  if (m_writeRequestTable.count(line_addr) > 0) {
224  return RequestStatus_Aliased;
225  }
226 
228  m_readRequestTable.insert(default_entry);
229 
230  if (r.second) {
231  RequestTable::iterator i = r.first;
232  i->second = new SequencerRequest(pkt, request_type, curCycle());
234  } else {
235  // There is an outstanding read request for the cache line
237  return RequestStatus_Aliased;
238  }
239  }
240 
242  assert(m_outstanding_count ==
243  (m_writeRequestTable.size() + m_readRequestTable.size()));
244 
245  return RequestStatus_Ready;
246 }
247 
248 void
250 {
252  assert(m_outstanding_count ==
253  m_writeRequestTable.size() + m_readRequestTable.size());
254 }
255 
256 void
258 {
260  // The controller has lost the coherence permissions, hence the lock
261  // on the cache line maintained by the cache should be cleared.
262  if (e && e->isLocked(m_version)) {
263  e->clearLocked();
264  }
265 }
266 
267 bool
269 {
271  if (!e)
272  return true;
273 
274  // The success flag indicates whether the LLSC operation was successful.
275  // LL ops will always succeed, but SC may fail if the cache line is no
276  // longer locked.
277  bool success = true;
278  if (request->m_type == RubyRequestType_Store_Conditional) {
279  if (!e->isLocked(m_version)) {
280  //
281  // For failed SC requests, indicate the failure to the cpu by
282  // setting the extra data to zero.
283  //
284  request->pkt->req->setExtraData(0);
285  success = false;
286  } else {
287  //
288  // For successful SC requests, indicate the success to the cpu by
289  // setting the extra data to one.
290  //
291  request->pkt->req->setExtraData(1);
292  }
293  //
294  // Independent of success, all SC operations must clear the lock
295  //
296  e->clearLocked();
297  } else if (request->m_type == RubyRequestType_Load_Linked) {
298  //
299  // Note: To fully follow Alpha LLSC semantics, should the LL clear any
300  // previously locked cache lines?
301  //
302  e->setLocked(m_version);
303  } else if (e->isLocked(m_version)) {
304  //
305  // Normal writes should clear the locked address
306  //
307  e->clearLocked();
308  }
309  return success;
310 }
311 
312 void
313 Sequencer::recordMissLatency(const Cycles cycles, const RubyRequestType type,
314  const MachineType respondingMach,
315  bool isExternalHit, Cycles issuedTime,
316  Cycles initialRequestTime,
317  Cycles forwardRequestTime,
318  Cycles firstResponseTime, Cycles completionTime)
319 {
320  m_latencyHist.sample(cycles);
321  m_typeLatencyHist[type]->sample(cycles);
322 
323  if (isExternalHit) {
324  m_missLatencyHist.sample(cycles);
325  m_missTypeLatencyHist[type]->sample(cycles);
326 
327  if (respondingMach != MachineType_NUM) {
328  m_missMachLatencyHist[respondingMach]->sample(cycles);
329  m_missTypeMachLatencyHist[type][respondingMach]->sample(cycles);
330 
331  if ((issuedTime <= initialRequestTime) &&
332  (initialRequestTime <= forwardRequestTime) &&
333  (forwardRequestTime <= firstResponseTime) &&
334  (firstResponseTime <= completionTime)) {
335 
336  m_IssueToInitialDelayHist[respondingMach]->sample(
337  initialRequestTime - issuedTime);
338  m_InitialToForwardDelayHist[respondingMach]->sample(
339  forwardRequestTime - initialRequestTime);
340  m_ForwardToFirstResponseDelayHist[respondingMach]->sample(
341  firstResponseTime - forwardRequestTime);
342  m_FirstResponseToCompletionDelayHist[respondingMach]->sample(
343  completionTime - firstResponseTime);
344  } else {
345  m_IncompleteTimes[respondingMach]++;
346  }
347  }
348  } else {
349  m_hitLatencyHist.sample(cycles);
350  m_hitTypeLatencyHist[type]->sample(cycles);
351 
352  if (respondingMach != MachineType_NUM) {
353  m_hitMachLatencyHist[respondingMach]->sample(cycles);
354  m_hitTypeMachLatencyHist[type][respondingMach]->sample(cycles);
355  }
356  }
357 }
358 
359 void
361  const bool externalHit, const MachineType mach,
362  const Cycles initialRequestTime,
363  const Cycles forwardRequestTime,
364  const Cycles firstResponseTime)
365 {
366  assert(address == makeLineAddress(address));
367  assert(m_writeRequestTable.count(makeLineAddress(address)));
368 
369  RequestTable::iterator i = m_writeRequestTable.find(address);
370  assert(i != m_writeRequestTable.end());
371  SequencerRequest* request = i->second;
372 
373  m_writeRequestTable.erase(i);
374  markRemoved();
375 
376  assert((request->m_type == RubyRequestType_ST) ||
377  (request->m_type == RubyRequestType_ATOMIC) ||
378  (request->m_type == RubyRequestType_RMW_Read) ||
379  (request->m_type == RubyRequestType_RMW_Write) ||
380  (request->m_type == RubyRequestType_Load_Linked) ||
381  (request->m_type == RubyRequestType_Store_Conditional) ||
382  (request->m_type == RubyRequestType_Locked_RMW_Read) ||
383  (request->m_type == RubyRequestType_Locked_RMW_Write) ||
384  (request->m_type == RubyRequestType_FLUSH));
385 
386  //
387  // For Alpha, properly handle LL, SC, and write requests with respect to
388  // locked cache blocks.
389  //
390  // Not valid for Garnet_standalone protocl
391  //
392  bool success = true;
394  success = handleLlsc(address, request);
395 
396  // Handle SLICC block_on behavior for Locked_RMW accesses. NOTE: the
397  // address variable here is assumed to be a line address, so when
398  // blocking buffers, must check line addresses.
399  if (request->m_type == RubyRequestType_Locked_RMW_Read) {
400  // blockOnQueue blocks all first-level cache controller queues
401  // waiting on memory accesses for the specified address that go to
402  // the specified queue. In this case, a Locked_RMW_Write must go to
403  // the mandatory_q before unblocking the first-level controller.
404  // This will block standard loads, stores, ifetches, etc.
406  } else if (request->m_type == RubyRequestType_Locked_RMW_Write) {
407  m_controller->unblock(address);
408  }
409 
410  hitCallback(request, data, success, mach, externalHit,
411  initialRequestTime, forwardRequestTime, firstResponseTime);
412 }
413 
414 void
416  bool externalHit, const MachineType mach,
417  Cycles initialRequestTime,
418  Cycles forwardRequestTime,
419  Cycles firstResponseTime)
420 {
421  assert(address == makeLineAddress(address));
422  assert(m_readRequestTable.count(makeLineAddress(address)));
423 
424  RequestTable::iterator i = m_readRequestTable.find(address);
425  assert(i != m_readRequestTable.end());
426  SequencerRequest* request = i->second;
427 
428  m_readRequestTable.erase(i);
429  markRemoved();
430 
431  assert((request->m_type == RubyRequestType_LD) ||
432  (request->m_type == RubyRequestType_IFETCH));
433 
434  hitCallback(request, data, true, mach, externalHit,
435  initialRequestTime, forwardRequestTime, firstResponseTime);
436 }
437 
438 void
440  bool llscSuccess,
441  const MachineType mach, const bool externalHit,
442  const Cycles initialRequestTime,
443  const Cycles forwardRequestTime,
444  const Cycles firstResponseTime)
445 {
446  warn_once("Replacement policy updates recently became the responsibility "
447  "of SLICC state machines. Make sure to setMRU() near callbacks "
448  "in .sm files!");
449 
450  PacketPtr pkt = srequest->pkt;
451  Addr request_address(pkt->getAddr());
452  RubyRequestType type = srequest->m_type;
453  Cycles issued_time = srequest->issue_time;
454 
455  assert(curCycle() >= issued_time);
456  Cycles total_latency = curCycle() - issued_time;
457 
458  // Profile the latency for all demand accesses.
459  recordMissLatency(total_latency, type, mach, externalHit, issued_time,
460  initialRequestTime, forwardRequestTime,
461  firstResponseTime, curCycle());
462 
463  DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %d cycles\n",
464  curTick(), m_version, "Seq",
465  llscSuccess ? "Done" : "SC_Failed", "", "",
466  printAddress(request_address), total_latency);
467 
468  // update the data unless it is a non-data-carrying flush
470  data.setData(pkt->getConstPtr<uint8_t>(),
471  getOffset(request_address), pkt->getSize());
472  } else if (!pkt->isFlush()) {
473  if ((type == RubyRequestType_LD) ||
474  (type == RubyRequestType_IFETCH) ||
475  (type == RubyRequestType_RMW_Read) ||
476  (type == RubyRequestType_Locked_RMW_Read) ||
477  (type == RubyRequestType_Load_Linked)) {
478  memcpy(pkt->getPtr<uint8_t>(),
479  data.getData(getOffset(request_address), pkt->getSize()),
480  pkt->getSize());
481  DPRINTF(RubySequencer, "read data %s\n", data);
482  } else if (pkt->req->isSwap()) {
483  std::vector<uint8_t> overwrite_val(pkt->getSize());
484  memcpy(&overwrite_val[0], pkt->getConstPtr<uint8_t>(),
485  pkt->getSize());
486  memcpy(pkt->getPtr<uint8_t>(),
487  data.getData(getOffset(request_address), pkt->getSize()),
488  pkt->getSize());
489  data.setData(&overwrite_val[0],
490  getOffset(request_address), pkt->getSize());
491  DPRINTF(RubySequencer, "swap data %s\n", data);
492  } else if (type != RubyRequestType_Store_Conditional || llscSuccess) {
493  // Types of stores set the actual data here, apart from
494  // failed Store Conditional requests
495  data.setData(pkt->getConstPtr<uint8_t>(),
496  getOffset(request_address), pkt->getSize());
497  DPRINTF(RubySequencer, "set data %s\n", data);
498  }
499  }
500 
501  // If using the RubyTester, update the RubyTester sender state's
502  // subBlock with the recieved data. The tester will later access
503  // this state.
504  if (m_usingRubyTester) {
505  DPRINTF(RubySequencer, "hitCallback %s 0x%x using RubyTester\n",
506  pkt->cmdString(), pkt->getAddr());
507  RubyTester::SenderState* testerSenderState =
509  assert(testerSenderState);
510  testerSenderState->subBlock.mergeFrom(data);
511  }
512 
513  delete srequest;
514 
517  assert(pkt->req);
518  delete pkt->req;
519  delete pkt;
521  } else if (RubySystem::getCooldownEnabled()) {
522  delete pkt;
524  } else {
525  ruby_hit_callback(pkt);
527  }
528 }
529 
530 bool
532 {
533  return m_writeRequestTable.empty() && m_readRequestTable.empty();
534 }
535 
536 RequestStatus
538 {
540  return RequestStatus_BufferFull;
541  }
542 
543  RubyRequestType primary_type = RubyRequestType_NULL;
544  RubyRequestType secondary_type = RubyRequestType_NULL;
545 
546  if (pkt->isLLSC()) {
547  //
548  // Alpha LL/SC instructions need to be handled carefully by the cache
549  // coherence protocol to ensure they follow the proper semantics. In
550  // particular, by identifying the operations as atomic, the protocol
551  // should understand that migratory sharing optimizations should not
552  // be performed (i.e. a load between the LL and SC should not steal
553  // away exclusive permission).
554  //
555  if (pkt->isWrite()) {
556  DPRINTF(RubySequencer, "Issuing SC\n");
557  primary_type = RubyRequestType_Store_Conditional;
558  } else {
559  DPRINTF(RubySequencer, "Issuing LL\n");
560  assert(pkt->isRead());
561  primary_type = RubyRequestType_Load_Linked;
562  }
563  secondary_type = RubyRequestType_ATOMIC;
564  } else if (pkt->req->isLockedRMW()) {
565  //
566  // x86 locked instructions are translated to store cache coherence
567  // requests because these requests should always be treated as read
568  // exclusive operations and should leverage any migratory sharing
569  // optimization built into the protocol.
570  //
571  if (pkt->isWrite()) {
572  DPRINTF(RubySequencer, "Issuing Locked RMW Write\n");
573  primary_type = RubyRequestType_Locked_RMW_Write;
574  } else {
575  DPRINTF(RubySequencer, "Issuing Locked RMW Read\n");
576  assert(pkt->isRead());
577  primary_type = RubyRequestType_Locked_RMW_Read;
578  }
579  secondary_type = RubyRequestType_ST;
580  } else {
581  //
582  // To support SwapReq, we need to check isWrite() first: a SwapReq
583  // should always be treated like a write, but since a SwapReq implies
584  // both isWrite() and isRead() are true, check isWrite() first here.
585  //
586  if (pkt->isWrite()) {
587  //
588  // Note: M5 packets do not differentiate ST from RMW_Write
589  //
590  primary_type = secondary_type = RubyRequestType_ST;
591  } else if (pkt->isRead()) {
592  if (pkt->req->isInstFetch()) {
593  primary_type = secondary_type = RubyRequestType_IFETCH;
594  } else {
595  bool storeCheck = false;
596  // only X86 need the store check
597  if (system->getArch() == Arch::X86ISA) {
598  uint32_t flags = pkt->req->getFlags();
599  storeCheck = flags &
601  }
602  if (storeCheck) {
603  primary_type = RubyRequestType_RMW_Read;
604  secondary_type = RubyRequestType_ST;
605  } else {
606  primary_type = secondary_type = RubyRequestType_LD;
607  }
608  }
609  } else if (pkt->isFlush()) {
610  primary_type = secondary_type = RubyRequestType_FLUSH;
611  } else {
612  panic("Unsupported ruby packet type\n");
613  }
614  }
615 
616  RequestStatus status = insertRequest(pkt, primary_type);
617  if (status != RequestStatus_Ready)
618  return status;
619 
620  issueRequest(pkt, secondary_type);
621 
622  // TODO: issue hardware prefetches here
623  return RequestStatus_Issued;
624 }
625 
626 void
627 Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type)
628 {
629  assert(pkt != NULL);
630  ContextID proc_id = pkt->req->hasContextId() ?
631  pkt->req->contextId() : InvalidContextID;
632 
633  ContextID core_id = coreId();
634 
635  // If valid, copy the pc to the ruby request
636  Addr pc = 0;
637  if (pkt->req->hasPC()) {
638  pc = pkt->req->getPC();
639  }
640 
641  // check if the packet has data as for example prefetch and flush
642  // requests do not
643  std::shared_ptr<RubyRequest> msg =
644  std::make_shared<RubyRequest>(clockEdge(), pkt->getAddr(),
645  pkt->isFlush() ?
646  nullptr : pkt->getPtr<uint8_t>(),
647  pkt->getSize(), pc, secondary_type,
648  RubyAccessMode_Supervisor, pkt,
649  PrefetchBit_No, proc_id, core_id);
650 
651  DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\n",
652  curTick(), m_version, "Seq", "Begin", "", "",
653  printAddress(msg->getPhysicalAddress()),
654  RubyRequestType_to_string(secondary_type));
655 
656  // The Sequencer currently assesses instruction and data cache hit latency
657  // for the top-level caches at the beginning of a memory access.
658  // TODO: Eventually, this latency should be moved to represent the actual
659  // cache access latency portion of the memory access. This will require
660  // changing cache controller protocol files to assess the latency on the
661  // access response path.
662  Cycles latency(0); // Initialize to zero to catch misconfigured latency
663  if (secondary_type == RubyRequestType_IFETCH)
664  latency = m_inst_cache_hit_latency;
665  else
666  latency = m_data_cache_hit_latency;
667 
668  // Send the message to the cache controller
669  assert(latency > 0);
670 
671  assert(m_mandatory_q_ptr != NULL);
673 }
674 
675 template <class KEY, class VALUE>
676 std::ostream &
677 operator<<(ostream &out, const std::unordered_map<KEY, VALUE> &map)
678 {
679  auto i = map.begin();
680  auto end = map.end();
681 
682  out << "[";
683  for (; i != end; ++i)
684  out << " " << i->first << "=" << i->second;
685  out << " ]";
686 
687  return out;
688 }
689 
690 void
691 Sequencer::print(ostream& out) const
692 {
693  out << "[Sequencer: " << m_version
694  << ", outstanding requests: " << m_outstanding_count
695  << ", read request table: " << m_readRequestTable
696  << ", write request table: " << m_writeRequestTable
697  << "]";
698 }
699 
700 // this can be called from setState whenever coherence permissions are
701 // upgraded when invoked, coherence violations will be checked for the
702 // given block
703 void
705 {
706 #ifdef CHECK_COHERENCE
707  m_ruby_system->checkGlobalCoherenceInvariant(addr);
708 #endif
709 }
710 
711 void
712 Sequencer::recordRequestType(SequencerRequestType requestType) {
713  DPRINTF(RubyStats, "Recorded statistic: %s\n",
714  SequencerRequestType_to_string(requestType));
715 }
716 
717 
718 void
720 {
721  ruby_eviction_callback(address);
722 }
723 
724 void
726 {
728 
730  .name(name() + ".store_waiting_on_load")
731  .desc("Number of times a store aliased with a pending load")
734  .name(name() + ".store_waiting_on_store")
735  .desc("Number of times a store aliased with a pending store")
738  .name(name() + ".load_waiting_on_load")
739  .desc("Number of times a load aliased with a pending load")
742  .name(name() + ".load_waiting_on_store")
743  .desc("Number of times a load aliased with a pending store")
745 
746  // These statistical variables are not for display.
747  // The profiler will collate these across different
748  // sequencers and display those collated statistics.
750  m_latencyHist.init(10);
753 
754  for (int i = 0; i < RubyRequestType_NUM; i++) {
755  m_typeLatencyHist.push_back(new Stats::Histogram());
756  m_typeLatencyHist[i]->init(10);
757 
758  m_hitTypeLatencyHist.push_back(new Stats::Histogram());
759  m_hitTypeLatencyHist[i]->init(10);
760 
761  m_missTypeLatencyHist.push_back(new Stats::Histogram());
762  m_missTypeLatencyHist[i]->init(10);
763  }
764 
765  for (int i = 0; i < MachineType_NUM; i++) {
766  m_hitMachLatencyHist.push_back(new Stats::Histogram());
767  m_hitMachLatencyHist[i]->init(10);
768 
769  m_missMachLatencyHist.push_back(new Stats::Histogram());
770  m_missMachLatencyHist[i]->init(10);
771 
773  m_IssueToInitialDelayHist[i]->init(10);
774 
776  m_InitialToForwardDelayHist[i]->init(10);
777 
780 
783  }
784 
785  for (int i = 0; i < RubyRequestType_NUM; i++) {
788 
789  for (int j = 0; j < MachineType_NUM; j++) {
790  m_hitTypeMachLatencyHist[i].push_back(new Stats::Histogram());
791  m_hitTypeMachLatencyHist[i][j]->init(10);
792 
793  m_missTypeMachLatencyHist[i].push_back(new Stats::Histogram());
794  m_missTypeMachLatencyHist[i][j]->init(10);
795  }
796  }
797 }
void enqueueNextFetchRequest()
Function for fetching warming up the memory and the caches.
#define DPRINTF(x,...)
Definition: trace.hh:212
Stats::Scalar m_store_waiting_on_load
Counters for recording aliasing information.
Definition: Sequencer.hh:197
bool isLLSC() const
Definition: packet.hh:527
int m_max_outstanding_requests
Definition: Sequencer.hh:176
void resetStats()
Reset statistics associated with this object.
Definition: Sequencer.cc:134
void hitCallback(SequencerRequest *request, DataBlock &data, bool llscSuccess, const MachineType mach, const bool externalHit, const Cycles initialRequestTime, const Cycles forwardRequestTime, const Cycles firstResponseTime)
Definition: Sequencer.cc:439
const int FlagShift
Definition: ldstflags.hh:52
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
SequencerWakeupEvent deadlockCheckEvent
Definition: Sequencer.hh:252
Cycles issue_time
Definition: Sequencer.hh:47
void print(std::ostream &out) const
Definition: Sequencer.cc:691
Bitfield< 7 > i
Definition: miscregs.hh:1378
std::vector< Stats::Histogram * > m_missTypeLatencyHist
Definition: Sequencer.hh:226
ContextID contextId() const
Accessor function for context ID.
Definition: request.hh:694
STL pair class.
Definition: stl.hh:61
#define panic(...)
Definition: misc.hh:153
~Sequencer()
Definition: Sequencer.cc:78
Running normally.
Tick cyclesToTicks(Cycles c) const
void setExtraData(uint64_t extraData)
Accessor function for store conditional return value.
Definition: request.hh:680
CacheRecorder * m_cache_recorder
Definition: RubySystem.hh:152
bool isLockedRMW() const
Definition: request.hh:773
AbstractController * m_controller
Definition: RubyPort.hh:190
ip6_addr_t addr
Definition: inet.hh:335
bool isWrite() const
Definition: packet.hh:503
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
#define warn_once(...)
Definition: misc.hh:226
bool hasPC() const
Definition: request.hh:708
PacketPtr pkt
Definition: Sequencer.hh:45
std::vector< Stats::Histogram * > m_FirstResponseToCompletionDelayHist
Definition: Sequencer.hh:237
RequestStatus insertRequest(PacketPtr pkt, RubyRequestType request_type)
Definition: Sequencer.cc:165
void recordRequestType(SequencerRequestType requestType)
Definition: Sequencer.cc:712
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2560
Addr getPC() const
Accessor function for pc.
Definition: request.hh:715
Stats::Histogram m_missLatencyHist
Histogram for holding latency profile of all requests that miss in the controller connected to this s...
Definition: Sequencer.hh:225
Stats::Histogram m_latencyHist
Histogram for holding latency profile of all requests.
Definition: Sequencer.hh:210
CacheMemory * m_dataCache_ptr
Definition: Sequencer.hh:179
void recordMissLatency(const Cycles t, const RubyRequestType type, const MachineType respondingMach, bool isExternalHit, Cycles issuedTime, Cycles initialRequestTime, Cycles forwardRequestTime, Cycles firstResponseTime, Cycles completionTime)
Definition: Sequencer.cc:313
Cycles m_inst_cache_hit_latency
Definition: Sequencer.hh:187
std::vector< Stats::Histogram * > m_typeLatencyHist
Definition: Sequencer.hh:211
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:311
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:959
RequestTable m_readRequestTable
Definition: Sequencer.hh:191
RubySystem * m_ruby_system
Definition: RubyPort.hh:188
Stats::Histogram m_outstandReqHist
Histogram for number of outstanding requests per cycle.
Definition: Sequencer.hh:207
std::vector< Stats::Histogram * > m_ForwardToFirstResponseDelayHist
Definition: Sequencer.hh:236
CacheMemory * m_instCache_ptr
Definition: Sequencer.hh:180
const char data[]
Definition: circlebuf.cc:43
bool hasContextId() const
Definition: request.hh:687
RubyRequestType m_type
Definition: Sequencer.hh:46
bool isBlocked(Addr) const
Bitfield< 5, 0 > status
Definition: miscregs.hh:1604
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
std::vector< Stats::Histogram * > m_InitialToForwardDelayHist
Definition: Sequencer.hh:235
static bool getWarmupEnabled()
Definition: RubySystem.hh:77
RequestTable m_writeRequestTable
Definition: Sequencer.hh:190
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...
Tick curTick()
The current simulated tick.
Definition: core.hh:47
void enqueueNextFlushRequest()
Function for flushing the memory contents of the caches to the main memory.
int coreId() const
Definition: Sequencer.hh:102
void ruby_eviction_callback(Addr address)
Definition: RubyPort.cc:534
void invalidateSC(Addr address)
Definition: Sequencer.cc:257
System * system
Definition: RubyPort.hh:193
void evictionCallback(Addr address)
Definition: Sequencer.cc:719
std::vector< Stats::Histogram * > m_hitTypeLatencyHist
Definition: Sequencer.hh:216
uint32_t m_version
Definition: RubyPort.hh:189
std::vector< Stats::Histogram * > m_IssueToInitialDelayHist
Histograms for recording the breakdown of miss latency.
Definition: Sequencer.hh:234
bool handleLlsc(Addr address, SequencerRequest *request)
Definition: Sequencer.cc:268
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
A simple histogram stat.
Definition: statistics.hh:2551
bool m_usingRubyTester
Definition: RubyPort.hh:192
Addr getOffset(Addr addr)
Definition: Address.cc:106
MemObjectParams Params
Definition: mem_object.hh:63
bool isLocked(int context) const
bool isInstFetch() const
Definition: request.hh:769
static bool getCooldownEnabled()
Definition: RubySystem.hh:78
bool isRead() const
Definition: packet.hh:502
std::vector< Stats::Histogram * > m_missMachLatencyHist
Histograms for profiling the latencies for requests that required external messages.
Definition: Sequencer.hh:230
bool isSwap() const
Definition: request.hh:774
void ruby_hit_callback(PacketPtr pkt)
Definition: RubyPort.cc:362
void setLocked(int context)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
void issueRequest(PacketPtr pkt, RubyRequestType type)
Definition: Sequencer.cc:627
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
Addr makeLineAddress(Addr addr)
Definition: Address.cc:112
std::string printAddress(Addr addr)
Definition: Address.cc:126
void reset()
Reset stat value to default.
Definition: statistics.hh:1893
int m_coreId
Definition: Sequencer.hh:202
void blockOnQueue(Addr, MessageBuffer *)
Bitfield< 24 > j
Definition: miscregs.hh:1369
Flags getFlags()
Accessor for flags.
Definition: request.hh:584
Bitfield< 9 > e
Definition: miscregs.hh:1376
MessageBuffer * m_mandatory_q_ptr
Definition: RubyPort.hh:191
std::vector< std::vector< Stats::Histogram * > > m_missTypeMachLatencyHist
Definition: Sequencer.hh:231
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:254
std::vector< Stats::Counter > m_IncompleteTimes
Definition: Sequencer.hh:238
void regStats()
Register statistics for this object.
Definition: Sequencer.cc:725
const uint8_t * getData(int offset, int len) const
Definition: DataBlock.cc:95
Tick clockPeriod() const
type
Definition: misc.hh:728
void testDrainComplete()
Definition: RubyPort.cc:411
virtual const std::string name() const
Definition: sim_object.hh:117
Declaration of the Packet class.
Cycles m_data_cache_hit_latency
Definition: Sequencer.hh:186
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:497
bool m_runningGarnetStandalone
Definition: Sequencer.hh:204
const ContextID InvalidContextID
Definition: types.hh:176
void markRemoved()
Definition: Sequencer.cc:249
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
Stats::Scalar m_store_waiting_on_store
Definition: Sequencer.hh:198
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:282
void setData(const uint8_t *data, int offset, int len)
Definition: DataBlock.cc:108
Stats::Scalar m_load_waiting_on_load
Definition: Sequencer.hh:200
IntReg pc
Definition: remote_gdb.hh:91
std::vector< Stats::Histogram * > m_hitMachLatencyHist
Histograms for profiling the latencies for requests that did not required external messages...
Definition: Sequencer.hh:220
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:484
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:287
const T * getConstPtr() const
Definition: packet.hh:967
Cycles m_deadlock_threshold
Definition: Sequencer.hh:177
unsigned getSize() const
Definition: packet.hh:649
void wakeup()
Definition: Sequencer.cc:83
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:415
bool empty() const
Definition: Sequencer.cc:531
RequestStatus makeRequest(PacketPtr pkt)
Definition: Sequencer.cc:537
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:57
Bitfield< 0 > p
Bitfield< 9, 8 > rs
Definition: miscregs.hh:1560
AbstractCacheEntry * lookup(Addr address)
Definition: CacheMemory.cc:322
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:360
void enqueue(MsgPtr message, Tick curTime, Tick delta)
void regStats() override
Register statistics for this object.
int m_outstanding_count
Definition: Sequencer.hh:193
Stats::Histogram m_hitLatencyHist
Histogram for holding latency profile of all requests that hit in the controller connected to this se...
Definition: Sequencer.hh:215
int ContextID
Globally unique thread context ID.
Definition: types.hh:175
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1869
void checkCoherence(Addr address)
Definition: Sequencer.cc:704
Stats::Scalar m_load_waiting_on_store
Definition: Sequencer.hh:199
Addr getAddr() const
Definition: packet.hh:639
Arch getArch() const
Get the architecture.
Definition: system.hh:286
bool isFlush() const
Definition: packet.hh:530
std::vector< std::vector< Stats::Histogram * > > m_hitTypeMachLatencyHist
Definition: Sequencer.hh:221
#define DPRINTFR(...)
Definition: trace.hh:214
Sequencer(const Params *)
Definition: Sequencer.cc:55

Generated on Fri Jun 9 2017 13:03:50 for gem5 by doxygen 1.8.6