gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
commit_impl.hh
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Google, Inc.
3  * Copyright (c) 2010-2014 ARM Limited
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2004-2006 The Regents of The University of Michigan
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  * Authors: Kevin Lim
42  * Korey Sewell
43  */
44 #ifndef __CPU_O3_COMMIT_IMPL_HH__
45 #define __CPU_O3_COMMIT_IMPL_HH__
46 
47 #include <algorithm>
48 #include <set>
49 #include <string>
50 
51 #include "arch/utility.hh"
52 #include "base/loader/symtab.hh"
53 #include "base/cp_annotate.hh"
54 #include "config/the_isa.hh"
55 #include "cpu/checker/cpu.hh"
56 #include "cpu/o3/commit.hh"
57 #include "cpu/o3/thread_state.hh"
58 #include "cpu/base.hh"
59 #include "cpu/exetrace.hh"
60 #include "cpu/timebuf.hh"
61 #include "debug/Activity.hh"
62 #include "debug/Commit.hh"
63 #include "debug/CommitRate.hh"
64 #include "debug/Drain.hh"
65 #include "debug/ExecFaulting.hh"
66 #include "debug/O3PipeView.hh"
67 #include "params/DerivO3CPU.hh"
68 #include "sim/faults.hh"
69 #include "sim/full_system.hh"
70 
71 using namespace std;
72 
73 template <class Impl>
75  ThreadID _tid)
76  : Event(CPU_Tick_Pri, AutoDelete), commit(_commit), tid(_tid)
77 {
78 }
79 
80 template <class Impl>
81 void
83 {
84  // This will get reset by commit if it was switched out at the
85  // time of this event processing.
86  commit->trapSquash[tid] = true;
87 }
88 
89 template <class Impl>
90 const char *
92 {
93  return "Trap";
94 }
95 
96 template <class Impl>
97 DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
98  : cpu(_cpu),
102  fetchToCommitDelay(params->commitToFetchDelay),
103  renameWidth(params->renameWidth),
104  commitWidth(params->commitWidth),
105  numThreads(params->numThreads),
106  drainPending(false),
107  drainImminent(false),
108  trapLatency(params->trapLatency),
109  canHandleInterrupts(true),
110  avoidQuiesceLiveLock(false)
111 {
112  if (commitWidth > Impl::MaxWidth)
113  fatal("commitWidth (%d) is larger than compiled limit (%d),\n"
114  "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
115  commitWidth, static_cast<int>(Impl::MaxWidth));
116 
117  _status = Active;
119  std::string policy = params->smtCommitPolicy;
120 
121  //Convert string to lowercase
122  std::transform(policy.begin(), policy.end(), policy.begin(),
123  (int(*)(int)) tolower);
124 
125  //Assign commit policy
126  if (policy == "aggressive"){
128 
129  DPRINTF(Commit,"Commit Policy set to Aggressive.\n");
130  } else if (policy == "roundrobin"){
132 
133  //Set-Up Priority List
134  for (ThreadID tid = 0; tid < numThreads; tid++) {
135  priority_list.push_back(tid);
136  }
137 
138  DPRINTF(Commit,"Commit Policy set to Round Robin.\n");
139  } else if (policy == "oldestready"){
141 
142  DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
143  } else {
144  assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
145  "RoundRobin,OldestReady}");
146  }
147 
148  for (ThreadID tid = 0; tid < numThreads; tid++) {
149  commitStatus[tid] = Idle;
150  changedROBNumEntries[tid] = false;
151  checkEmptyROB[tid] = false;
152  trapInFlight[tid] = false;
153  committedStores[tid] = false;
154  trapSquash[tid] = false;
155  tcSquash[tid] = false;
156  pc[tid].set(0);
157  lastCommitedSeqNum[tid] = 0;
158  squashAfterInst[tid] = NULL;
159  }
160  interrupt = NoFault;
161 }
162 
163 template <class Impl>
164 std::string
166 {
167  return cpu->name() + ".commit";
168 }
169 
170 template <class Impl>
171 void
173 {
174  ppCommit = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Commit");
175  ppCommitStall = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "CommitStall");
176  ppSquash = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Squash");
177 }
178 
179 template <class Impl>
180 void
182 {
183  using namespace Stats;
184  commitSquashedInsts
185  .name(name() + ".commitSquashedInsts")
186  .desc("The number of squashed insts skipped by commit")
187  .prereq(commitSquashedInsts);
188 
189  commitNonSpecStalls
190  .name(name() + ".commitNonSpecStalls")
191  .desc("The number of times commit has been forced to stall to "
192  "communicate backwards")
193  .prereq(commitNonSpecStalls);
194 
195  branchMispredicts
196  .name(name() + ".branchMispredicts")
197  .desc("The number of times a branch was mispredicted")
198  .prereq(branchMispredicts);
199 
200  numCommittedDist
201  .init(0,commitWidth,1)
202  .name(name() + ".committed_per_cycle")
203  .desc("Number of insts commited each cycle")
204  .flags(Stats::pdf)
205  ;
206 
207  instsCommitted
208  .init(cpu->numThreads)
209  .name(name() + ".committedInsts")
210  .desc("Number of instructions committed")
211  .flags(total)
212  ;
213 
214  opsCommitted
215  .init(cpu->numThreads)
216  .name(name() + ".committedOps")
217  .desc("Number of ops (including micro ops) committed")
218  .flags(total)
219  ;
220 
221  statComSwp
222  .init(cpu->numThreads)
223  .name(name() + ".swp_count")
224  .desc("Number of s/w prefetches committed")
225  .flags(total)
226  ;
227 
228  statComRefs
229  .init(cpu->numThreads)
230  .name(name() + ".refs")
231  .desc("Number of memory references committed")
232  .flags(total)
233  ;
234 
235  statComLoads
236  .init(cpu->numThreads)
237  .name(name() + ".loads")
238  .desc("Number of loads committed")
239  .flags(total)
240  ;
241 
242  statComMembars
243  .init(cpu->numThreads)
244  .name(name() + ".membars")
245  .desc("Number of memory barriers committed")
246  .flags(total)
247  ;
248 
249  statComBranches
250  .init(cpu->numThreads)
251  .name(name() + ".branches")
252  .desc("Number of branches committed")
253  .flags(total)
254  ;
255 
256  statComFloating
257  .init(cpu->numThreads)
258  .name(name() + ".fp_insts")
259  .desc("Number of committed floating point instructions.")
260  .flags(total)
261  ;
262 
263  statComInteger
264  .init(cpu->numThreads)
265  .name(name()+".int_insts")
266  .desc("Number of committed integer instructions.")
267  .flags(total)
268  ;
269 
270  statComFunctionCalls
271  .init(cpu->numThreads)
272  .name(name()+".function_calls")
273  .desc("Number of function calls committed.")
274  .flags(total)
275  ;
276 
277  statCommittedInstType
278  .init(numThreads,Enums::Num_OpClass)
279  .name(name() + ".op_class")
280  .desc("Class of committed instruction")
281  .flags(total | pdf | dist)
282  ;
283  statCommittedInstType.ysubnames(Enums::OpClassStrings);
284 
285  commitEligibleSamples
286  .name(name() + ".bw_lim_events")
287  .desc("number cycles where commit BW limit reached")
288  ;
289 }
290 
291 template <class Impl>
292 void
294 {
295  thread = threads;
296 }
297 
298 template <class Impl>
299 void
301 {
302  timeBuffer = tb_ptr;
303 
304  // Setup wire to send information back to IEW.
305  toIEW = timeBuffer->getWire(0);
306 
307  // Setup wire to read data from IEW (for the ROB).
308  robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
309 }
310 
311 template <class Impl>
312 void
314 {
315  fetchQueue = fq_ptr;
316 
317  // Setup wire to get instructions from rename (for the ROB).
318  fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
319 }
320 
321 template <class Impl>
322 void
324 {
325  renameQueue = rq_ptr;
326 
327  // Setup wire to get instructions from rename (for the ROB).
328  fromRename = renameQueue->getWire(-renameToROBDelay);
329 }
330 
331 template <class Impl>
332 void
334 {
335  iewQueue = iq_ptr;
336 
337  // Setup wire to get instructions from IEW.
338  fromIEW = iewQueue->getWire(-iewToCommitDelay);
339 }
340 
341 template <class Impl>
342 void
344 {
345  iewStage = iew_stage;
346 }
347 
348 template<class Impl>
349 void
351 {
352  activeThreads = at_ptr;
353 }
354 
355 template <class Impl>
356 void
358 {
359  for (ThreadID tid = 0; tid < numThreads; tid++)
360  renameMap[tid] = &rm_ptr[tid];
361 }
362 
363 template <class Impl>
364 void
366 {
367  rob = rob_ptr;
368 }
369 
370 template <class Impl>
371 void
373 {
374  rob->setActiveThreads(activeThreads);
375  rob->resetEntries();
376 
377  // Broadcast the number of free entries.
378  for (ThreadID tid = 0; tid < numThreads; tid++) {
379  toIEW->commitInfo[tid].usedROB = true;
380  toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
381  toIEW->commitInfo[tid].emptyROB = true;
382  }
383 
384  // Commit must broadcast the number of free entries it has at the
385  // start of the simulation, so it starts as active.
386  cpu->activateStage(O3CPU::CommitIdx);
387 
388  cpu->activityThisCycle();
389 }
390 
391 template <class Impl>
392 void
394 {
395  drainPending = true;
396 }
397 
398 template <class Impl>
399 void
401 {
402  drainPending = false;
403  drainImminent = false;
404 }
405 
406 template <class Impl>
407 void
409 {
410  assert(isDrained());
411  rob->drainSanityCheck();
412 }
413 
414 template <class Impl>
415 bool
417 {
418  /* Make sure no one is executing microcode. There are two reasons
419  * for this:
420  * - Hardware virtualized CPUs can't switch into the middle of a
421  * microcode sequence.
422  * - The current fetch implementation will most likely get very
423  * confused if it tries to start fetching an instruction that
424  * is executing in the middle of a ucode sequence that changes
425  * address mappings. This can happen on for example x86.
426  */
427  for (ThreadID tid = 0; tid < numThreads; tid++) {
428  if (pc[tid].microPC() != 0)
429  return false;
430  }
431 
432  /* Make sure that all instructions have finished committing before
433  * declaring the system as drained. We want the pipeline to be
434  * completely empty when we declare the CPU to be drained. This
435  * makes debugging easier since CPU handover and restoring from a
436  * checkpoint with a different CPU should have the same timing.
437  */
438  return rob->isEmpty() &&
439  interrupt == NoFault;
440 }
441 
442 template <class Impl>
443 void
445 {
446  _status = Active;
447  _nextStatus = Inactive;
448  for (ThreadID tid = 0; tid < numThreads; tid++) {
449  commitStatus[tid] = Idle;
450  changedROBNumEntries[tid] = false;
451  trapSquash[tid] = false;
452  tcSquash[tid] = false;
453  squashAfterInst[tid] = NULL;
454  }
455  rob->takeOverFrom();
456 }
457 
458 template <class Impl>
459 void
461 {
462  list<ThreadID>::iterator thread_it = std::find(priority_list.begin(),
463  priority_list.end(), tid);
464 
465  if (thread_it != priority_list.end()) {
466  priority_list.erase(thread_it);
467  }
468 }
469 
470 
471 template <class Impl>
472 void
474 {
475  // reset ROB changed variable
476  list<ThreadID>::iterator threads = activeThreads->begin();
477  list<ThreadID>::iterator end = activeThreads->end();
478 
479  while (threads != end) {
480  ThreadID tid = *threads++;
481 
482  changedROBNumEntries[tid] = false;
483 
484  // Also check if any of the threads has a trap pending
485  if (commitStatus[tid] == TrapPending ||
486  commitStatus[tid] == FetchTrapPending) {
487  _nextStatus = Active;
488  }
489  }
490 
491  if (_nextStatus == Inactive && _status == Active) {
492  DPRINTF(Activity, "Deactivating stage.\n");
493  cpu->deactivateStage(O3CPU::CommitIdx);
494  } else if (_nextStatus == Active && _status == Inactive) {
495  DPRINTF(Activity, "Activating stage.\n");
496  cpu->activateStage(O3CPU::CommitIdx);
497  }
498 
499  _status = _nextStatus;
500 }
501 
502 template <class Impl>
503 bool
505 {
506  list<ThreadID>::iterator threads = activeThreads->begin();
507  list<ThreadID>::iterator end = activeThreads->end();
508 
509  while (threads != end) {
510  ThreadID tid = *threads++;
511 
512  if (changedROBNumEntries[tid]) {
513  return true;
514  }
515  }
516 
517  return false;
518 }
519 
520 template <class Impl>
521 size_t
523 {
524  return rob->numFreeEntries(tid);
525 }
526 
527 template <class Impl>
528 void
530 {
531  DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
532 
533  TrapEvent *trap = new TrapEvent(this, tid);
534 
535  Cycles latency = dynamic_pointer_cast<SyscallRetryFault>(inst_fault) ?
536  cpu->syscallRetryLatency : trapLatency;
537 
538  cpu->schedule(trap, cpu->clockEdge(latency));
539  trapInFlight[tid] = true;
540  thread[tid]->trapPending = true;
541 }
542 
543 template <class Impl>
544 void
546 {
547  assert(!trapInFlight[tid]);
548  DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
549 
550  tcSquash[tid] = true;
551 }
552 
553 template <class Impl>
554 void
556 {
557  // If we want to include the squashing instruction in the squash,
558  // then use one older sequence number.
559  // Hopefully this doesn't mess things up. Basically I want to squash
560  // all instructions of this thread.
561  InstSeqNum squashed_inst = rob->isEmpty(tid) ?
562  lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1;
563 
564  // All younger instructions will be squashed. Set the sequence
565  // number as the youngest instruction in the ROB (0 in this case.
566  // Hopefully nothing breaks.)
567  youngestSeqNum[tid] = lastCommitedSeqNum[tid];
568 
569  rob->squash(squashed_inst, tid);
570  changedROBNumEntries[tid] = true;
571 
572  // Send back the sequence number of the squashed instruction.
573  toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
574 
575  // Send back the squash signal to tell stages that they should
576  // squash.
577  toIEW->commitInfo[tid].squash = true;
578 
579  // Send back the rob squashing signal so other stages know that
580  // the ROB is in the process of squashing.
581  toIEW->commitInfo[tid].robSquashing = true;
582 
583  toIEW->commitInfo[tid].mispredictInst = NULL;
584  toIEW->commitInfo[tid].squashInst = NULL;
585 
586  toIEW->commitInfo[tid].pc = pc[tid];
587 }
588 
589 template <class Impl>
590 void
592 {
593  squashAll(tid);
594 
595  DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
596 
597  thread[tid]->trapPending = false;
598  thread[tid]->noSquashFromTC = false;
599  trapInFlight[tid] = false;
600 
601  trapSquash[tid] = false;
602 
603  commitStatus[tid] = ROBSquashing;
604  cpu->activityThisCycle();
605 }
606 
607 template <class Impl>
608 void
610 {
611  squashAll(tid);
612 
613  DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
614 
615  thread[tid]->noSquashFromTC = false;
616  assert(!thread[tid]->trapPending);
617 
618  commitStatus[tid] = ROBSquashing;
619  cpu->activityThisCycle();
620 
621  tcSquash[tid] = false;
622 }
623 
624 template <class Impl>
625 void
627 {
628  DPRINTF(Commit, "Squashing after squash after request, "
629  "restarting at PC %s\n", pc[tid]);
630 
631  squashAll(tid);
632  // Make sure to inform the fetch stage of which instruction caused
633  // the squash. It'll try to re-fetch an instruction executing in
634  // microcode unless this is set.
635  toIEW->commitInfo[tid].squashInst = squashAfterInst[tid];
636  squashAfterInst[tid] = NULL;
637 
638  commitStatus[tid] = ROBSquashing;
639  cpu->activityThisCycle();
640 }
641 
642 template <class Impl>
643 void
645 {
646  DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n",
647  tid, head_inst->seqNum);
648 
649  assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
650  commitStatus[tid] = SquashAfterPending;
651  squashAfterInst[tid] = head_inst;
652 }
653 
654 template <class Impl>
655 void
657 {
658  wroteToTimeBuffer = false;
659  _nextStatus = Inactive;
660 
661  if (activeThreads->empty())
662  return;
663 
664  list<ThreadID>::iterator threads = activeThreads->begin();
665  list<ThreadID>::iterator end = activeThreads->end();
666 
667  // Check if any of the threads are done squashing. Change the
668  // status if they are done.
669  while (threads != end) {
670  ThreadID tid = *threads++;
671 
672  // Clear the bit saying if the thread has committed stores
673  // this cycle.
674  committedStores[tid] = false;
675 
676  if (commitStatus[tid] == ROBSquashing) {
677 
678  if (rob->isDoneSquashing(tid)) {
679  commitStatus[tid] = Running;
680  } else {
681  DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
682  " insts this cycle.\n", tid);
683  rob->doSquash(tid);
684  toIEW->commitInfo[tid].robSquashing = true;
685  wroteToTimeBuffer = true;
686  }
687  }
688  }
689 
690  commit();
691 
692  markCompletedInsts();
693 
694  threads = activeThreads->begin();
695 
696  while (threads != end) {
697  ThreadID tid = *threads++;
698 
699  if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
700  // The ROB has more instructions it can commit. Its next status
701  // will be active.
702  _nextStatus = Active;
703 
704  DynInstPtr inst = rob->readHeadInst(tid);
705 
706  DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
707  " ROB and ready to commit\n",
708  tid, inst->seqNum, inst->pcState());
709 
710  } else if (!rob->isEmpty(tid)) {
711  DynInstPtr inst = rob->readHeadInst(tid);
712 
713  ppCommitStall->notify(inst);
714 
715  DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
716  "%s is head of ROB and not ready\n",
717  tid, inst->seqNum, inst->pcState());
718  }
719 
720  DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
721  tid, rob->countInsts(tid), rob->numFreeEntries(tid));
722  }
723 
724 
725  if (wroteToTimeBuffer) {
726  DPRINTF(Activity, "Activity This Cycle.\n");
727  cpu->activityThisCycle();
728  }
729 
730  updateStatus();
731 }
732 
733 template <class Impl>
734 void
736 {
737  // Verify that we still have an interrupt to handle
738  if (!cpu->checkInterrupts(cpu->tcBase(0))) {
739  DPRINTF(Commit, "Pending interrupt is cleared by master before "
740  "it got handled. Restart fetching from the orig path.\n");
741  toIEW->commitInfo[0].clearInterrupt = true;
742  interrupt = NoFault;
743  avoidQuiesceLiveLock = true;
744  return;
745  }
746 
747  // Wait until all in flight instructions are finished before enterring
748  // the interrupt.
749  if (canHandleInterrupts && cpu->instList.empty()) {
750  // Squash or record that I need to squash this cycle if
751  // an interrupt needed to be handled.
752  DPRINTF(Commit, "Interrupt detected.\n");
753 
754  // Clear the interrupt now that it's going to be handled
755  toIEW->commitInfo[0].clearInterrupt = true;
756 
757  assert(!thread[0]->noSquashFromTC);
758  thread[0]->noSquashFromTC = true;
759 
760  if (cpu->checker) {
761  cpu->checker->handlePendingInt();
762  }
763 
764  // CPU will handle interrupt. Note that we ignore the local copy of
765  // interrupt. This is because the local copy may no longer be the
766  // interrupt that the interrupt controller thinks is being handled.
767  cpu->processInterrupts(cpu->getInterrupts());
768 
769  thread[0]->noSquashFromTC = false;
770 
771  commitStatus[0] = TrapPending;
772 
773  interrupt = NoFault;
774 
775  // Generate trap squash event.
776  generateTrapEvent(0, interrupt);
777 
778  avoidQuiesceLiveLock = false;
779  } else {
780  DPRINTF(Commit, "Interrupt pending: instruction is %sin "
781  "flight, ROB is %sempty\n",
782  canHandleInterrupts ? "not " : "",
783  cpu->instList.empty() ? "" : "not " );
784  }
785 }
786 
787 template <class Impl>
788 void
790 {
791  // Don't propagate intterupts if we are currently handling a trap or
792  // in draining and the last observable instruction has been committed.
793  if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
794  tcSquash[0] || drainImminent)
795  return;
796 
797  // Process interrupts if interrupts are enabled, not in PAL
798  // mode, and no other traps or external squashes are currently
799  // pending.
800  // @todo: Allow other threads to handle interrupts.
801 
802  // Get any interrupt that happened
803  interrupt = cpu->getInterrupts();
804 
805  // Tell fetch that there is an interrupt pending. This
806  // will make fetch wait until it sees a non PAL-mode PC,
807  // at which point it stops fetching instructions.
808  if (interrupt != NoFault)
809  toIEW->commitInfo[0].interruptPending = true;
810 }
811 
812 template <class Impl>
813 void
815 {
816  if (FullSystem) {
817  // Check if we have a interrupt and get read to handle it
818  if (cpu->checkInterrupts(cpu->tcBase(0)))
819  propagateInterrupt();
820  }
821 
823  // Check for any possible squashes, handle them first
825  list<ThreadID>::iterator threads = activeThreads->begin();
826  list<ThreadID>::iterator end = activeThreads->end();
827 
828  int num_squashing_threads = 0;
829 
830  while (threads != end) {
831  ThreadID tid = *threads++;
832 
833  // Not sure which one takes priority. I think if we have
834  // both, that's a bad sign.
835  if (trapSquash[tid]) {
836  assert(!tcSquash[tid]);
837  squashFromTrap(tid);
838  } else if (tcSquash[tid]) {
839  assert(commitStatus[tid] != TrapPending);
840  squashFromTC(tid);
841  } else if (commitStatus[tid] == SquashAfterPending) {
842  // A squash from the previous cycle of the commit stage (i.e.,
843  // commitInsts() called squashAfter) is pending. Squash the
844  // thread now.
845  squashFromSquashAfter(tid);
846  }
847 
848  // Squashed sequence number must be older than youngest valid
849  // instruction in the ROB. This prevents squashes from younger
850  // instructions overriding squashes from older instructions.
851  if (fromIEW->squash[tid] &&
852  commitStatus[tid] != TrapPending &&
853  fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
854 
855  if (fromIEW->mispredictInst[tid]) {
856  DPRINTF(Commit,
857  "[tid:%i]: Squashing due to branch mispred PC:%#x [sn:%i]\n",
858  tid,
859  fromIEW->mispredictInst[tid]->instAddr(),
860  fromIEW->squashedSeqNum[tid]);
861  } else {
862  DPRINTF(Commit,
863  "[tid:%i]: Squashing due to order violation [sn:%i]\n",
864  tid, fromIEW->squashedSeqNum[tid]);
865  }
866 
867  DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
868  tid,
869  fromIEW->pc[tid].nextInstAddr());
870 
871  commitStatus[tid] = ROBSquashing;
872 
873  // If we want to include the squashing instruction in the squash,
874  // then use one older sequence number.
875  InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
876 
877  if (fromIEW->includeSquashInst[tid]) {
878  squashed_inst--;
879  }
880 
881  // All younger instructions will be squashed. Set the sequence
882  // number as the youngest instruction in the ROB.
883  youngestSeqNum[tid] = squashed_inst;
884 
885  rob->squash(squashed_inst, tid);
886  changedROBNumEntries[tid] = true;
887 
888  toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
889 
890  toIEW->commitInfo[tid].squash = true;
891 
892  // Send back the rob squashing signal so other stages know that
893  // the ROB is in the process of squashing.
894  toIEW->commitInfo[tid].robSquashing = true;
895 
896  toIEW->commitInfo[tid].mispredictInst =
897  fromIEW->mispredictInst[tid];
898  toIEW->commitInfo[tid].branchTaken =
899  fromIEW->branchTaken[tid];
900  toIEW->commitInfo[tid].squashInst =
901  rob->findInst(tid, squashed_inst);
902  if (toIEW->commitInfo[tid].mispredictInst) {
903  if (toIEW->commitInfo[tid].mispredictInst->isUncondCtrl()) {
904  toIEW->commitInfo[tid].branchTaken = true;
905  }
906  ++branchMispredicts;
907  }
908 
909  toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
910  }
911 
912  if (commitStatus[tid] == ROBSquashing) {
913  num_squashing_threads++;
914  }
915  }
916 
917  // If commit is currently squashing, then it will have activity for the
918  // next cycle. Set its next status as active.
919  if (num_squashing_threads) {
920  _nextStatus = Active;
921  }
922 
923  if (num_squashing_threads != numThreads) {
924  // If we're not currently squashing, then get instructions.
925  getInsts();
926 
927  // Try to commit any instructions.
928  commitInsts();
929  }
930 
931  //Check for any activity
932  threads = activeThreads->begin();
933 
934  while (threads != end) {
935  ThreadID tid = *threads++;
936 
937  if (changedROBNumEntries[tid]) {
938  toIEW->commitInfo[tid].usedROB = true;
939  toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
940 
941  wroteToTimeBuffer = true;
942  changedROBNumEntries[tid] = false;
943  if (rob->isEmpty(tid))
944  checkEmptyROB[tid] = true;
945  }
946 
947  // ROB is only considered "empty" for previous stages if: a)
948  // ROB is empty, b) there are no outstanding stores, c) IEW
949  // stage has received any information regarding stores that
950  // committed.
951  // c) is checked by making sure to not consider the ROB empty
952  // on the same cycle as when stores have been committed.
953  // @todo: Make this handle multi-cycle communication between
954  // commit and IEW.
955  if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
956  !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
957  checkEmptyROB[tid] = false;
958  toIEW->commitInfo[tid].usedROB = true;
959  toIEW->commitInfo[tid].emptyROB = true;
960  toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
961  wroteToTimeBuffer = true;
962  }
963 
964  }
965 }
966 
967 template <class Impl>
968 void
970 {
972  // Handle commit
973  // Note that commit will be handled prior to putting new
974  // instructions in the ROB so that the ROB only tries to commit
975  // instructions it has in this current cycle, and not instructions
976  // it is writing in during this cycle. Can't commit and squash
977  // things at the same time...
979 
980  DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
981 
982  unsigned num_committed = 0;
983 
984  DynInstPtr head_inst;
985 
986  // Commit as many instructions as possible until the commit bandwidth
987  // limit is reached, or it becomes impossible to commit any more.
988  while (num_committed < commitWidth) {
989  // Check for any interrupt that we've already squashed for
990  // and start processing it.
991  if (interrupt != NoFault)
992  handleInterrupt();
993 
994  ThreadID commit_thread = getCommittingThread();
995 
996  if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
997  break;
998 
999  head_inst = rob->readHeadInst(commit_thread);
1000 
1001  ThreadID tid = head_inst->threadNumber;
1002 
1003  assert(tid == commit_thread);
1004 
1005  DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
1006  head_inst->seqNum, tid);
1007 
1008  // If the head instruction is squashed, it is ready to retire
1009  // (be removed from the ROB) at any time.
1010  if (head_inst->isSquashed()) {
1011 
1012  DPRINTF(Commit, "Retiring squashed instruction from "
1013  "ROB.\n");
1014 
1015  rob->retireHead(commit_thread);
1016 
1017  ++commitSquashedInsts;
1018  // Notify potential listeners that this instruction is squashed
1019  ppSquash->notify(head_inst);
1020 
1021  // Record that the number of ROB entries has changed.
1022  changedROBNumEntries[tid] = true;
1023  } else {
1024  pc[tid] = head_inst->pcState();
1025 
1026  // Increment the total number of non-speculative instructions
1027  // executed.
1028  // Hack for now: it really shouldn't happen until after the
1029  // commit is deemed to be successful, but this count is needed
1030  // for syscalls.
1031  thread[tid]->funcExeInst++;
1032 
1033  // Try to commit the head instruction.
1034  bool commit_success = commitHead(head_inst, num_committed);
1035 
1036  if (commit_success) {
1037  ++num_committed;
1038  statCommittedInstType[tid][head_inst->opClass()]++;
1039  ppCommit->notify(head_inst);
1040 
1041  changedROBNumEntries[tid] = true;
1042 
1043  // Set the doneSeqNum to the youngest committed instruction.
1044  toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
1045 
1046  if (tid == 0) {
1047  canHandleInterrupts = (!head_inst->isDelayedCommit()) &&
1048  ((THE_ISA != ALPHA_ISA) ||
1049  (!(pc[0].instAddr() & 0x3)));
1050  }
1051 
1052  // Updates misc. registers.
1053  head_inst->updateMiscRegs();
1054 
1055  // Check instruction execution if it successfully commits and
1056  // is not carrying a fault.
1057  if (cpu->checker) {
1058  cpu->checker->verify(head_inst);
1059  }
1060 
1061  cpu->traceFunctions(pc[tid].instAddr());
1062 
1063  TheISA::advancePC(pc[tid], head_inst->staticInst);
1064 
1065  // Keep track of the last sequence number commited
1066  lastCommitedSeqNum[tid] = head_inst->seqNum;
1067 
1068  // If this is an instruction that doesn't play nicely with
1069  // others squash everything and restart fetch
1070  if (head_inst->isSquashAfter())
1071  squashAfter(tid, head_inst);
1072 
1073  if (drainPending) {
1074  if (pc[tid].microPC() == 0 && interrupt == NoFault &&
1075  !thread[tid]->trapPending) {
1076  // Last architectually committed instruction.
1077  // Squash the pipeline, stall fetch, and use
1078  // drainImminent to disable interrupts
1079  DPRINTF(Drain, "Draining: %i:%s\n", tid, pc[tid]);
1080  squashAfter(tid, head_inst);
1081  cpu->commitDrained(tid);
1082  drainImminent = true;
1083  }
1084  }
1085 
1086  bool onInstBoundary = !head_inst->isMicroop() ||
1087  head_inst->isLastMicroop() ||
1088  !head_inst->isDelayedCommit();
1089 
1090  if (onInstBoundary) {
1091  int count = 0;
1092  Addr oldpc;
1093  // Make sure we're not currently updating state while
1094  // handling PC events.
1095  assert(!thread[tid]->noSquashFromTC &&
1096  !thread[tid]->trapPending);
1097  do {
1098  oldpc = pc[tid].instAddr();
1099  cpu->system->pcEventQueue.service(thread[tid]->getTC());
1100  count++;
1101  } while (oldpc != pc[tid].instAddr());
1102  if (count > 1) {
1103  DPRINTF(Commit,
1104  "PC skip function event, stopping commit\n");
1105  break;
1106  }
1107  }
1108 
1109  // Check if an instruction just enabled interrupts and we've
1110  // previously had an interrupt pending that was not handled
1111  // because interrupts were subsequently disabled before the
1112  // pipeline reached a place to handle the interrupt. In that
1113  // case squash now to make sure the interrupt is handled.
1114  //
1115  // If we don't do this, we might end up in a live lock situation
1116  if (!interrupt && avoidQuiesceLiveLock &&
1117  onInstBoundary && cpu->checkInterrupts(cpu->tcBase(0)))
1118  squashAfter(tid, head_inst);
1119  } else {
1120  DPRINTF(Commit, "Unable to commit head instruction PC:%s "
1121  "[tid:%i] [sn:%i].\n",
1122  head_inst->pcState(), tid ,head_inst->seqNum);
1123  break;
1124  }
1125  }
1126  }
1127 
1128  DPRINTF(CommitRate, "%i\n", num_committed);
1129  numCommittedDist.sample(num_committed);
1130 
1131  if (num_committed == commitWidth) {
1132  commitEligibleSamples++;
1133  }
1134 }
1135 
1136 template <class Impl>
1137 bool
1138 DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
1139 {
1140  assert(head_inst);
1141 
1142  ThreadID tid = head_inst->threadNumber;
1143 
1144  // If the instruction is not executed yet, then it will need extra
1145  // handling. Signal backwards that it should be executed.
1146  if (!head_inst->isExecuted()) {
1147  // Keep this number correct. We have not yet actually executed
1148  // and committed this instruction.
1149  thread[tid]->funcExeInst--;
1150 
1151  // Make sure we are only trying to commit un-executed instructions we
1152  // think are possible.
1153  assert(head_inst->isNonSpeculative() || head_inst->isStoreConditional()
1154  || head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
1155  (head_inst->isLoad() && head_inst->strictlyOrdered()));
1156 
1157  DPRINTF(Commit, "Encountered a barrier or non-speculative "
1158  "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
1159  head_inst->seqNum, head_inst->pcState());
1160 
1161  if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1162  DPRINTF(Commit, "Waiting for all stores to writeback.\n");
1163  return false;
1164  }
1165 
1166  toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1167 
1168  // Change the instruction so it won't try to commit again until
1169  // it is executed.
1170  head_inst->clearCanCommit();
1171 
1172  if (head_inst->isLoad() && head_inst->strictlyOrdered()) {
1173  DPRINTF(Commit, "[sn:%lli]: Strictly ordered load, PC %s.\n",
1174  head_inst->seqNum, head_inst->pcState());
1175  toIEW->commitInfo[tid].strictlyOrdered = true;
1176  toIEW->commitInfo[tid].strictlyOrderedLoad = head_inst;
1177  } else {
1178  ++commitNonSpecStalls;
1179  }
1180 
1181  return false;
1182  }
1183 
1184  if (head_inst->isThreadSync()) {
1185  // Not handled for now.
1186  panic("Thread sync instructions are not handled yet.\n");
1187  }
1188 
1189  // Check if the instruction caused a fault. If so, trap.
1190  Fault inst_fault = head_inst->getFault();
1191 
1192  // Stores mark themselves as completed.
1193  if (!head_inst->isStore() && inst_fault == NoFault) {
1194  head_inst->setCompleted();
1195  }
1196 
1197  if (inst_fault != NoFault) {
1198  DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
1199  head_inst->seqNum, head_inst->pcState());
1200 
1201  if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
1202  DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
1203  return false;
1204  }
1205 
1206  head_inst->setCompleted();
1207 
1208  // If instruction has faulted, let the checker execute it and
1209  // check if it sees the same fault and control flow.
1210  if (cpu->checker) {
1211  // Need to check the instruction before its fault is processed
1212  cpu->checker->verify(head_inst);
1213  }
1214 
1215  assert(!thread[tid]->noSquashFromTC);
1216 
1217  // Mark that we're in state update mode so that the trap's
1218  // execution doesn't generate extra squashes.
1219  thread[tid]->noSquashFromTC = true;
1220 
1221  // Execute the trap. Although it's slightly unrealistic in
1222  // terms of timing (as it doesn't wait for the full timing of
1223  // the trap event to complete before updating state), it's
1224  // needed to update the state as soon as possible. This
1225  // prevents external agents from changing any specific state
1226  // that the trap need.
1227  cpu->trap(inst_fault, tid, head_inst->staticInst);
1228 
1229  // Exit state update mode to avoid accidental updating.
1230  thread[tid]->noSquashFromTC = false;
1231 
1232  commitStatus[tid] = TrapPending;
1233 
1234  DPRINTF(Commit, "Committing instruction with fault [sn:%lli]\n",
1235  head_inst->seqNum);
1236  if (head_inst->traceData) {
1237  if (DTRACE(ExecFaulting)) {
1238  head_inst->traceData->setFetchSeq(head_inst->seqNum);
1239  head_inst->traceData->setCPSeq(thread[tid]->numOp);
1240  head_inst->traceData->dump();
1241  }
1242  delete head_inst->traceData;
1243  head_inst->traceData = NULL;
1244  }
1245 
1246  // Generate trap squash event.
1247  generateTrapEvent(tid, inst_fault);
1248  return false;
1249  }
1250 
1251  updateComInstStats(head_inst);
1252 
1253  if (FullSystem) {
1254  if (thread[tid]->profile) {
1255  thread[tid]->profilePC = head_inst->instAddr();
1256  ProfileNode *node = thread[tid]->profile->consume(
1257  thread[tid]->getTC(), head_inst->staticInst);
1258 
1259  if (node)
1260  thread[tid]->profileNode = node;
1261  }
1262  if (CPA::available()) {
1263  if (head_inst->isControl()) {
1264  ThreadContext *tc = thread[tid]->getTC();
1265  CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
1266  }
1267  }
1268  }
1269  DPRINTF(Commit, "Committing instruction with [sn:%lli] PC %s\n",
1270  head_inst->seqNum, head_inst->pcState());
1271  if (head_inst->traceData) {
1272  head_inst->traceData->setFetchSeq(head_inst->seqNum);
1273  head_inst->traceData->setCPSeq(thread[tid]->numOp);
1274  head_inst->traceData->dump();
1275  delete head_inst->traceData;
1276  head_inst->traceData = NULL;
1277  }
1278  if (head_inst->isReturn()) {
1279  DPRINTF(Commit,"Return Instruction Committed [sn:%lli] PC %s \n",
1280  head_inst->seqNum, head_inst->pcState());
1281  }
1282 
1283  // Update the commit rename map
1284  for (int i = 0; i < head_inst->numDestRegs(); i++) {
1285  renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),
1286  head_inst->renamedDestRegIdx(i));
1287  }
1288 
1289  // Finally clear the head ROB entry.
1290  rob->retireHead(tid);
1291 
1292 #if TRACING_ON
1293  if (DTRACE(O3PipeView)) {
1294  head_inst->commitTick = curTick() - head_inst->fetchTick;
1295  }
1296 #endif
1297 
1298  // If this was a store, record it for this cycle.
1299  if (head_inst->isStore())
1300  committedStores[tid] = true;
1301 
1302  // Return true to indicate that we have committed an instruction.
1303  return true;
1304 }
1305 
1306 template <class Impl>
1307 void
1309 {
1310  DPRINTF(Commit, "Getting instructions from Rename stage.\n");
1311 
1312  // Read any renamed instructions and place them into the ROB.
1313  int insts_to_process = std::min((int)renameWidth, fromRename->size);
1314 
1315  for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
1316  DynInstPtr inst;
1317 
1318  inst = fromRename->insts[inst_num];
1319  ThreadID tid = inst->threadNumber;
1320 
1321  if (!inst->isSquashed() &&
1322  commitStatus[tid] != ROBSquashing &&
1323  commitStatus[tid] != TrapPending) {
1324  changedROBNumEntries[tid] = true;
1325 
1326  DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
1327  inst->pcState(), inst->seqNum, tid);
1328 
1329  rob->insertInst(inst);
1330 
1331  assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1332 
1333  youngestSeqNum[tid] = inst->seqNum;
1334  } else {
1335  DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
1336  "squashed, skipping.\n",
1337  inst->pcState(), inst->seqNum, tid);
1338  }
1339  }
1340 }
1341 
1342 template <class Impl>
1343 void
1345 {
1346  // Grab completed insts out of the IEW instruction queue, and mark
1347  // instructions completed within the ROB.
1348  for (int inst_num = 0; inst_num < fromIEW->size; ++inst_num) {
1349  assert(fromIEW->insts[inst_num]);
1350  if (!fromIEW->insts[inst_num]->isSquashed()) {
1351  DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
1352  "within ROB.\n",
1353  fromIEW->insts[inst_num]->threadNumber,
1354  fromIEW->insts[inst_num]->pcState(),
1355  fromIEW->insts[inst_num]->seqNum);
1356 
1357  // Mark the instruction as ready to commit.
1358  fromIEW->insts[inst_num]->setCanCommit();
1359  }
1360  }
1361 }
1362 
1363 template <class Impl>
1364 void
1366 {
1367  ThreadID tid = inst->threadNumber;
1368 
1369  if (!inst->isMicroop() || inst->isLastMicroop())
1370  instsCommitted[tid]++;
1371  opsCommitted[tid]++;
1372 
1373  // To match the old model, don't count nops and instruction
1374  // prefetches towards the total commit count.
1375  if (!inst->isNop() && !inst->isInstPrefetch()) {
1376  cpu->instDone(tid, inst);
1377  }
1378 
1379  //
1380  // Control Instructions
1381  //
1382  if (inst->isControl())
1383  statComBranches[tid]++;
1384 
1385  //
1386  // Memory references
1387  //
1388  if (inst->isMemRef()) {
1389  statComRefs[tid]++;
1390 
1391  if (inst->isLoad()) {
1392  statComLoads[tid]++;
1393  }
1394  }
1395 
1396  if (inst->isMemBarrier()) {
1397  statComMembars[tid]++;
1398  }
1399 
1400  // Integer Instruction
1401  if (inst->isInteger())
1402  statComInteger[tid]++;
1403 
1404  // Floating Point Instruction
1405  if (inst->isFloating())
1406  statComFloating[tid]++;
1407 
1408  // Function Calls
1409  if (inst->isCall())
1410  statComFunctionCalls[tid]++;
1411 
1412 }
1413 
1415 // //
1416 // SMT COMMIT POLICY MAINTAINED HERE //
1417 // //
1419 template <class Impl>
1420 ThreadID
1422 {
1423  if (numThreads > 1) {
1424  switch (commitPolicy) {
1425 
1426  case Aggressive:
1427  //If Policy is Aggressive, commit will call
1428  //this function multiple times per
1429  //cycle
1430  return oldestReady();
1431 
1432  case RoundRobin:
1433  return roundRobin();
1434 
1435  case OldestReady:
1436  return oldestReady();
1437 
1438  default:
1439  return InvalidThreadID;
1440  }
1441  } else {
1442  assert(!activeThreads->empty());
1443  ThreadID tid = activeThreads->front();
1444 
1445  if (commitStatus[tid] == Running ||
1446  commitStatus[tid] == Idle ||
1447  commitStatus[tid] == FetchTrapPending) {
1448  return tid;
1449  } else {
1450  return InvalidThreadID;
1451  }
1452  }
1453 }
1454 
1455 template<class Impl>
1456 ThreadID
1458 {
1459  list<ThreadID>::iterator pri_iter = priority_list.begin();
1460  list<ThreadID>::iterator end = priority_list.end();
1461 
1462  while (pri_iter != end) {
1463  ThreadID tid = *pri_iter;
1464 
1465  if (commitStatus[tid] == Running ||
1466  commitStatus[tid] == Idle ||
1467  commitStatus[tid] == FetchTrapPending) {
1468 
1469  if (rob->isHeadReady(tid)) {
1470  priority_list.erase(pri_iter);
1471  priority_list.push_back(tid);
1472 
1473  return tid;
1474  }
1475  }
1476 
1477  pri_iter++;
1478  }
1479 
1480  return InvalidThreadID;
1481 }
1482 
1483 template<class Impl>
1484 ThreadID
1486 {
1487  unsigned oldest = 0;
1488  bool first = true;
1489 
1490  list<ThreadID>::iterator threads = activeThreads->begin();
1491  list<ThreadID>::iterator end = activeThreads->end();
1492 
1493  while (threads != end) {
1494  ThreadID tid = *threads++;
1495 
1496  if (!rob->isEmpty(tid) &&
1497  (commitStatus[tid] == Running ||
1498  commitStatus[tid] == Idle ||
1499  commitStatus[tid] == FetchTrapPending)) {
1500 
1501  if (rob->isHeadReady(tid)) {
1502 
1503  DynInstPtr head_inst = rob->readHeadInst(tid);
1504 
1505  if (first) {
1506  oldest = tid;
1507  first = false;
1508  } else if (head_inst->seqNum < oldest) {
1509  oldest = tid;
1510  }
1511  }
1512  }
1513  }
1514 
1515  if (!first) {
1516  return oldest;
1517  } else {
1518  return InvalidThreadID;
1519  }
1520 }
1521 
1522 #endif//__CPU_O3_COMMIT_IMPL_HH__
count
Definition: misc.hh:704
const unsigned commitWidth
Commit width, in instructions.
Definition: commit.hh:427
#define DPRINTF(x,...)
Definition: trace.hh:212
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:51
void handleInterrupt()
Handles processing an interrupt.
Definition: commit_impl.hh:735
void regProbePoints()
Registers probes.
Definition: commit_impl.hh:172
const Cycles fetchToCommitDelay
Definition: commit.hh:419
decltype(nullptr) constexpr NoFault
Definition: types.hh:189
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
static bool available()
Definition: cp_annotate.hh:85
void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads])
Sets pointer to the commited state rename map.
Definition: commit_impl.hh:357
bool trapInFlight[Impl::MaxThreads]
Records if there is a trap currently in flight.
Definition: commit.hh:467
const std::string & name()
Definition: trace.cc:49
TheISA::PCState pc[Impl::MaxThreads]
The commit PC state of each thread.
Definition: commit.hh:458
Bitfield< 7 > i
Definition: miscregs.hh:1378
bool drainImminent
Is a drain imminent? Commit has found an instruction boundary while no interrupts were present or in ...
Definition: commit.hh:445
#define panic(...)
Definition: misc.hh:153
void squashFromTC(ThreadID tid)
Handles squashing due to an TC write.
Definition: commit_impl.hh:609
const Cycles renameToROBDelay
Rename to ROB delay.
Definition: commit.hh:417
CPUPol::RenameMap RenameMap
Definition: commit.hh:91
const Cycles commitToIEWDelay
Commit to IEW delay.
Definition: commit.hh:414
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:146
void squashFromSquashAfter(ThreadID tid)
Handles a squash from a squashAfter() request.
Definition: commit_impl.hh:626
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets pointer to list of active threads.
Definition: commit_impl.hh:350
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the main time buffer pointer, used for backwards communication.
Definition: commit_impl.hh:300
bool tcSquash[Impl::MaxThreads]
Records if a thread has to squash this cycle due to an XC write.
Definition: commit.hh:396
void updateStatus()
Updates the overall status of commit with the nextStatus, and tell the CPU if commit is active/inacti...
Definition: commit_impl.hh:473
bool isDrained() const
Has the stage drained?
Definition: commit_impl.hh:416
void getInsts()
Gets instructions from rename and inserts them into the ROB.
void setRenameQueue(TimeBuffer< RenameStruct > *rq_ptr)
Sets the pointer to the queue coming from rename.
Definition: commit_impl.hh:323
std::string name() const
Returns the name of the DefaultCommit.
Definition: commit_impl.hh:165
bool avoidQuiesceLiveLock
Have we had an interrupt pending and then seen it de-asserted because of a masking change...
Definition: commit.hh:489
DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
Construct a DefaultCommit with the given parameters.
Definition: commit_impl.hh:97
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void tick()
Ticks the commit stage, which tries to commit instructions.
Definition: commit_impl.hh:656
STL vector class.
Definition: stl.hh:40
ThreadID roundRobin()
Returns the thread ID to use based on a round robin policy.
void commitInsts()
Commits as many instructions as possible.
Definition: commit_impl.hh:969
DefaultCommit handles single threaded and SMT commit.
Definition: commit.hh:83
void setIEWStage(IEW *iew_stage)
Sets the pointer to the IEW stage.
Definition: commit_impl.hh:343
CPUPol::IEW IEW
Definition: commit.hh:100
void drainResume()
Resumes execution after draining.
Definition: commit_impl.hh:400
void propagateInterrupt()
Get fetch redirecting so we can handle an interrupt.
Definition: commit_impl.hh:789
void swAutoBegin(ThreadContext *tc, Addr next_pc)
Definition: cp_annotate.hh:90
void generateTrapEvent(ThreadID tid, Fault inst_fault)
Generates an event to schedule a squash due to a trap.
Definition: commit_impl.hh:529
const Cycles trapLatency
The latency to handle a trap.
Definition: commit.hh:450
Tick curTick()
The current simulated tick.
Definition: core.hh:47
void setFetchQueue(TimeBuffer< FetchStruct > *fq_ptr)
Definition: commit_impl.hh:313
void squashFromTrap(ThreadID tid)
Handles squashing due to a trap.
Definition: commit_impl.hh:591
const unsigned renameWidth
Rename width, in instructions.
Definition: commit.hh:424
#define DTRACE(x)
Definition: trace.hh:210
ThreadID oldestReady()
Returns the thread ID to use based on an oldest instruction policy.
static CPA * cpa()
Definition: cp_annotate.hh:84
Impl::O3CPU O3CPU
Definition: commit.hh:87
void setThreads(std::vector< Thread * > &threads)
Sets the list of threads.
Definition: commit_impl.hh:293
ThreadStatus commitStatus[Impl::MaxThreads]
Per-thread status.
Definition: commit.hh:150
virtual Addr nextInstAddr()=0
#define fatal(...)
Definition: misc.hh:163
void squashAll(ThreadID tid)
Squashes all in flight instructions.
Definition: commit_impl.hh:555
void generateTCEvent(ThreadID tid)
Records that commit needs to initiate a squash due to an external state update through the TC...
Definition: commit_impl.hh:545
O3CPU * cpu
Pointer to O3CPU.
Definition: commit.hh:377
uint64_t InstSeqNum
Definition: inst_seq.hh:40
void squashAfter(ThreadID tid, DynInstPtr &head_inst)
Handle squashing from instruction with SquashAfter set.
Definition: commit_impl.hh:644
void regStats()
Registers statistics.
Definition: commit_impl.hh:181
void deactivateThread(ThreadID tid)
Deschedules a thread from scheduling.
Definition: commit_impl.hh:460
void setROB(ROB *rob_ptr)
Sets pointer to the ROB.
Definition: commit_impl.hh:365
bool checkEmptyROB[Impl::MaxThreads]
Records if commit should check if the ROB is truly empty (see commit_impl.hh).
Definition: commit.hh:474
Fault interrupt
The interrupt fault.
Definition: commit.hh:453
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
void takeOverFrom()
Takes over from another CPU's thread.
Definition: commit_impl.hh:444
void advancePC(PCState &pc, const StaticInstPtr &inst)
Definition: utility.hh:108
const Cycles iewToCommitDelay
IEW to Commit delay.
Definition: commit.hh:411
bool changedROBEntries()
Returns if any of the threads have the number of ROB entries changed on this cycle.
Definition: commit_impl.hh:504
bool drainPending
Is a drain pending? Commit is looking for an instruction boundary while there are no pending interrup...
Definition: commit.hh:438
const FlagsType total
Print the total.
Definition: info.hh:49
CommitPolicy commitPolicy
Commit policy used in SMT mode.
Definition: commit.hh:152
const ThreadID InvalidThreadID
Definition: types.hh:172
cbk_int func interrupt
Definition: gpu_nomali.cc:94
void drain()
Initializes the draining of commit.
Definition: commit_impl.hh:393
size_t numROBFreeEntries(ThreadID tid)
Returns the number of free ROB entries for a specific thread.
Definition: commit_impl.hh:522
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:171
InstSeqNum lastCommitedSeqNum[Impl::MaxThreads]
The sequence number of the last commited instruction.
Definition: commit.hh:464
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: commit_impl.hh:408
std::list< ThreadID > priority_list
Priority List used for Commit Policy.
Definition: commit.hh:408
bool trapSquash[Impl::MaxThreads]
Records if a thread has to squash this cycle due to a trap.
Definition: commit.hh:393
void commit()
Handles any squashes that are sent from IEW, and adds instructions to the ROB and tries to commit ins...
Definition: commit_impl.hh:814
Definition: eventq.hh:185
const ThreadID numThreads
Number of Active Threads.
Definition: commit.hh:433
void updateComInstStats(DynInstPtr &inst)
Updates commit stats based on this instruction.
ThreadID getCommittingThread()
Gets the thread to commit, based on the SMT policy.
wire getWire(int idx)
Definition: timebuf.hh:232
void setIEWQueue(TimeBuffer< IEWStruct > *iq_ptr)
Sets the pointer to the queue coming from IEW.
Definition: commit_impl.hh:333
IntReg pc
Definition: remote_gdb.hh:91
bool committedStores[Impl::MaxThreads]
Records if there were any stores committed this cycle.
Definition: commit.hh:470
TrapEvent(DefaultCommit< Impl > *_commit, ThreadID _tid)
Definition: commit_impl.hh:74
DynInstPtr squashAfterInst[Impl::MaxThreads]
Instruction passed to squashAfter().
Definition: commit.hh:405
const char * description() const
Return a C string describing the event.
Definition: commit_impl.hh:91
Event class used to schedule a squash due to a trap (fault or interrupt) to happen on a specific cycl...
Definition: commit.hh:107
CommitStatus _nextStatus
Next commit status, to be set at the end of the cycle.
Definition: commit.hh:148
ROB class.
Definition: rob.hh:61
Impl::DynInstPtr DynInstPtr
Definition: commit.hh:88
const FlagsType dist
Print the distribution.
Definition: info.hh:55
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
bool commitHead(DynInstPtr &head_inst, unsigned inst_num)
Tries to commit the head ROB instruction passed in.
CommitStatus _status
Overall commit status.
Definition: commit.hh:146
bool canHandleInterrupts
True if last committed microop can be followed by an interrupt.
Definition: commit.hh:483
void startupStage()
Initializes stage by sending back the number of free entries.
Definition: commit_impl.hh:372
bool changedROBNumEntries[Impl::MaxThreads]
Records if the number of ROB entries has changed this cycle.
Definition: commit.hh:390
void markCompletedInsts()
Marks completed instructions using information sent from IEW.

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