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

Generated on Fri Feb 28 2020 16:26:59 for gem5 by doxygen 1.8.13