2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2010-2014, 2017, 2020 ARM Limited
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.
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * All rights reserved.
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.
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.
41 #ifndef __CPU_O3_COMMIT_IMPL_HH__
42 #define __CPU_O3_COMMIT_IMPL_HH__
48 #include "arch/utility.hh"
49 #include "base/loader/symtab.hh"
50 #include "base/logging.hh"
51 #include "config/the_isa.hh"
52 #include "cpu/checker/cpu.hh"
53 #include "cpu/o3/commit.hh"
54 #include "cpu/o3/thread_state.hh"
55 #include "cpu/base.hh"
56 #include "cpu/exetrace.hh"
57 #include "cpu/timebuf.hh"
58 #include "debug/Activity.hh"
59 #include "debug/Commit.hh"
60 #include "debug/CommitRate.hh"
61 #include "debug/Drain.hh"
62 #include "debug/ExecFaulting.hh"
63 #include "debug/HtmCpu.hh"
64 #include "debug/O3PipeView.hh"
65 #include "params/DerivO3CPU.hh"
66 #include "sim/faults.hh"
67 #include "sim/full_system.hh"
73 DefaultCommit<Impl>::processTrapEvent(ThreadID tid)
75 // This will get reset by commit if it was switched out at the
76 // time of this event processing.
77 trapSquash[tid] = true;
81 DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
82 : commitPolicy(params->smtCommitPolicy),
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),
93 trapLatency(params->trapLatency),
94 canHandleInterrupts(true),
95 avoidQuiesceLiveLock(false),
98 if (commitWidth > Impl::MaxWidth)
99 fatal("commitWidth (%d) is larger than compiled limit (%d),\n"
100 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
101 commitWidth, static_cast<int>(Impl::MaxWidth));
104 _nextStatus = Inactive;
106 if (commitPolicy == CommitPolicy::RoundRobin) {
107 //Set-Up Priority List
108 for (ThreadID tid = 0; tid < numThreads; tid++) {
109 priority_list.push_back(tid);
113 for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
114 commitStatus[tid] = Idle;
115 changedROBNumEntries[tid] = false;
116 trapSquash[tid] = false;
117 tcSquash[tid] = false;
118 squashAfterInst[tid] = nullptr;
120 youngestSeqNum[tid] = 0;
121 lastCommitedSeqNum[tid] = 0;
122 trapInFlight[tid] = false;
123 committedStores[tid] = false;
124 checkEmptyROB[tid] = false;
125 renameMap[tid] = nullptr;
132 template <class Impl>
134 DefaultCommit<Impl>::name() const
136 return cpu->name() + ".commit";
139 template <class Impl>
141 DefaultCommit<Impl>::regProbePoints()
143 ppCommit = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Commit");
144 ppCommitStall = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "CommitStall");
145 ppSquash = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Squash");
148 template <class Impl>
149 DefaultCommit<Impl>::CommitStats::CommitStats(O3CPU *cpu,
150 DefaultCommit *commit)
151 : Stats::Group(cpu, "commit"),
152 ADD_STAT(commitSquashedInsts, "The number of squashed insts skipped by"
154 ADD_STAT(commitNonSpecStalls, "The number of times commit has been"
155 " forced to stall to communicate backwards"),
156 ADD_STAT(branchMispredicts, "The number of times a branch was"
158 ADD_STAT(numCommittedDist, "Number of insts commited each cycle"),
159 ADD_STAT(instsCommitted, "Number of instructions committed"),
160 ADD_STAT(opsCommitted, "Number of ops (including micro ops) committed"),
161 ADD_STAT(memRefs, "Number of memory references committed"),
162 ADD_STAT(loads, "Number of loads committed"),
163 ADD_STAT(amos, "Number of atomic instructions committed"),
164 ADD_STAT(membars, "Number of memory barriers committed"),
165 ADD_STAT(branches, "Number of branches committed"),
166 ADD_STAT(vector, "Number of committed Vector instructions."),
167 ADD_STAT(floating, "Number of committed floating point"
169 ADD_STAT(integer, "Number of committed integer instructions."),
170 ADD_STAT(functionCalls, "Number of function calls committed."),
171 ADD_STAT(committedInstType, "Class of committed instruction"),
172 ADD_STAT(commitEligibleSamples, "number cycles where commit BW limit"
175 using namespace Stats;
177 commitSquashedInsts.prereq(commitSquashedInsts);
178 commitNonSpecStalls.prereq(commitNonSpecStalls);
179 branchMispredicts.prereq(branchMispredicts);
182 .init(0,commit->commitWidth,1)
186 .init(cpu->numThreads)
190 .init(cpu->numThreads)
194 .init(cpu->numThreads)
198 .init(cpu->numThreads)
202 .init(cpu->numThreads)
206 .init(cpu->numThreads)
210 .init(cpu->numThreads)
214 .init(cpu->numThreads)
218 .init(cpu->numThreads)
222 .init(cpu->numThreads)
226 .init(commit->numThreads)
230 .init(commit->numThreads,Enums::Num_OpClass)
231 .flags(total | pdf | dist);
233 committedInstType.ysubnames(Enums::OpClassStrings);
236 template <class Impl>
238 DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
243 template <class Impl>
245 DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
249 // Setup wire to send information back to IEW.
250 toIEW = timeBuffer->getWire(0);
252 // Setup wire to read data from IEW (for the ROB).
253 robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
256 template <class Impl>
258 DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
262 // Setup wire to get instructions from rename (for the ROB).
263 fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
266 template <class Impl>
268 DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
270 renameQueue = rq_ptr;
272 // Setup wire to get instructions from rename (for the ROB).
273 fromRename = renameQueue->getWire(-renameToROBDelay);
276 template <class Impl>
278 DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
282 // Setup wire to get instructions from IEW.
283 fromIEW = iewQueue->getWire(-iewToCommitDelay);
286 template <class Impl>
288 DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
290 iewStage = iew_stage;
295 DefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
297 activeThreads = at_ptr;
300 template <class Impl>
302 DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
304 for (ThreadID tid = 0; tid < numThreads; tid++)
305 renameMap[tid] = &rm_ptr[tid];
308 template <class Impl>
310 DefaultCommit<Impl>::setROB(ROB *rob_ptr)
315 template <class Impl>
317 DefaultCommit<Impl>::startupStage()
319 rob->setActiveThreads(activeThreads);
322 // Broadcast the number of free entries.
323 for (ThreadID tid = 0; tid < numThreads; tid++) {
324 toIEW->commitInfo[tid].usedROB = true;
325 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
326 toIEW->commitInfo[tid].emptyROB = true;
329 // Commit must broadcast the number of free entries it has at the
330 // start of the simulation, so it starts as active.
331 cpu->activateStage(O3CPU::CommitIdx);
333 cpu->activityThisCycle();
336 template <class Impl>
338 DefaultCommit<Impl>::clearStates(ThreadID tid)
340 commitStatus[tid] = Idle;
341 changedROBNumEntries[tid] = false;
342 checkEmptyROB[tid] = false;
343 trapInFlight[tid] = false;
344 committedStores[tid] = false;
345 trapSquash[tid] = false;
346 tcSquash[tid] = false;
348 lastCommitedSeqNum[tid] = 0;
349 squashAfterInst[tid] = NULL;
352 template <class Impl>
354 DefaultCommit<Impl>::drain()
359 template <class Impl>
361 DefaultCommit<Impl>::drainResume()
363 drainPending = false;
364 drainImminent = false;
367 template <class Impl>
369 DefaultCommit<Impl>::drainSanityCheck() const
372 rob->drainSanityCheck();
374 // hardware transactional memory
375 // cannot drain partially through a transaction
376 for (ThreadID tid = 0; tid < numThreads; tid++) {
377 if (executingHtmTransaction(tid)) {
378 panic("cannot drain partially through a HTM transaction");
383 template <class Impl>
385 DefaultCommit<Impl>::isDrained() const
387 /* Make sure no one is executing microcode. There are two reasons
389 * - Hardware virtualized CPUs can't switch into the middle of a
390 * microcode sequence.
391 * - The current fetch implementation will most likely get very
392 * confused if it tries to start fetching an instruction that
393 * is executing in the middle of a ucode sequence that changes
394 * address mappings. This can happen on for example x86.
396 for (ThreadID tid = 0; tid < numThreads; tid++) {
397 if (pc[tid].microPC() != 0)
401 /* Make sure that all instructions have finished committing before
402 * declaring the system as drained. We want the pipeline to be
403 * completely empty when we declare the CPU to be drained. This
404 * makes debugging easier since CPU handover and restoring from a
405 * checkpoint with a different CPU should have the same timing.
407 return rob->isEmpty() &&
408 interrupt == NoFault;
411 template <class Impl>
413 DefaultCommit<Impl>::takeOverFrom()
416 _nextStatus = Inactive;
417 for (ThreadID tid = 0; tid < numThreads; tid++) {
418 commitStatus[tid] = Idle;
419 changedROBNumEntries[tid] = false;
420 trapSquash[tid] = false;
421 tcSquash[tid] = false;
422 squashAfterInst[tid] = NULL;
427 template <class Impl>
429 DefaultCommit<Impl>::deactivateThread(ThreadID tid)
431 list<ThreadID>::iterator thread_it = std::find(priority_list.begin(),
432 priority_list.end(), tid);
434 if (thread_it != priority_list.end()) {
435 priority_list.erase(thread_it);
439 template <class Impl>
441 DefaultCommit<Impl>::executingHtmTransaction(ThreadID tid) const
443 if (tid == InvalidThreadID)
446 return (htmStarts[tid] > htmStops[tid]);
449 template <class Impl>
451 DefaultCommit<Impl>::resetHtmStartsStops(ThreadID tid)
453 if (tid != InvalidThreadID)
461 template <class Impl>
463 DefaultCommit<Impl>::updateStatus()
465 // reset ROB changed variable
466 list<ThreadID>::iterator threads = activeThreads->begin();
467 list<ThreadID>::iterator end = activeThreads->end();
469 while (threads != end) {
470 ThreadID tid = *threads++;
472 changedROBNumEntries[tid] = false;
474 // Also check if any of the threads has a trap pending
475 if (commitStatus[tid] == TrapPending ||
476 commitStatus[tid] == FetchTrapPending) {
477 _nextStatus = Active;
481 if (_nextStatus == Inactive && _status == Active) {
482 DPRINTF(Activity, "Deactivating stage.\n");
483 cpu->deactivateStage(O3CPU::CommitIdx);
484 } else if (_nextStatus == Active && _status == Inactive) {
485 DPRINTF(Activity, "Activating stage.\n");
486 cpu->activateStage(O3CPU::CommitIdx);
489 _status = _nextStatus;
492 template <class Impl>
494 DefaultCommit<Impl>::changedROBEntries()
496 list<ThreadID>::iterator threads = activeThreads->begin();
497 list<ThreadID>::iterator end = activeThreads->end();
499 while (threads != end) {
500 ThreadID tid = *threads++;
502 if (changedROBNumEntries[tid]) {
510 template <class Impl>
512 DefaultCommit<Impl>::numROBFreeEntries(ThreadID tid)
514 return rob->numFreeEntries(tid);
517 template <class Impl>
519 DefaultCommit<Impl>::generateTrapEvent(ThreadID tid, Fault inst_fault)
521 DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
523 EventFunctionWrapper *trap = new EventFunctionWrapper(
524 [this, tid]{ processTrapEvent(tid); },
525 "Trap", true, Event::CPU_Tick_Pri);
527 Cycles latency = dynamic_pointer_cast<SyscallRetryFault>(inst_fault) ?
528 cpu->syscallRetryLatency : trapLatency;
530 // hardware transactional memory
531 if (inst_fault != nullptr &&
532 std::dynamic_pointer_cast<GenericHtmFailureFault>(inst_fault)) {
534 // latency = default abort/restore latency
535 // could also do some kind of exponential back off if desired
538 cpu->schedule(trap, cpu->clockEdge(latency));
539 trapInFlight[tid] = true;
540 thread[tid]->trapPending = true;
543 template <class Impl>
545 DefaultCommit<Impl>::generateTCEvent(ThreadID tid)
547 assert(!trapInFlight[tid]);
548 DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
550 tcSquash[tid] = true;
553 template <class Impl>
555 DefaultCommit<Impl>::squashAll(ThreadID tid)
557 // If we want to include the squashing instruction in the squash,
558 // then use one older sequence number.
559 // Hopefully this doesn't mess things up. Basically I want to squash
560 // all instructions of this thread.
561 InstSeqNum squashed_inst = rob->isEmpty(tid) ?
562 lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1;
564 // All younger instructions will be squashed. Set the sequence
565 // number as the youngest instruction in the ROB (0 in this case.
566 // Hopefully nothing breaks.)
567 youngestSeqNum[tid] = lastCommitedSeqNum[tid];
569 rob->squash(squashed_inst, tid);
570 changedROBNumEntries[tid] = true;
572 // Send back the sequence number of the squashed instruction.
573 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
575 // Send back the squash signal to tell stages that they should
577 toIEW->commitInfo[tid].squash = true;
579 // Send back the rob squashing signal so other stages know that
580 // the ROB is in the process of squashing.
581 toIEW->commitInfo[tid].robSquashing = true;
583 toIEW->commitInfo[tid].mispredictInst = NULL;
584 toIEW->commitInfo[tid].squashInst = NULL;
586 toIEW->commitInfo[tid].pc = pc[tid];
589 template <class Impl>
591 DefaultCommit<Impl>::squashFromTrap(ThreadID tid)
595 DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
597 thread[tid]->trapPending = false;
598 thread[tid]->noSquashFromTC = false;
599 trapInFlight[tid] = false;
601 trapSquash[tid] = false;
603 commitStatus[tid] = ROBSquashing;
604 cpu->activityThisCycle();
607 template <class Impl>
609 DefaultCommit<Impl>::squashFromTC(ThreadID tid)
613 DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
615 thread[tid]->noSquashFromTC = false;
616 assert(!thread[tid]->trapPending);
618 commitStatus[tid] = ROBSquashing;
619 cpu->activityThisCycle();
621 tcSquash[tid] = false;
624 template <class Impl>
626 DefaultCommit<Impl>::squashFromSquashAfter(ThreadID tid)
628 DPRINTF(Commit, "Squashing after squash after request, "
629 "restarting at PC %s\n", pc[tid]);
632 // Make sure to inform the fetch stage of which instruction caused
633 // the squash. It'll try to re-fetch an instruction executing in
634 // microcode unless this is set.
635 toIEW->commitInfo[tid].squashInst = squashAfterInst[tid];
636 squashAfterInst[tid] = NULL;
638 commitStatus[tid] = ROBSquashing;
639 cpu->activityThisCycle();
642 template <class Impl>
644 DefaultCommit<Impl>::squashAfter(ThreadID tid, const DynInstPtr &head_inst)
646 DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%llu]\n",
647 tid, head_inst->seqNum);
649 assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
650 commitStatus[tid] = SquashAfterPending;
651 squashAfterInst[tid] = head_inst;
654 template <class Impl>
656 DefaultCommit<Impl>::tick()
658 wroteToTimeBuffer = false;
659 _nextStatus = Inactive;
661 if (activeThreads->empty())
664 list<ThreadID>::iterator threads = activeThreads->begin();
665 list<ThreadID>::iterator end = activeThreads->end();
667 // Check if any of the threads are done squashing. Change the
668 // status if they are done.
669 while (threads != end) {
670 ThreadID tid = *threads++;
672 // Clear the bit saying if the thread has committed stores
674 committedStores[tid] = false;
676 if (commitStatus[tid] == ROBSquashing) {
678 if (rob->isDoneSquashing(tid)) {
679 commitStatus[tid] = Running;
681 DPRINTF(Commit,"[tid:%i] Still Squashing, cannot commit any"
682 " insts this cycle.\n", tid);
684 toIEW->commitInfo[tid].robSquashing = true;
685 wroteToTimeBuffer = true;
692 markCompletedInsts();
694 threads = activeThreads->begin();
696 while (threads != end) {
697 ThreadID tid = *threads++;
699 if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
700 // The ROB has more instructions it can commit. Its next status
702 _nextStatus = Active;
704 const DynInstPtr &inst M5_VAR_USED = rob->readHeadInst(tid);
706 DPRINTF(Commit,"[tid:%i] Instruction [sn:%llu] PC %s is head of"
707 " ROB and ready to commit\n",
708 tid, inst->seqNum, inst->pcState());
710 } else if (!rob->isEmpty(tid)) {
711 const DynInstPtr &inst = rob->readHeadInst(tid);
713 ppCommitStall->notify(inst);
715 DPRINTF(Commit,"[tid:%i] Can't commit, Instruction [sn:%llu] PC "
716 "%s is head of ROB and not ready\n",
717 tid, inst->seqNum, inst->pcState());
720 DPRINTF(Commit, "[tid:%i] ROB has %d insts & %d free entries.\n",
721 tid, rob->countInsts(tid), rob->numFreeEntries(tid));
725 if (wroteToTimeBuffer) {
726 DPRINTF(Activity, "Activity This Cycle.\n");
727 cpu->activityThisCycle();
733 template <class Impl>
735 DefaultCommit<Impl>::handleInterrupt()
737 // Verify that we still have an interrupt to handle
738 if (!cpu->checkInterrupts(0)) {
739 DPRINTF(Commit, "Pending interrupt is cleared by requestor before "
740 "it got handled. Restart fetching from the orig path.\n");
741 toIEW->commitInfo[0].clearInterrupt = true;
743 avoidQuiesceLiveLock = true;
747 // Wait until all in flight instructions are finished before enterring
749 if (canHandleInterrupts && cpu->instList.empty()) {
750 // Squash or record that I need to squash this cycle if
751 // an interrupt needed to be handled.
752 DPRINTF(Commit, "Interrupt detected.\n");
754 // Clear the interrupt now that it's going to be handled
755 toIEW->commitInfo[0].clearInterrupt = true;
757 assert(!thread[0]->noSquashFromTC);
758 thread[0]->noSquashFromTC = true;
761 cpu->checker->handlePendingInt();
764 // CPU will handle interrupt. Note that we ignore the local copy of
765 // interrupt. This is because the local copy may no longer be the
766 // interrupt that the interrupt controller thinks is being handled.
767 cpu->processInterrupts(cpu->getInterrupts());
769 thread[0]->noSquashFromTC = false;
771 commitStatus[0] = TrapPending;
775 // Generate trap squash event.
776 generateTrapEvent(0, interrupt);
778 avoidQuiesceLiveLock = false;
780 DPRINTF(Commit, "Interrupt pending: instruction is %sin "
781 "flight, ROB is %sempty\n",
782 canHandleInterrupts ? "not " : "",
783 cpu->instList.empty() ? "" : "not " );
787 template <class Impl>
789 DefaultCommit<Impl>::propagateInterrupt()
791 // Don't propagate intterupts if we are currently handling a trap or
792 // in draining and the last observable instruction has been committed.
793 if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
794 tcSquash[0] || drainImminent)
797 // Process interrupts if interrupts are enabled, not in PAL
798 // mode, and no other traps or external squashes are currently
800 // @todo: Allow other threads to handle interrupts.
802 // Get any interrupt that happened
803 interrupt = cpu->getInterrupts();
805 // Tell fetch that there is an interrupt pending. This
806 // will make fetch wait until it sees a non PAL-mode PC,
807 // at which point it stops fetching instructions.
808 if (interrupt != NoFault)
809 toIEW->commitInfo[0].interruptPending = true;
812 template <class Impl>
814 DefaultCommit<Impl>::commit()
817 // Check if we have a interrupt and get read to handle it
818 if (cpu->checkInterrupts(0))
819 propagateInterrupt();
822 ////////////////////////////////////
823 // Check for any possible squashes, handle them first
824 ////////////////////////////////////
825 list<ThreadID>::iterator threads = activeThreads->begin();
826 list<ThreadID>::iterator end = activeThreads->end();
828 int num_squashing_threads = 0;
830 while (threads != end) {
831 ThreadID tid = *threads++;
833 // Not sure which one takes priority. I think if we have
834 // both, that's a bad sign.
835 if (trapSquash[tid]) {
836 assert(!tcSquash[tid]);
839 // If the thread is trying to exit (i.e., an exit syscall was
840 // executed), this trapSquash was originated by the exit
841 // syscall earlier. In this case, schedule an exit event in
842 // the next cycle to fully terminate this thread
843 if (cpu->isThreadExiting(tid))
844 cpu->scheduleThreadExitEvent(tid);
845 } else if (tcSquash[tid]) {
846 assert(commitStatus[tid] != TrapPending);
848 } else if (commitStatus[tid] == SquashAfterPending) {
849 // A squash from the previous cycle of the commit stage (i.e.,
850 // commitInsts() called squashAfter) is pending. Squash the
852 squashFromSquashAfter(tid);
855 // Squashed sequence number must be older than youngest valid
856 // instruction in the ROB. This prevents squashes from younger
857 // instructions overriding squashes from older instructions.
858 if (fromIEW->squash[tid] &&
859 commitStatus[tid] != TrapPending &&
860 fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
862 if (fromIEW->mispredictInst[tid]) {
864 "[tid:%i] Squashing due to branch mispred "
865 "PC:%#x [sn:%llu]\n",
867 fromIEW->mispredictInst[tid]->instAddr(),
868 fromIEW->squashedSeqNum[tid]);
871 "[tid:%i] Squashing due to order violation [sn:%llu]\n",
872 tid, fromIEW->squashedSeqNum[tid]);
875 DPRINTF(Commit, "[tid:%i] Redirecting to PC %#x\n",
877 fromIEW->pc[tid].nextInstAddr());
879 commitStatus[tid] = ROBSquashing;
881 // If we want to include the squashing instruction in the squash,
882 // then use one older sequence number.
883 InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
885 if (fromIEW->includeSquashInst[tid]) {
889 // All younger instructions will be squashed. Set the sequence
890 // number as the youngest instruction in the ROB.
891 youngestSeqNum[tid] = squashed_inst;
893 rob->squash(squashed_inst, tid);
894 changedROBNumEntries[tid] = true;
896 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
898 toIEW->commitInfo[tid].squash = true;
900 // Send back the rob squashing signal so other stages know that
901 // the ROB is in the process of squashing.
902 toIEW->commitInfo[tid].robSquashing = true;
904 toIEW->commitInfo[tid].mispredictInst =
905 fromIEW->mispredictInst[tid];
906 toIEW->commitInfo[tid].branchTaken =
907 fromIEW->branchTaken[tid];
908 toIEW->commitInfo[tid].squashInst =
909 rob->findInst(tid, squashed_inst);
910 if (toIEW->commitInfo[tid].mispredictInst) {
911 if (toIEW->commitInfo[tid].mispredictInst->isUncondCtrl()) {
912 toIEW->commitInfo[tid].branchTaken = true;
914 ++stats.branchMispredicts;
917 toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
920 if (commitStatus[tid] == ROBSquashing) {
921 num_squashing_threads++;
925 // If commit is currently squashing, then it will have activity for the
926 // next cycle. Set its next status as active.
927 if (num_squashing_threads) {
928 _nextStatus = Active;
931 if (num_squashing_threads != numThreads) {
932 // If we're not currently squashing, then get instructions.
935 // Try to commit any instructions.
939 //Check for any activity
940 threads = activeThreads->begin();
942 while (threads != end) {
943 ThreadID tid = *threads++;
945 if (changedROBNumEntries[tid]) {
946 toIEW->commitInfo[tid].usedROB = true;
947 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
949 wroteToTimeBuffer = true;
950 changedROBNumEntries[tid] = false;
951 if (rob->isEmpty(tid))
952 checkEmptyROB[tid] = true;
955 // ROB is only considered "empty" for previous stages if: a)
956 // ROB is empty, b) there are no outstanding stores, c) IEW
957 // stage has received any information regarding stores that
959 // c) is checked by making sure to not consider the ROB empty
960 // on the same cycle as when stores have been committed.
961 // @todo: Make this handle multi-cycle communication between
963 if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
964 !iewStage->hasStoresToWB(tid) && !committedStores[tid]) {
965 checkEmptyROB[tid] = false;
966 toIEW->commitInfo[tid].usedROB = true;
967 toIEW->commitInfo[tid].emptyROB = true;
968 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
969 wroteToTimeBuffer = true;
975 template <class Impl>
977 DefaultCommit<Impl>::commitInsts()
979 ////////////////////////////////////
981 // Note that commit will be handled prior to putting new
982 // instructions in the ROB so that the ROB only tries to commit
983 // instructions it has in this current cycle, and not instructions
984 // it is writing in during this cycle. Can't commit and squash
985 // things at the same time...
986 ////////////////////////////////////
988 DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
990 unsigned num_committed = 0;
992 DynInstPtr head_inst;
994 // Commit as many instructions as possible until the commit bandwidth
995 // limit is reached, or it becomes impossible to commit any more.
996 while (num_committed < commitWidth) {
997 // hardware transactionally memory
998 // If executing within a transaction,
999 // need to handle interrupts specially
1001 ThreadID commit_thread = getCommittingThread();
1003 // Check for any interrupt that we've already squashed for
1004 // and start processing it.
1005 if (interrupt != NoFault) {
1006 // If inside a transaction, postpone interrupts
1007 if (executingHtmTransaction(commit_thread)) {
1008 cpu->clearInterrupts(0);
1009 toIEW->commitInfo[0].clearInterrupt = true;
1010 interrupt = NoFault;
1011 avoidQuiesceLiveLock = true;
1017 // ThreadID commit_thread = getCommittingThread();
1019 if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
1022 head_inst = rob->readHeadInst(commit_thread);
1024 ThreadID tid = head_inst->threadNumber;
1026 assert(tid == commit_thread);
1029 "Trying to commit head instruction, [tid:%i] [sn:%llu]\n",
1030 tid, head_inst->seqNum);
1032 // If the head instruction is squashed, it is ready to retire
1033 // (be removed from the ROB) at any time.
1034 if (head_inst->isSquashed()) {
1036 DPRINTF(Commit, "Retiring squashed instruction from "
1039 rob->retireHead(commit_thread);
1041 ++stats.commitSquashedInsts;
1042 // Notify potential listeners that this instruction is squashed
1043 ppSquash->notify(head_inst);
1045 // Record that the number of ROB entries has changed.
1046 changedROBNumEntries[tid] = true;
1048 pc[tid] = head_inst->pcState();
1050 // Increment the total number of non-speculative instructions
1052 // Hack for now: it really shouldn't happen until after the
1053 // commit is deemed to be successful, but this count is needed
1055 thread[tid]->funcExeInst++;
1057 // Try to commit the head instruction.
1058 bool commit_success = commitHead(head_inst, num_committed);
1060 if (commit_success) {
1062 stats.committedInstType[tid][head_inst->opClass()]++;
1063 ppCommit->notify(head_inst);
1065 // hardware transactional memory
1067 // update nesting depth
1068 if (head_inst->isHtmStart())
1072 if (head_inst->inHtmTransactionalState()) {
1073 assert(executingHtmTransaction(tid));
1075 assert(!executingHtmTransaction(tid));
1078 // update nesting depth
1079 if (head_inst->isHtmStop())
1082 changedROBNumEntries[tid] = true;
1084 // Set the doneSeqNum to the youngest committed instruction.
1085 toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
1088 canHandleInterrupts = !head_inst->isDelayedCommit();
1090 // at this point store conditionals should either have
1091 // been completed or predicated false
1092 assert(!head_inst->isStoreConditional() ||
1093 head_inst->isCompleted() ||
1094 !head_inst->readPredicate());
1096 // Updates misc. registers.
1097 head_inst->updateMiscRegs();
1099 // Check instruction execution if it successfully commits and
1100 // is not carrying a fault.
1102 cpu->checker->verify(head_inst);
1105 cpu->traceFunctions(pc[tid].instAddr());
1107 TheISA::advancePC(pc[tid], head_inst->staticInst);
1109 // Keep track of the last sequence number commited
1110 lastCommitedSeqNum[tid] = head_inst->seqNum;
1112 // If this is an instruction that doesn't play nicely with
1113 // others squash everything and restart fetch
1114 if (head_inst->isSquashAfter())
1115 squashAfter(tid, head_inst);
1118 if (pc[tid].microPC() == 0 && interrupt == NoFault &&
1119 !thread[tid]->trapPending) {
1120 // Last architectually committed instruction.
1121 // Squash the pipeline, stall fetch, and use
1122 // drainImminent to disable interrupts
1123 DPRINTF(Drain, "Draining: %i:%s\n", tid, pc[tid]);
1124 squashAfter(tid, head_inst);
1125 cpu->commitDrained(tid);
1126 drainImminent = true;
1130 bool onInstBoundary = !head_inst->isMicroop() ||
1131 head_inst->isLastMicroop() ||
1132 !head_inst->isDelayedCommit();
1134 if (onInstBoundary) {
1137 // Make sure we're not currently updating state while
1138 // handling PC events.
1139 assert(!thread[tid]->noSquashFromTC &&
1140 !thread[tid]->trapPending);
1142 oldpc = pc[tid].instAddr();
1143 thread[tid]->pcEventQueue.service(
1144 oldpc, thread[tid]->getTC());
1146 } while (oldpc != pc[tid].instAddr());
1149 "PC skip function event, stopping commit\n");
1154 // Check if an instruction just enabled interrupts and we've
1155 // previously had an interrupt pending that was not handled
1156 // because interrupts were subsequently disabled before the
1157 // pipeline reached a place to handle the interrupt. In that
1158 // case squash now to make sure the interrupt is handled.
1160 // If we don't do this, we might end up in a live lock situation
1161 if (!interrupt && avoidQuiesceLiveLock &&
1162 onInstBoundary && cpu->checkInterrupts(0))
1163 squashAfter(tid, head_inst);
1165 DPRINTF(Commit, "Unable to commit head instruction PC:%s "
1166 "[tid:%i] [sn:%llu].\n",
1167 head_inst->pcState(), tid ,head_inst->seqNum);
1173 DPRINTF(CommitRate, "%i\n", num_committed);
1174 stats.numCommittedDist.sample(num_committed);
1176 if (num_committed == commitWidth) {
1177 stats.commitEligibleSamples++;
1181 template <class Impl>
1183 DefaultCommit<Impl>::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
1187 ThreadID tid = head_inst->threadNumber;
1189 // If the instruction is not executed yet, then it will need extra
1190 // handling. Signal backwards that it should be executed.
1191 if (!head_inst->isExecuted()) {
1192 // Keep this number correct. We have not yet actually executed
1193 // and committed this instruction.
1194 thread[tid]->funcExeInst--;
1196 // Make sure we are only trying to commit un-executed instructions we
1197 // think are possible.
1198 assert(head_inst->isNonSpeculative() || head_inst->isStoreConditional()
1199 || head_inst->isMemBarrier() || head_inst->isWriteBarrier()
1200 || head_inst->isAtomic()
1201 || (head_inst->isLoad() && head_inst->strictlyOrdered()));
1204 "Encountered a barrier or non-speculative "
1205 "instruction [tid:%i] [sn:%llu] "
1206 "at the head of the ROB, PC %s.\n",
1207 tid, head_inst->seqNum, head_inst->pcState());
1209 if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1211 "[tid:%i] [sn:%llu] "
1212 "Waiting for all stores to writeback.\n",
1213 tid, head_inst->seqNum);
1217 toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1219 // Change the instruction so it won't try to commit again until
1221 head_inst->clearCanCommit();
1223 if (head_inst->isLoad() && head_inst->strictlyOrdered()) {
1224 DPRINTF(Commit, "[tid:%i] [sn:%llu] "
1225 "Strictly ordered load, PC %s.\n",
1226 tid, head_inst->seqNum, head_inst->pcState());
1227 toIEW->commitInfo[tid].strictlyOrdered = true;
1228 toIEW->commitInfo[tid].strictlyOrderedLoad = head_inst;
1230 ++stats.commitNonSpecStalls;
1236 if (head_inst->isThreadSync()) {
1237 // Not handled for now.
1238 panic("Thread sync instructions are not handled yet.\n");
1241 // Check if the instruction caused a fault. If so, trap.
1242 Fault inst_fault = head_inst->getFault();
1244 // hardware transactional memory
1245 // if a fault occurred within a HTM transaction
1246 // ensure that the transaction aborts
1247 if (inst_fault != NoFault && head_inst->inHtmTransactionalState()) {
1248 // There exists a generic HTM fault common to all ISAs
1249 if (!std::dynamic_pointer_cast<GenericHtmFailureFault>(inst_fault)) {
1250 DPRINTF(HtmCpu, "%s - fault (%s) encountered within transaction"
1251 " - converting to GenericHtmFailureFault\n",
1252 head_inst->staticInst->getName(), inst_fault->name());
1253 inst_fault = std::make_shared<GenericHtmFailureFault>(
1254 head_inst->getHtmTransactionUid(),
1255 HtmFailureFaultCause::EXCEPTION);
1257 // If this point is reached and the fault inherits from the HTM fault,
1258 // then there is no need to raise a new fault
1261 // Stores mark themselves as completed.
1262 if (!head_inst->isStore() && inst_fault == NoFault) {
1263 head_inst->setCompleted();
1266 if (inst_fault != NoFault) {
1267 DPRINTF(Commit, "Inst [tid:%i] [sn:%llu] PC %s has a fault\n",
1268 tid, head_inst->seqNum, head_inst->pcState());
1270 if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
1272 "[tid:%i] [sn:%llu] "
1273 "Stores outstanding, fault must wait.\n",
1274 tid, head_inst->seqNum);
1278 head_inst->setCompleted();
1280 // If instruction has faulted, let the checker execute it and
1281 // check if it sees the same fault and control flow.
1283 // Need to check the instruction before its fault is processed
1284 cpu->checker->verify(head_inst);
1287 assert(!thread[tid]->noSquashFromTC);
1289 // Mark that we're in state update mode so that the trap's
1290 // execution doesn't generate extra squashes.
1291 thread[tid]->noSquashFromTC = true;
1293 // Execute the trap. Although it's slightly unrealistic in
1294 // terms of timing (as it doesn't wait for the full timing of
1295 // the trap event to complete before updating state), it's
1296 // needed to update the state as soon as possible. This
1297 // prevents external agents from changing any specific state
1298 // that the trap need.
1299 cpu->trap(inst_fault, tid,
1300 head_inst->notAnInst() ?
1301 StaticInst::nullStaticInstPtr :
1302 head_inst->staticInst);
1304 // Exit state update mode to avoid accidental updating.
1305 thread[tid]->noSquashFromTC = false;
1307 commitStatus[tid] = TrapPending;
1310 "[tid:%i] [sn:%llu] Committing instruction with fault\n",
1311 tid, head_inst->seqNum);
1312 if (head_inst->traceData) {
1313 // We ignore ReExecution "faults" here as they are not real
1314 // (architectural) faults but signal flush/replays.
1315 if (DTRACE(ExecFaulting)
1316 && dynamic_cast<ReExec*>(inst_fault.get()) == nullptr) {
1318 head_inst->traceData->setFaulting(true);
1319 head_inst->traceData->setFetchSeq(head_inst->seqNum);
1320 head_inst->traceData->setCPSeq(thread[tid]->numOp);
1321 head_inst->traceData->dump();
1323 delete head_inst->traceData;
1324 head_inst->traceData = NULL;
1327 // Generate trap squash event.
1328 generateTrapEvent(tid, inst_fault);
1332 updateComInstStats(head_inst);
1335 "[tid:%i] [sn:%llu] Committing instruction with PC %s\n",
1336 tid, head_inst->seqNum, head_inst->pcState());
1337 if (head_inst->traceData) {
1338 head_inst->traceData->setFetchSeq(head_inst->seqNum);
1339 head_inst->traceData->setCPSeq(thread[tid]->numOp);
1340 head_inst->traceData->dump();
1341 delete head_inst->traceData;
1342 head_inst->traceData = NULL;
1344 if (head_inst->isReturn()) {
1346 "[tid:%i] [sn:%llu] Return Instruction Committed PC %s \n",
1347 tid, head_inst->seqNum, head_inst->pcState());
1350 // Update the commit rename map
1351 for (int i = 0; i < head_inst->numDestRegs(); i++) {
1352 renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),
1353 head_inst->renamedDestRegIdx(i));
1356 // hardware transactional memory
1357 // the HTM UID is purely for correctness and debugging purposes
1358 if (head_inst->isHtmStart())
1359 iewStage->setLastRetiredHtmUid(tid, head_inst->getHtmTransactionUid());
1361 // Finally clear the head ROB entry.
1362 rob->retireHead(tid);
1365 if (DTRACE(O3PipeView)) {
1366 head_inst->commitTick = curTick() - head_inst->fetchTick;
1370 // If this was a store, record it for this cycle.
1371 if (head_inst->isStore() || head_inst->isAtomic())
1372 committedStores[tid] = true;
1374 // Return true to indicate that we have committed an instruction.
1378 template <class Impl>
1380 DefaultCommit<Impl>::getInsts()
1382 DPRINTF(Commit, "Getting instructions from Rename stage.\n");
1384 // Read any renamed instructions and place them into the ROB.
1385 int insts_to_process = std::min((int)renameWidth, fromRename->size);
1387 for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
1388 const DynInstPtr &inst = fromRename->insts[inst_num];
1389 ThreadID tid = inst->threadNumber;
1391 if (!inst->isSquashed() &&
1392 commitStatus[tid] != ROBSquashing &&
1393 commitStatus[tid] != TrapPending) {
1394 changedROBNumEntries[tid] = true;
1396 DPRINTF(Commit, "[tid:%i] [sn:%llu] Inserting PC %s into ROB.\n",
1397 inst->seqNum, tid, inst->pcState());
1399 rob->insertInst(inst);
1401 assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1403 youngestSeqNum[tid] = inst->seqNum;
1405 DPRINTF(Commit, "[tid:%i] [sn:%llu] "
1406 "Instruction PC %s was squashed, skipping.\n",
1407 inst->seqNum, tid, inst->pcState());
1412 template <class Impl>
1414 DefaultCommit<Impl>::markCompletedInsts()
1416 // Grab completed insts out of the IEW instruction queue, and mark
1417 // instructions completed within the ROB.
1418 for (int inst_num = 0; inst_num < fromIEW->size; ++inst_num) {
1419 assert(fromIEW->insts[inst_num]);
1420 if (!fromIEW->insts[inst_num]->isSquashed()) {
1421 DPRINTF(Commit, "[tid:%i] Marking PC %s, [sn:%llu] ready "
1423 fromIEW->insts[inst_num]->threadNumber,
1424 fromIEW->insts[inst_num]->pcState(),
1425 fromIEW->insts[inst_num]->seqNum);
1427 // Mark the instruction as ready to commit.
1428 fromIEW->insts[inst_num]->setCanCommit();
1433 template <class Impl>
1435 DefaultCommit<Impl>::updateComInstStats(const DynInstPtr &inst)
1437 ThreadID tid = inst->threadNumber;
1439 if (!inst->isMicroop() || inst->isLastMicroop())
1440 stats.instsCommitted[tid]++;
1441 stats.opsCommitted[tid]++;
1443 // To match the old model, don't count nops and instruction
1444 // prefetches towards the total commit count.
1445 if (!inst->isNop() && !inst->isInstPrefetch()) {
1446 cpu->instDone(tid, inst);
1450 // Control Instructions
1452 if (inst->isControl())
1453 stats.branches[tid]++;
1456 // Memory references
1458 if (inst->isMemRef()) {
1459 stats.memRefs[tid]++;
1461 if (inst->isLoad()) {
1465 if (inst->isAtomic()) {
1470 if (inst->isMemBarrier()) {
1471 stats.membars[tid]++;
1474 // Integer Instruction
1475 if (inst->isInteger())
1476 stats.integer[tid]++;
1478 // Floating Point Instruction
1479 if (inst->isFloating())
1480 stats.floating[tid]++;
1481 // Vector Instruction
1482 if (inst->isVector())
1483 stats.vector[tid]++;
1487 stats.functionCalls[tid]++;
1491 ////////////////////////////////////////
1493 // SMT COMMIT POLICY MAINTAINED HERE //
1495 ////////////////////////////////////////
1496 template <class Impl>
1498 DefaultCommit<Impl>::getCommittingThread()
1500 if (numThreads > 1) {
1501 switch (commitPolicy) {
1503 case CommitPolicy::Aggressive:
1504 //If Policy is Aggressive, commit will call
1505 //this function multiple times per
1507 return oldestReady();
1509 case CommitPolicy::RoundRobin:
1510 return roundRobin();
1512 case CommitPolicy::OldestReady:
1513 return oldestReady();
1516 return InvalidThreadID;
1519 assert(!activeThreads->empty());
1520 ThreadID tid = activeThreads->front();
1522 if (commitStatus[tid] == Running ||
1523 commitStatus[tid] == Idle ||
1524 commitStatus[tid] == FetchTrapPending) {
1527 return InvalidThreadID;
1532 template<class Impl>
1534 DefaultCommit<Impl>::roundRobin()
1536 list<ThreadID>::iterator pri_iter = priority_list.begin();
1537 list<ThreadID>::iterator end = priority_list.end();
1539 while (pri_iter != end) {
1540 ThreadID tid = *pri_iter;
1542 if (commitStatus[tid] == Running ||
1543 commitStatus[tid] == Idle ||
1544 commitStatus[tid] == FetchTrapPending) {
1546 if (rob->isHeadReady(tid)) {
1547 priority_list.erase(pri_iter);
1548 priority_list.push_back(tid);
1557 return InvalidThreadID;
1560 template<class Impl>
1562 DefaultCommit<Impl>::oldestReady()
1564 unsigned oldest = 0;
1567 list<ThreadID>::iterator threads = activeThreads->begin();
1568 list<ThreadID>::iterator end = activeThreads->end();
1570 while (threads != end) {
1571 ThreadID tid = *threads++;
1573 if (!rob->isEmpty(tid) &&
1574 (commitStatus[tid] == Running ||
1575 commitStatus[tid] == Idle ||
1576 commitStatus[tid] == FetchTrapPending)) {
1578 if (rob->isHeadReady(tid)) {
1580 const DynInstPtr &head_inst = rob->readHeadInst(tid);
1585 } else if (head_inst->seqNum < oldest) {
1595 return InvalidThreadID;
1599 #endif//__CPU_O3_COMMIT_IMPL_HH__