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