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