1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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;

--- 268 unchanged lines hidden (view full) ---

277 "detected at decode.\n", tid);
278
279 // Send back mispredict information.
280 toFetch->decodeInfo[tid].branchMispredict = true;
281 toFetch->decodeInfo[tid].predIncorrect = true;
282 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
283 toFetch->decodeInfo[tid].squash = true;
284 toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
285 ///FIXME There needs to be a way to set the nextPC and nextNPC
286 ///explicitly for ISAs with delay slots.
287 toFetch->decodeInfo[tid].nextNPC =
288 inst->branchTarget() + sizeof(TheISA::MachInst);
289#if ISA_HAS_DELAY_SLOT
290 toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() !=
291 (inst->readNextPC() + sizeof(TheISA::MachInst));
292
293 toFetch->decodeInfo[tid].bdelayDoneSeqNum = bdelayDoneSeqNum[tid];
294 squashAfterDelaySlot[tid] = false;
295
296 InstSeqNum squash_seq_num = bdelayDoneSeqNum[tid];

--- 126 unchanged lines hidden (view full) ---

423 // fetch past its skidbuffer
424 assert(skidBuffer[tid].size() <= skidBufferMax);
425}
426
427template<class Impl>
428bool
429DefaultDecode<Impl>::skidsEmpty()
430{
427 std::list<unsigned>::iterator threads = activeThreads->begin();
428 std::list<unsigned>::iterator end = activeThreads->end();
431 std::list<unsigned>::iterator threads = (*activeThreads).begin();
432
430 while (threads != end) {
431 unsigned tid = *threads++;
432 if (!skidBuffer[tid].empty())
433 while (threads != (*activeThreads).end()) {
434 if (!skidBuffer[*threads++].empty())
435 return false;
436 }
437
438 return true;
439}
440
441template<class Impl>
442void
443DefaultDecode<Impl>::updateStatus()
444{
445 bool any_unblocking = false;
446
445 std::list<unsigned>::iterator threads = activeThreads->begin();
446 std::list<unsigned>::iterator end = activeThreads->end();
447 std::list<unsigned>::iterator threads = (*activeThreads).begin();
448
448 while (threads != end) {
449 threads = (*activeThreads).begin();
450
451 while (threads != (*activeThreads).end()) {
452 unsigned tid = *threads++;
453
454 if (decodeStatus[tid] == Unblocking) {
455 any_unblocking = true;
456 break;
457 }
458 }
459

--- 136 unchanged lines hidden (view full) ---

596DefaultDecode<Impl>::tick()
597{
598 wroteToTimeBuffer = false;
599
600 bool status_change = false;
601
602 toRenameIndex = 0;
603
601 std::list<unsigned>::iterator threads = activeThreads->begin();
602 std::list<unsigned>::iterator end = activeThreads->end();
604 std::list<unsigned>::iterator threads = (*activeThreads).begin();
605
606 sortInsts();
607
608 //Check stall and squash signals.
607 while (threads != end) {
608 unsigned tid = *threads++;
609 while (threads != (*activeThreads).end()) {
610 unsigned tid = *threads++;
611
612 DPRINTF(Decode,"Processing [tid:%i]\n",tid);
613 status_change = checkSignalsAndUpdate(tid) || status_change;
614
615 decode(status_change, tid);
616 }
617
618 if (status_change) {

--- 121 unchanged lines hidden (view full) ---

740
741 ++(toRename->size);
742 ++toRenameIndex;
743 ++decodeDecodedInsts;
744 --insts_available;
745
746 // Ensure that if it was predicted as a branch, it really is a
747 // branch.
746 if (inst->predTaken() && !inst->isControl()) {
747 DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC,
748 inst->nextPC + 4);
748 if (inst->readPredTaken() && !inst->isControl()) {
749 DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",
750 inst->readPredPC(), inst->readNextPC() + 4);
751
752 panic("Instruction predicted as a branch!");
753
754 ++decodeControlMispred;
755
756 // Might want to set some sort of boolean and just do
757 // a check at the end
758 squash(inst, inst->threadNumber);
759
760 break;
761 }
762
763 // Go ahead and compute any PC-relative branches.
764 if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
765 ++decodeBranchResolved;
766
765 if (inst->branchTarget() != inst->readPredTarg()) {
767 if (inst->branchTarget() != inst->readPredPC()) {
768 ++decodeBranchMispred;
769
770 // Might want to set some sort of boolean and just do
771 // a check at the end
772#if !ISA_HAS_DELAY_SLOT
773 squash(inst, inst->threadNumber);
772 inst->setPredTarg(inst->branchTarget());
774 Addr target = inst->branchTarget();
775 inst->setPredTarg(target, target + sizeof(TheISA::MachInst));
776 break;
777#else
778 // If mispredicted as taken, then ignore delay slot
779 // instruction... else keep delay slot and squash
780 // after it is sent to rename
778 if (inst->predTaken() && inst->isCondDelaySlot()) {
781 if (inst->readPredTaken() && inst->isCondDelaySlot()) {
782 DPRINTF(Decode, "[tid:%i]: Conditional delay slot inst."
783 "[sn:%i] PC %#x mispredicted as taken.\n", tid,
784 inst->seqNum, inst->PC);
785 bdelayDoneSeqNum[tid] = inst->seqNum;
786 squash(inst, inst->threadNumber);
784 inst->setPredTarg(inst->branchTarget());
787 Addr target = inst->branchTarget();
788 inst->setPredTarg(target,
789 target + sizeof(TheISA::MachInst));
790 break;
791 } else {
792 DPRINTF(Decode, "[tid:%i]: Misprediction detected at "
793 "[sn:%i] PC %#x, will squash after delay slot "
794 "inst. is sent to Rename\n",
795 tid, inst->seqNum, inst->PC);
796 bdelayDoneSeqNum[tid] = inst->seqNum + 1;
797 squashAfterDelaySlot[tid] = true;
798 squashInst[tid] = inst;
799 continue;
800 }
801#endif
802 }
803 }
804
805 if (squashAfterDelaySlot[tid]) {
806 assert(!inst->isSquashed());
807 squash(squashInst[tid], squashInst[tid]->threadNumber);
803 squashInst[tid]->setPredTarg(squashInst[tid]->branchTarget());
808 Addr target = squashInst[tid]->branchTarget();
809 squashInst[tid]->setPredTarg(target,
810 target + sizeof(TheISA::MachInst));
811 assert(!inst->isSquashed());
812 break;
813 }
814 }
815
816 // If we didn't process all instructions, then we will need to block
817 // and put all those instructions into the skid buffer.
818 if (!insts_to_decode.empty()) {
819 block(tid);
820 }
821
822 // Record that decode has written to the time buffer for activity
823 // tracking.
824 if (toRenameIndex) {
825 wroteToTimeBuffer = true;
826 }
827}