1/* 2 * Copyright (c) 2011-2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 243 unchanged lines hidden (view full) --- 252 renameQueue(params->backComSize, params->forwardComSize), 253 iewQueue(params->backComSize, params->forwardComSize), 254 activityRec(name(), NumStages, 255 params->backComSize + params->forwardComSize, 256 params->activity), 257 258 globalSeqNum(1), 259 system(params->system), |
260 drainManager(NULL), |
261 lastRunningCycle(curCycle()) 262{ 263 if (!params->switched_out) { 264 _status = Running; 265 } else { 266 _status = SwitchedOut; 267 } 268 --- 310 unchanged lines hidden (view full) --- 579 .prereq(miscRegfileWrites); 580} 581 582template <class Impl> 583void 584FullO3CPU<Impl>::tick() 585{ 586 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); |
587 assert(!switchedOut()); 588 assert(getDrainState() != Drainable::Drained); |
589 590 ++numCycles; 591 592// activity = false; 593 594 //Tick each of the stages 595 fetch.tick(); 596 --- 18 unchanged lines hidden (view full) --- 615 616 activityRec.advance(); 617 618 if (removeInstsThisCycle) { 619 cleanUpRemovedInsts(); 620 } 621 622 if (!tickEvent.scheduled()) { |
623 if (_status == SwitchedOut) { |
624 DPRINTF(O3CPU, "Switched out!\n"); 625 // increment stat 626 lastRunningCycle = curCycle(); 627 } else if (!activityRec.active() || _status == Idle) { 628 DPRINTF(O3CPU, "Idle!\n"); 629 lastRunningCycle = curCycle(); 630 timesIdled++; 631 } else { 632 schedule(tickEvent, clockEdge(Cycles(1))); 633 DPRINTF(O3CPU, "Scheduling next tick!\n"); 634 } 635 } 636 637 if (!FullSystem) 638 updateThreadPriority(); |
639 640 tryDrain(); |
641} 642 643template <class Impl> 644void 645FullO3CPU<Impl>::init() 646{ 647 BaseCPU::init(); 648 --- 6 unchanged lines hidden (view full) --- 655 for (ThreadID tid = 0; tid < numThreads; ++tid) { 656 // Set noSquashFromTC so that the CPU doesn't squash when initially 657 // setting up registers. 658 thread[tid]->noSquashFromTC = true; 659 // Initialise the ThreadContext's memory proxies 660 thread[tid]->initMemProxies(thread[tid]->getTC()); 661 } 662 |
663 if (FullSystem && !params()->switched_out) { 664 for (ThreadID tid = 0; tid < numThreads; tid++) { 665 ThreadContext *src_tc = threadContexts[tid]; 666 TheISA::initCPU(src_tc, src_tc->contextId()); 667 } 668 } 669 670 // Clear noSquashFromTC. 671 for (int tid = 0; tid < numThreads; ++tid) 672 thread[tid]->noSquashFromTC = false; 673 674 commit.setThreads(thread); 675} 676 677template <class Impl> 678void 679FullO3CPU<Impl>::startup() 680{ 681 fetch.startupStage(); |
682 decode.startupStage(); |
683 iew.startupStage(); 684 rename.startupStage(); 685 commit.startupStage(); 686} 687 688template <class Impl> 689void 690FullO3CPU<Impl>::activateThread(ThreadID tid) 691{ 692 list<ThreadID>::iterator isActive = 693 std::find(activeThreads.begin(), activeThreads.end(), tid); 694 695 DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid); |
696 assert(!switchedOut()); |
697 698 if (isActive == activeThreads.end()) { 699 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 700 tid); 701 702 activeThreads.push_back(tid); 703 } 704} 705 706template <class Impl> 707void 708FullO3CPU<Impl>::deactivateThread(ThreadID tid) 709{ 710 //Remove From Active List, if Active 711 list<ThreadID>::iterator thread_it = 712 std::find(activeThreads.begin(), activeThreads.end(), tid); 713 714 DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid); |
715 assert(!switchedOut()); |
716 717 if (thread_it != activeThreads.end()) { 718 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 719 tid); 720 activeThreads.erase(thread_it); 721 } 722} 723 --- 22 unchanged lines hidden (view full) --- 746 747 return total; 748} 749 750template <class Impl> 751void 752FullO3CPU<Impl>::activateContext(ThreadID tid, Cycles delay) 753{ |
754 assert(!switchedOut()); 755 |
756 // Needs to set each stage to running as well. 757 if (delay){ 758 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 759 "on cycle %d\n", tid, clockEdge(delay)); 760 scheduleActivateThreadEvent(tid, delay); 761 } else { 762 activateThread(tid); 763 } 764 |
765 // We don't want to wake the CPU if it is drained. In that case, 766 // we just want to flag the thread as active and schedule the tick 767 // event from drainResume() instead. 768 if (getDrainState() == Drainable::Drained) 769 return; 770 |
771 // If we are time 0 or if the last activation time is in the past, 772 // schedule the next tick and wake up the fetch unit 773 if (lastActivatedCycle == 0 || lastActivatedCycle < curTick()) { 774 scheduleTickEvent(delay); 775 776 // Be sure to signal that there's some activity so the CPU doesn't 777 // deschedule itself. 778 activityRec.activity(); --- 30 unchanged lines hidden (view full) --- 809 } 810} 811 812template <class Impl> 813void 814FullO3CPU<Impl>::suspendContext(ThreadID tid) 815{ 816 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); |
817 assert(!switchedOut()); |
818 bool deallocated = scheduleDeallocateContext(tid, false, Cycles(1)); 819 // If this was the last thread then unschedule the tick event. 820 if ((activeThreads.size() == 1 && !deallocated) || 821 activeThreads.size() == 0) 822 unscheduleTickEvent(); 823 824 DPRINTF(Quiesce, "Suspending Context\n"); 825 lastRunningCycle = curCycle(); 826 _status = Idle; 827} 828 829template <class Impl> 830void 831FullO3CPU<Impl>::haltContext(ThreadID tid) 832{ 833 //For now, this is the same as deallocate 834 DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); |
835 assert(!switchedOut()); |
836 scheduleDeallocateContext(tid, true, Cycles(1)); 837} 838 839template <class Impl> 840void 841FullO3CPU<Impl>::insertThread(ThreadID tid) 842{ 843 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); --- 280 unchanged lines hidden (view full) --- 1124 activateThread(i); 1125 } 1126} 1127 1128template <class Impl> 1129unsigned int 1130FullO3CPU<Impl>::drain(DrainManager *drain_manager) 1131{ |
1132 // If the CPU isn't doing anything, then return immediately. |
1133 if (switchedOut()) { 1134 setDrainState(Drainable::Drained); |
1135 return 0; |
1136 } |
1137 |
1138 DPRINTF(Drain, "Draining...\n"); 1139 setDrainState(Drainable::Draining); 1140 1141 // We only need to signal a drain to the commit stage as this 1142 // initiates squashing controls the draining. Once the commit 1143 // stage commits an instruction where it is safe to stop, it'll 1144 // squash the rest of the instructions in the pipeline and force 1145 // the fetch stage to stall. The pipeline will be drained once all 1146 // in-flight instructions have retired. |
1147 commit.drain(); 1148 1149 // Wake the CPU and record activity so everything can drain out if 1150 // the CPU was not able to immediately drain. |
1151 if (!isDrained()) { |
1152 drainManager = drain_manager; 1153 1154 wakeCPU(); 1155 activityRec.activity(); 1156 1157 DPRINTF(Drain, "CPU not drained\n"); 1158 1159 return 1; 1160 } else { |
1161 setDrainState(Drainable::Drained); 1162 DPRINTF(Drain, "CPU is already drained\n"); 1163 if (tickEvent.scheduled()) 1164 deschedule(tickEvent); 1165 1166 // Flush out any old data from the time buffers. In 1167 // particular, there might be some data in flight from the 1168 // fetch stage that isn't visible in any of the CPU buffers we 1169 // test in isDrained(). 1170 for (int i = 0; i < timeBuffer.getSize(); ++i) { 1171 timeBuffer.advance(); 1172 fetchQueue.advance(); 1173 decodeQueue.advance(); 1174 renameQueue.advance(); 1175 iewQueue.advance(); 1176 } 1177 1178 drainSanityCheck(); |
1179 return 0; 1180 } 1181} 1182 1183template <class Impl> |
1184bool 1185FullO3CPU<Impl>::tryDrain() 1186{ 1187 if (!drainManager || !isDrained()) 1188 return false; 1189 1190 if (tickEvent.scheduled()) 1191 deschedule(tickEvent); 1192 1193 DPRINTF(Drain, "CPU done draining, processing drain event\n"); 1194 drainManager->signalDrainDone(); 1195 drainManager = NULL; 1196 1197 return true; 1198} 1199 1200template <class Impl> |
1201void |
1202FullO3CPU<Impl>::drainSanityCheck() const |
1203{ |
1204 assert(isDrained()); 1205 fetch.drainSanityCheck(); 1206 decode.drainSanityCheck(); 1207 rename.drainSanityCheck(); 1208 iew.drainSanityCheck(); 1209 commit.drainSanityCheck(); 1210} |
1211 |
1212template <class Impl> 1213bool 1214FullO3CPU<Impl>::isDrained() const 1215{ 1216 bool drained(true); |
1217 |
1218 for (ThreadID i = 0; i < thread.size(); ++i) { 1219 if (activateThreadEvent[i].scheduled()) { 1220 DPRINTF(Drain, "CPU not drained, tread %i has a " 1221 "pending activate event\n", i); 1222 drained = false; 1223 } 1224 if (deallocateContextEvent[i].scheduled()) { 1225 DPRINTF(Drain, "CPU not drained, tread %i has a " 1226 "pending deallocate context event\n", i); 1227 drained = false; 1228 } 1229 } |
1230 |
1231 if (!instList.empty() || !removeList.empty()) { 1232 DPRINTF(Drain, "Main CPU structures not drained.\n"); 1233 drained = false; |
1234 } 1235 |
1236 if (!fetch.isDrained()) { 1237 DPRINTF(Drain, "Fetch not drained.\n"); 1238 drained = false; 1239 } 1240 1241 if (!decode.isDrained()) { 1242 DPRINTF(Drain, "Decode not drained.\n"); 1243 drained = false; 1244 } 1245 1246 if (!rename.isDrained()) { 1247 DPRINTF(Drain, "Rename not drained.\n"); 1248 drained = false; 1249 } 1250 1251 if (!iew.isDrained()) { 1252 DPRINTF(Drain, "IEW not drained.\n"); 1253 drained = false; 1254 } 1255 1256 if (!commit.isDrained()) { 1257 DPRINTF(Drain, "Commit not drained.\n"); 1258 drained = false; 1259 } 1260 1261 return drained; |
1262} 1263 1264template <class Impl> 1265void |
1266FullO3CPU<Impl>::commitDrained(ThreadID tid) |
1267{ |
1268 fetch.drainStall(tid); 1269} |
1270 |
1271template <class Impl> 1272void 1273FullO3CPU<Impl>::drainResume() 1274{ 1275 setDrainState(Drainable::Running); 1276 if (switchedOut()) 1277 return; |
1278 |
1279 DPRINTF(Drain, "Resuming...\n"); 1280 1281 if (system->getMemoryMode() != Enums::timing) { 1282 fatal("The O3 CPU requires the memory system to be in " 1283 "'timing' mode.\n"); 1284 } 1285 1286 fetch.drainResume(); 1287 commit.drainResume(); 1288 1289 _status = Idle; 1290 for (ThreadID i = 0; i < thread.size(); i++) { 1291 if (thread[i]->status() == ThreadContext::Active) { 1292 DPRINTF(Drain, "Activating thread: %i\n", i); 1293 activateThread(i); 1294 _status = Running; |
1295 } 1296 } |
1297 1298 assert(!tickEvent.scheduled()); 1299 if (_status == Running) 1300 schedule(tickEvent, nextCycle()); |
1301} 1302 1303template <class Impl> 1304void 1305FullO3CPU<Impl>::switchOut() 1306{ |
1307 DPRINTF(O3CPU, "Switching out\n"); |
1308 BaseCPU::switchOut(); 1309 |
1310 activityRec.reset(); |
1311 1312 _status = SwitchedOut; 1313 1314 if (checker) 1315 checker->switchOut(); |
1316} 1317 1318template <class Impl> 1319void 1320FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 1321{ |
1322 BaseCPU::takeOverFrom(oldCPU); 1323 1324 fetch.takeOverFrom(); 1325 decode.takeOverFrom(); 1326 rename.takeOverFrom(); 1327 iew.takeOverFrom(); 1328 commit.takeOverFrom(); 1329 |
1330 assert(!tickEvent.scheduled()); |
1331 1332 FullO3CPU<Impl> *oldO3CPU = dynamic_cast<FullO3CPU<Impl>*>(oldCPU); 1333 if (oldO3CPU) 1334 globalSeqNum = oldO3CPU->globalSeqNum; 1335 |
1336 lastRunningCycle = curCycle(); |
1337 _status = Idle; |
1338} 1339 1340template <class Impl> 1341TheISA::MiscReg 1342FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid) 1343{ 1344 return this->isa[tid]->readMiscRegNoEffect(misc_reg); 1345} --- 459 unchanged lines hidden --- |