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

Generated on Mon Jan 13 2025 04:28:31 for gem5 by doxygen 1.9.8