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