cpu.cc revision 2665:a124942bacb8
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 * Authors: Kevin Lim 29 */ 30 31#include "config/full_system.hh" 32 33#if FULL_SYSTEM 34#include "sim/system.hh" 35#else 36#include "sim/process.hh" 37#endif 38#include "sim/root.hh" 39 40#include "cpu/cpu_exec_context.hh" 41#include "cpu/exec_context.hh" 42#include "cpu/o3/alpha_dyn_inst.hh" 43#include "cpu/o3/alpha_impl.hh" 44#include "cpu/o3/cpu.hh" 45 46using namespace std; 47 48BaseFullCPU::BaseFullCPU(Params ¶ms) 49 : BaseCPU(¶ms), cpu_id(0) 50{ 51} 52 53template <class Impl> 54FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 55 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 56{ 57} 58 59template <class Impl> 60void 61FullO3CPU<Impl>::TickEvent::process() 62{ 63 cpu->tick(); 64} 65 66template <class Impl> 67const char * 68FullO3CPU<Impl>::TickEvent::description() 69{ 70 return "FullO3CPU tick event"; 71} 72 73//Call constructor to all the pipeline stages here 74template <class Impl> 75FullO3CPU<Impl>::FullO3CPU(Params ¶ms) 76#if FULL_SYSTEM 77 : BaseFullCPU(params), 78#else 79 : BaseFullCPU(params), 80#endif // FULL_SYSTEM 81 tickEvent(this), 82 fetch(params), 83 decode(params), 84 rename(params), 85 iew(params), 86 commit(params), 87 88 regFile(params.numPhysIntRegs, params.numPhysFloatRegs), 89 90 freeList(TheISA::NumIntRegs, params.numPhysIntRegs, 91 TheISA::NumFloatRegs, params.numPhysFloatRegs), 92 93 renameMap(TheISA::NumIntRegs, params.numPhysIntRegs, 94 TheISA::NumFloatRegs, params.numPhysFloatRegs, 95 TheISA::NumMiscRegs, 96 TheISA::ZeroReg, 97 TheISA::ZeroReg + TheISA::NumIntRegs), 98 99 rob(params.numROBEntries, params.squashWidth), 100 101 // What to pass to these time buffers? 102 // For now just have these time buffers be pretty big. 103 timeBuffer(5, 5), 104 fetchQueue(5, 5), 105 decodeQueue(5, 5), 106 renameQueue(5, 5), 107 iewQueue(5, 5), 108 109 cpuXC(NULL), 110 111 globalSeqNum(1), 112 113#if FULL_SYSTEM 114 system(params.system), 115 memCtrl(system->memctrl), 116 physmem(system->physmem), 117 itb(params.itb), 118 dtb(params.dtb), 119 mem(params.mem), 120#else 121 // Hardcoded for a single thread!! 122 mem(params.workload[0]->getMemory()), 123#endif // FULL_SYSTEM 124 125 icacheInterface(params.icacheInterface), 126 dcacheInterface(params.dcacheInterface), 127 deferRegistration(params.defReg), 128 numInsts(0), 129 funcExeInst(0) 130{ 131 _status = Idle; 132 133#if !FULL_SYSTEM 134 thread.resize(this->number_of_threads); 135#endif 136 137 for (int i = 0; i < this->number_of_threads; ++i) { 138#if FULL_SYSTEM 139 assert(i == 0); 140 thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem); 141 system->execContexts[i] = thread[i]->getProxy(); 142 143 execContexts.push_back(system->execContexts[i]); 144#else 145 if (i < params.workload.size()) { 146 DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, " 147 "process is %#x", 148 i, params.workload[i]->prog_entry, thread[i]); 149 thread[i] = new CPUExecContext(this, i, params.workload[i], i); 150 } 151 assert(params.workload[i]->getMemory() != NULL); 152 assert(mem != NULL); 153 execContexts.push_back(thread[i]->getProxy()); 154#endif // !FULL_SYSTEM 155 } 156 157 // Note that this is a hack so that my code which still uses xc-> will 158 // still work. I should remove this eventually 159 cpuXC = thread[0]; 160 161 // The stages also need their CPU pointer setup. However this must be 162 // done at the upper level CPU because they have pointers to the upper 163 // level CPU, and not this FullO3CPU. 164 165 // Give each of the stages the time buffer they will use. 166 fetch.setTimeBuffer(&timeBuffer); 167 decode.setTimeBuffer(&timeBuffer); 168 rename.setTimeBuffer(&timeBuffer); 169 iew.setTimeBuffer(&timeBuffer); 170 commit.setTimeBuffer(&timeBuffer); 171 172 // Also setup each of the stages' queues. 173 fetch.setFetchQueue(&fetchQueue); 174 decode.setFetchQueue(&fetchQueue); 175 decode.setDecodeQueue(&decodeQueue); 176 rename.setDecodeQueue(&decodeQueue); 177 rename.setRenameQueue(&renameQueue); 178 iew.setRenameQueue(&renameQueue); 179 iew.setIEWQueue(&iewQueue); 180 commit.setIEWQueue(&iewQueue); 181 commit.setRenameQueue(&renameQueue); 182 183 // Setup the rename map for whichever stages need it. 184 rename.setRenameMap(&renameMap); 185 iew.setRenameMap(&renameMap); 186 187 // Setup the free list for whichever stages need it. 188 rename.setFreeList(&freeList); 189 renameMap.setFreeList(&freeList); 190 191 // Setup the ROB for whichever stages need it. 192 commit.setROB(&rob); 193} 194 195template <class Impl> 196FullO3CPU<Impl>::~FullO3CPU() 197{ 198} 199 200template <class Impl> 201void 202FullO3CPU<Impl>::fullCPURegStats() 203{ 204 // Register any of the FullCPU's stats here. 205} 206 207template <class Impl> 208void 209FullO3CPU<Impl>::tick() 210{ 211 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n"); 212 213 //Tick each of the stages if they're actually running. 214 //Will want to figure out a way to unschedule itself if they're all 215 //going to be idle for a long time. 216 fetch.tick(); 217 218 decode.tick(); 219 220 rename.tick(); 221 222 iew.tick(); 223 224 commit.tick(); 225 226 // Now advance the time buffers, unless the stage is stalled. 227 timeBuffer.advance(); 228 229 fetchQueue.advance(); 230 decodeQueue.advance(); 231 renameQueue.advance(); 232 iewQueue.advance(); 233 234 if (_status == Running && !tickEvent.scheduled()) 235 tickEvent.schedule(curTick + 1); 236} 237 238template <class Impl> 239void 240FullO3CPU<Impl>::init() 241{ 242 if(!deferRegistration) 243 { 244 this->registerExecContexts(); 245 246 // Need to do a copy of the xc->regs into the CPU's regfile so 247 // that it can start properly. 248#if FULL_SYSTEM 249 ExecContext *src_xc = system->execContexts[0]; 250 TheISA::initCPU(src_xc, src_xc->readCpuId()); 251#else 252 ExecContext *src_xc = thread[0]->getProxy(); 253#endif 254 // First loop through the integer registers. 255 for (int i = 0; i < TheISA::NumIntRegs; ++i) 256 { 257 regFile.intRegFile[i] = src_xc->readIntReg(i); 258 } 259 260 // Then loop through the floating point registers. 261 for (int i = 0; i < TheISA::NumFloatRegs; ++i) 262 { 263 regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i)) 264 } 265/* 266 // Then loop through the misc registers. 267 regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr; 268 regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq; 269 regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag; 270 regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr; 271*/ 272 // Then finally set the PC and the next PC. 273 regFile.pc = src_xc->readPC(); 274 regFile.npc = src_xc->readNextPC(); 275 } 276} 277 278template <class Impl> 279void 280FullO3CPU<Impl>::activateContext(int thread_num, int delay) 281{ 282 // Needs to set each stage to running as well. 283 284 scheduleTickEvent(delay); 285 286 _status = Running; 287} 288 289template <class Impl> 290void 291FullO3CPU<Impl>::suspendContext(int thread_num) 292{ 293 panic("suspendContext unimplemented!"); 294} 295 296template <class Impl> 297void 298FullO3CPU<Impl>::deallocateContext(int thread_num) 299{ 300 panic("deallocateContext unimplemented!"); 301} 302 303template <class Impl> 304void 305FullO3CPU<Impl>::haltContext(int thread_num) 306{ 307 panic("haltContext unimplemented!"); 308} 309 310template <class Impl> 311void 312FullO3CPU<Impl>::switchOut() 313{ 314 panic("FullO3CPU does not have a switch out function.\n"); 315} 316 317template <class Impl> 318void 319FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 320{ 321 BaseCPU::takeOverFrom(oldCPU); 322 323 assert(!tickEvent.scheduled()); 324 325 // Set all status's to active, schedule the 326 // CPU's tick event. 327 for (int i = 0; i < execContexts.size(); ++i) { 328 ExecContext *xc = execContexts[i]; 329 if (xc->status() == ExecContext::Active && _status != Running) { 330 _status = Running; 331 tickEvent.schedule(curTick); 332 } 333 } 334} 335 336template <class Impl> 337InstSeqNum 338FullO3CPU<Impl>::getAndIncrementInstSeq() 339{ 340 // Hopefully this works right. 341 return globalSeqNum++; 342} 343 344template <class Impl> 345uint64_t 346FullO3CPU<Impl>::readIntReg(int reg_idx) 347{ 348 return regFile.readIntReg(reg_idx); 349} 350 351template <class Impl> 352FloatReg 353FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 354{ 355 return regFile.readFloatReg(reg_idx, width); 356} 357 358template <class Impl> 359FloatReg 360FullO3CPU<Impl>::readFloatReg(int reg_idx) 361{ 362 return regFile.readFloatReg(reg_idx); 363} 364 365template <class Impl> 366FloatRegBits 367FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 368{ 369 return regFile.readFloatRegBits(reg_idx, width); 370} 371 372template <class Impl> 373FloatRegBits 374FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 375{ 376 return regFile.readFloatRegBits(reg_idx); 377} 378 379template <class Impl> 380void 381FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 382{ 383 regFile.setIntReg(reg_idx, val); 384} 385 386template <class Impl> 387void 388FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 389{ 390 regFile.setFloatReg(reg_idx, val, width); 391} 392 393template <class Impl> 394void 395FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 396{ 397 regFile.setFloatReg(reg_idx, val); 398} 399 400template <class Impl> 401void 402FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 403{ 404 regFile.setFloatRegBits(reg_idx, val, width); 405} 406 407template <class Impl> 408void 409FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 410{ 411 regFile.setFloatRegBits(reg_idx, val); 412} 413 414template <class Impl> 415uint64_t 416FullO3CPU<Impl>::readPC() 417{ 418 return regFile.readPC(); 419} 420 421template <class Impl> 422void 423FullO3CPU<Impl>::setNextPC(uint64_t val) 424{ 425 regFile.setNextPC(val); 426} 427 428template <class Impl> 429void 430FullO3CPU<Impl>::setPC(Addr new_PC) 431{ 432 regFile.setPC(new_PC); 433} 434 435template <class Impl> 436void 437FullO3CPU<Impl>::addInst(DynInstPtr &inst) 438{ 439 instList.push_back(inst); 440} 441 442template <class Impl> 443void 444FullO3CPU<Impl>::instDone() 445{ 446 // Keep an instruction count. 447 numInsts++; 448 449 // Check for instruction-count-based events. 450 comInstEventQueue[0]->serviceEvents(numInsts); 451} 452 453template <class Impl> 454void 455FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst) 456{ 457 DynInstPtr inst_to_delete; 458 459 // Walk through the instruction list, removing any instructions 460 // that were inserted after the given instruction, inst. 461 while (instList.back() != inst) 462 { 463 assert(!instList.empty()); 464 465 // Obtain the pointer to the instruction. 466 inst_to_delete = instList.back(); 467 468 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", 469 inst_to_delete->seqNum, inst_to_delete->readPC()); 470 471 // Remove the instruction from the list. 472 instList.pop_back(); 473 474 // Mark it as squashed. 475 inst_to_delete->setSquashed(); 476 } 477} 478 479template <class Impl> 480void 481FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 482{ 483 DynInstPtr inst_to_remove; 484 485 // The front instruction should be the same one being asked to be removed. 486 assert(instList.front() == inst); 487 488 // Remove the front instruction. 489 inst_to_remove = inst; 490 instList.pop_front(); 491 492 DPRINTF(FullCPU, "FullCPU: Removing committed instruction %#x, PC %#x\n", 493 inst_to_remove, inst_to_remove->readPC()); 494} 495 496template <class Impl> 497void 498FullO3CPU<Impl>::removeInstsNotInROB() 499{ 500 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " 501 "list.\n"); 502 503 DynInstPtr rob_tail = rob.readTailInst(); 504 505 removeBackInst(rob_tail); 506} 507 508template <class Impl> 509void 510FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num) 511{ 512 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " 513 "list.\n"); 514 515 DynInstPtr inst_to_delete; 516 517 while (instList.back()->seqNum > seq_num) { 518 assert(!instList.empty()); 519 520 // Obtain the pointer to the instruction. 521 inst_to_delete = instList.back(); 522 523 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", 524 inst_to_delete->seqNum, inst_to_delete->readPC()); 525 526 // Remove the instruction from the list. 527 instList.back() = NULL; 528 instList.pop_back(); 529 530 // Mark it as squashed. 531 inst_to_delete->setSquashed(); 532 } 533 534} 535 536template <class Impl> 537void 538FullO3CPU<Impl>::removeAllInsts() 539{ 540 instList.clear(); 541} 542 543template <class Impl> 544void 545FullO3CPU<Impl>::dumpInsts() 546{ 547 int num = 0; 548 typename list<DynInstPtr>::iterator inst_list_it = instList.begin(); 549 550 while (inst_list_it != instList.end()) 551 { 552 cprintf("Instruction:%i\nPC:%#x\nSN:%lli\nIssued:%i\nSquashed:%i\n\n", 553 num, (*inst_list_it)->readPC(), (*inst_list_it)->seqNum, 554 (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); 555 inst_list_it++; 556 ++num; 557 } 558} 559 560template <class Impl> 561void 562FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 563{ 564 iew.wakeDependents(inst); 565} 566 567// Forward declaration of FullO3CPU. 568template class FullO3CPU<AlphaSimpleImpl>; 569