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

Generated on Thu May 28 2020 16:21:31 for gem5 by doxygen 1.8.13