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; --- 104 unchanged lines hidden (view full) --- 113 } else { 114 assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive," 115 "RoundRobin,OldestReady}"); 116 } 117 118 for (int i=0; i < numThreads; i++) { 119 commitStatus[i] = Idle; 120 changedROBNumEntries[i] = false; |
121 trapSquash[i] = false; 122 tcSquash[i] = false; 123 PC[i] = nextPC[i] = nextNPC[i] = 0; 124 } 125#if FULL_SYSTEM 126 interrupt = NoFault; 127#endif 128} --- 201 unchanged lines hidden (view full) --- 330{ 331 rob->setActiveThreads(activeThreads); 332 rob->resetEntries(); 333 334 // Broadcast the number of free entries. 335 for (int i=0; i < numThreads; i++) { 336 toIEW->commitInfo[i].usedROB = true; 337 toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i); |
338 } 339 340 cpu->activityThisCycle(); 341} 342 343template <class Impl> 344bool 345DefaultCommit<Impl>::drain() --- 122 unchanged lines hidden (view full) --- 468void 469DefaultCommit<Impl>::generateTrapEvent(unsigned tid) 470{ 471 DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid); 472 473 TrapEvent *trap = new TrapEvent(this, tid); 474 475 trap->schedule(curTick + trapLatency); |
476 477 thread[tid]->trapPending = true; |
478} 479 480template <class Impl> 481void 482DefaultCommit<Impl>::generateTCEvent(unsigned tid) 483{ |
484 DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid); 485 486 tcSquash[tid] = true; 487} 488 489template <class Impl> 490void 491DefaultCommit<Impl>::squashAll(unsigned tid) 492{ 493 // If we want to include the squashing instruction in the squash, 494 // then use one older sequence number. 495 // Hopefully this doesn't mess things up. Basically I want to squash 496 // all instructions of this thread. 497 InstSeqNum squashed_inst = rob->isEmpty() ? |
498 0 : rob->readHeadInst(tid)->seqNum - 1;; |
499 500 // All younger instructions will be squashed. Set the sequence 501 // number as the youngest instruction in the ROB (0 in this case. 502 // Hopefully nothing breaks.) 503 youngestSeqNum[tid] = 0; 504 505 rob->squash(squashed_inst, tid); 506 changedROBNumEntries[tid] = true; --- 20 unchanged lines hidden (view full) --- 527DefaultCommit<Impl>::squashFromTrap(unsigned tid) 528{ 529 squashAll(tid); 530 531 DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]); 532 533 thread[tid]->trapPending = false; 534 thread[tid]->inSyscall = false; |
535 536 trapSquash[tid] = false; 537 538 commitStatus[tid] = ROBSquashing; 539 cpu->activityThisCycle(); 540} 541 542template <class Impl> --- 32 unchanged lines hidden (view full) --- 575 std::list<unsigned>::iterator threads = activeThreads->begin(); 576 std::list<unsigned>::iterator end = activeThreads->end(); 577 578 // Check if any of the threads are done squashing. Change the 579 // status if they are done. 580 while (threads != end) { 581 unsigned tid = *threads++; 582 |
583 if (commitStatus[tid] == ROBSquashing) { 584 585 if (rob->isDoneSquashing(tid)) { 586 commitStatus[tid] = Running; 587 } else { 588 DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any" 589 " insts this cycle.\n", tid); 590 rob->doSquash(tid); --- 39 unchanged lines hidden (view full) --- 630 if (wroteToTimeBuffer) { 631 DPRINTF(Activity, "Activity This Cycle.\n"); 632 cpu->activityThisCycle(); 633 } 634 635 updateStatus(); 636} 637 |
638template <class Impl> 639void |
640DefaultCommit<Impl>::commit() |
641{ |
642 643 ////////////////////////////////////// 644 // Check for interrupts 645 ////////////////////////////////////// 646 647#if FULL_SYSTEM |
648 if (interrupt != NoFault) { 649 // Wait until the ROB is empty and all stores have drained in 650 // order to enter the interrupt. 651 if (rob->isEmpty() && !iewStage->hasStoresToWB()) { 652 // Squash or record that I need to squash this cycle if 653 // an interrupt needed to be handled. 654 DPRINTF(Commit, "Interrupt detected.\n"); 655 |
656 assert(!thread[0]->inSyscall); 657 thread[0]->inSyscall = true; 658 659 // CPU will handle interrupt. 660 cpu->processInterrupts(interrupt); 661 662 thread[0]->inSyscall = false; 663 664 commitStatus[0] = TrapPending; 665 666 // Generate trap squash event. 667 generateTrapEvent(0); 668 |
669 // Clear the interrupt now that it's been handled 670 toIEW->commitInfo[0].clearInterrupt = true; |
671 interrupt = NoFault; 672 } else { 673 DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n"); 674 } |
675 } else if (cpu->check_interrupts(cpu->tcBase(0)) && 676 commitStatus[0] != TrapPending && 677 !trapSquash[0] && 678 !tcSquash[0]) { |
679 // Process interrupts if interrupts are enabled, not in PAL 680 // mode, and no other traps or external squashes are currently 681 // pending. 682 // @todo: Allow other threads to handle interrupts. 683 684 // Get any interrupt that happened 685 interrupt = cpu->getInterrupts(); 686 687 if (interrupt != NoFault) { 688 // Tell fetch that there is an interrupt pending. This 689 // will make fetch wait until it sees a non PAL-mode PC, 690 // at which point it stops fetching instructions. 691 toIEW->commitInfo[0].interruptPending = true; 692 } 693 } |
694 |
695#endif // FULL_SYSTEM 696 697 //////////////////////////////////// 698 // Check for any possible squashes, handle them first 699 //////////////////////////////////// 700 std::list<unsigned>::iterator threads = activeThreads->begin(); 701 std::list<unsigned>::iterator end = activeThreads->end(); 702 703 while (threads != end) { 704 unsigned tid = *threads++; 705 706 // Not sure which one takes priority. I think if we have 707 // both, that's a bad sign. 708 if (trapSquash[tid] == true) { 709 assert(!tcSquash[tid]); 710 squashFromTrap(tid); 711 } else if (tcSquash[tid] == true) { |
712 squashFromTC(tid); 713 } 714 715 // Squashed sequence number must be older than youngest valid 716 // instruction in the ROB. This prevents squashes from younger 717 // instructions overriding squashes from older instructions. 718 if (fromIEW->squash[tid] && 719 commitStatus[tid] != TrapPending && --- 28 unchanged lines hidden (view full) --- 748#endif 749 750 if (fromIEW->includeSquashInst[tid] == true) { 751 squashed_inst--; 752#if ISA_HAS_DELAY_SLOT 753 bdelay_done_seq_num--; 754#endif 755 } |
756 // All younger instructions will be squashed. Set the sequence 757 // number as the youngest instruction in the ROB. 758 youngestSeqNum[tid] = squashed_inst; 759 760#if ISA_HAS_DELAY_SLOT 761 rob->squash(bdelay_done_seq_num, tid); 762 toIEW->commitInfo[tid].squashDelaySlot = squash_bdelay_slot; 763 toIEW->commitInfo[tid].bdelayDoneSeqNum = bdelay_done_seq_num; --- 48 unchanged lines hidden (view full) --- 812 813 while (threads != end) { 814 unsigned tid = *threads++; 815 816 if (changedROBNumEntries[tid]) { 817 toIEW->commitInfo[tid].usedROB = true; 818 toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid); 819 |
820 if (rob->isEmpty(tid)) { 821 toIEW->commitInfo[tid].emptyROB = true; 822 } 823 |
824 wroteToTimeBuffer = true; 825 changedROBNumEntries[tid] = false; |
826 } |
827 } 828} 829 830template <class Impl> 831void 832DefaultCommit<Impl>::commitInsts() 833{ 834 //////////////////////////////////// --- 126 unchanged lines hidden (view full) --- 961 962 // If the instruction is not executed yet, then it will need extra 963 // handling. Signal backwards that it should be executed. 964 if (!head_inst->isExecuted()) { 965 // Keep this number correct. We have not yet actually executed 966 // and committed this instruction. 967 thread[tid]->funcExeInst--; 968 |
969 head_inst->setAtCommit(); 970 |
971 if (head_inst->isNonSpeculative() || 972 head_inst->isStoreConditional() || 973 head_inst->isMemBarrier() || 974 head_inst->isWriteBarrier()) { 975 976 DPRINTF(Commit, "Encountered a barrier or non-speculative " 977 "instruction [sn:%lli] at the head of the ROB, PC %#x.\n", 978 head_inst->seqNum, head_inst->readPC()); 979 |
980 // Hack to make sure syscalls/memory barriers/quiesces 981 // aren't executed until all stores write back their data. 982 // This direct communication shouldn't be used for 983 // anything other than this. 984 if ((head_inst->isMemBarrier() || head_inst->isWriteBarrier() || 985 head_inst->isQuiesce()) && 986 iewStage->hasStoresToWB()) 987 { |
988 DPRINTF(Commit, "Waiting for all stores to writeback.\n"); 989 return false; |
990 } else if (inst_num > 0 || iewStage->hasStoresToWB()) { 991 DPRINTF(Commit, "Waiting to become head of commit.\n"); 992 return false; |
993 } 994 995 toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 996 997 // Change the instruction so it won't try to commit again until 998 // it is executed. 999 head_inst->clearCanCommit(); 1000 1001 ++commitNonSpecStalls; 1002 1003 return false; 1004 } else if (head_inst->isLoad()) { |
1005 DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n", 1006 head_inst->seqNum, head_inst->readPC()); 1007 1008 // Send back the non-speculative instruction's sequence 1009 // number. Tell the lsq to re-execute the load. 1010 toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum; 1011 toIEW->commitInfo[tid].uncached = true; 1012 toIEW->commitInfo[tid].uncachedLoad = head_inst; --- 7 unchanged lines hidden (view full) --- 1020 } 1021 } 1022 1023 if (head_inst->isThreadSync()) { 1024 // Not handled for now. 1025 panic("Thread sync instructions are not handled yet.\n"); 1026 } 1027 |
1028 // Stores mark themselves as completed. |
1029 if (!head_inst->isStore()) { |
1030 head_inst->setCompleted(); 1031 } 1032 1033#if USE_CHECKER 1034 // Use checker prior to updating anything due to traps or PC 1035 // based events. 1036 if (cpu->checker) { 1037 cpu->checker->verify(head_inst); 1038 } 1039#endif 1040 |
1041 // Check if the instruction caused a fault. If so, trap. 1042 Fault inst_fault = head_inst->getFault(); 1043 |
1044 // DTB will sometimes need the machine instruction for when 1045 // faults happen. So we will set it here, prior to the DTB 1046 // possibly needing it for its fault. 1047 thread[tid]->setInst( 1048 static_cast<TheISA::MachInst>(head_inst->staticInst->machInst)); 1049 1050 if (inst_fault != NoFault) { |
1051 head_inst->setCompleted(); |
1052 DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", 1053 head_inst->seqNum, head_inst->readPC()); 1054 1055 if (iewStage->hasStoresToWB() || inst_num > 0) { 1056 DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); 1057 return false; 1058 } 1059 |
1060#if USE_CHECKER 1061 if (cpu->checker && head_inst->isStore()) { 1062 cpu->checker->verify(head_inst); 1063 } 1064#endif 1065 1066 assert(!thread[tid]->inSyscall); 1067 --- 9 unchanged lines hidden (view full) --- 1077 // that the trap need. 1078 cpu->trap(inst_fault, tid); 1079 1080 // Exit state update mode to avoid accidental updating. 1081 thread[tid]->inSyscall = false; 1082 1083 commitStatus[tid] = TrapPending; 1084 |
1085 // Generate trap squash event. 1086 generateTrapEvent(tid); 1087// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC()); 1088 return false; 1089 } 1090 1091 updateComInstStats(head_inst); 1092 --- 8 unchanged lines hidden (view full) --- 1101 if (node) 1102 thread[tid]->profileNode = node; 1103 } 1104#endif 1105 1106 if (head_inst->traceData) { 1107 head_inst->traceData->setFetchSeq(head_inst->seqNum); 1108 head_inst->traceData->setCPSeq(thread[tid]->numInst); |
1109 head_inst->traceData->dump(); 1110 delete head_inst->traceData; |
1111 head_inst->traceData = NULL; 1112 } 1113 1114 // Update the commit rename map 1115 for (int i = 0; i < head_inst->numDestRegs(); i++) { 1116 renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i), 1117 head_inst->renamedDestRegIdx(i)); 1118 } 1119 1120 if (head_inst->isCopy()) 1121 panic("Should not commit any copy instructions!"); 1122 1123 // Finally clear the head ROB entry. 1124 rob->retireHead(tid); 1125 |
1126 // Return true to indicate that we have committed an instruction. 1127 return true; 1128} 1129 1130template <class Impl> 1131void 1132DefaultCommit<Impl>::getInsts() 1133{ --- 28 unchanged lines hidden (view full) --- 1162 inst = fromRename->insts[rename_idx++]; 1163 } 1164#else 1165 inst = fromRename->insts[inst_num]; 1166#endif 1167 int tid = inst->threadNumber; 1168 1169 if (!inst->isSquashed() && |
1170 commitStatus[tid] != ROBSquashing) { |
1171 changedROBNumEntries[tid] = true; 1172 1173 DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n", 1174 inst->readPC(), inst->seqNum, tid); 1175 1176 rob->insertInst(inst); 1177 1178 assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid)); --- 245 unchanged lines hidden --- |