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/the_isa.hh"
32 #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->ticks(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() const
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->numThreads)
192 .name(name() + ".ROB:cap_events")
193 .desc("number of cycles where ROB cap was active")
198 .init(cpu->numThreads)
199 .name(name() + ".ROB:cap_inst")
200 .desc("number of instructions held up by ROB cap")
205 .init(cpu->numThreads)
206 .name(name() +".IQ:cap_events" )
207 .desc("number of cycles where IQ cap was active")
212 .init(cpu->numThreads)
213 .name(name() + ".IQ:cap_inst")
214 .desc("number of instructions held up by IQ cap")
219 .init(cpu->numThreads)
220 .name(name() + ".ISSUE:count")
221 .desc("number of insts issued")
226 .init(cpu->numThreads)
227 .name(name() + ".ISSUE:swp")
228 .desc("number of swp insts issued")
233 .init(cpu->numThreads)
234 .name(name() + ".ISSUE:nop")
235 .desc("number of nop insts issued")
240 .init(cpu->numThreads)
241 .name(name() + ".ISSUE:refs")
242 .desc("number of memory reference insts issued")
247 .init(cpu->numThreads)
248 .name(name() + ".ISSUE:loads")
249 .desc("number of load insts issued")
254 .init(cpu->numThreads)
255 .name(name() + ".ISSUE:branches")
256 .desc("Number of branches issued")
261 .init(cpu->numThreads)
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->numThreads)
279 .name(name() + ".LSQ:forw_loads")
280 .desc("number of loads forwarded via LSQ")
285 .init(cpu->numThreads)
286 .name(name() + ".ISSUE:addr_loads")
287 .desc("number of invalid-address loads")
292 .init(cpu->numThreads)
293 .name(name() + ".ISSUE:addr_swpfs")
294 .desc("number of invalid-address SW prefetches")
299 .init(cpu->numThreads)
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->numThreads)
336 .name(name() + ".WB:count")
337 .desc("cumulative count of insts written-back")
342 .init(cpu->numThreads)
343 .name(name() + ".WB:producers")
344 .desc("num instructions producing a value")
349 .init(cpu->numThreads)
350 .name(name() + ".WB:consumers")
351 .desc("num instructions consuming a value")
356 .init(cpu->numThreads)
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->numThreads)
388 .name(name() + ".COM:count")
389 .desc("Number of instructions committed")
394 .init(cpu->numThreads)
395 .name(name() + ".COM:swp_count")
396 .desc("Number of s/w prefetches committed")
401 .init(cpu->numThreads)
402 .name(name() + ".COM:refs")
403 .desc("Number of memory references committed")
408 .init(cpu->numThreads)
409 .name(name() + ".COM:loads")
410 .desc("Number of loads committed")
415 .init(cpu->numThreads)
416 .name(name() + ".COM:membars")
417 .desc("Number of memory barriers committed")
422 .init(cpu->numThreads)
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->numThreads)
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->numThreads)
461 .name(name() + ".COM:squashed_insts")
462 .desc("Number of instructions removed from inst list")
466 .init(cpu->numThreads)
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->numThreads)
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->numThreads, 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(tc) && !trapSquash && !tcSquash) {
529 frontEnd->interruptPending = true;
530 if (robEmpty() && !LSQ.hasStoresToWB()) {
531 // Will need to squash all instructions currently in flight and have
532 // the interrupt handler restart at the last non-committed inst.
533 // Most of that can be handled through the trap() function. The
534 // processInterrupts() function really just checks for interrupts
535 // and then calls trap() if there is an interrupt present.
537 // Not sure which thread should be the one to interrupt. For now
538 // always do thread 0.
539 assert(!thread->inSyscall);
540 thread->inSyscall = true;
542 // CPU will handle implementation of the interrupt.
543 cpu->processInterrupts();
545 // Now squash or record that I need to squash this cycle.
546 commitStatus = TrapPending;
548 // Exit state update mode to avoid accidental updating.
549 thread->inSyscall = false;
551 // Generate trap squash event.
554 DPRINTF(BE, "Interrupt detected.\n");
556 DPRINTF(BE, "Interrupt must wait for ROB to drain.\n");
562 template <class Impl>
564 LWBackEnd<Impl>::handleFault(Fault &fault, Tick latency)
566 DPRINTF(BE, "Handling fault!\n");
568 assert(!thread->inSyscall);
570 thread->inSyscall = true;
572 // Consider holding onto the trap and waiting until the trap event
573 // happens for this to be executed.
574 fault->invoke(thread->getTC());
576 // Exit state update mode to avoid accidental updating.
577 thread->inSyscall = false;
579 commitStatus = TrapPending;
581 // Generate trap squash event.
582 generateTrapEvent(latency);
585 template <class Impl>
587 LWBackEnd<Impl>::tick()
589 DPRINTF(BE, "Ticking back end\n");
591 // Read in any done instruction information and update the IQ or LSQ.
594 if (switchPending && robEmpty() && !LSQ.hasStoresToWB()) {
595 cpu->signalSwitched();
599 readyInstsForCommit();
601 numInstsToWB.advance();
603 ROBCount[0]+= numInsts;
614 } else if (tcSquash) {
618 if (dispatchStatus != Blocked) {
621 checkDispatchStatus();
624 if (commitStatus != TrapPending) {
630 LSQ.writebackStores();
632 DPRINTF(BE, "Waiting insts: %i, mem ops: %i, ROB entries in use: %i, "
633 "LSQ loads: %i, LSQ stores: %i\n",
634 waitingInsts, numWaitingMemOps, numInsts,
635 LSQ.numLoads(), LSQ.numStores());
638 assert(numInsts == instList.size());
639 assert(waitingInsts == waitingList.size());
640 assert(numWaitingMemOps == waitingMemOps.size());
641 assert(!switchedOut);
645 template <class Impl>
647 LWBackEnd<Impl>::updateStructures()
649 if (fromCommit->doneSeqNum) {
650 LSQ.commitLoads(fromCommit->doneSeqNum);
651 LSQ.commitStores(fromCommit->doneSeqNum);
654 if (fromCommit->nonSpecSeqNum) {
655 if (fromCommit->uncached) {
656 // LSQ.executeLoad(fromCommit->lqIdx);
658 // IQ.scheduleNonSpec(
659 // fromCommit->nonSpecSeqNum);
664 template <class Impl>
666 LWBackEnd<Impl>::addToLSQ(DynInstPtr &inst)
668 // Do anything LSQ specific here?
672 template <class Impl>
674 LWBackEnd<Impl>::dispatchInsts()
676 DPRINTF(BE, "Trying to dispatch instructions.\n");
678 while (numInsts < numROBEntries &&
679 numWaitingMemOps < maxOutstandingMemOps) {
680 // Get instruction from front of time buffer
681 if (lsqLimits && LSQ.isFull()) {
685 DynInstPtr inst = frontEnd->getInst();
688 } else if (inst->isSquashed()) {
693 instList.push_front(inst);
697 DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n",
698 inst->seqNum, inst->readPC());
700 for (int i = 0; i < inst->numDestRegs(); ++i)
701 renameTable[inst->destRegIdx(i)] = inst;
703 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
705 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
706 "barrier [sn:%lli].\n",
707 inst->seqNum, memBarrier->seqNum);
708 memBarrier->addMemDependent(inst);
709 inst->addSrcMemInst(memBarrier);
712 inst->setCanCommit();
713 } else if (inst->readyToIssue() &&
714 !inst->isNonSpeculative() &&
715 !inst->isStoreConditional()) {
716 if (inst->isMemRef()) {
720 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
721 "barrier [sn:%lli].\n",
722 inst->seqNum, memBarrier->seqNum);
723 memBarrier->addMemDependent(inst);
724 inst->addSrcMemInst(memBarrier);
725 addWaitingMemOp(inst);
727 waitingList.push_front(inst);
728 inst->iqIt = waitingList.begin();
729 inst->iqItValid = true;
732 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
737 } else if (inst->isNop()) {
738 DPRINTF(BE, "Nop encountered [sn:%lli], skipping exeList.\n",
742 inst->setCanCommit();
745 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
751 if (inst->isNonSpeculative() || inst->isStoreConditional()) {
752 inst->setCanCommit();
753 DPRINTF(BE, "Adding non speculative instruction\n");
756 if (inst->isMemRef()) {
757 addWaitingMemOp(inst);
760 memBarrier->addMemDependent(inst);
761 inst->addSrcMemInst(memBarrier);
763 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
764 "barrier [sn:%lli].\n",
765 inst->seqNum, memBarrier->seqNum);
769 DPRINTF(BE, "Instruction [sn:%lli] not ready, addding to "
772 waitingList.push_front(inst);
773 inst->iqIt = waitingList.begin();
774 inst->iqItValid = true;
779 // Check if IQ or LSQ is full. If so we'll need to break and stop
780 // removing instructions. Also update the number of insts to remove
781 // from the queue. Check here if we don't care about exact stall
786 DPRINTF(BE, "IQ is full!\n");
788 } else if (LSQ.isFull()) {
789 DPRINTF(BE, "LSQ is full!\n");
791 } else if (isFull()) {
792 DPRINTF(BE, "ROB is full!\n");
804 template <class Impl>
806 LWBackEnd<Impl>::dispatchStall()
808 dispatchStatus = Blocked;
809 if (!cpu->decoupledFrontEnd) {
810 // Tell front end to stall here through a timebuffer, or just tell
815 template <class Impl>
817 LWBackEnd<Impl>::checkDispatchStatus()
819 DPRINTF(BE, "Checking dispatch status\n");
820 assert(dispatchStatus == Blocked);
821 if (!LSQ.isFull() && !isFull()) {
822 DPRINTF(BE, "Dispatch no longer blocked\n");
823 dispatchStatus = Running;
828 template <class Impl>
830 LWBackEnd<Impl>::executeInsts()
832 DPRINTF(BE, "Trying to execute instructions\n");
834 int num_executed = 0;
835 while (!exeList.empty() && num_executed < issueWidth) {
836 DynInstPtr inst = exeList.top();
838 DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n",
839 inst->seqNum, inst->readPC());
841 // Check if the instruction is squashed; if so then skip it
842 // and don't count it towards the FU usage.
843 if (inst->isSquashed()) {
844 DPRINTF(BE, "Execute: Instruction was squashed.\n");
846 // Not sure how to handle this plus the method of sending # of
847 // instructions to use. Probably will just have to count it
848 // towards the bandwidth usage, but not the FU usage.
851 // Consider this instruction executed so that commit can go
852 // ahead and retire the instruction.
855 // Not sure if I should set this here or just let commit try to
856 // commit any squashed instructions. I like the latter a bit more.
857 inst->setCanCommit();
859 // ++iewExecSquashedInsts;
865 Fault fault = NoFault;
867 // Execute instruction.
868 // Note that if the instruction faults, it will be handled
869 // at the commit stage.
870 if (inst->isMemRef() &&
871 (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
872 DPRINTF(BE, "Execute: Initiating access for memory "
875 if (inst->isLoad()) {
876 LSQ.executeLoad(inst);
877 } else if (inst->isStore()) {
878 Fault fault = LSQ.executeStore(inst);
880 if (!inst->isStoreConditional() && fault == NoFault) {
884 } else if (fault != NoFault) {
885 // If the instruction faulted, then we need to send it along to commit
886 // without the instruction completing.
887 // Send this instruction to commit, also make sure iew stage
888 // realizes there is activity.
894 panic("Unknown mem type!");
904 updateExeInstStats(inst);
911 if (inst->mispredicted()) {
912 squashDueToBranch(inst);
914 } else if (LSQ.violation()) {
915 // Get the DynInst that caused the violation. Note that this
916 // clears the violation signal.
918 violator = LSQ.getMemDepViolator();
920 DPRINTF(BE, "LDSTQ detected a violation. Violator PC: "
921 "%#x, inst PC: %#x. Addr is: %#x.\n",
922 violator->readPC(), inst->readPC(), inst->physEffAddr);
925 squashDueToMemViolation(inst);
929 issuedOps[0]+= num_executed;
930 nIssuedDist[num_executed]++;
935 LWBackEnd<Impl>::instToCommit(DynInstPtr &inst)
937 DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n",
938 inst->seqNum, inst->readPC());
940 if (!inst->isSquashed()) {
941 if (inst->isExecuted()) {
942 inst->setResultReady();
943 int dependents = wakeDependents(inst);
946 consumerInst[0]+= dependents;
951 writeback.push_back(inst);
958 template <class Impl>
960 LWBackEnd<Impl>::readyInstsForCommit()
962 for (int i = numInstsToWB[-latency];
963 !writeback.empty() && i;
966 DynInstPtr inst = writeback.front();
967 writeback.pop_front();
968 if (!inst->isSquashed()) {
969 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
970 inst->seqNum, inst->readPC());
972 inst->setCanCommit();
978 template <class Impl>
980 LWBackEnd<Impl>::writebackInsts()
982 int wb_width = wbWidth;
983 // Using this method I'm not quite sure how to prevent an
984 // instruction from waking its own dependents multiple times,
985 // without the guarantee that commit always has enough bandwidth
986 // to accept all instructions being written back. This guarantee
987 // might not be too unrealistic.
988 InstListIt wb_inst_it = writeback.begin();
989 InstListIt wb_end_it = writeback.end();
991 int consumer_insts = 0;
993 for (; inst_num < wb_width &&
994 wb_inst_it != wb_end_it; inst_num++) {
995 DynInstPtr inst = (*wb_inst_it);
997 // Some instructions will be sent to commit without having
998 // executed because they need commit to handle them.
999 // E.g. Uncached loads have not actually executed when they
1000 // are first sent to commit. Instead commit must tell the LSQ
1001 // when it's ready to execute the uncached load.
1002 if (!inst->isSquashed()) {
1003 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
1004 inst->seqNum, inst->readPC());
1006 inst->setCanCommit();
1007 inst->setResultReady();
1009 if (inst->isExecuted()) {
1010 int dependents = wakeDependents(inst);
1013 consumer_insts+= dependents;
1018 writeback.erase(wb_inst_it++);
1020 LSQ.writebackStores();
1021 consumer_inst[0]+= consumer_insts;
1022 writeback_count[0]+= inst_num;
1025 template <class Impl>
1027 LWBackEnd<Impl>::commitInst(int inst_num)
1029 // Read instruction from the head of the ROB
1030 DynInstPtr inst = instList.back();
1032 // Make sure instruction is valid
1035 if (!inst->readyToCommit())
1038 DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n",
1039 inst->seqNum, inst->readPC());
1041 thread->setPC(inst->readPC());
1042 thread->setNextPC(inst->readNextPC());
1043 inst->setAtCommit();
1045 // If the instruction is not executed yet, then it is a non-speculative
1046 // or store inst. Signal backwards that it should be executed.
1047 if (!inst->isExecuted()) {
1048 if (inst->isNonSpeculative() ||
1049 (inst->isStoreConditional() && inst->getFault() == NoFault) ||
1050 inst->isMemBarrier() ||
1051 inst->isWriteBarrier()) {
1053 // Hack to make sure syscalls aren't executed until all stores
1054 // write back their data. This direct communication shouldn't
1055 // be used for anything other than this.
1056 if (inst_num > 0 || LSQ.hasStoresToWB())
1058 if ((inst->isMemBarrier() || inst->isWriteBarrier() ||
1059 inst->isQuiesce()) &&
1060 LSQ.hasStoresToWB())
1063 DPRINTF(BE, "Waiting for all stores to writeback.\n");
1067 DPRINTF(BE, "Encountered a store or non-speculative "
1068 "instruction at the head of the ROB, PC %#x.\n",
1071 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
1072 DPRINTF(BE, "Waking dependents on barrier [sn:%lli]\n",
1075 wakeDependents(inst, true);
1076 if (memBarrier == inst)
1078 inst->clearMemDependents();
1081 // Send back the non-speculative instruction's sequence number.
1082 if (inst->iqItValid) {
1083 DPRINTF(BE, "Removing instruction from waiting list\n");
1084 waitingList.erase(inst->iqIt);
1085 inst->iqItValid = false;
1087 assert(waitingInsts >= 0);
1088 if (inst->isStore())
1089 removeWaitingMemOp(inst);
1094 // Change the instruction so it won't try to commit again until
1096 inst->clearCanCommit();
1098 // ++commitNonSpecStalls;
1101 } else if (inst->isLoad()) {
1102 DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n",
1103 inst->seqNum, inst->readPC());
1105 // Send back the non-speculative instruction's sequence
1106 // number. Maybe just tell the lsq to re-execute the load.
1108 // Send back the non-speculative instruction's sequence number.
1109 if (inst->iqItValid) {
1110 DPRINTF(BE, "Removing instruction from waiting list\n");
1111 waitingList.erase(inst->iqIt);
1112 inst->iqItValid = false;
1114 assert(waitingInsts >= 0);
1115 removeWaitingMemOp(inst);
1117 replayMemInst(inst);
1119 inst->clearCanCommit();
1123 panic("Trying to commit un-executed instruction "
1124 "of unknown type!\n");
1128 // Not handled for now.
1129 assert(!inst->isThreadSync());
1130 assert(inst->memDepReady());
1131 // Stores will mark themselves as totally completed as they need
1132 // to wait to writeback to memory. @todo: Hack...attempt to fix
1133 // having the checker be forced to wait until a store completes in
1134 // order to check all of the instructions. If the store at the
1135 // head of the check list misses, but a later store hits, then
1136 // loads in the checker may see the younger store values instead
1137 // of the store they should see. Either the checker needs its own
1138 // memory (annoying to update), its own store buffer (how to tell
1139 // which value is correct?), or something else...
1140 if (!inst->isStore()) {
1141 inst->setCompleted();
1143 // Check if the instruction caused a fault. If so, trap.
1144 Fault inst_fault = inst->getFault();
1146 // Use checker prior to updating anything due to traps or PC
1150 checker->verify(inst);
1154 if (inst_fault != NoFault) {
1155 DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
1156 inst->seqNum, inst->readPC());
1158 // Instruction is completed as it has a fault.
1159 inst->setCompleted();
1161 if (LSQ.hasStoresToWB()) {
1162 DPRINTF(BE, "Stores still in flight, will wait until drained.\n");
1164 } else if (inst_num != 0) {
1165 DPRINTF(BE, "Will wait until instruction is head of commit group.\n");
1169 else if (checker && inst->isStore()) {
1170 checker->verify(inst);
1174 handleFault(inst_fault);
1180 for (int i = 0; i < inst->numDestRegs(); ++i) {
1181 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1182 (int)inst->destRegIdx(i), inst->seqNum);
1183 thread->renameTable[inst->destRegIdx(i)] = inst;
1188 if (thread->profile) {
1190 // (xc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
1191 // thread->profilePC = usermode ? 1 : inst->readPC();
1192 thread->profilePC = inst->readPC();
1193 ProfileNode *node = thread->profile->consume(thread->getTC(),
1197 thread->profileNode = node;
1201 if (inst->traceData) {
1202 inst->traceData->setFetchSeq(inst->seqNum);
1203 inst->traceData->setCPSeq(thread->numInst);
1204 inst->traceData->finalize();
1205 inst->traceData = NULL;
1209 panic("Should not commit any copy instructions!");
1211 inst->clearDependents();
1213 frontEnd->addFreeRegs(freed_regs);
1215 instList.pop_back();
1218 ++thread->funcExeInst;
1219 // Maybe move this to where the fault is handled; if the fault is
1220 // handled, don't try to set this myself as the fault will set it.
1221 // If not, then I set thread->PC = thread->nextPC and
1222 // thread->nextPC = thread->nextPC + 4.
1223 thread->setPC(thread->readNextPC());
1224 thread->setNextPC(thread->readNextPC() + sizeof(TheISA::MachInst));
1225 updateComInstStats(inst);
1227 // Write the done sequence number here.
1228 toIEW->doneSeqNum = inst->seqNum;
1229 lastCommitCycle = curTick;
1236 assert(!thread->inSyscall && !thread->trapPending);
1237 oldpc = thread->readPC();
1238 cpu->system->pcEventQueue.service(
1241 } while (oldpc != thread->readPC());
1243 DPRINTF(BE, "PC skip function event, stopping commit\n");
1251 template <class Impl>
1253 LWBackEnd<Impl>::commitInsts()
1255 // Not sure this should be a loop or not.
1257 while (!instList.empty() && inst_num < commitWidth) {
1258 if (instList.back()->isSquashed()) {
1259 instList.back()->clearDependents();
1260 ROBSquashedInsts[instList.back()->threadNumber]++;
1261 instList.pop_back();
1266 if (!commitInst(inst_num++)) {
1267 DPRINTF(BE, "Can't commit, Instruction [sn:%lli] PC "
1268 "%#x is head of ROB and not ready\n",
1269 instList.back()->seqNum, instList.back()->readPC());
1274 nCommittedDist.sample(inst_num);
1277 template <class Impl>
1279 LWBackEnd<Impl>::squash(const InstSeqNum &sn)
1284 InstListIt insts_end_it = waitingList.end();
1285 InstListIt insts_it = waitingList.begin();
1287 while (insts_it != insts_end_it && (*insts_it)->seqNum > sn)
1289 if ((*insts_it)->isSquashed()) {
1293 DPRINTF(BE, "Squashing instruction on waitingList PC %#x, [sn:%lli].\n",
1294 (*insts_it)->readPC(),
1295 (*insts_it)->seqNum);
1297 if ((*insts_it)->isMemRef()) {
1298 DPRINTF(BE, "Squashing a waiting mem op [sn:%lli]\n",
1299 (*insts_it)->seqNum);
1300 removeWaitingMemOp((*insts_it));
1303 waitingList.erase(insts_it++);
1306 assert(waitingInsts >= 0);
1308 insts_it = instList.begin();
1310 while (!instList.empty() && (*insts_it)->seqNum > sn)
1312 if ((*insts_it)->isSquashed()) {
1313 panic("Instruction should not be already squashed and on list!");
1317 DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n",
1318 (*insts_it)->readPC(),
1319 (*insts_it)->seqNum);
1321 // Mark the instruction as squashed, and ready to commit so that
1322 // it can drain out of the pipeline.
1323 (*insts_it)->setSquashed();
1325 (*insts_it)->setCanCommit();
1327 (*insts_it)->clearInROB();
1329 for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
1330 DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
1331 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1332 (int)(*insts_it)->destRegIdx(i), prev_dest->seqNum);
1333 renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
1337 (*insts_it)->clearDependents();
1339 squashedInsts[(*insts_it)->threadNumber]++;
1341 instList.erase(insts_it++);
1345 while (memBarrier && memBarrier->seqNum > sn) {
1346 DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously "
1347 "squashed)\n", memBarrier->seqNum);
1348 memBarrier->clearMemDependents();
1349 if (memBarrier->memDepReady()) {
1350 DPRINTF(BE, "No previous barrier\n");
1353 std::list<DynInstPtr> &srcs = memBarrier->getMemSrcs();
1354 memBarrier = srcs.front();
1356 assert(srcs.empty());
1357 DPRINTF(BE, "Previous barrier: [sn:%lli]\n",
1358 memBarrier->seqNum);
1362 insts_it = replayList.begin();
1363 insts_end_it = replayList.end();
1364 while (!replayList.empty() && insts_it != insts_end_it) {
1365 if ((*insts_it)->seqNum < sn) {
1369 assert((*insts_it)->isSquashed());
1371 replayList.erase(insts_it++);
1374 frontEnd->addFreeRegs(freed_regs);
1377 template <class Impl>
1379 LWBackEnd<Impl>::squashFromTC()
1381 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1382 squash(squashed_inst);
1383 frontEnd->squash(squashed_inst, thread->readPC(),
1385 frontEnd->interruptPending = false;
1387 thread->trapPending = false;
1388 thread->inSyscall = false;
1390 commitStatus = Running;
1393 template <class Impl>
1395 LWBackEnd<Impl>::squashFromTrap()
1397 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1398 squash(squashed_inst);
1399 frontEnd->squash(squashed_inst, thread->readPC(),
1401 frontEnd->interruptPending = false;
1403 thread->trapPending = false;
1404 thread->inSyscall = false;
1406 commitStatus = Running;
1409 template <class Impl>
1411 LWBackEnd<Impl>::squashDueToBranch(DynInstPtr &inst)
1413 // Update the branch predictor state I guess
1414 DPRINTF(BE, "Squashing due to branch [sn:%lli], will restart at PC %#x\n",
1415 inst->seqNum, inst->readNextPC());
1416 squash(inst->seqNum);
1417 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1418 true, inst->mispredicted());
1421 template <class Impl>
1423 LWBackEnd<Impl>::squashDueToMemViolation(DynInstPtr &inst)
1425 // Update the branch predictor state I guess
1426 DPRINTF(BE, "Squashing due to violation [sn:%lli], will restart at PC %#x\n",
1427 inst->seqNum, inst->readNextPC());
1428 squash(inst->seqNum);
1429 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1430 false, inst->mispredicted());
1433 template <class Impl>
1435 LWBackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst)
1437 DPRINTF(IEW, "Memory blocked, squashing load and younger insts, "
1438 "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum);
1440 squash(inst->seqNum - 1);
1441 frontEnd->squash(inst->seqNum - 1, inst->readPC());
1444 template <class Impl>
1446 LWBackEnd<Impl>::switchOut()
1448 switchPending = true;
1451 template <class Impl>
1453 LWBackEnd<Impl>::doSwitchOut()
1456 switchPending = false;
1457 // Need to get rid of all committed, non-speculative state and write it
1458 // to memory/TC. In this case this is stores that have committed and not
1459 // yet written back.
1461 assert(!LSQ.hasStoresToWB());
1463 for (int i = 0; i < numInstsToWB.getSize() + 1; ++i)
1464 numInstsToWB.advance();
1467 assert(waitingList.empty());
1468 assert(instList.empty());
1469 assert(replayList.empty());
1470 assert(writeback.empty());
1474 template <class Impl>
1476 LWBackEnd<Impl>::takeOverFrom(ThreadContext *old_tc)
1478 assert(!squashPending);
1485 numWaitingMemOps = 0;
1486 waitingMemOps.clear();
1488 switchedOut = false;
1489 dispatchStatus = Running;
1490 commitStatus = Running;
1491 LSQ.takeOverFrom(old_tc);
1494 template <class Impl>
1496 LWBackEnd<Impl>::updateExeInstStats(DynInstPtr &inst)
1498 ThreadID tid = inst->threadNumber;
1501 // Pick off the software prefetches
1504 if (inst->isDataPrefetch())
1513 // Control operations
1515 if (inst->isControl())
1519 // Memory operations
1521 if (inst->isMemRef()) {
1529 template <class Impl>
1531 LWBackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
1533 ThreadID tid = inst->threadNumber;
1535 // keep an instruction count
1541 // Pick off the software prefetches
1544 if (inst->isDataPrefetch()) {
1554 // Control Instructions
1556 if (inst->isControl())
1557 statComBranches[tid]++;
1560 // Memory references
1562 if (inst->isMemRef()) {
1565 if (inst->isLoad()) {
1566 statComLoads[tid]++;
1570 if (inst->isMemBarrier()) {
1571 statComMembars[tid]++;
1575 template <class Impl>
1577 LWBackEnd<Impl>::dumpInsts()
1582 InstListIt inst_list_it = --(instList.end());
1584 cprintf("ExeList size: %i\n", exeList.size());
1586 cprintf("Inst list size: %i\n", instList.size());
1588 while (inst_list_it != instList.end())
1590 cprintf("Instruction:%i\n",
1592 if (!(*inst_list_it)->isSquashed()) {
1593 if (!(*inst_list_it)->isIssued()) {
1595 cprintf("Count:%i\n", valid_num);
1596 } else if ((*inst_list_it)->isMemRef() &&
1597 !(*inst_list_it)->memOpDone) {
1598 // Loads that have not been marked as executed still count
1599 // towards the total instructions.
1601 cprintf("Count:%i\n", valid_num);
1605 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1606 "Issued:%i\nSquashed:%i\n",
1607 (*inst_list_it)->readPC(),
1608 (*inst_list_it)->seqNum,
1609 (*inst_list_it)->threadNumber,
1610 (*inst_list_it)->isIssued(),
1611 (*inst_list_it)->isSquashed());
1613 if ((*inst_list_it)->isMemRef()) {
1614 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1623 inst_list_it = --(writeback.end());
1625 cprintf("Writeback list size: %i\n", writeback.size());
1627 while (inst_list_it != writeback.end())
1629 cprintf("Instruction:%i\n",
1631 if (!(*inst_list_it)->isSquashed()) {
1632 if (!(*inst_list_it)->isIssued()) {
1634 cprintf("Count:%i\n", valid_num);
1635 } else if ((*inst_list_it)->isMemRef() &&
1636 !(*inst_list_it)->memOpDone) {
1637 // Loads that have not been marked as executed still count
1638 // towards the total instructions.
1640 cprintf("Count:%i\n", valid_num);
1644 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1645 "Issued:%i\nSquashed:%i\n",
1646 (*inst_list_it)->readPC(),
1647 (*inst_list_it)->seqNum,
1648 (*inst_list_it)->threadNumber,
1649 (*inst_list_it)->isIssued(),
1650 (*inst_list_it)->isSquashed());
1652 if ((*inst_list_it)->isMemRef()) {
1653 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1662 cprintf("Waiting list size: %i\n", waitingList.size());
1664 inst_list_it = --(waitingList.end());
1666 while (inst_list_it != waitingList.end())
1668 cprintf("Instruction:%i\n",
1670 if (!(*inst_list_it)->isSquashed()) {
1671 if (!(*inst_list_it)->isIssued()) {
1673 cprintf("Count:%i\n", valid_num);
1674 } else if ((*inst_list_it)->isMemRef() &&
1675 !(*inst_list_it)->memOpDone) {
1676 // Loads that have not been marked as executed still count
1677 // towards the total instructions.
1679 cprintf("Count:%i\n", valid_num);
1683 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1684 "Issued:%i\nSquashed:%i\n",
1685 (*inst_list_it)->readPC(),
1686 (*inst_list_it)->seqNum,
1687 (*inst_list_it)->threadNumber,
1688 (*inst_list_it)->isIssued(),
1689 (*inst_list_it)->isSquashed());
1691 if ((*inst_list_it)->isMemRef()) {
1692 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1701 cprintf("waitingMemOps list size: %i\n", waitingMemOps.size());
1703 MemIt waiting_it = waitingMemOps.begin();
1705 while (waiting_it != waitingMemOps.end())
1707 cprintf("[sn:%lli] ", (*waiting_it));