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; 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. 15 * 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. 27 * 28 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/full_system.hh" 33#include "config/use_checker.hh" 34 35#if FULL_SYSTEM 36#include "sim/system.hh" 37#else 38#include "sim/process.hh" 39#endif 40 41#include "cpu/activity.hh" 42#include "cpu/simple_thread.hh" 43#include "cpu/thread_context.hh" 44#include "cpu/o3/isa_specific.hh" 45#include "cpu/o3/cpu.hh" 46 47#include "sim/root.hh" 48#include "sim/stat_control.hh" 49 50#if USE_CHECKER 51#include "cpu/checker/cpu.hh" 52#endif 53 54using namespace std; 55using namespace TheISA; 56 57BaseO3CPU::BaseO3CPU(Params *params) 58 : BaseCPU(params), cpu_id(0) 59{ 60} 61 62void 63BaseO3CPU::regStats() 64{ 65 BaseCPU::regStats(); 66} 67 68template <class Impl> 69FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 70 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 71{ 72} 73 74template <class Impl> 75void 76FullO3CPU<Impl>::TickEvent::process() 77{ 78 cpu->tick(); 79} 80 81template <class Impl> 82const char * 83FullO3CPU<Impl>::TickEvent::description() 84{ 85 return "FullO3CPU tick event"; 86} 87 88template <class Impl> 89FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 90 : Event(&mainEventQueue, CPU_Tick_Pri) 91{ 92} 93 94template <class Impl> 95void 96FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 97 FullO3CPU<Impl> *thread_cpu) 98{ 99 tid = thread_num; 100 cpu = thread_cpu; 101} 102 103template <class Impl> 104void 105FullO3CPU<Impl>::ActivateThreadEvent::process() 106{ 107 cpu->activateThread(tid); 108} 109 110template <class Impl> 111const char * 112FullO3CPU<Impl>::ActivateThreadEvent::description() 113{ 114 return "FullO3CPU \"Activate Thread\" event"; 115} 116 117template <class Impl> 118FullO3CPU<Impl>::FullO3CPU(Params *params) 119 : BaseO3CPU(params), 120 tickEvent(this), 121 removeInstsThisCycle(false), 122 fetch(params), 123 decode(params), 124 rename(params), 125 iew(params), 126 commit(params), 127 128 regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 129 130 freeList(params->numberOfThreads, 131 TheISA::NumIntRegs, params->numPhysIntRegs, 132 TheISA::NumFloatRegs, params->numPhysFloatRegs), 133 134 rob(params->numROBEntries, params->squashWidth, 135 params->smtROBPolicy, params->smtROBThreshold, 136 params->numberOfThreads), 137 138 scoreboard(params->numberOfThreads, 139 TheISA::NumIntRegs, params->numPhysIntRegs, 140 TheISA::NumFloatRegs, params->numPhysFloatRegs, 141 TheISA::NumMiscRegs * number_of_threads, 142 TheISA::ZeroReg), 143 144 // For now just have these time buffers be pretty big. 145 // @todo: Make these time buffer sizes parameters or derived 146 // from latencies 147 timeBuffer(5, 5), 148 fetchQueue(5, 5), 149 decodeQueue(5, 5), 150 renameQueue(5, 5), 151 iewQueue(5, 5), 152 activityRec(NumStages, 10, params->activity), 153 154 globalSeqNum(1), 155 156#if FULL_SYSTEM 157 system(params->system), 158 physmem(system->physmem), 159#endif // FULL_SYSTEM 160 mem(params->mem),
| 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; 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. 15 * 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. 27 * 28 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/full_system.hh" 33#include "config/use_checker.hh" 34 35#if FULL_SYSTEM 36#include "sim/system.hh" 37#else 38#include "sim/process.hh" 39#endif 40 41#include "cpu/activity.hh" 42#include "cpu/simple_thread.hh" 43#include "cpu/thread_context.hh" 44#include "cpu/o3/isa_specific.hh" 45#include "cpu/o3/cpu.hh" 46 47#include "sim/root.hh" 48#include "sim/stat_control.hh" 49 50#if USE_CHECKER 51#include "cpu/checker/cpu.hh" 52#endif 53 54using namespace std; 55using namespace TheISA; 56 57BaseO3CPU::BaseO3CPU(Params *params) 58 : BaseCPU(params), cpu_id(0) 59{ 60} 61 62void 63BaseO3CPU::regStats() 64{ 65 BaseCPU::regStats(); 66} 67 68template <class Impl> 69FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 70 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 71{ 72} 73 74template <class Impl> 75void 76FullO3CPU<Impl>::TickEvent::process() 77{ 78 cpu->tick(); 79} 80 81template <class Impl> 82const char * 83FullO3CPU<Impl>::TickEvent::description() 84{ 85 return "FullO3CPU tick event"; 86} 87 88template <class Impl> 89FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 90 : Event(&mainEventQueue, CPU_Tick_Pri) 91{ 92} 93 94template <class Impl> 95void 96FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 97 FullO3CPU<Impl> *thread_cpu) 98{ 99 tid = thread_num; 100 cpu = thread_cpu; 101} 102 103template <class Impl> 104void 105FullO3CPU<Impl>::ActivateThreadEvent::process() 106{ 107 cpu->activateThread(tid); 108} 109 110template <class Impl> 111const char * 112FullO3CPU<Impl>::ActivateThreadEvent::description() 113{ 114 return "FullO3CPU \"Activate Thread\" event"; 115} 116 117template <class Impl> 118FullO3CPU<Impl>::FullO3CPU(Params *params) 119 : BaseO3CPU(params), 120 tickEvent(this), 121 removeInstsThisCycle(false), 122 fetch(params), 123 decode(params), 124 rename(params), 125 iew(params), 126 commit(params), 127 128 regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 129 130 freeList(params->numberOfThreads, 131 TheISA::NumIntRegs, params->numPhysIntRegs, 132 TheISA::NumFloatRegs, params->numPhysFloatRegs), 133 134 rob(params->numROBEntries, params->squashWidth, 135 params->smtROBPolicy, params->smtROBThreshold, 136 params->numberOfThreads), 137 138 scoreboard(params->numberOfThreads, 139 TheISA::NumIntRegs, params->numPhysIntRegs, 140 TheISA::NumFloatRegs, params->numPhysFloatRegs, 141 TheISA::NumMiscRegs * number_of_threads, 142 TheISA::ZeroReg), 143 144 // For now just have these time buffers be pretty big. 145 // @todo: Make these time buffer sizes parameters or derived 146 // from latencies 147 timeBuffer(5, 5), 148 fetchQueue(5, 5), 149 decodeQueue(5, 5), 150 renameQueue(5, 5), 151 iewQueue(5, 5), 152 activityRec(NumStages, 10, params->activity), 153 154 globalSeqNum(1), 155 156#if FULL_SYSTEM 157 system(params->system), 158 physmem(system->physmem), 159#endif // FULL_SYSTEM 160 mem(params->mem),
|
161 switchCount(0),
| 161 drainCount(0),
|
162 deferRegistration(params->deferRegistration), 163 numThreads(number_of_threads) 164{ 165 _status = Idle; 166 167 checker = NULL; 168 169 if (params->checker) { 170#if USE_CHECKER 171 BaseCPU *temp_checker = params->checker; 172 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 173 checker->setMemory(mem); 174#if FULL_SYSTEM 175 checker->setSystem(params->system); 176#endif 177#else 178 panic("Checker enabled but not compiled in!"); 179#endif // USE_CHECKER 180 } 181 182#if !FULL_SYSTEM 183 thread.resize(number_of_threads); 184 tids.resize(number_of_threads); 185#endif 186 187 // The stages also need their CPU pointer setup. However this 188 // must be done at the upper level CPU because they have pointers 189 // to the upper level CPU, and not this FullO3CPU. 190 191 // Set up Pointers to the activeThreads list for each stage 192 fetch.setActiveThreads(&activeThreads); 193 decode.setActiveThreads(&activeThreads); 194 rename.setActiveThreads(&activeThreads); 195 iew.setActiveThreads(&activeThreads); 196 commit.setActiveThreads(&activeThreads); 197 198 // Give each of the stages the time buffer they will use. 199 fetch.setTimeBuffer(&timeBuffer); 200 decode.setTimeBuffer(&timeBuffer); 201 rename.setTimeBuffer(&timeBuffer); 202 iew.setTimeBuffer(&timeBuffer); 203 commit.setTimeBuffer(&timeBuffer); 204 205 // Also setup each of the stages' queues. 206 fetch.setFetchQueue(&fetchQueue); 207 decode.setFetchQueue(&fetchQueue); 208 commit.setFetchQueue(&fetchQueue); 209 decode.setDecodeQueue(&decodeQueue); 210 rename.setDecodeQueue(&decodeQueue); 211 rename.setRenameQueue(&renameQueue); 212 iew.setRenameQueue(&renameQueue); 213 iew.setIEWQueue(&iewQueue); 214 commit.setIEWQueue(&iewQueue); 215 commit.setRenameQueue(&renameQueue); 216 217 commit.setFetchStage(&fetch); 218 commit.setIEWStage(&iew); 219 rename.setIEWStage(&iew); 220 rename.setCommitStage(&commit); 221 222#if !FULL_SYSTEM 223 int active_threads = params->workload.size(); 224 225 if (active_threads > Impl::MaxThreads) { 226 panic("Workload Size too large. Increase the 'MaxThreads'" 227 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 228 "edit your workload size."); 229 } 230#else 231 int active_threads = 1; 232#endif 233 234 //Make Sure That this a Valid Architeture 235 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 236 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 237 238 rename.setScoreboard(&scoreboard); 239 iew.setScoreboard(&scoreboard); 240 241 // Setup the rename map for whichever stages need it. 242 PhysRegIndex lreg_idx = 0; 243 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 244 245 for (int tid=0; tid < numThreads; tid++) { 246 bool bindRegs = (tid <= active_threads - 1); 247 248 commitRenameMap[tid].init(TheISA::NumIntRegs, 249 params->numPhysIntRegs, 250 lreg_idx, //Index for Logical. Regs 251 252 TheISA::NumFloatRegs, 253 params->numPhysFloatRegs, 254 freg_idx, //Index for Float Regs 255 256 TheISA::NumMiscRegs, 257 258 TheISA::ZeroReg, 259 TheISA::ZeroReg, 260 261 tid, 262 false); 263 264 renameMap[tid].init(TheISA::NumIntRegs, 265 params->numPhysIntRegs, 266 lreg_idx, //Index for Logical. Regs 267 268 TheISA::NumFloatRegs, 269 params->numPhysFloatRegs, 270 freg_idx, //Index for Float Regs 271 272 TheISA::NumMiscRegs, 273 274 TheISA::ZeroReg, 275 TheISA::ZeroReg, 276 277 tid, 278 bindRegs); 279 } 280 281 rename.setRenameMap(renameMap); 282 commit.setRenameMap(commitRenameMap); 283 284 // Give renameMap & rename stage access to the freeList; 285 for (int i=0; i < numThreads; i++) { 286 renameMap[i].setFreeList(&freeList); 287 } 288 rename.setFreeList(&freeList); 289 290 // Setup the ROB for whichever stages need it. 291 commit.setROB(&rob); 292 293 lastRunningCycle = curTick; 294 295 lastActivatedCycle = -1; 296 297 contextSwitch = false; 298} 299 300template <class Impl> 301FullO3CPU<Impl>::~FullO3CPU() 302{ 303} 304 305template <class Impl> 306void 307FullO3CPU<Impl>::fullCPURegStats() 308{ 309 BaseO3CPU::regStats(); 310 311 // Register any of the O3CPU's stats here. 312 timesIdled 313 .name(name() + ".timesIdled") 314 .desc("Number of times that the entire CPU went into an idle state and" 315 " unscheduled itself") 316 .prereq(timesIdled); 317 318 idleCycles 319 .name(name() + ".idleCycles") 320 .desc("Total number of cycles that the CPU has spent unscheduled due " 321 "to idling") 322 .prereq(idleCycles); 323 324 // Number of Instructions simulated 325 // -------------------------------- 326 // Should probably be in Base CPU but need templated 327 // MaxThreads so put in here instead 328 committedInsts 329 .init(numThreads) 330 .name(name() + ".committedInsts") 331 .desc("Number of Instructions Simulated"); 332 333 totalCommittedInsts 334 .name(name() + ".committedInsts_total") 335 .desc("Number of Instructions Simulated"); 336 337 cpi 338 .name(name() + ".cpi") 339 .desc("CPI: Cycles Per Instruction") 340 .precision(6); 341 cpi = simTicks / committedInsts; 342 343 totalCpi 344 .name(name() + ".cpi_total") 345 .desc("CPI: Total CPI of All Threads") 346 .precision(6); 347 totalCpi = simTicks / totalCommittedInsts; 348 349 ipc 350 .name(name() + ".ipc") 351 .desc("IPC: Instructions Per Cycle") 352 .precision(6); 353 ipc = committedInsts / simTicks; 354 355 totalIpc 356 .name(name() + ".ipc_total") 357 .desc("IPC: Total IPC of All Threads") 358 .precision(6); 359 totalIpc = totalCommittedInsts / simTicks; 360 361} 362 363template <class Impl> 364void 365FullO3CPU<Impl>::tick() 366{ 367 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 368 369 ++numCycles; 370 371// activity = false; 372 373 //Tick each of the stages 374 fetch.tick(); 375 376 decode.tick(); 377 378 rename.tick(); 379 380 iew.tick(); 381 382 commit.tick(); 383 384#if !FULL_SYSTEM 385 doContextSwitch(); 386#endif 387 388 // Now advance the time buffers 389 timeBuffer.advance(); 390 391 fetchQueue.advance(); 392 decodeQueue.advance(); 393 renameQueue.advance(); 394 iewQueue.advance(); 395 396 activityRec.advance(); 397 398 if (removeInstsThisCycle) { 399 cleanUpRemovedInsts(); 400 } 401 402 if (!tickEvent.scheduled()) { 403 if (_status == SwitchedOut) { 404 // increment stat 405 lastRunningCycle = curTick; 406 } else if (!activityRec.active()) { 407 lastRunningCycle = curTick; 408 timesIdled++; 409 } else { 410 tickEvent.schedule(curTick + cycles(1)); 411 } 412 } 413 414#if !FULL_SYSTEM 415 updateThreadPriority(); 416#endif 417 418} 419 420template <class Impl> 421void 422FullO3CPU<Impl>::init() 423{ 424 if (!deferRegistration) { 425 registerThreadContexts(); 426 } 427 428 // Set inSyscall so that the CPU doesn't squash when initially 429 // setting up registers. 430 for (int i = 0; i < number_of_threads; ++i) 431 thread[i]->inSyscall = true; 432 433 for (int tid=0; tid < number_of_threads; tid++) { 434#if FULL_SYSTEM 435 ThreadContext *src_tc = threadContexts[tid]; 436#else 437 ThreadContext *src_tc = thread[tid]->getTC(); 438#endif 439 // Threads start in the Suspended State 440 if (src_tc->status() != ThreadContext::Suspended) { 441 continue; 442 } 443 444#if FULL_SYSTEM 445 TheISA::initCPU(src_tc, src_tc->readCpuId()); 446#endif 447 } 448 449 // Clear inSyscall. 450 for (int i = 0; i < number_of_threads; ++i) 451 thread[i]->inSyscall = false; 452 453 // Initialize stages. 454 fetch.initStage(); 455 iew.initStage(); 456 rename.initStage(); 457 commit.initStage(); 458 459 commit.setThreads(thread); 460} 461 462template <class Impl> 463void 464FullO3CPU<Impl>::insertThread(unsigned tid) 465{ 466 DPRINTF(O3CPU,"[tid:%i] Initializing thread data"); 467 // Will change now that the PC and thread state is internal to the CPU 468 // and not in the ThreadContext. 469#if 0 470#if FULL_SYSTEM 471 ThreadContext *src_tc = system->threadContexts[tid]; 472#else 473 ThreadContext *src_tc = thread[tid]; 474#endif 475 476 //Bind Int Regs to Rename Map 477 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 478 PhysRegIndex phys_reg = freeList.getIntReg(); 479 480 renameMap[tid].setEntry(ireg,phys_reg); 481 scoreboard.setReg(phys_reg); 482 } 483 484 //Bind Float Regs to Rename Map 485 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 486 PhysRegIndex phys_reg = freeList.getFloatReg(); 487 488 renameMap[tid].setEntry(freg,phys_reg); 489 scoreboard.setReg(phys_reg); 490 } 491 492 //Copy Thread Data Into RegFile 493 this->copyFromTC(tid); 494 495 //Set PC/NPC 496 regFile.pc[tid] = src_tc->readPC(); 497 regFile.npc[tid] = src_tc->readNextPC(); 498 499 src_tc->setStatus(ThreadContext::Active); 500 501 activateContext(tid,1); 502 503 //Reset ROB/IQ/LSQ Entries 504 commit.rob->resetEntries(); 505 iew.resetEntries(); 506#endif 507} 508 509template <class Impl> 510void 511FullO3CPU<Impl>::removeThread(unsigned tid) 512{ 513 DPRINTF(O3CPU,"[tid:%i] Removing thread data"); 514#if 0 515 //Unbind Int Regs from Rename Map 516 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 517 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 518 519 scoreboard.unsetReg(phys_reg); 520 freeList.addReg(phys_reg); 521 } 522 523 //Unbind Float Regs from Rename Map 524 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 525 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 526 527 scoreboard.unsetReg(phys_reg); 528 freeList.addReg(phys_reg); 529 } 530 531 //Copy Thread Data From RegFile 532 /* Fix Me: 533 * Do we really need to do this if we are removing a thread 534 * in the sense that it's finished (exiting)? If the thread is just 535 * being suspended we might... 536 */ 537// this->copyToTC(tid); 538 539 //Squash Throughout Pipeline 540 fetch.squash(0,tid); 541 decode.squash(tid); 542 rename.squash(tid); 543 544 assert(iew.ldstQueue.getCount(tid) == 0); 545 546 //Reset ROB/IQ/LSQ Entries 547 if (activeThreads.size() >= 1) { 548 commit.rob->resetEntries(); 549 iew.resetEntries(); 550 } 551#endif 552} 553 554 555template <class Impl> 556void 557FullO3CPU<Impl>::activateWhenReady(int tid) 558{ 559 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 560 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 561 tid); 562 563 bool ready = true; 564 565 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 566 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 567 "Phys. Int. Regs.\n", 568 tid); 569 ready = false; 570 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 571 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 572 "Phys. Float. Regs.\n", 573 tid); 574 ready = false; 575 } else if (commit.rob->numFreeEntries() >= 576 commit.rob->entryAmount(activeThreads.size() + 1)) { 577 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 578 "ROB entries.\n", 579 tid); 580 ready = false; 581 } else if (iew.instQueue.numFreeEntries() >= 582 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 583 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 584 "IQ entries.\n", 585 tid); 586 ready = false; 587 } else if (iew.ldstQueue.numFreeEntries() >= 588 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 589 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 590 "LSQ entries.\n", 591 tid); 592 ready = false; 593 } 594 595 if (ready) { 596 insertThread(tid); 597 598 contextSwitch = false; 599 600 cpuWaitList.remove(tid); 601 } else { 602 suspendContext(tid); 603 604 //blocks fetch 605 contextSwitch = true; 606 607 //do waitlist 608 cpuWaitList.push_back(tid); 609 } 610} 611 612template <class Impl> 613void 614FullO3CPU<Impl>::activateThread(unsigned int tid) 615{ 616 list<unsigned>::iterator isActive = find( 617 activeThreads.begin(), activeThreads.end(), tid); 618 619 if (isActive == activeThreads.end()) { 620 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 621 tid); 622 623 activeThreads.push_back(tid); 624 } 625} 626 627 628template <class Impl> 629void 630FullO3CPU<Impl>::activateContext(int tid, int delay) 631{ 632 // Needs to set each stage to running as well. 633 if (delay){ 634 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 635 "on cycle %d\n", tid, curTick + cycles(delay)); 636 scheduleActivateThreadEvent(tid, delay); 637 } else { 638 activateThread(tid); 639 } 640 641 if(lastActivatedCycle < curTick) { 642 scheduleTickEvent(delay); 643 644 // Be sure to signal that there's some activity so the CPU doesn't 645 // deschedule itself. 646 activityRec.activity(); 647 fetch.wakeFromQuiesce(); 648 649 lastActivatedCycle = curTick; 650 651 _status = Running; 652 } 653} 654 655template <class Impl> 656void 657FullO3CPU<Impl>::suspendContext(int tid) 658{ 659 DPRINTF(O3CPU,"[tid: %i]: Suspended ...\n", tid); 660 unscheduleTickEvent(); 661 _status = Idle; 662/* 663 //Remove From Active List, if Active 664 list<unsigned>::iterator isActive = find( 665 activeThreads.begin(), activeThreads.end(), tid); 666 667 if (isActive != activeThreads.end()) { 668 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 669 tid); 670 activeThreads.erase(isActive); 671 } 672*/ 673} 674 675template <class Impl> 676void 677FullO3CPU<Impl>::deallocateContext(int tid) 678{ 679 DPRINTF(O3CPU,"[tid:%i]: Deallocating ...", tid); 680/* 681 //Remove From Active List, if Active 682 list<unsigned>::iterator isActive = find( 683 activeThreads.begin(), activeThreads.end(), tid); 684 685 if (isActive != activeThreads.end()) { 686 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 687 tid); 688 activeThreads.erase(isActive); 689 690 removeThread(tid); 691 } 692*/ 693} 694 695template <class Impl> 696void 697FullO3CPU<Impl>::haltContext(int tid) 698{ 699 DPRINTF(O3CPU,"[tid:%i]: Halted ...", tid); 700/* 701 //Remove From Active List, if Active 702 list<unsigned>::iterator isActive = find( 703 activeThreads.begin(), activeThreads.end(), tid); 704 705 if (isActive != activeThreads.end()) { 706 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 707 tid); 708 activeThreads.erase(isActive); 709 710 removeThread(tid); 711 } 712*/ 713} 714 715template <class Impl>
| 162 deferRegistration(params->deferRegistration), 163 numThreads(number_of_threads) 164{ 165 _status = Idle; 166 167 checker = NULL; 168 169 if (params->checker) { 170#if USE_CHECKER 171 BaseCPU *temp_checker = params->checker; 172 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 173 checker->setMemory(mem); 174#if FULL_SYSTEM 175 checker->setSystem(params->system); 176#endif 177#else 178 panic("Checker enabled but not compiled in!"); 179#endif // USE_CHECKER 180 } 181 182#if !FULL_SYSTEM 183 thread.resize(number_of_threads); 184 tids.resize(number_of_threads); 185#endif 186 187 // The stages also need their CPU pointer setup. However this 188 // must be done at the upper level CPU because they have pointers 189 // to the upper level CPU, and not this FullO3CPU. 190 191 // Set up Pointers to the activeThreads list for each stage 192 fetch.setActiveThreads(&activeThreads); 193 decode.setActiveThreads(&activeThreads); 194 rename.setActiveThreads(&activeThreads); 195 iew.setActiveThreads(&activeThreads); 196 commit.setActiveThreads(&activeThreads); 197 198 // Give each of the stages the time buffer they will use. 199 fetch.setTimeBuffer(&timeBuffer); 200 decode.setTimeBuffer(&timeBuffer); 201 rename.setTimeBuffer(&timeBuffer); 202 iew.setTimeBuffer(&timeBuffer); 203 commit.setTimeBuffer(&timeBuffer); 204 205 // Also setup each of the stages' queues. 206 fetch.setFetchQueue(&fetchQueue); 207 decode.setFetchQueue(&fetchQueue); 208 commit.setFetchQueue(&fetchQueue); 209 decode.setDecodeQueue(&decodeQueue); 210 rename.setDecodeQueue(&decodeQueue); 211 rename.setRenameQueue(&renameQueue); 212 iew.setRenameQueue(&renameQueue); 213 iew.setIEWQueue(&iewQueue); 214 commit.setIEWQueue(&iewQueue); 215 commit.setRenameQueue(&renameQueue); 216 217 commit.setFetchStage(&fetch); 218 commit.setIEWStage(&iew); 219 rename.setIEWStage(&iew); 220 rename.setCommitStage(&commit); 221 222#if !FULL_SYSTEM 223 int active_threads = params->workload.size(); 224 225 if (active_threads > Impl::MaxThreads) { 226 panic("Workload Size too large. Increase the 'MaxThreads'" 227 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 228 "edit your workload size."); 229 } 230#else 231 int active_threads = 1; 232#endif 233 234 //Make Sure That this a Valid Architeture 235 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 236 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 237 238 rename.setScoreboard(&scoreboard); 239 iew.setScoreboard(&scoreboard); 240 241 // Setup the rename map for whichever stages need it. 242 PhysRegIndex lreg_idx = 0; 243 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 244 245 for (int tid=0; tid < numThreads; tid++) { 246 bool bindRegs = (tid <= active_threads - 1); 247 248 commitRenameMap[tid].init(TheISA::NumIntRegs, 249 params->numPhysIntRegs, 250 lreg_idx, //Index for Logical. Regs 251 252 TheISA::NumFloatRegs, 253 params->numPhysFloatRegs, 254 freg_idx, //Index for Float Regs 255 256 TheISA::NumMiscRegs, 257 258 TheISA::ZeroReg, 259 TheISA::ZeroReg, 260 261 tid, 262 false); 263 264 renameMap[tid].init(TheISA::NumIntRegs, 265 params->numPhysIntRegs, 266 lreg_idx, //Index for Logical. Regs 267 268 TheISA::NumFloatRegs, 269 params->numPhysFloatRegs, 270 freg_idx, //Index for Float Regs 271 272 TheISA::NumMiscRegs, 273 274 TheISA::ZeroReg, 275 TheISA::ZeroReg, 276 277 tid, 278 bindRegs); 279 } 280 281 rename.setRenameMap(renameMap); 282 commit.setRenameMap(commitRenameMap); 283 284 // Give renameMap & rename stage access to the freeList; 285 for (int i=0; i < numThreads; i++) { 286 renameMap[i].setFreeList(&freeList); 287 } 288 rename.setFreeList(&freeList); 289 290 // Setup the ROB for whichever stages need it. 291 commit.setROB(&rob); 292 293 lastRunningCycle = curTick; 294 295 lastActivatedCycle = -1; 296 297 contextSwitch = false; 298} 299 300template <class Impl> 301FullO3CPU<Impl>::~FullO3CPU() 302{ 303} 304 305template <class Impl> 306void 307FullO3CPU<Impl>::fullCPURegStats() 308{ 309 BaseO3CPU::regStats(); 310 311 // Register any of the O3CPU's stats here. 312 timesIdled 313 .name(name() + ".timesIdled") 314 .desc("Number of times that the entire CPU went into an idle state and" 315 " unscheduled itself") 316 .prereq(timesIdled); 317 318 idleCycles 319 .name(name() + ".idleCycles") 320 .desc("Total number of cycles that the CPU has spent unscheduled due " 321 "to idling") 322 .prereq(idleCycles); 323 324 // Number of Instructions simulated 325 // -------------------------------- 326 // Should probably be in Base CPU but need templated 327 // MaxThreads so put in here instead 328 committedInsts 329 .init(numThreads) 330 .name(name() + ".committedInsts") 331 .desc("Number of Instructions Simulated"); 332 333 totalCommittedInsts 334 .name(name() + ".committedInsts_total") 335 .desc("Number of Instructions Simulated"); 336 337 cpi 338 .name(name() + ".cpi") 339 .desc("CPI: Cycles Per Instruction") 340 .precision(6); 341 cpi = simTicks / committedInsts; 342 343 totalCpi 344 .name(name() + ".cpi_total") 345 .desc("CPI: Total CPI of All Threads") 346 .precision(6); 347 totalCpi = simTicks / totalCommittedInsts; 348 349 ipc 350 .name(name() + ".ipc") 351 .desc("IPC: Instructions Per Cycle") 352 .precision(6); 353 ipc = committedInsts / simTicks; 354 355 totalIpc 356 .name(name() + ".ipc_total") 357 .desc("IPC: Total IPC of All Threads") 358 .precision(6); 359 totalIpc = totalCommittedInsts / simTicks; 360 361} 362 363template <class Impl> 364void 365FullO3CPU<Impl>::tick() 366{ 367 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 368 369 ++numCycles; 370 371// activity = false; 372 373 //Tick each of the stages 374 fetch.tick(); 375 376 decode.tick(); 377 378 rename.tick(); 379 380 iew.tick(); 381 382 commit.tick(); 383 384#if !FULL_SYSTEM 385 doContextSwitch(); 386#endif 387 388 // Now advance the time buffers 389 timeBuffer.advance(); 390 391 fetchQueue.advance(); 392 decodeQueue.advance(); 393 renameQueue.advance(); 394 iewQueue.advance(); 395 396 activityRec.advance(); 397 398 if (removeInstsThisCycle) { 399 cleanUpRemovedInsts(); 400 } 401 402 if (!tickEvent.scheduled()) { 403 if (_status == SwitchedOut) { 404 // increment stat 405 lastRunningCycle = curTick; 406 } else if (!activityRec.active()) { 407 lastRunningCycle = curTick; 408 timesIdled++; 409 } else { 410 tickEvent.schedule(curTick + cycles(1)); 411 } 412 } 413 414#if !FULL_SYSTEM 415 updateThreadPriority(); 416#endif 417 418} 419 420template <class Impl> 421void 422FullO3CPU<Impl>::init() 423{ 424 if (!deferRegistration) { 425 registerThreadContexts(); 426 } 427 428 // Set inSyscall so that the CPU doesn't squash when initially 429 // setting up registers. 430 for (int i = 0; i < number_of_threads; ++i) 431 thread[i]->inSyscall = true; 432 433 for (int tid=0; tid < number_of_threads; tid++) { 434#if FULL_SYSTEM 435 ThreadContext *src_tc = threadContexts[tid]; 436#else 437 ThreadContext *src_tc = thread[tid]->getTC(); 438#endif 439 // Threads start in the Suspended State 440 if (src_tc->status() != ThreadContext::Suspended) { 441 continue; 442 } 443 444#if FULL_SYSTEM 445 TheISA::initCPU(src_tc, src_tc->readCpuId()); 446#endif 447 } 448 449 // Clear inSyscall. 450 for (int i = 0; i < number_of_threads; ++i) 451 thread[i]->inSyscall = false; 452 453 // Initialize stages. 454 fetch.initStage(); 455 iew.initStage(); 456 rename.initStage(); 457 commit.initStage(); 458 459 commit.setThreads(thread); 460} 461 462template <class Impl> 463void 464FullO3CPU<Impl>::insertThread(unsigned tid) 465{ 466 DPRINTF(O3CPU,"[tid:%i] Initializing thread data"); 467 // Will change now that the PC and thread state is internal to the CPU 468 // and not in the ThreadContext. 469#if 0 470#if FULL_SYSTEM 471 ThreadContext *src_tc = system->threadContexts[tid]; 472#else 473 ThreadContext *src_tc = thread[tid]; 474#endif 475 476 //Bind Int Regs to Rename Map 477 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 478 PhysRegIndex phys_reg = freeList.getIntReg(); 479 480 renameMap[tid].setEntry(ireg,phys_reg); 481 scoreboard.setReg(phys_reg); 482 } 483 484 //Bind Float Regs to Rename Map 485 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 486 PhysRegIndex phys_reg = freeList.getFloatReg(); 487 488 renameMap[tid].setEntry(freg,phys_reg); 489 scoreboard.setReg(phys_reg); 490 } 491 492 //Copy Thread Data Into RegFile 493 this->copyFromTC(tid); 494 495 //Set PC/NPC 496 regFile.pc[tid] = src_tc->readPC(); 497 regFile.npc[tid] = src_tc->readNextPC(); 498 499 src_tc->setStatus(ThreadContext::Active); 500 501 activateContext(tid,1); 502 503 //Reset ROB/IQ/LSQ Entries 504 commit.rob->resetEntries(); 505 iew.resetEntries(); 506#endif 507} 508 509template <class Impl> 510void 511FullO3CPU<Impl>::removeThread(unsigned tid) 512{ 513 DPRINTF(O3CPU,"[tid:%i] Removing thread data"); 514#if 0 515 //Unbind Int Regs from Rename Map 516 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 517 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 518 519 scoreboard.unsetReg(phys_reg); 520 freeList.addReg(phys_reg); 521 } 522 523 //Unbind Float Regs from Rename Map 524 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 525 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 526 527 scoreboard.unsetReg(phys_reg); 528 freeList.addReg(phys_reg); 529 } 530 531 //Copy Thread Data From RegFile 532 /* Fix Me: 533 * Do we really need to do this if we are removing a thread 534 * in the sense that it's finished (exiting)? If the thread is just 535 * being suspended we might... 536 */ 537// this->copyToTC(tid); 538 539 //Squash Throughout Pipeline 540 fetch.squash(0,tid); 541 decode.squash(tid); 542 rename.squash(tid); 543 544 assert(iew.ldstQueue.getCount(tid) == 0); 545 546 //Reset ROB/IQ/LSQ Entries 547 if (activeThreads.size() >= 1) { 548 commit.rob->resetEntries(); 549 iew.resetEntries(); 550 } 551#endif 552} 553 554 555template <class Impl> 556void 557FullO3CPU<Impl>::activateWhenReady(int tid) 558{ 559 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 560 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 561 tid); 562 563 bool ready = true; 564 565 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 566 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 567 "Phys. Int. Regs.\n", 568 tid); 569 ready = false; 570 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 571 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 572 "Phys. Float. Regs.\n", 573 tid); 574 ready = false; 575 } else if (commit.rob->numFreeEntries() >= 576 commit.rob->entryAmount(activeThreads.size() + 1)) { 577 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 578 "ROB entries.\n", 579 tid); 580 ready = false; 581 } else if (iew.instQueue.numFreeEntries() >= 582 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 583 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 584 "IQ entries.\n", 585 tid); 586 ready = false; 587 } else if (iew.ldstQueue.numFreeEntries() >= 588 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 589 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 590 "LSQ entries.\n", 591 tid); 592 ready = false; 593 } 594 595 if (ready) { 596 insertThread(tid); 597 598 contextSwitch = false; 599 600 cpuWaitList.remove(tid); 601 } else { 602 suspendContext(tid); 603 604 //blocks fetch 605 contextSwitch = true; 606 607 //do waitlist 608 cpuWaitList.push_back(tid); 609 } 610} 611 612template <class Impl> 613void 614FullO3CPU<Impl>::activateThread(unsigned int tid) 615{ 616 list<unsigned>::iterator isActive = find( 617 activeThreads.begin(), activeThreads.end(), tid); 618 619 if (isActive == activeThreads.end()) { 620 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 621 tid); 622 623 activeThreads.push_back(tid); 624 } 625} 626 627 628template <class Impl> 629void 630FullO3CPU<Impl>::activateContext(int tid, int delay) 631{ 632 // Needs to set each stage to running as well. 633 if (delay){ 634 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 635 "on cycle %d\n", tid, curTick + cycles(delay)); 636 scheduleActivateThreadEvent(tid, delay); 637 } else { 638 activateThread(tid); 639 } 640 641 if(lastActivatedCycle < curTick) { 642 scheduleTickEvent(delay); 643 644 // Be sure to signal that there's some activity so the CPU doesn't 645 // deschedule itself. 646 activityRec.activity(); 647 fetch.wakeFromQuiesce(); 648 649 lastActivatedCycle = curTick; 650 651 _status = Running; 652 } 653} 654 655template <class Impl> 656void 657FullO3CPU<Impl>::suspendContext(int tid) 658{ 659 DPRINTF(O3CPU,"[tid: %i]: Suspended ...\n", tid); 660 unscheduleTickEvent(); 661 _status = Idle; 662/* 663 //Remove From Active List, if Active 664 list<unsigned>::iterator isActive = find( 665 activeThreads.begin(), activeThreads.end(), tid); 666 667 if (isActive != activeThreads.end()) { 668 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 669 tid); 670 activeThreads.erase(isActive); 671 } 672*/ 673} 674 675template <class Impl> 676void 677FullO3CPU<Impl>::deallocateContext(int tid) 678{ 679 DPRINTF(O3CPU,"[tid:%i]: Deallocating ...", tid); 680/* 681 //Remove From Active List, if Active 682 list<unsigned>::iterator isActive = find( 683 activeThreads.begin(), activeThreads.end(), tid); 684 685 if (isActive != activeThreads.end()) { 686 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 687 tid); 688 activeThreads.erase(isActive); 689 690 removeThread(tid); 691 } 692*/ 693} 694 695template <class Impl> 696void 697FullO3CPU<Impl>::haltContext(int tid) 698{ 699 DPRINTF(O3CPU,"[tid:%i]: Halted ...", tid); 700/* 701 //Remove From Active List, if Active 702 list<unsigned>::iterator isActive = find( 703 activeThreads.begin(), activeThreads.end(), tid); 704 705 if (isActive != activeThreads.end()) { 706 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 707 tid); 708 activeThreads.erase(isActive); 709 710 removeThread(tid); 711 } 712*/ 713} 714 715template <class Impl>
|
716void 717FullO3CPU<Impl>::switchOut()
| 716bool 717FullO3CPU<Impl>::drain(Event *drain_event)
|
718{
| 718{
|
719 switchCount = 0; 720 fetch.switchOut(); 721 decode.switchOut(); 722 rename.switchOut(); 723 iew.switchOut(); 724 commit.switchOut();
| 719 drainCount = 0; 720 drainEvent = drain_event; 721 fetch.drain(); 722 decode.drain(); 723 rename.drain(); 724 iew.drain(); 725 commit.drain();
|
725 726 // Wake the CPU and record activity so everything can drain out if 727 // the CPU is currently idle. 728 wakeCPU(); 729 activityRec.activity();
| 726 727 // Wake the CPU and record activity so everything can drain out if 728 // the CPU is currently idle. 729 wakeCPU(); 730 activityRec.activity();
|
| 731 732 return false;
|
730} 731 732template <class Impl> 733void
| 733} 734 735template <class Impl> 736void
|
734FullO3CPU<Impl>::signalSwitched()
| 737FullO3CPU<Impl>::resume()
|
735{
| 738{
|
736 if (++switchCount == NumStages) { 737 fetch.doSwitchOut(); 738 rename.doSwitchOut(); 739 commit.doSwitchOut(); 740 instList.clear(); 741 while (!removeList.empty()) { 742 removeList.pop(); 743 }
| 739 if (_status == SwitchedOut) 740 return; 741 fetch.resume(); 742 decode.resume(); 743 rename.resume(); 744 iew.resume(); 745 commit.resume();
|
744
| 746
|
745#if USE_CHECKER 746 if (checker) 747 checker->switchOut(); 748#endif
| 747 if (!tickEvent.scheduled()) 748 tickEvent.schedule(curTick); 749 _status = Running; 750}
|
749
| 751
|
| 752template <class Impl> 753void 754FullO3CPU<Impl>::signalDrained() 755{ 756 if (++drainCount == NumStages) {
|
750 if (tickEvent.scheduled()) 751 tickEvent.squash();
| 757 if (tickEvent.scheduled()) 758 tickEvent.squash();
|
752 _status = SwitchedOut;
| 759 _status = Drained; 760 drainEvent->process();
|
753 }
| 761 }
|
754 assert(switchCount <= 5);
| 762 assert(drainCount <= 5);
|
755} 756 757template <class Impl> 758void
| 763} 764 765template <class Impl> 766void
|
| 767FullO3CPU<Impl>::switchOut() 768{ 769 fetch.switchOut(); 770 rename.switchOut(); 771 commit.switchOut(); 772 instList.clear(); 773 while (!removeList.empty()) { 774 removeList.pop(); 775 } 776 777 _status = SwitchedOut; 778#if USE_CHECKER 779 if (checker) 780 checker->switchOut(); 781#endif 782} 783 784template <class Impl> 785void
|
759FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 760{ 761 // Flush out any old data from the time buffers. 762 for (int i = 0; i < 10; ++i) { 763 timeBuffer.advance(); 764 fetchQueue.advance(); 765 decodeQueue.advance(); 766 renameQueue.advance(); 767 iewQueue.advance(); 768 } 769 770 activityRec.reset(); 771 772 BaseCPU::takeOverFrom(oldCPU); 773 774 fetch.takeOverFrom(); 775 decode.takeOverFrom(); 776 rename.takeOverFrom(); 777 iew.takeOverFrom(); 778 commit.takeOverFrom(); 779 780 assert(!tickEvent.scheduled()); 781 782 // @todo: Figure out how to properly select the tid to put onto 783 // the active threads list. 784 int tid = 0; 785 786 list<unsigned>::iterator isActive = find( 787 activeThreads.begin(), activeThreads.end(), tid); 788 789 if (isActive == activeThreads.end()) { 790 //May Need to Re-code this if the delay variable is the delay 791 //needed for thread to activate 792 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 793 tid); 794 795 activeThreads.push_back(tid); 796 } 797 798 // Set all statuses to active, schedule the CPU's tick event. 799 // @todo: Fix up statuses so this is handled properly 800 for (int i = 0; i < threadContexts.size(); ++i) { 801 ThreadContext *tc = threadContexts[i]; 802 if (tc->status() == ThreadContext::Active && _status != Running) { 803 _status = Running; 804 tickEvent.schedule(curTick); 805 } 806 } 807 if (!tickEvent.scheduled()) 808 tickEvent.schedule(curTick); 809} 810 811template <class Impl> 812uint64_t 813FullO3CPU<Impl>::readIntReg(int reg_idx) 814{ 815 return regFile.readIntReg(reg_idx); 816} 817 818template <class Impl> 819FloatReg 820FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 821{ 822 return regFile.readFloatReg(reg_idx, width); 823} 824 825template <class Impl> 826FloatReg 827FullO3CPU<Impl>::readFloatReg(int reg_idx) 828{ 829 return regFile.readFloatReg(reg_idx); 830} 831 832template <class Impl> 833FloatRegBits 834FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 835{ 836 return regFile.readFloatRegBits(reg_idx, width); 837} 838 839template <class Impl> 840FloatRegBits 841FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 842{ 843 return regFile.readFloatRegBits(reg_idx); 844} 845 846template <class Impl> 847void 848FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 849{ 850 regFile.setIntReg(reg_idx, val); 851} 852 853template <class Impl> 854void 855FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 856{ 857 regFile.setFloatReg(reg_idx, val, width); 858} 859 860template <class Impl> 861void 862FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 863{ 864 regFile.setFloatReg(reg_idx, val); 865} 866 867template <class Impl> 868void 869FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 870{ 871 regFile.setFloatRegBits(reg_idx, val, width); 872} 873 874template <class Impl> 875void 876FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 877{ 878 regFile.setFloatRegBits(reg_idx, val); 879} 880 881template <class Impl> 882uint64_t 883FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 884{ 885 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 886 887 return regFile.readIntReg(phys_reg); 888} 889 890template <class Impl> 891float 892FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 893{ 894 int idx = reg_idx + TheISA::FP_Base_DepTag; 895 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 896 897 return regFile.readFloatReg(phys_reg); 898} 899 900template <class Impl> 901double 902FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 903{ 904 int idx = reg_idx + TheISA::FP_Base_DepTag; 905 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 906 907 return regFile.readFloatReg(phys_reg, 64); 908} 909 910template <class Impl> 911uint64_t 912FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 913{ 914 int idx = reg_idx + TheISA::FP_Base_DepTag; 915 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 916 917 return regFile.readFloatRegBits(phys_reg); 918} 919 920template <class Impl> 921void 922FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 923{ 924 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 925 926 regFile.setIntReg(phys_reg, val); 927} 928 929template <class Impl> 930void 931FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 932{ 933 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 934 935 regFile.setFloatReg(phys_reg, val); 936} 937 938template <class Impl> 939void 940FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 941{ 942 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 943 944 regFile.setFloatReg(phys_reg, val, 64); 945} 946 947template <class Impl> 948void 949FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 950{ 951 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 952 953 regFile.setFloatRegBits(phys_reg, val); 954} 955 956template <class Impl> 957uint64_t 958FullO3CPU<Impl>::readPC(unsigned tid) 959{ 960 return commit.readPC(tid); 961} 962 963template <class Impl> 964void 965FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 966{ 967 commit.setPC(new_PC, tid); 968} 969 970template <class Impl> 971uint64_t 972FullO3CPU<Impl>::readNextPC(unsigned tid) 973{ 974 return commit.readNextPC(tid); 975} 976 977template <class Impl> 978void 979FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 980{ 981 commit.setNextPC(val, tid); 982} 983 984#if THE_ISA != ALPHA_ISA 985template <class Impl> 986uint64_t 987FullO3CPU<Impl>::readNextNPC(unsigned tid) 988{ 989 return commit.readNextNPC(tid); 990} 991 992template <class Impl> 993void 994FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) 995{ 996 commit.setNextNPC(val, tid); 997} 998#endif 999 1000template <class Impl> 1001typename FullO3CPU<Impl>::ListIt 1002FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1003{ 1004 instList.push_back(inst); 1005 1006 return --(instList.end()); 1007} 1008 1009template <class Impl> 1010void 1011FullO3CPU<Impl>::instDone(unsigned tid) 1012{ 1013 // Keep an instruction count. 1014 thread[tid]->numInst++; 1015 thread[tid]->numInsts++; 1016 committedInsts[tid]++; 1017 totalCommittedInsts++; 1018 1019 // Check for instruction-count-based events. 1020 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1021} 1022 1023template <class Impl> 1024void 1025FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1026{ 1027 removeInstsThisCycle = true; 1028 1029 removeList.push(inst->getInstListIt()); 1030} 1031 1032template <class Impl> 1033void 1034FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1035{ 1036 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1037 "[sn:%lli]\n", 1038 inst->threadNumber, inst->readPC(), inst->seqNum); 1039 1040 removeInstsThisCycle = true; 1041 1042 // Remove the front instruction. 1043 removeList.push(inst->getInstListIt()); 1044} 1045 1046template <class Impl> 1047void 1048FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1049{ 1050 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1051 " list.\n", tid); 1052 1053 ListIt end_it; 1054 1055 bool rob_empty = false; 1056 1057 if (instList.empty()) { 1058 return; 1059 } else if (rob.isEmpty(/*tid*/)) { 1060 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1061 end_it = instList.begin(); 1062 rob_empty = true; 1063 } else { 1064 end_it = (rob.readTailInst(tid))->getInstListIt(); 1065 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1066 } 1067 1068 removeInstsThisCycle = true; 1069 1070 ListIt inst_it = instList.end(); 1071 1072 inst_it--; 1073 1074 // Walk through the instruction list, removing any instructions 1075 // that were inserted after the given instruction iterator, end_it. 1076 while (inst_it != end_it) { 1077 assert(!instList.empty()); 1078 1079 squashInstIt(inst_it, tid); 1080 1081 inst_it--; 1082 } 1083 1084 // If the ROB was empty, then we actually need to remove the first 1085 // instruction as well. 1086 if (rob_empty) { 1087 squashInstIt(inst_it, tid); 1088 } 1089} 1090 1091template <class Impl> 1092void 1093FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1094 unsigned tid) 1095{ 1096 assert(!instList.empty()); 1097 1098 removeInstsThisCycle = true; 1099 1100 ListIt inst_iter = instList.end(); 1101 1102 inst_iter--; 1103 1104 DPRINTF(O3CPU, "Deleting instructions from instruction " 1105 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1106 tid, seq_num, (*inst_iter)->seqNum); 1107 1108 while ((*inst_iter)->seqNum > seq_num) { 1109 1110 bool break_loop = (inst_iter == instList.begin()); 1111 1112 squashInstIt(inst_iter, tid); 1113 1114 inst_iter--; 1115 1116 if (break_loop) 1117 break; 1118 } 1119} 1120 1121template <class Impl> 1122inline void 1123FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1124{ 1125 if ((*instIt)->threadNumber == tid) { 1126 DPRINTF(O3CPU, "Squashing instruction, " 1127 "[tid:%i] [sn:%lli] PC %#x\n", 1128 (*instIt)->threadNumber, 1129 (*instIt)->seqNum, 1130 (*instIt)->readPC()); 1131 1132 // Mark it as squashed. 1133 (*instIt)->setSquashed(); 1134 1135 // @todo: Formulate a consistent method for deleting 1136 // instructions from the instruction list 1137 // Remove the instruction from the list. 1138 removeList.push(instIt); 1139 } 1140} 1141 1142template <class Impl> 1143void 1144FullO3CPU<Impl>::cleanUpRemovedInsts() 1145{ 1146 while (!removeList.empty()) { 1147 DPRINTF(O3CPU, "Removing instruction, " 1148 "[tid:%i] [sn:%lli] PC %#x\n", 1149 (*removeList.front())->threadNumber, 1150 (*removeList.front())->seqNum, 1151 (*removeList.front())->readPC()); 1152 1153 instList.erase(removeList.front()); 1154 1155 removeList.pop(); 1156 } 1157 1158 removeInstsThisCycle = false; 1159} 1160/* 1161template <class Impl> 1162void 1163FullO3CPU<Impl>::removeAllInsts() 1164{ 1165 instList.clear(); 1166} 1167*/ 1168template <class Impl> 1169void 1170FullO3CPU<Impl>::dumpInsts() 1171{ 1172 int num = 0; 1173 1174 ListIt inst_list_it = instList.begin(); 1175 1176 cprintf("Dumping Instruction List\n"); 1177 1178 while (inst_list_it != instList.end()) { 1179 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1180 "Squashed:%i\n\n", 1181 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1182 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1183 (*inst_list_it)->isSquashed()); 1184 inst_list_it++; 1185 ++num; 1186 } 1187} 1188/* 1189template <class Impl> 1190void 1191FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1192{ 1193 iew.wakeDependents(inst); 1194} 1195*/ 1196template <class Impl> 1197void 1198FullO3CPU<Impl>::wakeCPU() 1199{ 1200 if (activityRec.active() || tickEvent.scheduled()) { 1201 DPRINTF(Activity, "CPU already running.\n"); 1202 return; 1203 } 1204 1205 DPRINTF(Activity, "Waking up CPU\n"); 1206 1207 idleCycles += (curTick - 1) - lastRunningCycle; 1208 1209 tickEvent.schedule(curTick); 1210} 1211 1212template <class Impl> 1213int 1214FullO3CPU<Impl>::getFreeTid() 1215{ 1216 for (int i=0; i < numThreads; i++) { 1217 if (!tids[i]) { 1218 tids[i] = true; 1219 return i; 1220 } 1221 } 1222 1223 return -1; 1224} 1225 1226template <class Impl> 1227void 1228FullO3CPU<Impl>::doContextSwitch() 1229{ 1230 if (contextSwitch) { 1231 1232 //ADD CODE TO DEACTIVE THREAD HERE (???) 1233 1234 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1235 activateWhenReady(tid); 1236 } 1237 1238 if (cpuWaitList.size() == 0) 1239 contextSwitch = true; 1240 } 1241} 1242 1243template <class Impl> 1244void 1245FullO3CPU<Impl>::updateThreadPriority() 1246{ 1247 if (activeThreads.size() > 1) 1248 { 1249 //DEFAULT TO ROUND ROBIN SCHEME 1250 //e.g. Move highest priority to end of thread list 1251 list<unsigned>::iterator list_begin = activeThreads.begin(); 1252 list<unsigned>::iterator list_end = activeThreads.end(); 1253 1254 unsigned high_thread = *list_begin; 1255 1256 activeThreads.erase(list_begin); 1257 1258 activeThreads.push_back(high_thread); 1259 } 1260} 1261 1262// Forward declaration of FullO3CPU. 1263template class FullO3CPU<O3CPUImpl>;
| 786FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 787{ 788 // Flush out any old data from the time buffers. 789 for (int i = 0; i < 10; ++i) { 790 timeBuffer.advance(); 791 fetchQueue.advance(); 792 decodeQueue.advance(); 793 renameQueue.advance(); 794 iewQueue.advance(); 795 } 796 797 activityRec.reset(); 798 799 BaseCPU::takeOverFrom(oldCPU); 800 801 fetch.takeOverFrom(); 802 decode.takeOverFrom(); 803 rename.takeOverFrom(); 804 iew.takeOverFrom(); 805 commit.takeOverFrom(); 806 807 assert(!tickEvent.scheduled()); 808 809 // @todo: Figure out how to properly select the tid to put onto 810 // the active threads list. 811 int tid = 0; 812 813 list<unsigned>::iterator isActive = find( 814 activeThreads.begin(), activeThreads.end(), tid); 815 816 if (isActive == activeThreads.end()) { 817 //May Need to Re-code this if the delay variable is the delay 818 //needed for thread to activate 819 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 820 tid); 821 822 activeThreads.push_back(tid); 823 } 824 825 // Set all statuses to active, schedule the CPU's tick event. 826 // @todo: Fix up statuses so this is handled properly 827 for (int i = 0; i < threadContexts.size(); ++i) { 828 ThreadContext *tc = threadContexts[i]; 829 if (tc->status() == ThreadContext::Active && _status != Running) { 830 _status = Running; 831 tickEvent.schedule(curTick); 832 } 833 } 834 if (!tickEvent.scheduled()) 835 tickEvent.schedule(curTick); 836} 837 838template <class Impl> 839uint64_t 840FullO3CPU<Impl>::readIntReg(int reg_idx) 841{ 842 return regFile.readIntReg(reg_idx); 843} 844 845template <class Impl> 846FloatReg 847FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 848{ 849 return regFile.readFloatReg(reg_idx, width); 850} 851 852template <class Impl> 853FloatReg 854FullO3CPU<Impl>::readFloatReg(int reg_idx) 855{ 856 return regFile.readFloatReg(reg_idx); 857} 858 859template <class Impl> 860FloatRegBits 861FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 862{ 863 return regFile.readFloatRegBits(reg_idx, width); 864} 865 866template <class Impl> 867FloatRegBits 868FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 869{ 870 return regFile.readFloatRegBits(reg_idx); 871} 872 873template <class Impl> 874void 875FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 876{ 877 regFile.setIntReg(reg_idx, val); 878} 879 880template <class Impl> 881void 882FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 883{ 884 regFile.setFloatReg(reg_idx, val, width); 885} 886 887template <class Impl> 888void 889FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 890{ 891 regFile.setFloatReg(reg_idx, val); 892} 893 894template <class Impl> 895void 896FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 897{ 898 regFile.setFloatRegBits(reg_idx, val, width); 899} 900 901template <class Impl> 902void 903FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 904{ 905 regFile.setFloatRegBits(reg_idx, val); 906} 907 908template <class Impl> 909uint64_t 910FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 911{ 912 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 913 914 return regFile.readIntReg(phys_reg); 915} 916 917template <class Impl> 918float 919FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 920{ 921 int idx = reg_idx + TheISA::FP_Base_DepTag; 922 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 923 924 return regFile.readFloatReg(phys_reg); 925} 926 927template <class Impl> 928double 929FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 930{ 931 int idx = reg_idx + TheISA::FP_Base_DepTag; 932 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 933 934 return regFile.readFloatReg(phys_reg, 64); 935} 936 937template <class Impl> 938uint64_t 939FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 940{ 941 int idx = reg_idx + TheISA::FP_Base_DepTag; 942 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 943 944 return regFile.readFloatRegBits(phys_reg); 945} 946 947template <class Impl> 948void 949FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 950{ 951 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 952 953 regFile.setIntReg(phys_reg, val); 954} 955 956template <class Impl> 957void 958FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 959{ 960 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 961 962 regFile.setFloatReg(phys_reg, val); 963} 964 965template <class Impl> 966void 967FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 968{ 969 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 970 971 regFile.setFloatReg(phys_reg, val, 64); 972} 973 974template <class Impl> 975void 976FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 977{ 978 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 979 980 regFile.setFloatRegBits(phys_reg, val); 981} 982 983template <class Impl> 984uint64_t 985FullO3CPU<Impl>::readPC(unsigned tid) 986{ 987 return commit.readPC(tid); 988} 989 990template <class Impl> 991void 992FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 993{ 994 commit.setPC(new_PC, tid); 995} 996 997template <class Impl> 998uint64_t 999FullO3CPU<Impl>::readNextPC(unsigned tid) 1000{ 1001 return commit.readNextPC(tid); 1002} 1003 1004template <class Impl> 1005void 1006FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1007{ 1008 commit.setNextPC(val, tid); 1009} 1010 1011#if THE_ISA != ALPHA_ISA 1012template <class Impl> 1013uint64_t 1014FullO3CPU<Impl>::readNextNPC(unsigned tid) 1015{ 1016 return commit.readNextNPC(tid); 1017} 1018 1019template <class Impl> 1020void 1021FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) 1022{ 1023 commit.setNextNPC(val, tid); 1024} 1025#endif 1026 1027template <class Impl> 1028typename FullO3CPU<Impl>::ListIt 1029FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1030{ 1031 instList.push_back(inst); 1032 1033 return --(instList.end()); 1034} 1035 1036template <class Impl> 1037void 1038FullO3CPU<Impl>::instDone(unsigned tid) 1039{ 1040 // Keep an instruction count. 1041 thread[tid]->numInst++; 1042 thread[tid]->numInsts++; 1043 committedInsts[tid]++; 1044 totalCommittedInsts++; 1045 1046 // Check for instruction-count-based events. 1047 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1048} 1049 1050template <class Impl> 1051void 1052FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1053{ 1054 removeInstsThisCycle = true; 1055 1056 removeList.push(inst->getInstListIt()); 1057} 1058 1059template <class Impl> 1060void 1061FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1062{ 1063 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1064 "[sn:%lli]\n", 1065 inst->threadNumber, inst->readPC(), inst->seqNum); 1066 1067 removeInstsThisCycle = true; 1068 1069 // Remove the front instruction. 1070 removeList.push(inst->getInstListIt()); 1071} 1072 1073template <class Impl> 1074void 1075FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1076{ 1077 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1078 " list.\n", tid); 1079 1080 ListIt end_it; 1081 1082 bool rob_empty = false; 1083 1084 if (instList.empty()) { 1085 return; 1086 } else if (rob.isEmpty(/*tid*/)) { 1087 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1088 end_it = instList.begin(); 1089 rob_empty = true; 1090 } else { 1091 end_it = (rob.readTailInst(tid))->getInstListIt(); 1092 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1093 } 1094 1095 removeInstsThisCycle = true; 1096 1097 ListIt inst_it = instList.end(); 1098 1099 inst_it--; 1100 1101 // Walk through the instruction list, removing any instructions 1102 // that were inserted after the given instruction iterator, end_it. 1103 while (inst_it != end_it) { 1104 assert(!instList.empty()); 1105 1106 squashInstIt(inst_it, tid); 1107 1108 inst_it--; 1109 } 1110 1111 // If the ROB was empty, then we actually need to remove the first 1112 // instruction as well. 1113 if (rob_empty) { 1114 squashInstIt(inst_it, tid); 1115 } 1116} 1117 1118template <class Impl> 1119void 1120FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1121 unsigned tid) 1122{ 1123 assert(!instList.empty()); 1124 1125 removeInstsThisCycle = true; 1126 1127 ListIt inst_iter = instList.end(); 1128 1129 inst_iter--; 1130 1131 DPRINTF(O3CPU, "Deleting instructions from instruction " 1132 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1133 tid, seq_num, (*inst_iter)->seqNum); 1134 1135 while ((*inst_iter)->seqNum > seq_num) { 1136 1137 bool break_loop = (inst_iter == instList.begin()); 1138 1139 squashInstIt(inst_iter, tid); 1140 1141 inst_iter--; 1142 1143 if (break_loop) 1144 break; 1145 } 1146} 1147 1148template <class Impl> 1149inline void 1150FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1151{ 1152 if ((*instIt)->threadNumber == tid) { 1153 DPRINTF(O3CPU, "Squashing instruction, " 1154 "[tid:%i] [sn:%lli] PC %#x\n", 1155 (*instIt)->threadNumber, 1156 (*instIt)->seqNum, 1157 (*instIt)->readPC()); 1158 1159 // Mark it as squashed. 1160 (*instIt)->setSquashed(); 1161 1162 // @todo: Formulate a consistent method for deleting 1163 // instructions from the instruction list 1164 // Remove the instruction from the list. 1165 removeList.push(instIt); 1166 } 1167} 1168 1169template <class Impl> 1170void 1171FullO3CPU<Impl>::cleanUpRemovedInsts() 1172{ 1173 while (!removeList.empty()) { 1174 DPRINTF(O3CPU, "Removing instruction, " 1175 "[tid:%i] [sn:%lli] PC %#x\n", 1176 (*removeList.front())->threadNumber, 1177 (*removeList.front())->seqNum, 1178 (*removeList.front())->readPC()); 1179 1180 instList.erase(removeList.front()); 1181 1182 removeList.pop(); 1183 } 1184 1185 removeInstsThisCycle = false; 1186} 1187/* 1188template <class Impl> 1189void 1190FullO3CPU<Impl>::removeAllInsts() 1191{ 1192 instList.clear(); 1193} 1194*/ 1195template <class Impl> 1196void 1197FullO3CPU<Impl>::dumpInsts() 1198{ 1199 int num = 0; 1200 1201 ListIt inst_list_it = instList.begin(); 1202 1203 cprintf("Dumping Instruction List\n"); 1204 1205 while (inst_list_it != instList.end()) { 1206 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1207 "Squashed:%i\n\n", 1208 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1209 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1210 (*inst_list_it)->isSquashed()); 1211 inst_list_it++; 1212 ++num; 1213 } 1214} 1215/* 1216template <class Impl> 1217void 1218FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1219{ 1220 iew.wakeDependents(inst); 1221} 1222*/ 1223template <class Impl> 1224void 1225FullO3CPU<Impl>::wakeCPU() 1226{ 1227 if (activityRec.active() || tickEvent.scheduled()) { 1228 DPRINTF(Activity, "CPU already running.\n"); 1229 return; 1230 } 1231 1232 DPRINTF(Activity, "Waking up CPU\n"); 1233 1234 idleCycles += (curTick - 1) - lastRunningCycle; 1235 1236 tickEvent.schedule(curTick); 1237} 1238 1239template <class Impl> 1240int 1241FullO3CPU<Impl>::getFreeTid() 1242{ 1243 for (int i=0; i < numThreads; i++) { 1244 if (!tids[i]) { 1245 tids[i] = true; 1246 return i; 1247 } 1248 } 1249 1250 return -1; 1251} 1252 1253template <class Impl> 1254void 1255FullO3CPU<Impl>::doContextSwitch() 1256{ 1257 if (contextSwitch) { 1258 1259 //ADD CODE TO DEACTIVE THREAD HERE (???) 1260 1261 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1262 activateWhenReady(tid); 1263 } 1264 1265 if (cpuWaitList.size() == 0) 1266 contextSwitch = true; 1267 } 1268} 1269 1270template <class Impl> 1271void 1272FullO3CPU<Impl>::updateThreadPriority() 1273{ 1274 if (activeThreads.size() > 1) 1275 { 1276 //DEFAULT TO ROUND ROBIN SCHEME 1277 //e.g. Move highest priority to end of thread list 1278 list<unsigned>::iterator list_begin = activeThreads.begin(); 1279 list<unsigned>::iterator list_end = activeThreads.end(); 1280 1281 unsigned high_thread = *list_begin; 1282 1283 activeThreads.erase(list_begin); 1284 1285 activeThreads.push_back(high_thread); 1286 } 1287} 1288 1289// Forward declaration of FullO3CPU. 1290template class FullO3CPU<O3CPUImpl>;
|