75d065fd51781577992c7570f7d21b6307669aea
[gem5.git] / src / cpu / o3 / commit_impl.hh
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-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 #ifndef __CPU_O3_COMMIT_IMPL_HH__
42 #define __CPU_O3_COMMIT_IMPL_HH__
43
44 #include <algorithm>
45 #include <set>
46 #include <string>
47
48 #include "arch/utility.hh"
49 #include "base/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"
68
69 using namespace std;
70
71 template <class Impl>
72 void
73 DefaultCommit<Impl>::processTrapEvent(ThreadID tid)
74 {
75 // This will get reset by commit if it was switched out at the
76 // time of this event processing.
77 trapSquash[tid] = true;
78 }
79
80 template <class Impl>
81 DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
82 : commitPolicy(params->smtCommitPolicy),
83 cpu(_cpu),
84 iewToCommitDelay(params->iewToCommitDelay),
85 commitToIEWDelay(params->commitToIEWDelay),
86 renameToROBDelay(params->renameToROBDelay),
87 fetchToCommitDelay(params->commitToFetchDelay),
88 renameWidth(params->renameWidth),
89 commitWidth(params->commitWidth),
90 numThreads(params->numThreads),
91 drainPending(false),
92 drainImminent(false),
93 trapLatency(params->trapLatency),
94 canHandleInterrupts(true),
95 avoidQuiesceLiveLock(false),
96 stats(_cpu, this)
97 {
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));
102
103 _status = Active;
104 _nextStatus = Inactive;
105
106 if (commitPolicy == CommitPolicy::RoundRobin) {
107 //Set-Up Priority List
108 for (ThreadID tid = 0; tid < numThreads; tid++) {
109 priority_list.push_back(tid);
110 }
111 }
112
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;
119 pc[tid].set(0);
120 youngestSeqNum[tid] = 0;
121 lastCommitedSeqNum[tid] = 0;
122 trapInFlight[tid] = false;
123 committedStores[tid] = false;
124 checkEmptyROB[tid] = false;
125 renameMap[tid] = nullptr;
126 htmStarts[tid] = 0;
127 htmStops[tid] = 0;
128 }
129 interrupt = NoFault;
130 }
131
132 template <class Impl>
133 std::string
134 DefaultCommit<Impl>::name() const
135 {
136 return cpu->name() + ".commit";
137 }
138
139 template <class Impl>
140 void
141 DefaultCommit<Impl>::regProbePoints()
142 {
143 ppCommit = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Commit");
144 ppCommitStall = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "CommitStall");
145 ppSquash = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Squash");
146 }
147
148 template <class Impl>
149 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"
153 " commit"),
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"
157 " mispredicted"),
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"
168 " instructions."),
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"
173 " reached")
174 {
175 using namespace Stats;
176
177 commitSquashedInsts.prereq(commitSquashedInsts);
178 commitNonSpecStalls.prereq(commitNonSpecStalls);
179 branchMispredicts.prereq(branchMispredicts);
180
181 numCommittedDist
182 .init(0,commit->commitWidth,1)
183 .flags(Stats::pdf);
184
185 instsCommitted
186 .init(cpu->numThreads)
187 .flags(total);
188
189 opsCommitted
190 .init(cpu->numThreads)
191 .flags(total);
192
193 memRefs
194 .init(cpu->numThreads)
195 .flags(total);
196
197 loads
198 .init(cpu->numThreads)
199 .flags(total);
200
201 amos
202 .init(cpu->numThreads)
203 .flags(total);
204
205 membars
206 .init(cpu->numThreads)
207 .flags(total);
208
209 branches
210 .init(cpu->numThreads)
211 .flags(total);
212
213 vector
214 .init(cpu->numThreads)
215 .flags(total);
216
217 floating
218 .init(cpu->numThreads)
219 .flags(total);
220
221 integer
222 .init(cpu->numThreads)
223 .flags(total);
224
225 functionCalls
226 .init(commit->numThreads)
227 .flags(total);
228
229 committedInstType
230 .init(commit->numThreads,Enums::Num_OpClass)
231 .flags(total | pdf | dist);
232
233 committedInstType.ysubnames(Enums::OpClassStrings);
234 }
235
236 template <class Impl>
237 void
238 DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
239 {
240 thread = threads;
241 }
242
243 template <class Impl>
244 void
245 DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
246 {
247 timeBuffer = tb_ptr;
248
249 // Setup wire to send information back to IEW.
250 toIEW = timeBuffer->getWire(0);
251
252 // Setup wire to read data from IEW (for the ROB).
253 robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
254 }
255
256 template <class Impl>
257 void
258 DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
259 {
260 fetchQueue = fq_ptr;
261
262 // Setup wire to get instructions from rename (for the ROB).
263 fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
264 }
265
266 template <class Impl>
267 void
268 DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
269 {
270 renameQueue = rq_ptr;
271
272 // Setup wire to get instructions from rename (for the ROB).
273 fromRename = renameQueue->getWire(-renameToROBDelay);
274 }
275
276 template <class Impl>
277 void
278 DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
279 {
280 iewQueue = iq_ptr;
281
282 // Setup wire to get instructions from IEW.
283 fromIEW = iewQueue->getWire(-iewToCommitDelay);
284 }
285
286 template <class Impl>
287 void
288 DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
289 {
290 iewStage = iew_stage;
291 }
292
293 template<class Impl>
294 void
295 DefaultCommit<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
296 {
297 activeThreads = at_ptr;
298 }
299
300 template <class Impl>
301 void
302 DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
303 {
304 for (ThreadID tid = 0; tid < numThreads; tid++)
305 renameMap[tid] = &rm_ptr[tid];
306 }
307
308 template <class Impl>
309 void
310 DefaultCommit<Impl>::setROB(ROB *rob_ptr)
311 {
312 rob = rob_ptr;
313 }
314
315 template <class Impl>
316 void
317 DefaultCommit<Impl>::startupStage()
318 {
319 rob->setActiveThreads(activeThreads);
320 rob->resetEntries();
321
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;
327 }
328
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);
332
333 cpu->activityThisCycle();
334 }
335
336 template <class Impl>
337 void
338 DefaultCommit<Impl>::clearStates(ThreadID tid)
339 {
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;
347 pc[tid].set(0);
348 lastCommitedSeqNum[tid] = 0;
349 squashAfterInst[tid] = NULL;
350 }
351
352 template <class Impl>
353 void
354 DefaultCommit<Impl>::drain()
355 {
356 drainPending = true;
357 }
358
359 template <class Impl>
360 void
361 DefaultCommit<Impl>::drainResume()
362 {
363 drainPending = false;
364 drainImminent = false;
365 }
366
367 template <class Impl>
368 void
369 DefaultCommit<Impl>::drainSanityCheck() const
370 {
371 assert(isDrained());
372 rob->drainSanityCheck();
373
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");
379 }
380 }
381 }
382
383 template <class Impl>
384 bool
385 DefaultCommit<Impl>::isDrained() const
386 {
387 /* Make sure no one is executing microcode. There are two reasons
388 * for this:
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.
395 */
396 for (ThreadID tid = 0; tid < numThreads; tid++) {
397 if (pc[tid].microPC() != 0)
398 return false;
399 }
400
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.
406 */
407 return rob->isEmpty() &&
408 interrupt == NoFault;
409 }
410
411 template <class Impl>
412 void
413 DefaultCommit<Impl>::takeOverFrom()
414 {
415 _status = Active;
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;
423 }
424 rob->takeOverFrom();
425 }
426
427 template <class Impl>
428 void
429 DefaultCommit<Impl>::deactivateThread(ThreadID tid)
430 {
431 list<ThreadID>::iterator thread_it = std::find(priority_list.begin(),
432 priority_list.end(), tid);
433
434 if (thread_it != priority_list.end()) {
435 priority_list.erase(thread_it);
436 }
437 }
438
439 template <class Impl>
440 bool
441 DefaultCommit<Impl>::executingHtmTransaction(ThreadID tid) const
442 {
443 if (tid == InvalidThreadID)
444 return false;
445 else
446 return (htmStarts[tid] > htmStops[tid]);
447 }
448
449 template <class Impl>
450 void
451 DefaultCommit<Impl>::resetHtmStartsStops(ThreadID tid)
452 {
453 if (tid != InvalidThreadID)
454 {
455 htmStarts[tid] = 0;
456 htmStops[tid] = 0;
457 }
458 }
459
460
461 template <class Impl>
462 void
463 DefaultCommit<Impl>::updateStatus()
464 {
465 // reset ROB changed variable
466 list<ThreadID>::iterator threads = activeThreads->begin();
467 list<ThreadID>::iterator end = activeThreads->end();
468
469 while (threads != end) {
470 ThreadID tid = *threads++;
471
472 changedROBNumEntries[tid] = false;
473
474 // Also check if any of the threads has a trap pending
475 if (commitStatus[tid] == TrapPending ||
476 commitStatus[tid] == FetchTrapPending) {
477 _nextStatus = Active;
478 }
479 }
480
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);
487 }
488
489 _status = _nextStatus;
490 }
491
492 template <class Impl>
493 bool
494 DefaultCommit<Impl>::changedROBEntries()
495 {
496 list<ThreadID>::iterator threads = activeThreads->begin();
497 list<ThreadID>::iterator end = activeThreads->end();
498
499 while (threads != end) {
500 ThreadID tid = *threads++;
501
502 if (changedROBNumEntries[tid]) {
503 return true;
504 }
505 }
506
507 return false;
508 }
509
510 template <class Impl>
511 size_t
512 DefaultCommit<Impl>::numROBFreeEntries(ThreadID tid)
513 {
514 return rob->numFreeEntries(tid);
515 }
516
517 template <class Impl>
518 void
519 DefaultCommit<Impl>::generateTrapEvent(ThreadID tid, Fault inst_fault)
520 {
521 DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
522
523 EventFunctionWrapper *trap = new EventFunctionWrapper(
524 [this, tid]{ processTrapEvent(tid); },
525 "Trap", true, Event::CPU_Tick_Pri);
526
527 Cycles latency = dynamic_pointer_cast<SyscallRetryFault>(inst_fault) ?
528 cpu->syscallRetryLatency : trapLatency;
529
530 // hardware transactional memory
531 if (inst_fault != nullptr &&
532 std::dynamic_pointer_cast<GenericHtmFailureFault>(inst_fault)) {
533 // TODO
534 // latency = default abort/restore latency
535 // could also do some kind of exponential back off if desired
536 }
537
538 cpu->schedule(trap, cpu->clockEdge(latency));
539 trapInFlight[tid] = true;
540 thread[tid]->trapPending = true;
541 }
542
543 template <class Impl>
544 void
545 DefaultCommit<Impl>::generateTCEvent(ThreadID tid)
546 {
547 assert(!trapInFlight[tid]);
548 DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
549
550 tcSquash[tid] = true;
551 }
552
553 template <class Impl>
554 void
555 DefaultCommit<Impl>::squashAll(ThreadID tid)
556 {
557 // If we want to include the squashing instruction in the squash,
558 // then use one older sequence number.
559 // Hopefully this doesn't mess things up. Basically I want to squash
560 // all instructions of this thread.
561 InstSeqNum squashed_inst = rob->isEmpty(tid) ?
562 lastCommitedSeqNum[tid] : rob->readHeadInst(tid)->seqNum - 1;
563
564 // All younger instructions will be squashed. Set the sequence
565 // number as the youngest instruction in the ROB (0 in this case.
566 // Hopefully nothing breaks.)
567 youngestSeqNum[tid] = lastCommitedSeqNum[tid];
568
569 rob->squash(squashed_inst, tid);
570 changedROBNumEntries[tid] = true;
571
572 // Send back the sequence number of the squashed instruction.
573 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
574
575 // Send back the squash signal to tell stages that they should
576 // squash.
577 toIEW->commitInfo[tid].squash = true;
578
579 // Send back the rob squashing signal so other stages know that
580 // the ROB is in the process of squashing.
581 toIEW->commitInfo[tid].robSquashing = true;
582
583 toIEW->commitInfo[tid].mispredictInst = NULL;
584 toIEW->commitInfo[tid].squashInst = NULL;
585
586 toIEW->commitInfo[tid].pc = pc[tid];
587 }
588
589 template <class Impl>
590 void
591 DefaultCommit<Impl>::squashFromTrap(ThreadID tid)
592 {
593 squashAll(tid);
594
595 DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
596
597 thread[tid]->trapPending = false;
598 thread[tid]->noSquashFromTC = false;
599 trapInFlight[tid] = false;
600
601 trapSquash[tid] = false;
602
603 commitStatus[tid] = ROBSquashing;
604 cpu->activityThisCycle();
605 }
606
607 template <class Impl>
608 void
609 DefaultCommit<Impl>::squashFromTC(ThreadID tid)
610 {
611 squashAll(tid);
612
613 DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
614
615 thread[tid]->noSquashFromTC = false;
616 assert(!thread[tid]->trapPending);
617
618 commitStatus[tid] = ROBSquashing;
619 cpu->activityThisCycle();
620
621 tcSquash[tid] = false;
622 }
623
624 template <class Impl>
625 void
626 DefaultCommit<Impl>::squashFromSquashAfter(ThreadID tid)
627 {
628 DPRINTF(Commit, "Squashing after squash after request, "
629 "restarting at PC %s\n", pc[tid]);
630
631 squashAll(tid);
632 // Make sure to inform the fetch stage of which instruction caused
633 // the squash. It'll try to re-fetch an instruction executing in
634 // microcode unless this is set.
635 toIEW->commitInfo[tid].squashInst = squashAfterInst[tid];
636 squashAfterInst[tid] = NULL;
637
638 commitStatus[tid] = ROBSquashing;
639 cpu->activityThisCycle();
640 }
641
642 template <class Impl>
643 void
644 DefaultCommit<Impl>::squashAfter(ThreadID tid, const DynInstPtr &head_inst)
645 {
646 DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%llu]\n",
647 tid, head_inst->seqNum);
648
649 assert(!squashAfterInst[tid] || squashAfterInst[tid] == head_inst);
650 commitStatus[tid] = SquashAfterPending;
651 squashAfterInst[tid] = head_inst;
652 }
653
654 template <class Impl>
655 void
656 DefaultCommit<Impl>::tick()
657 {
658 wroteToTimeBuffer = false;
659 _nextStatus = Inactive;
660
661 if (activeThreads->empty())
662 return;
663
664 list<ThreadID>::iterator threads = activeThreads->begin();
665 list<ThreadID>::iterator end = activeThreads->end();
666
667 // Check if any of the threads are done squashing. Change the
668 // status if they are done.
669 while (threads != end) {
670 ThreadID tid = *threads++;
671
672 // Clear the bit saying if the thread has committed stores
673 // this cycle.
674 committedStores[tid] = false;
675
676 if (commitStatus[tid] == ROBSquashing) {
677
678 if (rob->isDoneSquashing(tid)) {
679 commitStatus[tid] = Running;
680 } else {
681 DPRINTF(Commit,"[tid:%i] Still Squashing, cannot commit any"
682 " insts this cycle.\n", tid);
683 rob->doSquash(tid);
684 toIEW->commitInfo[tid].robSquashing = true;
685 wroteToTimeBuffer = true;
686 }
687 }
688 }
689
690 commit();
691
692 markCompletedInsts();
693
694 threads = activeThreads->begin();
695
696 while (threads != end) {
697 ThreadID tid = *threads++;
698
699 if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
700 // The ROB has more instructions it can commit. Its next status
701 // will be active.
702 _nextStatus = Active;
703
704 const DynInstPtr &inst M5_VAR_USED = rob->readHeadInst(tid);
705
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());
709
710 } else if (!rob->isEmpty(tid)) {
711 const DynInstPtr &inst = rob->readHeadInst(tid);
712
713 ppCommitStall->notify(inst);
714
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());
718 }
719
720 DPRINTF(Commit, "[tid:%i] ROB has %d insts & %d free entries.\n",
721 tid, rob->countInsts(tid), rob->numFreeEntries(tid));
722 }
723
724
725 if (wroteToTimeBuffer) {
726 DPRINTF(Activity, "Activity This Cycle.\n");
727 cpu->activityThisCycle();
728 }
729
730 updateStatus();
731 }
732
733 template <class Impl>
734 void
735 DefaultCommit<Impl>::handleInterrupt()
736 {
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;
742 interrupt = NoFault;
743 avoidQuiesceLiveLock = true;
744 return;
745 }
746
747 // Wait until all in flight instructions are finished before enterring
748 // the interrupt.
749 if (canHandleInterrupts && cpu->instList.empty()) {
750 // Squash or record that I need to squash this cycle if
751 // an interrupt needed to be handled.
752 DPRINTF(Commit, "Interrupt detected.\n");
753
754 // Clear the interrupt now that it's going to be handled
755 toIEW->commitInfo[0].clearInterrupt = true;
756
757 assert(!thread[0]->noSquashFromTC);
758 thread[0]->noSquashFromTC = true;
759
760 if (cpu->checker) {
761 cpu->checker->handlePendingInt();
762 }
763
764 // CPU will handle interrupt. Note that we ignore the local copy of
765 // interrupt. This is because the local copy may no longer be the
766 // interrupt that the interrupt controller thinks is being handled.
767 cpu->processInterrupts(cpu->getInterrupts());
768
769 thread[0]->noSquashFromTC = false;
770
771 commitStatus[0] = TrapPending;
772
773 interrupt = NoFault;
774
775 // Generate trap squash event.
776 generateTrapEvent(0, interrupt);
777
778 avoidQuiesceLiveLock = false;
779 } else {
780 DPRINTF(Commit, "Interrupt pending: instruction is %sin "
781 "flight, ROB is %sempty\n",
782 canHandleInterrupts ? "not " : "",
783 cpu->instList.empty() ? "" : "not " );
784 }
785 }
786
787 template <class Impl>
788 void
789 DefaultCommit<Impl>::propagateInterrupt()
790 {
791 // Don't propagate intterupts if we are currently handling a trap or
792 // in draining and the last observable instruction has been committed.
793 if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
794 tcSquash[0] || drainImminent)
795 return;
796
797 // Process interrupts if interrupts are enabled, not in PAL
798 // mode, and no other traps or external squashes are currently
799 // pending.
800 // @todo: Allow other threads to handle interrupts.
801
802 // Get any interrupt that happened
803 interrupt = cpu->getInterrupts();
804
805 // Tell fetch that there is an interrupt pending. This
806 // will make fetch wait until it sees a non PAL-mode PC,
807 // at which point it stops fetching instructions.
808 if (interrupt != NoFault)
809 toIEW->commitInfo[0].interruptPending = true;
810 }
811
812 template <class Impl>
813 void
814 DefaultCommit<Impl>::commit()
815 {
816 if (FullSystem) {
817 // Check if we have a interrupt and get read to handle it
818 if (cpu->checkInterrupts(0))
819 propagateInterrupt();
820 }
821
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();
827
828 int num_squashing_threads = 0;
829
830 while (threads != end) {
831 ThreadID tid = *threads++;
832
833 // Not sure which one takes priority. I think if we have
834 // both, that's a bad sign.
835 if (trapSquash[tid]) {
836 assert(!tcSquash[tid]);
837 squashFromTrap(tid);
838
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);
847 squashFromTC(tid);
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
851 // thread now.
852 squashFromSquashAfter(tid);
853 }
854
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]) {
861
862 if (fromIEW->mispredictInst[tid]) {
863 DPRINTF(Commit,
864 "[tid:%i] Squashing due to branch mispred "
865 "PC:%#x [sn:%llu]\n",
866 tid,
867 fromIEW->mispredictInst[tid]->instAddr(),
868 fromIEW->squashedSeqNum[tid]);
869 } else {
870 DPRINTF(Commit,
871 "[tid:%i] Squashing due to order violation [sn:%llu]\n",
872 tid, fromIEW->squashedSeqNum[tid]);
873 }
874
875 DPRINTF(Commit, "[tid:%i] Redirecting to PC %#x\n",
876 tid,
877 fromIEW->pc[tid].nextInstAddr());
878
879 commitStatus[tid] = ROBSquashing;
880
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];
884
885 if (fromIEW->includeSquashInst[tid]) {
886 squashed_inst--;
887 }
888
889 // All younger instructions will be squashed. Set the sequence
890 // number as the youngest instruction in the ROB.
891 youngestSeqNum[tid] = squashed_inst;
892
893 rob->squash(squashed_inst, tid);
894 changedROBNumEntries[tid] = true;
895
896 toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
897
898 toIEW->commitInfo[tid].squash = true;
899
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;
903
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;
913 }
914 ++stats.branchMispredicts;
915 }
916
917 toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
918 }
919
920 if (commitStatus[tid] == ROBSquashing) {
921 num_squashing_threads++;
922 }
923 }
924
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;
929 }
930
931 if (num_squashing_threads != numThreads) {
932 // If we're not currently squashing, then get instructions.
933 getInsts();
934
935 // Try to commit any instructions.
936 commitInsts();
937 }
938
939 //Check for any activity
940 threads = activeThreads->begin();
941
942 while (threads != end) {
943 ThreadID tid = *threads++;
944
945 if (changedROBNumEntries[tid]) {
946 toIEW->commitInfo[tid].usedROB = true;
947 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
948
949 wroteToTimeBuffer = true;
950 changedROBNumEntries[tid] = false;
951 if (rob->isEmpty(tid))
952 checkEmptyROB[tid] = true;
953 }
954
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
958 // committed.
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
962 // commit and IEW.
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;
970 }
971
972 }
973 }
974
975 template <class Impl>
976 void
977 DefaultCommit<Impl>::commitInsts()
978 {
979 ////////////////////////////////////
980 // Handle commit
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 ////////////////////////////////////
987
988 DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
989
990 unsigned num_committed = 0;
991
992 DynInstPtr head_inst;
993
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
1000
1001 ThreadID commit_thread = getCommittingThread();
1002
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;
1012 } else {
1013 handleInterrupt();
1014 }
1015 }
1016
1017 // ThreadID commit_thread = getCommittingThread();
1018
1019 if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
1020 break;
1021
1022 head_inst = rob->readHeadInst(commit_thread);
1023
1024 ThreadID tid = head_inst->threadNumber;
1025
1026 assert(tid == commit_thread);
1027
1028 DPRINTF(Commit,
1029 "Trying to commit head instruction, [tid:%i] [sn:%llu]\n",
1030 tid, head_inst->seqNum);
1031
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()) {
1035
1036 DPRINTF(Commit, "Retiring squashed instruction from "
1037 "ROB.\n");
1038
1039 rob->retireHead(commit_thread);
1040
1041 ++stats.commitSquashedInsts;
1042 // Notify potential listeners that this instruction is squashed
1043 ppSquash->notify(head_inst);
1044
1045 // Record that the number of ROB entries has changed.
1046 changedROBNumEntries[tid] = true;
1047 } else {
1048 pc[tid] = head_inst->pcState();
1049
1050 // Increment the total number of non-speculative instructions
1051 // executed.
1052 // Hack for now: it really shouldn't happen until after the
1053 // commit is deemed to be successful, but this count is needed
1054 // for syscalls.
1055 thread[tid]->funcExeInst++;
1056
1057 // Try to commit the head instruction.
1058 bool commit_success = commitHead(head_inst, num_committed);
1059
1060 if (commit_success) {
1061 ++num_committed;
1062 stats.committedInstType[tid][head_inst->opClass()]++;
1063 ppCommit->notify(head_inst);
1064
1065 // hardware transactional memory
1066
1067 // update nesting depth
1068 if (head_inst->isHtmStart())
1069 htmStarts[tid]++;
1070
1071 // sanity check
1072 if (head_inst->inHtmTransactionalState()) {
1073 assert(executingHtmTransaction(tid));
1074 } else {
1075 assert(!executingHtmTransaction(tid));
1076 }
1077
1078 // update nesting depth
1079 if (head_inst->isHtmStop())
1080 htmStops[tid]++;
1081
1082 changedROBNumEntries[tid] = true;
1083
1084 // Set the doneSeqNum to the youngest committed instruction.
1085 toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
1086
1087 if (tid == 0)
1088 canHandleInterrupts = !head_inst->isDelayedCommit();
1089
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());
1095
1096 // Updates misc. registers.
1097 head_inst->updateMiscRegs();
1098
1099 // Check instruction execution if it successfully commits and
1100 // is not carrying a fault.
1101 if (cpu->checker) {
1102 cpu->checker->verify(head_inst);
1103 }
1104
1105 cpu->traceFunctions(pc[tid].instAddr());
1106
1107 TheISA::advancePC(pc[tid], head_inst->staticInst);
1108
1109 // Keep track of the last sequence number commited
1110 lastCommitedSeqNum[tid] = head_inst->seqNum;
1111
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);
1116
1117 if (drainPending) {
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;
1127 }
1128 }
1129
1130 bool onInstBoundary = !head_inst->isMicroop() ||
1131 head_inst->isLastMicroop() ||
1132 !head_inst->isDelayedCommit();
1133
1134 if (onInstBoundary) {
1135 int count = 0;
1136 Addr oldpc;
1137 // Make sure we're not currently updating state while
1138 // handling PC events.
1139 assert(!thread[tid]->noSquashFromTC &&
1140 !thread[tid]->trapPending);
1141 do {
1142 oldpc = pc[tid].instAddr();
1143 thread[tid]->pcEventQueue.service(
1144 oldpc, thread[tid]->getTC());
1145 count++;
1146 } while (oldpc != pc[tid].instAddr());
1147 if (count > 1) {
1148 DPRINTF(Commit,
1149 "PC skip function event, stopping commit\n");
1150 break;
1151 }
1152 }
1153
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.
1159 //
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);
1164 } else {
1165 DPRINTF(Commit, "Unable to commit head instruction PC:%s "
1166 "[tid:%i] [sn:%llu].\n",
1167 head_inst->pcState(), tid ,head_inst->seqNum);
1168 break;
1169 }
1170 }
1171 }
1172
1173 DPRINTF(CommitRate, "%i\n", num_committed);
1174 stats.numCommittedDist.sample(num_committed);
1175
1176 if (num_committed == commitWidth) {
1177 stats.commitEligibleSamples++;
1178 }
1179 }
1180
1181 template <class Impl>
1182 bool
1183 DefaultCommit<Impl>::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
1184 {
1185 assert(head_inst);
1186
1187 ThreadID tid = head_inst->threadNumber;
1188
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--;
1195
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()));
1202
1203 DPRINTF(Commit,
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());
1208
1209 if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
1210 DPRINTF(Commit,
1211 "[tid:%i] [sn:%llu] "
1212 "Waiting for all stores to writeback.\n",
1213 tid, head_inst->seqNum);
1214 return false;
1215 }
1216
1217 toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
1218
1219 // Change the instruction so it won't try to commit again until
1220 // it is executed.
1221 head_inst->clearCanCommit();
1222
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;
1229 } else {
1230 ++stats.commitNonSpecStalls;
1231 }
1232
1233 return false;
1234 }
1235
1236 if (head_inst->isThreadSync()) {
1237 // Not handled for now.
1238 panic("Thread sync instructions are not handled yet.\n");
1239 }
1240
1241 // Check if the instruction caused a fault. If so, trap.
1242 Fault inst_fault = head_inst->getFault();
1243
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);
1256 }
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
1259 }
1260
1261 // Stores mark themselves as completed.
1262 if (!head_inst->isStore() && inst_fault == NoFault) {
1263 head_inst->setCompleted();
1264 }
1265
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());
1269
1270 if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
1271 DPRINTF(Commit,
1272 "[tid:%i] [sn:%llu] "
1273 "Stores outstanding, fault must wait.\n",
1274 tid, head_inst->seqNum);
1275 return false;
1276 }
1277
1278 head_inst->setCompleted();
1279
1280 // If instruction has faulted, let the checker execute it and
1281 // check if it sees the same fault and control flow.
1282 if (cpu->checker) {
1283 // Need to check the instruction before its fault is processed
1284 cpu->checker->verify(head_inst);
1285 }
1286
1287 assert(!thread[tid]->noSquashFromTC);
1288
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;
1292
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);
1303
1304 // Exit state update mode to avoid accidental updating.
1305 thread[tid]->noSquashFromTC = false;
1306
1307 commitStatus[tid] = TrapPending;
1308
1309 DPRINTF(Commit,
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) {
1317
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();
1322 }
1323 delete head_inst->traceData;
1324 head_inst->traceData = NULL;
1325 }
1326
1327 // Generate trap squash event.
1328 generateTrapEvent(tid, inst_fault);
1329 return false;
1330 }
1331
1332 updateComInstStats(head_inst);
1333
1334 DPRINTF(Commit,
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;
1343 }
1344 if (head_inst->isReturn()) {
1345 DPRINTF(Commit,
1346 "[tid:%i] [sn:%llu] Return Instruction Committed PC %s \n",
1347 tid, head_inst->seqNum, head_inst->pcState());
1348 }
1349
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));
1354 }
1355
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());
1360
1361 // Finally clear the head ROB entry.
1362 rob->retireHead(tid);
1363
1364 #if TRACING_ON
1365 if (DTRACE(O3PipeView)) {
1366 head_inst->commitTick = curTick() - head_inst->fetchTick;
1367 }
1368 #endif
1369
1370 // If this was a store, record it for this cycle.
1371 if (head_inst->isStore() || head_inst->isAtomic())
1372 committedStores[tid] = true;
1373
1374 // Return true to indicate that we have committed an instruction.
1375 return true;
1376 }
1377
1378 template <class Impl>
1379 void
1380 DefaultCommit<Impl>::getInsts()
1381 {
1382 DPRINTF(Commit, "Getting instructions from Rename stage.\n");
1383
1384 // Read any renamed instructions and place them into the ROB.
1385 int insts_to_process = std::min((int)renameWidth, fromRename->size);
1386
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;
1390
1391 if (!inst->isSquashed() &&
1392 commitStatus[tid] != ROBSquashing &&
1393 commitStatus[tid] != TrapPending) {
1394 changedROBNumEntries[tid] = true;
1395
1396 DPRINTF(Commit, "[tid:%i] [sn:%llu] Inserting PC %s into ROB.\n",
1397 inst->seqNum, tid, inst->pcState());
1398
1399 rob->insertInst(inst);
1400
1401 assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
1402
1403 youngestSeqNum[tid] = inst->seqNum;
1404 } else {
1405 DPRINTF(Commit, "[tid:%i] [sn:%llu] "
1406 "Instruction PC %s was squashed, skipping.\n",
1407 inst->seqNum, tid, inst->pcState());
1408 }
1409 }
1410 }
1411
1412 template <class Impl>
1413 void
1414 DefaultCommit<Impl>::markCompletedInsts()
1415 {
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 "
1422 "within ROB.\n",
1423 fromIEW->insts[inst_num]->threadNumber,
1424 fromIEW->insts[inst_num]->pcState(),
1425 fromIEW->insts[inst_num]->seqNum);
1426
1427 // Mark the instruction as ready to commit.
1428 fromIEW->insts[inst_num]->setCanCommit();
1429 }
1430 }
1431 }
1432
1433 template <class Impl>
1434 void
1435 DefaultCommit<Impl>::updateComInstStats(const DynInstPtr &inst)
1436 {
1437 ThreadID tid = inst->threadNumber;
1438
1439 if (!inst->isMicroop() || inst->isLastMicroop())
1440 stats.instsCommitted[tid]++;
1441 stats.opsCommitted[tid]++;
1442
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);
1447 }
1448
1449 //
1450 // Control Instructions
1451 //
1452 if (inst->isControl())
1453 stats.branches[tid]++;
1454
1455 //
1456 // Memory references
1457 //
1458 if (inst->isMemRef()) {
1459 stats.memRefs[tid]++;
1460
1461 if (inst->isLoad()) {
1462 stats.loads[tid]++;
1463 }
1464
1465 if (inst->isAtomic()) {
1466 stats.amos[tid]++;
1467 }
1468 }
1469
1470 if (inst->isMemBarrier()) {
1471 stats.membars[tid]++;
1472 }
1473
1474 // Integer Instruction
1475 if (inst->isInteger())
1476 stats.integer[tid]++;
1477
1478 // Floating Point Instruction
1479 if (inst->isFloating())
1480 stats.floating[tid]++;
1481 // Vector Instruction
1482 if (inst->isVector())
1483 stats.vector[tid]++;
1484
1485 // Function Calls
1486 if (inst->isCall())
1487 stats.functionCalls[tid]++;
1488
1489 }
1490
1491 ////////////////////////////////////////
1492 // //
1493 // SMT COMMIT POLICY MAINTAINED HERE //
1494 // //
1495 ////////////////////////////////////////
1496 template <class Impl>
1497 ThreadID
1498 DefaultCommit<Impl>::getCommittingThread()
1499 {
1500 if (numThreads > 1) {
1501 switch (commitPolicy) {
1502
1503 case CommitPolicy::Aggressive:
1504 //If Policy is Aggressive, commit will call
1505 //this function multiple times per
1506 //cycle
1507 return oldestReady();
1508
1509 case CommitPolicy::RoundRobin:
1510 return roundRobin();
1511
1512 case CommitPolicy::OldestReady:
1513 return oldestReady();
1514
1515 default:
1516 return InvalidThreadID;
1517 }
1518 } else {
1519 assert(!activeThreads->empty());
1520 ThreadID tid = activeThreads->front();
1521
1522 if (commitStatus[tid] == Running ||
1523 commitStatus[tid] == Idle ||
1524 commitStatus[tid] == FetchTrapPending) {
1525 return tid;
1526 } else {
1527 return InvalidThreadID;
1528 }
1529 }
1530 }
1531
1532 template<class Impl>
1533 ThreadID
1534 DefaultCommit<Impl>::roundRobin()
1535 {
1536 list<ThreadID>::iterator pri_iter = priority_list.begin();
1537 list<ThreadID>::iterator end = priority_list.end();
1538
1539 while (pri_iter != end) {
1540 ThreadID tid = *pri_iter;
1541
1542 if (commitStatus[tid] == Running ||
1543 commitStatus[tid] == Idle ||
1544 commitStatus[tid] == FetchTrapPending) {
1545
1546 if (rob->isHeadReady(tid)) {
1547 priority_list.erase(pri_iter);
1548 priority_list.push_back(tid);
1549
1550 return tid;
1551 }
1552 }
1553
1554 pri_iter++;
1555 }
1556
1557 return InvalidThreadID;
1558 }
1559
1560 template<class Impl>
1561 ThreadID
1562 DefaultCommit<Impl>::oldestReady()
1563 {
1564 unsigned oldest = 0;
1565 bool first = true;
1566
1567 list<ThreadID>::iterator threads = activeThreads->begin();
1568 list<ThreadID>::iterator end = activeThreads->end();
1569
1570 while (threads != end) {
1571 ThreadID tid = *threads++;
1572
1573 if (!rob->isEmpty(tid) &&
1574 (commitStatus[tid] == Running ||
1575 commitStatus[tid] == Idle ||
1576 commitStatus[tid] == FetchTrapPending)) {
1577
1578 if (rob->isHeadReady(tid)) {
1579
1580 const DynInstPtr &head_inst = rob->readHeadInst(tid);
1581
1582 if (first) {
1583 oldest = tid;
1584 first = false;
1585 } else if (head_inst->seqNum < oldest) {
1586 oldest = tid;
1587 }
1588 }
1589 }
1590 }
1591
1592 if (!first) {
1593 return oldest;
1594 } else {
1595 return InvalidThreadID;
1596 }
1597 }
1598
1599 #endif//__CPU_O3_COMMIT_IMPL_HH__