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