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