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