2 * Copyright (c) 2006 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config/use_checker.hh"
33 #include "cpu/ozone/lw_back_end.hh"
34 #include "cpu/op_class.hh"
37 #include "cpu/checker/cpu.hh"
42 LWBackEnd<Impl>::generateTrapEvent(Tick latency)
44 DPRINTF(BE, "Generating trap event\n");
46 TrapEvent *trap = new TrapEvent(this);
48 trap->schedule(curTick + cpu->cycles(latency));
50 thread->trapPending = true;
55 LWBackEnd<Impl>::wakeDependents(DynInstPtr &inst, bool memory_deps)
57 assert(!inst->isSquashed());
58 std::vector<DynInstPtr> &dependents = memory_deps ? inst->getMemDeps() :
59 inst->getDependents();
60 int num_outputs = dependents.size();
62 DPRINTF(BE, "Waking instruction [sn:%lli] dependents in IQ\n", inst->seqNum);
64 for (int i = 0; i < num_outputs; i++) {
65 DynInstPtr dep_inst = dependents[i];
67 dep_inst->markSrcRegReady();
69 if (!dep_inst->isSquashed())
70 dep_inst->markMemInstReady(inst.get());
73 DPRINTF(BE, "Marking source reg ready [sn:%lli] in IQ\n", dep_inst->seqNum);
75 if (dep_inst->readyToIssue() && dep_inst->isInROB() &&
76 !dep_inst->isNonSpeculative() && !dep_inst->isStoreConditional() &&
77 dep_inst->memDepReady() && !dep_inst->isMemBarrier() &&
78 !dep_inst->isWriteBarrier()) {
79 DPRINTF(BE, "Adding instruction to exeList [sn:%lli]\n",
81 exeList.push(dep_inst);
82 if (dep_inst->iqItValid) {
83 DPRINTF(BE, "Removing instruction from waiting list\n");
84 waitingList.erase(dep_inst->iqIt);
86 dep_inst->iqItValid = false;
87 assert(waitingInsts >= 0);
89 if (dep_inst->isMemRef()) {
90 removeWaitingMemOp(dep_inst);
91 DPRINTF(BE, "Issued a waiting mem op [sn:%lli]\n",
101 LWBackEnd<Impl>::rescheduleMemInst(DynInstPtr &inst)
103 replayList.push_front(inst);
106 template <class Impl>
107 LWBackEnd<Impl>::TrapEvent::TrapEvent(LWBackEnd<Impl> *_be)
108 : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
110 this->setFlags(Event::AutoDelete);
113 template <class Impl>
115 LWBackEnd<Impl>::TrapEvent::process()
117 be->trapSquash = true;
120 template <class Impl>
122 LWBackEnd<Impl>::TrapEvent::description()
127 template <class Impl>
129 LWBackEnd<Impl>::replayMemInst(DynInstPtr &inst)
131 bool found_inst = false;
132 while (!replayList.empty()) {
133 exeList.push(replayList.front());
134 if (replayList.front() == inst) {
137 replayList.pop_front();
142 template <class Impl>
143 LWBackEnd<Impl>::LWBackEnd(Params *params)
144 : d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(params->backEndLatency, 0),
145 trapSquash(false), tcSquash(false),
146 latency(params->backEndLatency),
147 width(params->backEndWidth), lsqLimits(params->lsqLimits),
150 numROBEntries = params->numROBEntries;
152 maxOutstandingMemOps = params->maxOutstandingMemOps;
153 numWaitingMemOps = 0;
156 switchPending = false;
160 // Setup IQ and LSQ with their parameters here.
161 instsToDispatch = d2i.getWire(-1);
163 instsToExecute = i2e.getWire(-1);
165 dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width;
166 issueWidth = params->issueWidth ? params->issueWidth : width;
167 wbWidth = params->wbWidth ? params->wbWidth : width;
168 commitWidth = params->commitWidth ? params->commitWidth : width;
170 LSQ.init(params, params->LQEntries, params->SQEntries, 0);
172 dispatchStatus = Running;
173 commitStatus = Running;
176 template <class Impl>
178 LWBackEnd<Impl>::name() const
180 return cpu->name() + ".backend";
183 template <class Impl>
185 LWBackEnd<Impl>::regStats()
187 using namespace Stats;
191 .init(cpu->number_of_threads)
192 .name(name() + ".ROB:cap_events")
193 .desc("number of cycles where ROB cap was active")
198 .init(cpu->number_of_threads)
199 .name(name() + ".ROB:cap_inst")
200 .desc("number of instructions held up by ROB cap")
205 .init(cpu->number_of_threads)
206 .name(name() +".IQ:cap_events" )
207 .desc("number of cycles where IQ cap was active")
212 .init(cpu->number_of_threads)
213 .name(name() + ".IQ:cap_inst")
214 .desc("number of instructions held up by IQ cap")
219 .init(cpu->number_of_threads)
220 .name(name() + ".ISSUE:count")
221 .desc("number of insts issued")
226 .init(cpu->number_of_threads)
227 .name(name() + ".ISSUE:swp")
228 .desc("number of swp insts issued")
233 .init(cpu->number_of_threads)
234 .name(name() + ".ISSUE:nop")
235 .desc("number of nop insts issued")
240 .init(cpu->number_of_threads)
241 .name(name() + ".ISSUE:refs")
242 .desc("number of memory reference insts issued")
247 .init(cpu->number_of_threads)
248 .name(name() + ".ISSUE:loads")
249 .desc("number of load insts issued")
254 .init(cpu->number_of_threads)
255 .name(name() + ".ISSUE:branches")
256 .desc("Number of branches issued")
261 .init(cpu->number_of_threads)
262 .name(name() + ".ISSUE:op_count")
263 .desc("number of insts issued")
268 for (int i=0; i<Num_OpClasses; ++i) {
269 stringstream subname;
270 subname << opClassStrings[i] << "_delay";
271 issue_delay_dist.subname(i, subname.str());
278 .init(cpu->number_of_threads)
279 .name(name() + ".LSQ:forw_loads")
280 .desc("number of loads forwarded via LSQ")
285 .init(cpu->number_of_threads)
286 .name(name() + ".ISSUE:addr_loads")
287 .desc("number of invalid-address loads")
292 .init(cpu->number_of_threads)
293 .name(name() + ".ISSUE:addr_swpfs")
294 .desc("number of invalid-address SW prefetches")
299 .init(cpu->number_of_threads)
300 .name(name() + ".LSQ:blocked_loads")
301 .desc("number of ready loads not issued due to memory disambiguation")
306 .name(name() + ".ISSUE:lsq_invert")
307 .desc("Number of times LSQ instruction issued early")
311 .init(issueWidth + 1)
312 .name(name() + ".ISSUE:issued_per_cycle")
313 .desc("Number of insts issued each cycle")
314 .flags(total | pdf | dist)
318 .init(Num_OpClasses,0,99,2)
319 .name(name() + ".ISSUE:")
320 .desc("cycles from operands ready to issue")
325 .init(Num_OpClasses, 0, 99, 2)
326 .name(name() + ".IQ:residence:")
327 .desc("cycles from dispatch to issue")
328 .flags(total | pdf | cdf )
330 for (int i = 0; i < Num_OpClasses; ++i) {
331 queueResDist.subname(i, opClassStrings[i]);
335 .init(cpu->number_of_threads)
336 .name(name() + ".WB:count")
337 .desc("cumulative count of insts written-back")
342 .init(cpu->number_of_threads)
343 .name(name() + ".WB:producers")
344 .desc("num instructions producing a value")
349 .init(cpu->number_of_threads)
350 .name(name() + ".WB:consumers")
351 .desc("num instructions consuming a value")
356 .init(cpu->number_of_threads)
357 .name(name() + ".WB:penalized")
358 .desc("number of instrctions required to write to 'other' IQ")
364 .name(name() + ".WB:penalized_rate")
365 .desc ("fraction of instructions written-back that wrote to 'other' IQ")
369 wbPenalizedRate = wbPenalized / writebackCount;
372 .name(name() + ".WB:fanout")
373 .desc("average fanout of values written-back")
377 wbFanout = producerInst / consumerInst;
380 .name(name() + ".WB:rate")
381 .desc("insts written-back per cycle")
384 wbRate = writebackCount / cpu->numCycles;
387 .init(cpu->number_of_threads)
388 .name(name() + ".COM:count")
389 .desc("Number of instructions committed")
394 .init(cpu->number_of_threads)
395 .name(name() + ".COM:swp_count")
396 .desc("Number of s/w prefetches committed")
401 .init(cpu->number_of_threads)
402 .name(name() + ".COM:refs")
403 .desc("Number of memory references committed")
408 .init(cpu->number_of_threads)
409 .name(name() + ".COM:loads")
410 .desc("Number of loads committed")
415 .init(cpu->number_of_threads)
416 .name(name() + ".COM:membars")
417 .desc("Number of memory barriers committed")
422 .init(cpu->number_of_threads)
423 .name(name() + ".COM:branches")
424 .desc("Number of branches committed")
428 .init(0,commitWidth,1)
429 .name(name() + ".COM:committed_per_cycle")
430 .desc("Number of insts commited each cycle")
435 // Commit-Eligible instructions...
437 // -> The number of instructions eligible to commit in those
438 // cycles where we reached our commit BW limit (less the number
439 // actually committed)
441 // -> The average value is computed over ALL CYCLES... not just
442 // the BW limited cycles
444 // -> The standard deviation is computed only over cycles where
445 // we reached the BW limit
448 .init(cpu->number_of_threads)
449 .name(name() + ".COM:bw_limited")
450 .desc("number of insts not committed due to BW limits")
454 commitEligibleSamples
455 .name(name() + ".COM:bw_lim_events")
456 .desc("number cycles where commit BW limit reached")
460 .init(cpu->number_of_threads)
461 .name(name() + ".COM:squashed_insts")
462 .desc("Number of instructions removed from inst list")
466 .init(cpu->number_of_threads)
467 .name(name() + ".COM:rob_squashed_insts")
468 .desc("Number of instructions removed from inst list when they reached the head of the ROB")
472 .name(name() + ".ROB:full_count")
473 .desc("number of cycles where ROB was full")
477 .init(cpu->number_of_threads)
478 .name(name() + ".ROB:occupancy")
479 .desc(name() + ".ROB occupancy (cumulative)")
484 .name(name() + ".ROB:full_rate")
485 .desc("ROB full per cycle")
487 ROBFullRate = ROBFcount / cpu->numCycles;
490 .name(name() + ".ROB:occ_rate")
491 .desc("ROB occupancy rate")
494 ROBOccRate = ROBCount / cpu->numCycles;
497 .init(cpu->number_of_threads,0,numROBEntries,2)
498 .name(name() + ".ROB:occ_dist")
499 .desc("ROB Occupancy per cycle")
505 template <class Impl>
507 LWBackEnd<Impl>::setCPU(OzoneCPU *cpu_ptr)
511 checker = cpu->checker;
514 template <class Impl>
516 LWBackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
519 toIEW = comm->getWire(0);
520 fromCommit = comm->getWire(-1);
524 template <class Impl>
526 LWBackEnd<Impl>::checkInterrupts()
528 if (cpu->checkInterrupts &&
529 cpu->check_interrupts() &&
530 !cpu->inPalMode(thread->readPC()) &&
533 frontEnd->interruptPending = true;
534 if (robEmpty() && !LSQ.hasStoresToWB()) {
535 // Will need to squash all instructions currently in flight and have
536 // the interrupt handler restart at the last non-committed inst.
537 // Most of that can be handled through the trap() function. The
538 // processInterrupts() function really just checks for interrupts
539 // and then calls trap() if there is an interrupt present.
541 // Not sure which thread should be the one to interrupt. For now
542 // always do thread 0.
543 assert(!thread->inSyscall);
544 thread->inSyscall = true;
546 // CPU will handle implementation of the interrupt.
547 cpu->processInterrupts();
549 // Now squash or record that I need to squash this cycle.
550 commitStatus = TrapPending;
552 // Exit state update mode to avoid accidental updating.
553 thread->inSyscall = false;
555 // Generate trap squash event.
558 DPRINTF(BE, "Interrupt detected.\n");
560 DPRINTF(BE, "Interrupt must wait for ROB to drain.\n");
566 template <class Impl>
568 LWBackEnd<Impl>::handleFault(Fault &fault, Tick latency)
570 DPRINTF(BE, "Handling fault!\n");
572 assert(!thread->inSyscall);
574 thread->inSyscall = true;
576 // Consider holding onto the trap and waiting until the trap event
577 // happens for this to be executed.
578 fault->invoke(thread->getTC());
580 // Exit state update mode to avoid accidental updating.
581 thread->inSyscall = false;
583 commitStatus = TrapPending;
585 // Generate trap squash event.
586 generateTrapEvent(latency);
589 template <class Impl>
591 LWBackEnd<Impl>::tick()
593 DPRINTF(BE, "Ticking back end\n");
595 // Read in any done instruction information and update the IQ or LSQ.
598 if (switchPending && robEmpty() && !LSQ.hasStoresToWB()) {
599 cpu->signalSwitched();
603 readyInstsForCommit();
605 numInstsToWB.advance();
607 ROBCount[0]+= numInsts;
618 } else if (tcSquash) {
622 if (dispatchStatus != Blocked) {
625 checkDispatchStatus();
628 if (commitStatus != TrapPending) {
634 LSQ.writebackStores();
636 DPRINTF(BE, "Waiting insts: %i, mem ops: %i, ROB entries in use: %i, "
637 "LSQ loads: %i, LSQ stores: %i\n",
638 waitingInsts, numWaitingMemOps, numInsts,
639 LSQ.numLoads(), LSQ.numStores());
642 assert(numInsts == instList.size());
643 assert(waitingInsts == waitingList.size());
644 assert(numWaitingMemOps == waitingMemOps.size());
645 assert(!switchedOut);
649 template <class Impl>
651 LWBackEnd<Impl>::updateStructures()
653 if (fromCommit->doneSeqNum) {
654 LSQ.commitLoads(fromCommit->doneSeqNum);
655 LSQ.commitStores(fromCommit->doneSeqNum);
658 if (fromCommit->nonSpecSeqNum) {
659 if (fromCommit->uncached) {
660 // LSQ.executeLoad(fromCommit->lqIdx);
662 // IQ.scheduleNonSpec(
663 // fromCommit->nonSpecSeqNum);
668 template <class Impl>
670 LWBackEnd<Impl>::addToLSQ(DynInstPtr &inst)
672 // Do anything LSQ specific here?
676 template <class Impl>
678 LWBackEnd<Impl>::dispatchInsts()
680 DPRINTF(BE, "Trying to dispatch instructions.\n");
682 while (numInsts < numROBEntries &&
683 numWaitingMemOps < maxOutstandingMemOps) {
684 // Get instruction from front of time buffer
685 if (lsqLimits && LSQ.isFull()) {
689 DynInstPtr inst = frontEnd->getInst();
692 } else if (inst->isSquashed()) {
697 instList.push_front(inst);
701 DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n",
702 inst->seqNum, inst->readPC());
704 for (int i = 0; i < inst->numDestRegs(); ++i)
705 renameTable[inst->destRegIdx(i)] = inst;
707 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
709 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
710 "barrier [sn:%lli].\n",
711 inst->seqNum, memBarrier->seqNum);
712 memBarrier->addMemDependent(inst);
713 inst->addSrcMemInst(memBarrier);
716 inst->setCanCommit();
717 } else if (inst->readyToIssue() &&
718 !inst->isNonSpeculative() &&
719 !inst->isStoreConditional()) {
720 if (inst->isMemRef()) {
724 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
725 "barrier [sn:%lli].\n",
726 inst->seqNum, memBarrier->seqNum);
727 memBarrier->addMemDependent(inst);
728 inst->addSrcMemInst(memBarrier);
729 addWaitingMemOp(inst);
731 waitingList.push_front(inst);
732 inst->iqIt = waitingList.begin();
733 inst->iqItValid = true;
736 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
741 } else if (inst->isNop()) {
742 DPRINTF(BE, "Nop encountered [sn:%lli], skipping exeList.\n",
746 inst->setCanCommit();
749 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
755 if (inst->isNonSpeculative() || inst->isStoreConditional()) {
756 inst->setCanCommit();
757 DPRINTF(BE, "Adding non speculative instruction\n");
760 if (inst->isMemRef()) {
761 addWaitingMemOp(inst);
764 memBarrier->addMemDependent(inst);
765 inst->addSrcMemInst(memBarrier);
767 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
768 "barrier [sn:%lli].\n",
769 inst->seqNum, memBarrier->seqNum);
773 DPRINTF(BE, "Instruction [sn:%lli] not ready, addding to "
776 waitingList.push_front(inst);
777 inst->iqIt = waitingList.begin();
778 inst->iqItValid = true;
783 // Check if IQ or LSQ is full. If so we'll need to break and stop
784 // removing instructions. Also update the number of insts to remove
785 // from the queue. Check here if we don't care about exact stall
790 DPRINTF(BE, "IQ is full!\n");
792 } else if (LSQ.isFull()) {
793 DPRINTF(BE, "LSQ is full!\n");
795 } else if (isFull()) {
796 DPRINTF(BE, "ROB is full!\n");
808 template <class Impl>
810 LWBackEnd<Impl>::dispatchStall()
812 dispatchStatus = Blocked;
813 if (!cpu->decoupledFrontEnd) {
814 // Tell front end to stall here through a timebuffer, or just tell
819 template <class Impl>
821 LWBackEnd<Impl>::checkDispatchStatus()
823 DPRINTF(BE, "Checking dispatch status\n");
824 assert(dispatchStatus == Blocked);
825 if (!LSQ.isFull() && !isFull()) {
826 DPRINTF(BE, "Dispatch no longer blocked\n");
827 dispatchStatus = Running;
832 template <class Impl>
834 LWBackEnd<Impl>::executeInsts()
836 DPRINTF(BE, "Trying to execute instructions\n");
838 int num_executed = 0;
839 while (!exeList.empty() && num_executed < issueWidth) {
840 DynInstPtr inst = exeList.top();
842 DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n",
843 inst->seqNum, inst->readPC());
845 // Check if the instruction is squashed; if so then skip it
846 // and don't count it towards the FU usage.
847 if (inst->isSquashed()) {
848 DPRINTF(BE, "Execute: Instruction was squashed.\n");
850 // Not sure how to handle this plus the method of sending # of
851 // instructions to use. Probably will just have to count it
852 // towards the bandwidth usage, but not the FU usage.
855 // Consider this instruction executed so that commit can go
856 // ahead and retire the instruction.
859 // Not sure if I should set this here or just let commit try to
860 // commit any squashed instructions. I like the latter a bit more.
861 inst->setCanCommit();
863 // ++iewExecSquashedInsts;
869 Fault fault = NoFault;
871 // Execute instruction.
872 // Note that if the instruction faults, it will be handled
873 // at the commit stage.
874 if (inst->isMemRef() &&
875 (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
876 DPRINTF(BE, "Execute: Initiating access for memory "
879 if (inst->isLoad()) {
880 LSQ.executeLoad(inst);
881 } else if (inst->isStore()) {
882 Fault fault = LSQ.executeStore(inst);
884 if (!inst->isStoreConditional() && fault == NoFault) {
888 } else if (fault != NoFault) {
889 // If the instruction faulted, then we need to send it along to commit
890 // without the instruction completing.
891 // Send this instruction to commit, also make sure iew stage
892 // realizes there is activity.
898 panic("Unknown mem type!");
908 updateExeInstStats(inst);
915 if (inst->mispredicted()) {
916 squashDueToBranch(inst);
918 } else if (LSQ.violation()) {
919 // Get the DynInst that caused the violation. Note that this
920 // clears the violation signal.
922 violator = LSQ.getMemDepViolator();
924 DPRINTF(BE, "LDSTQ detected a violation. Violator PC: "
925 "%#x, inst PC: %#x. Addr is: %#x.\n",
926 violator->readPC(), inst->readPC(), inst->physEffAddr);
929 squashDueToMemViolation(inst);
933 issuedOps[0]+= num_executed;
934 nIssuedDist[num_executed]++;
939 LWBackEnd<Impl>::instToCommit(DynInstPtr &inst)
941 DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n",
942 inst->seqNum, inst->readPC());
944 if (!inst->isSquashed()) {
945 if (inst->isExecuted()) {
946 inst->setResultReady();
947 int dependents = wakeDependents(inst);
950 consumerInst[0]+= dependents;
955 writeback.push_back(inst);
962 template <class Impl>
964 LWBackEnd<Impl>::readyInstsForCommit()
966 for (int i = numInstsToWB[-latency];
967 !writeback.empty() && i;
970 DynInstPtr inst = writeback.front();
971 writeback.pop_front();
972 if (!inst->isSquashed()) {
973 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
974 inst->seqNum, inst->readPC());
976 inst->setCanCommit();
982 template <class Impl>
984 LWBackEnd<Impl>::writebackInsts()
986 int wb_width = wbWidth;
987 // Using this method I'm not quite sure how to prevent an
988 // instruction from waking its own dependents multiple times,
989 // without the guarantee that commit always has enough bandwidth
990 // to accept all instructions being written back. This guarantee
991 // might not be too unrealistic.
992 InstListIt wb_inst_it = writeback.begin();
993 InstListIt wb_end_it = writeback.end();
995 int consumer_insts = 0;
997 for (; inst_num < wb_width &&
998 wb_inst_it != wb_end_it; inst_num++) {
999 DynInstPtr inst = (*wb_inst_it);
1001 // Some instructions will be sent to commit without having
1002 // executed because they need commit to handle them.
1003 // E.g. Uncached loads have not actually executed when they
1004 // are first sent to commit. Instead commit must tell the LSQ
1005 // when it's ready to execute the uncached load.
1006 if (!inst->isSquashed()) {
1007 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
1008 inst->seqNum, inst->readPC());
1010 inst->setCanCommit();
1011 inst->setResultReady();
1013 if (inst->isExecuted()) {
1014 int dependents = wakeDependents(inst);
1017 consumer_insts+= dependents;
1022 writeback.erase(wb_inst_it++);
1024 LSQ.writebackStores();
1025 consumer_inst[0]+= consumer_insts;
1026 writeback_count[0]+= inst_num;
1029 template <class Impl>
1031 LWBackEnd<Impl>::commitInst(int inst_num)
1033 // Read instruction from the head of the ROB
1034 DynInstPtr inst = instList.back();
1036 // Make sure instruction is valid
1039 if (!inst->readyToCommit())
1042 DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n",
1043 inst->seqNum, inst->readPC());
1045 thread->setPC(inst->readPC());
1046 thread->setNextPC(inst->readNextPC());
1047 inst->setAtCommit();
1049 // If the instruction is not executed yet, then it is a non-speculative
1050 // or store inst. Signal backwards that it should be executed.
1051 if (!inst->isExecuted()) {
1052 if (inst->isNonSpeculative() ||
1053 (inst->isStoreConditional() && inst->getFault() == NoFault) ||
1054 inst->isMemBarrier() ||
1055 inst->isWriteBarrier()) {
1057 // Hack to make sure syscalls aren't executed until all stores
1058 // write back their data. This direct communication shouldn't
1059 // be used for anything other than this.
1060 if (inst_num > 0 || LSQ.hasStoresToWB())
1062 if ((inst->isMemBarrier() || inst->isWriteBarrier() ||
1063 inst->isQuiesce()) &&
1064 LSQ.hasStoresToWB())
1067 DPRINTF(BE, "Waiting for all stores to writeback.\n");
1071 DPRINTF(BE, "Encountered a store or non-speculative "
1072 "instruction at the head of the ROB, PC %#x.\n",
1075 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
1076 DPRINTF(BE, "Waking dependents on barrier [sn:%lli]\n",
1079 wakeDependents(inst, true);
1080 if (memBarrier == inst)
1082 inst->clearMemDependents();
1085 // Send back the non-speculative instruction's sequence number.
1086 if (inst->iqItValid) {
1087 DPRINTF(BE, "Removing instruction from waiting list\n");
1088 waitingList.erase(inst->iqIt);
1089 inst->iqItValid = false;
1091 assert(waitingInsts >= 0);
1092 if (inst->isStore())
1093 removeWaitingMemOp(inst);
1098 // Change the instruction so it won't try to commit again until
1100 inst->clearCanCommit();
1102 // ++commitNonSpecStalls;
1105 } else if (inst->isLoad()) {
1106 DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n",
1107 inst->seqNum, inst->readPC());
1109 // Send back the non-speculative instruction's sequence
1110 // number. Maybe just tell the lsq to re-execute the load.
1112 // Send back the non-speculative instruction's sequence number.
1113 if (inst->iqItValid) {
1114 DPRINTF(BE, "Removing instruction from waiting list\n");
1115 waitingList.erase(inst->iqIt);
1116 inst->iqItValid = false;
1118 assert(waitingInsts >= 0);
1119 removeWaitingMemOp(inst);
1121 replayMemInst(inst);
1123 inst->clearCanCommit();
1127 panic("Trying to commit un-executed instruction "
1128 "of unknown type!\n");
1132 // Not handled for now.
1133 assert(!inst->isThreadSync());
1134 assert(inst->memDepReady());
1135 // Stores will mark themselves as totally completed as they need
1136 // to wait to writeback to memory. @todo: Hack...attempt to fix
1137 // having the checker be forced to wait until a store completes in
1138 // order to check all of the instructions. If the store at the
1139 // head of the check list misses, but a later store hits, then
1140 // loads in the checker may see the younger store values instead
1141 // of the store they should see. Either the checker needs its own
1142 // memory (annoying to update), its own store buffer (how to tell
1143 // which value is correct?), or something else...
1144 if (!inst->isStore()) {
1145 inst->setCompleted();
1147 // Check if the instruction caused a fault. If so, trap.
1148 Fault inst_fault = inst->getFault();
1150 // Use checker prior to updating anything due to traps or PC
1154 checker->verify(inst);
1158 if (inst_fault != NoFault) {
1159 DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
1160 inst->seqNum, inst->readPC());
1162 // Instruction is completed as it has a fault.
1163 inst->setCompleted();
1165 if (LSQ.hasStoresToWB()) {
1166 DPRINTF(BE, "Stores still in flight, will wait until drained.\n");
1168 } else if (inst_num != 0) {
1169 DPRINTF(BE, "Will wait until instruction is head of commit group.\n");
1173 else if (checker && inst->isStore()) {
1174 checker->verify(inst);
1179 static_cast<TheISA::MachInst>(inst->staticInst->machInst));
1181 handleFault(inst_fault);
1187 for (int i = 0; i < inst->numDestRegs(); ++i) {
1188 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1189 (int)inst->destRegIdx(i), inst->seqNum);
1190 thread->renameTable[inst->destRegIdx(i)] = inst;
1195 if (thread->profile) {
1197 // (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
1198 // thread->profilePC = usermode ? 1 : inst->readPC();
1199 thread->profilePC = inst->readPC();
1200 ProfileNode *node = thread->profile->consume(thread->getTC(),
1204 thread->profileNode = node;
1208 if (inst->traceData) {
1209 inst->traceData->setFetchSeq(inst->seqNum);
1210 inst->traceData->setCPSeq(thread->numInst);
1211 inst->traceData->finalize();
1212 inst->traceData = NULL;
1216 panic("Should not commit any copy instructions!");
1218 inst->clearDependents();
1220 frontEnd->addFreeRegs(freed_regs);
1222 instList.pop_back();
1225 ++thread->funcExeInst;
1226 // Maybe move this to where the fault is handled; if the fault is
1227 // handled, don't try to set this myself as the fault will set it.
1228 // If not, then I set thread->PC = thread->nextPC and
1229 // thread->nextPC = thread->nextPC + 4.
1230 thread->setPC(thread->readNextPC());
1231 thread->setNextPC(thread->readNextPC() + sizeof(TheISA::MachInst));
1232 updateComInstStats(inst);
1234 // Write the done sequence number here.
1235 toIEW->doneSeqNum = inst->seqNum;
1236 lastCommitCycle = curTick;
1243 assert(!thread->inSyscall && !thread->trapPending);
1244 oldpc = thread->readPC();
1245 cpu->system->pcEventQueue.service(
1248 } while (oldpc != thread->readPC());
1250 DPRINTF(BE, "PC skip function event, stopping commit\n");
1258 template <class Impl>
1260 LWBackEnd<Impl>::commitInsts()
1262 // Not sure this should be a loop or not.
1264 while (!instList.empty() && inst_num < commitWidth) {
1265 if (instList.back()->isSquashed()) {
1266 instList.back()->clearDependents();
1267 ROBSquashedInsts[instList.back()->threadNumber]++;
1268 instList.pop_back();
1273 if (!commitInst(inst_num++)) {
1274 DPRINTF(BE, "Can't commit, Instruction [sn:%lli] PC "
1275 "%#x is head of ROB and not ready\n",
1276 instList.back()->seqNum, instList.back()->readPC());
1281 nCommittedDist.sample(inst_num);
1284 template <class Impl>
1286 LWBackEnd<Impl>::squash(const InstSeqNum &sn)
1291 InstListIt insts_end_it = waitingList.end();
1292 InstListIt insts_it = waitingList.begin();
1294 while (insts_it != insts_end_it && (*insts_it)->seqNum > sn)
1296 if ((*insts_it)->isSquashed()) {
1300 DPRINTF(BE, "Squashing instruction on waitingList PC %#x, [sn:%lli].\n",
1301 (*insts_it)->readPC(),
1302 (*insts_it)->seqNum);
1304 if ((*insts_it)->isMemRef()) {
1305 DPRINTF(BE, "Squashing a waiting mem op [sn:%lli]\n",
1306 (*insts_it)->seqNum);
1307 removeWaitingMemOp((*insts_it));
1310 waitingList.erase(insts_it++);
1313 assert(waitingInsts >= 0);
1315 insts_it = instList.begin();
1317 while (!instList.empty() && (*insts_it)->seqNum > sn)
1319 if ((*insts_it)->isSquashed()) {
1320 panic("Instruction should not be already squashed and on list!");
1324 DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n",
1325 (*insts_it)->readPC(),
1326 (*insts_it)->seqNum);
1328 // Mark the instruction as squashed, and ready to commit so that
1329 // it can drain out of the pipeline.
1330 (*insts_it)->setSquashed();
1332 (*insts_it)->setCanCommit();
1334 (*insts_it)->clearInROB();
1336 for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
1337 DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
1338 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1339 (int)(*insts_it)->destRegIdx(i), prev_dest->seqNum);
1340 renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
1344 (*insts_it)->clearDependents();
1346 squashedInsts[(*insts_it)->threadNumber]++;
1348 instList.erase(insts_it++);
1352 while (memBarrier && memBarrier->seqNum > sn) {
1353 DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously "
1354 "squashed)\n", memBarrier->seqNum);
1355 memBarrier->clearMemDependents();
1356 if (memBarrier->memDepReady()) {
1357 DPRINTF(BE, "No previous barrier\n");
1360 std::list<DynInstPtr> &srcs = memBarrier->getMemSrcs();
1361 memBarrier = srcs.front();
1363 assert(srcs.empty());
1364 DPRINTF(BE, "Previous barrier: [sn:%lli]\n",
1365 memBarrier->seqNum);
1369 insts_it = replayList.begin();
1370 insts_end_it = replayList.end();
1371 while (!replayList.empty() && insts_it != insts_end_it) {
1372 if ((*insts_it)->seqNum < sn) {
1376 assert((*insts_it)->isSquashed());
1378 replayList.erase(insts_it++);
1381 frontEnd->addFreeRegs(freed_regs);
1384 template <class Impl>
1386 LWBackEnd<Impl>::squashFromTC()
1388 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1389 squash(squashed_inst);
1390 frontEnd->squash(squashed_inst, thread->readPC(),
1392 frontEnd->interruptPending = false;
1394 thread->trapPending = false;
1395 thread->inSyscall = false;
1397 commitStatus = Running;
1400 template <class Impl>
1402 LWBackEnd<Impl>::squashFromTrap()
1404 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1405 squash(squashed_inst);
1406 frontEnd->squash(squashed_inst, thread->readPC(),
1408 frontEnd->interruptPending = false;
1410 thread->trapPending = false;
1411 thread->inSyscall = false;
1413 commitStatus = Running;
1416 template <class Impl>
1418 LWBackEnd<Impl>::squashDueToBranch(DynInstPtr &inst)
1420 // Update the branch predictor state I guess
1421 DPRINTF(BE, "Squashing due to branch [sn:%lli], will restart at PC %#x\n",
1422 inst->seqNum, inst->readNextPC());
1423 squash(inst->seqNum);
1424 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1425 true, inst->mispredicted());
1428 template <class Impl>
1430 LWBackEnd<Impl>::squashDueToMemViolation(DynInstPtr &inst)
1432 // Update the branch predictor state I guess
1433 DPRINTF(BE, "Squashing due to violation [sn:%lli], will restart at PC %#x\n",
1434 inst->seqNum, inst->readNextPC());
1435 squash(inst->seqNum);
1436 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1437 false, inst->mispredicted());
1440 template <class Impl>
1442 LWBackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst)
1444 DPRINTF(IEW, "Memory blocked, squashing load and younger insts, "
1445 "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum);
1447 squash(inst->seqNum - 1);
1448 frontEnd->squash(inst->seqNum - 1, inst->readPC());
1451 template <class Impl>
1453 LWBackEnd<Impl>::switchOut()
1455 switchPending = true;
1458 template <class Impl>
1460 LWBackEnd<Impl>::doSwitchOut()
1463 switchPending = false;
1464 // Need to get rid of all committed, non-speculative state and write it
1465 // to memory/TC. In this case this is stores that have committed and not
1466 // yet written back.
1468 assert(!LSQ.hasStoresToWB());
1470 for (int i = 0; i < numInstsToWB.getSize() + 1; ++i)
1471 numInstsToWB.advance();
1474 assert(waitingList.empty());
1475 assert(instList.empty());
1476 assert(replayList.empty());
1477 assert(writeback.empty());
1481 template <class Impl>
1483 LWBackEnd<Impl>::takeOverFrom(ThreadContext *old_tc)
1485 assert(!squashPending);
1492 numWaitingMemOps = 0;
1493 waitingMemOps.clear();
1495 switchedOut = false;
1496 dispatchStatus = Running;
1497 commitStatus = Running;
1498 LSQ.takeOverFrom(old_tc);
1501 template <class Impl>
1503 LWBackEnd<Impl>::updateExeInstStats(DynInstPtr &inst)
1505 int thread_number = inst->threadNumber;
1508 // Pick off the software prefetches
1511 if (inst->isDataPrefetch())
1512 exeSwp[thread_number]++;
1514 exeInst[thread_number]++;
1516 exeInst[thread_number]++;
1520 // Control operations
1522 if (inst->isControl())
1523 exeBranches[thread_number]++;
1526 // Memory operations
1528 if (inst->isMemRef()) {
1529 exeRefs[thread_number]++;
1532 exeLoads[thread_number]++;
1536 template <class Impl>
1538 LWBackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
1540 unsigned tid = inst->threadNumber;
1542 // keep an instruction count
1548 // Pick off the software prefetches
1551 if (inst->isDataPrefetch()) {
1561 // Control Instructions
1563 if (inst->isControl())
1564 statComBranches[tid]++;
1567 // Memory references
1569 if (inst->isMemRef()) {
1572 if (inst->isLoad()) {
1573 statComLoads[tid]++;
1577 if (inst->isMemBarrier()) {
1578 statComMembars[tid]++;
1582 template <class Impl>
1584 LWBackEnd<Impl>::dumpInsts()
1589 InstListIt inst_list_it = --(instList.end());
1591 cprintf("ExeList size: %i\n", exeList.size());
1593 cprintf("Inst list size: %i\n", instList.size());
1595 while (inst_list_it != instList.end())
1597 cprintf("Instruction:%i\n",
1599 if (!(*inst_list_it)->isSquashed()) {
1600 if (!(*inst_list_it)->isIssued()) {
1602 cprintf("Count:%i\n", valid_num);
1603 } else if ((*inst_list_it)->isMemRef() &&
1604 !(*inst_list_it)->memOpDone) {
1605 // Loads that have not been marked as executed still count
1606 // towards the total instructions.
1608 cprintf("Count:%i\n", valid_num);
1612 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1613 "Issued:%i\nSquashed:%i\n",
1614 (*inst_list_it)->readPC(),
1615 (*inst_list_it)->seqNum,
1616 (*inst_list_it)->threadNumber,
1617 (*inst_list_it)->isIssued(),
1618 (*inst_list_it)->isSquashed());
1620 if ((*inst_list_it)->isMemRef()) {
1621 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1630 inst_list_it = --(writeback.end());
1632 cprintf("Writeback list size: %i\n", writeback.size());
1634 while (inst_list_it != writeback.end())
1636 cprintf("Instruction:%i\n",
1638 if (!(*inst_list_it)->isSquashed()) {
1639 if (!(*inst_list_it)->isIssued()) {
1641 cprintf("Count:%i\n", valid_num);
1642 } else if ((*inst_list_it)->isMemRef() &&
1643 !(*inst_list_it)->memOpDone) {
1644 // Loads that have not been marked as executed still count
1645 // towards the total instructions.
1647 cprintf("Count:%i\n", valid_num);
1651 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1652 "Issued:%i\nSquashed:%i\n",
1653 (*inst_list_it)->readPC(),
1654 (*inst_list_it)->seqNum,
1655 (*inst_list_it)->threadNumber,
1656 (*inst_list_it)->isIssued(),
1657 (*inst_list_it)->isSquashed());
1659 if ((*inst_list_it)->isMemRef()) {
1660 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1669 cprintf("Waiting list size: %i\n", waitingList.size());
1671 inst_list_it = --(waitingList.end());
1673 while (inst_list_it != waitingList.end())
1675 cprintf("Instruction:%i\n",
1677 if (!(*inst_list_it)->isSquashed()) {
1678 if (!(*inst_list_it)->isIssued()) {
1680 cprintf("Count:%i\n", valid_num);
1681 } else if ((*inst_list_it)->isMemRef() &&
1682 !(*inst_list_it)->memOpDone) {
1683 // Loads that have not been marked as executed still count
1684 // towards the total instructions.
1686 cprintf("Count:%i\n", valid_num);
1690 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1691 "Issued:%i\nSquashed:%i\n",
1692 (*inst_list_it)->readPC(),
1693 (*inst_list_it)->seqNum,
1694 (*inst_list_it)->threadNumber,
1695 (*inst_list_it)->isIssued(),
1696 (*inst_list_it)->isSquashed());
1698 if ((*inst_list_it)->isMemRef()) {
1699 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1708 cprintf("waitingMemOps list size: %i\n", waitingMemOps.size());
1710 MemIt waiting_it = waitingMemOps.begin();
1712 while (waiting_it != waitingMemOps.end())
1714 cprintf("[sn:%lli] ", (*waiting_it));