cpu.cc revision 2918
17150Sgblack@eecs.umich.edu/* 27150Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 37150Sgblack@eecs.umich.edu * All rights reserved. 47150Sgblack@eecs.umich.edu * 57150Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67150Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77150Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87150Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97150Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107150Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117150Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127150Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137150Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147150Sgblack@eecs.umich.edu * this software without specific prior written permission. 157150Sgblack@eecs.umich.edu * 167150Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177150Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187150Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197150Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207150Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217150Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227150Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237150Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247150Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257150Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267150Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277150Sgblack@eecs.umich.edu * 287150Sgblack@eecs.umich.edu * Authors: Kevin Lim 297150Sgblack@eecs.umich.edu * Korey Sewell 307150Sgblack@eecs.umich.edu */ 317150Sgblack@eecs.umich.edu 327150Sgblack@eecs.umich.edu#include "config/full_system.hh" 337150Sgblack@eecs.umich.edu#include "config/use_checker.hh" 347150Sgblack@eecs.umich.edu 357150Sgblack@eecs.umich.edu#if FULL_SYSTEM 367150Sgblack@eecs.umich.edu#include "sim/system.hh" 377150Sgblack@eecs.umich.edu#else 387150Sgblack@eecs.umich.edu#include "sim/process.hh" 397150Sgblack@eecs.umich.edu#endif 407150Sgblack@eecs.umich.edu 417150Sgblack@eecs.umich.edu#include "cpu/activity.hh" 427150Sgblack@eecs.umich.edu#include "cpu/simple_thread.hh" 437150Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 447150Sgblack@eecs.umich.edu#include "cpu/o3/isa_specific.hh" 457150Sgblack@eecs.umich.edu#include "cpu/o3/cpu.hh" 467150Sgblack@eecs.umich.edu 477150Sgblack@eecs.umich.edu#include "sim/root.hh" 487150Sgblack@eecs.umich.edu#include "sim/stat_control.hh" 497150Sgblack@eecs.umich.edu 507150Sgblack@eecs.umich.edu#if USE_CHECKER 517150Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 527150Sgblack@eecs.umich.edu#endif 537150Sgblack@eecs.umich.edu 547150Sgblack@eecs.umich.eduusing namespace std; 557150Sgblack@eecs.umich.eduusing namespace TheISA; 567848SAli.Saidi@ARM.com 577848SAli.Saidi@ARM.comBaseO3CPU::BaseO3CPU(Params *params) 587848SAli.Saidi@ARM.com : BaseCPU(params), cpu_id(0) 597848SAli.Saidi@ARM.com{ 608146SAli.Saidi@ARM.com} 618146SAli.Saidi@ARM.com 628146SAli.Saidi@ARM.comvoid 637848SAli.Saidi@ARM.comBaseO3CPU::regStats() 648146SAli.Saidi@ARM.com{ 657150Sgblack@eecs.umich.edu BaseCPU::regStats(); 667150Sgblack@eecs.umich.edu} 677150Sgblack@eecs.umich.edu 687150Sgblack@eecs.umich.edutemplate <class Impl> 697150Sgblack@eecs.umich.eduFullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 707150Sgblack@eecs.umich.edu : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 717150Sgblack@eecs.umich.edu{ 727150Sgblack@eecs.umich.edu} 737150Sgblack@eecs.umich.edu 747150Sgblack@eecs.umich.edutemplate <class Impl> 757150Sgblack@eecs.umich.eduvoid 768146SAli.Saidi@ARM.comFullO3CPU<Impl>::TickEvent::process() 777150Sgblack@eecs.umich.edu{ 787150Sgblack@eecs.umich.edu cpu->tick(); 797150Sgblack@eecs.umich.edu} 807150Sgblack@eecs.umich.edu 817150Sgblack@eecs.umich.edutemplate <class Impl> 827150Sgblack@eecs.umich.educonst char * 837150Sgblack@eecs.umich.eduFullO3CPU<Impl>::TickEvent::description() 847150Sgblack@eecs.umich.edu{ 857150Sgblack@eecs.umich.edu return "FullO3CPU tick event"; 867150Sgblack@eecs.umich.edu} 877150Sgblack@eecs.umich.edu 887848SAli.Saidi@ARM.comtemplate <class Impl> 897848SAli.Saidi@ARM.comFullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 907848SAli.Saidi@ARM.com : Event(&mainEventQueue, CPU_Tick_Pri) 917848SAli.Saidi@ARM.com{ 928146SAli.Saidi@ARM.com} 938146SAli.Saidi@ARM.com 948146SAli.Saidi@ARM.comtemplate <class Impl> 957848SAli.Saidi@ARM.comvoid 967150Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 977150Sgblack@eecs.umich.edu FullO3CPU<Impl> *thread_cpu) 987150Sgblack@eecs.umich.edu{ 997150Sgblack@eecs.umich.edu tid = thread_num; 1007150Sgblack@eecs.umich.edu cpu = thread_cpu; 1017150Sgblack@eecs.umich.edu} 1027150Sgblack@eecs.umich.edu 1037150Sgblack@eecs.umich.edutemplate <class Impl> 1047150Sgblack@eecs.umich.eduvoid 1057150Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::process() 1067150Sgblack@eecs.umich.edu{ 1077150Sgblack@eecs.umich.edu cpu->activateThread(tid); 1087150Sgblack@eecs.umich.edu} 1097150Sgblack@eecs.umich.edu 1107150Sgblack@eecs.umich.edutemplate <class Impl> 1117150Sgblack@eecs.umich.educonst char * 1127150Sgblack@eecs.umich.eduFullO3CPU<Impl>::ActivateThreadEvent::description() 1137150Sgblack@eecs.umich.edu{ 1147150Sgblack@eecs.umich.edu return "FullO3CPU \"Activate Thread\" event"; 1157848SAli.Saidi@ARM.com} 1167848SAli.Saidi@ARM.com 1177848SAli.Saidi@ARM.comtemplate <class Impl> 1187848SAli.Saidi@ARM.comFullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() 1198146SAli.Saidi@ARM.com : Event(&mainEventQueue, CPU_Tick_Pri) 1208146SAli.Saidi@ARM.com{ 1218146SAli.Saidi@ARM.com} 1227848SAli.Saidi@ARM.com 1238203SAli.Saidi@ARM.comtemplate <class Impl> 1248203SAli.Saidi@ARM.comvoid 1257150Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, 1267150Sgblack@eecs.umich.edu FullO3CPU<Impl> *thread_cpu) 1277150Sgblack@eecs.umich.edu{ 1287150Sgblack@eecs.umich.edu tid = thread_num; 1297150Sgblack@eecs.umich.edu cpu = thread_cpu; 1307150Sgblack@eecs.umich.edu} 1317150Sgblack@eecs.umich.edu 1327150Sgblack@eecs.umich.edutemplate <class Impl> 1337150Sgblack@eecs.umich.eduvoid 1347150Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::process() 1357150Sgblack@eecs.umich.edu{ 1367150Sgblack@eecs.umich.edu cpu->deactivateThread(tid); 1377150Sgblack@eecs.umich.edu cpu->removeThread(tid); 1387150Sgblack@eecs.umich.edu} 1397150Sgblack@eecs.umich.edu 1407150Sgblack@eecs.umich.edutemplate <class Impl> 1417150Sgblack@eecs.umich.educonst char * 1427150Sgblack@eecs.umich.eduFullO3CPU<Impl>::DeallocateContextEvent::description() 1437150Sgblack@eecs.umich.edu{ 1447150Sgblack@eecs.umich.edu return "FullO3CPU \"Deallocate Context\" event"; 1457150Sgblack@eecs.umich.edu} 1467150Sgblack@eecs.umich.edu 1477848SAli.Saidi@ARM.comtemplate <class Impl> 1487848SAli.Saidi@ARM.comFullO3CPU<Impl>::FullO3CPU(Params *params) 1497848SAli.Saidi@ARM.com : BaseO3CPU(params), 1507848SAli.Saidi@ARM.com tickEvent(this), 1518146SAli.Saidi@ARM.com removeInstsThisCycle(false), 1528146SAli.Saidi@ARM.com fetch(params), 1538146SAli.Saidi@ARM.com decode(params), 1547848SAli.Saidi@ARM.com rename(params), 1558203SAli.Saidi@ARM.com iew(params), 1568203SAli.Saidi@ARM.com commit(params), 1577150Sgblack@eecs.umich.edu 1587150Sgblack@eecs.umich.edu regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 1597150Sgblack@eecs.umich.edu 1607150Sgblack@eecs.umich.edu freeList(params->numberOfThreads, 1617150Sgblack@eecs.umich.edu TheISA::NumIntRegs, params->numPhysIntRegs, 1627150Sgblack@eecs.umich.edu TheISA::NumFloatRegs, params->numPhysFloatRegs), 1637150Sgblack@eecs.umich.edu 1647150Sgblack@eecs.umich.edu rob(params->numROBEntries, params->squashWidth, 1657150Sgblack@eecs.umich.edu params->smtROBPolicy, params->smtROBThreshold, 1667150Sgblack@eecs.umich.edu params->numberOfThreads), 1677150Sgblack@eecs.umich.edu 1687150Sgblack@eecs.umich.edu scoreboard(params->numberOfThreads, 1697150Sgblack@eecs.umich.edu TheISA::NumIntRegs, params->numPhysIntRegs, 1707150Sgblack@eecs.umich.edu TheISA::NumFloatRegs, params->numPhysFloatRegs, 1717150Sgblack@eecs.umich.edu TheISA::NumMiscRegs * number_of_threads, 1727150Sgblack@eecs.umich.edu TheISA::ZeroReg), 1737150Sgblack@eecs.umich.edu 1747150Sgblack@eecs.umich.edu timeBuffer(params->backComSize, params->forwardComSize), 1757150Sgblack@eecs.umich.edu fetchQueue(params->backComSize, params->forwardComSize), 1767150Sgblack@eecs.umich.edu decodeQueue(params->backComSize, params->forwardComSize), 1777150Sgblack@eecs.umich.edu renameQueue(params->backComSize, params->forwardComSize), 1787150Sgblack@eecs.umich.edu iewQueue(params->backComSize, params->forwardComSize), 1797150Sgblack@eecs.umich.edu activityRec(NumStages, 1807150Sgblack@eecs.umich.edu params->backComSize + params->forwardComSize, 1817150Sgblack@eecs.umich.edu params->activity), 1827150Sgblack@eecs.umich.edu 1837150Sgblack@eecs.umich.edu globalSeqNum(1), 1847150Sgblack@eecs.umich.edu 1857150Sgblack@eecs.umich.edu#if FULL_SYSTEM 1867150Sgblack@eecs.umich.edu system(params->system), 1877150Sgblack@eecs.umich.edu physmem(system->physmem), 1887150Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 1897150Sgblack@eecs.umich.edu mem(params->mem), 1907150Sgblack@eecs.umich.edu drainCount(0), 1917150Sgblack@eecs.umich.edu deferRegistration(params->deferRegistration), 1927150Sgblack@eecs.umich.edu numThreads(number_of_threads) 1937848SAli.Saidi@ARM.com{ 1947848SAli.Saidi@ARM.com _status = Idle; 1957848SAli.Saidi@ARM.com 1967848SAli.Saidi@ARM.com checker = NULL; 1978146SAli.Saidi@ARM.com 1988146SAli.Saidi@ARM.com if (params->checker) { 1998146SAli.Saidi@ARM.com#if USE_CHECKER 2007848SAli.Saidi@ARM.com BaseCPU *temp_checker = params->checker; 2017150Sgblack@eecs.umich.edu checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 2027150Sgblack@eecs.umich.edu checker->setMemory(mem); 2037150Sgblack@eecs.umich.edu#if FULL_SYSTEM 2047150Sgblack@eecs.umich.edu checker->setSystem(params->system); 2057150Sgblack@eecs.umich.edu#endif 2067150Sgblack@eecs.umich.edu#else 2077150Sgblack@eecs.umich.edu panic("Checker enabled but not compiled in!"); 2087150Sgblack@eecs.umich.edu#endif // USE_CHECKER 2097150Sgblack@eecs.umich.edu } 2107150Sgblack@eecs.umich.edu 2117150Sgblack@eecs.umich.edu#if !FULL_SYSTEM 2127150Sgblack@eecs.umich.edu thread.resize(number_of_threads); 2137150Sgblack@eecs.umich.edu tids.resize(number_of_threads); 2147150Sgblack@eecs.umich.edu#endif 2157150Sgblack@eecs.umich.edu 2167150Sgblack@eecs.umich.edu // The stages also need their CPU pointer setup. However this 2177150Sgblack@eecs.umich.edu // must be done at the upper level CPU because they have pointers 2187150Sgblack@eecs.umich.edu // to the upper level CPU, and not this FullO3CPU. 2197150Sgblack@eecs.umich.edu 2207150Sgblack@eecs.umich.edu // Set up Pointers to the activeThreads list for each stage 2217150Sgblack@eecs.umich.edu fetch.setActiveThreads(&activeThreads); 2227848SAli.Saidi@ARM.com decode.setActiveThreads(&activeThreads); 2237848SAli.Saidi@ARM.com rename.setActiveThreads(&activeThreads); 2247848SAli.Saidi@ARM.com iew.setActiveThreads(&activeThreads); 2257848SAli.Saidi@ARM.com commit.setActiveThreads(&activeThreads); 2268146SAli.Saidi@ARM.com 2278146SAli.Saidi@ARM.com // Give each of the stages the time buffer they will use. 2288146SAli.Saidi@ARM.com fetch.setTimeBuffer(&timeBuffer); 2297848SAli.Saidi@ARM.com decode.setTimeBuffer(&timeBuffer); 2307150Sgblack@eecs.umich.edu rename.setTimeBuffer(&timeBuffer); 2317150Sgblack@eecs.umich.edu iew.setTimeBuffer(&timeBuffer); 2328146SAli.Saidi@ARM.com commit.setTimeBuffer(&timeBuffer); 2338146SAli.Saidi@ARM.com 2348146SAli.Saidi@ARM.com // Also setup each of the stages' queues. 2358146SAli.Saidi@ARM.com fetch.setFetchQueue(&fetchQueue); 2368146SAli.Saidi@ARM.com decode.setFetchQueue(&fetchQueue); 2378146SAli.Saidi@ARM.com commit.setFetchQueue(&fetchQueue); 2388146SAli.Saidi@ARM.com decode.setDecodeQueue(&decodeQueue); 2398146SAli.Saidi@ARM.com rename.setDecodeQueue(&decodeQueue); 2408146SAli.Saidi@ARM.com rename.setRenameQueue(&renameQueue); 2418146SAli.Saidi@ARM.com iew.setRenameQueue(&renameQueue); 2428146SAli.Saidi@ARM.com iew.setIEWQueue(&iewQueue); 2438146SAli.Saidi@ARM.com commit.setIEWQueue(&iewQueue); 2448146SAli.Saidi@ARM.com commit.setRenameQueue(&renameQueue); 2458146SAli.Saidi@ARM.com 2468146SAli.Saidi@ARM.com commit.setIEWStage(&iew); 2478146SAli.Saidi@ARM.com rename.setIEWStage(&iew); 2488146SAli.Saidi@ARM.com rename.setCommitStage(&commit); 249 250#if !FULL_SYSTEM 251 int active_threads = params->workload.size(); 252 253 if (active_threads > Impl::MaxThreads) { 254 panic("Workload Size too large. Increase the 'MaxThreads'" 255 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 256 "edit your workload size."); 257 } 258#else 259 int active_threads = 1; 260#endif 261 262 //Make Sure That this a Valid Architeture 263 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 264 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 265 266 rename.setScoreboard(&scoreboard); 267 iew.setScoreboard(&scoreboard); 268 269 // Setup the rename map for whichever stages need it. 270 PhysRegIndex lreg_idx = 0; 271 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 272 273 for (int tid=0; tid < numThreads; tid++) { 274 bool bindRegs = (tid <= active_threads - 1); 275 276 commitRenameMap[tid].init(TheISA::NumIntRegs, 277 params->numPhysIntRegs, 278 lreg_idx, //Index for Logical. Regs 279 280 TheISA::NumFloatRegs, 281 params->numPhysFloatRegs, 282 freg_idx, //Index for Float Regs 283 284 TheISA::NumMiscRegs, 285 286 TheISA::ZeroReg, 287 TheISA::ZeroReg, 288 289 tid, 290 false); 291 292 renameMap[tid].init(TheISA::NumIntRegs, 293 params->numPhysIntRegs, 294 lreg_idx, //Index for Logical. Regs 295 296 TheISA::NumFloatRegs, 297 params->numPhysFloatRegs, 298 freg_idx, //Index for Float Regs 299 300 TheISA::NumMiscRegs, 301 302 TheISA::ZeroReg, 303 TheISA::ZeroReg, 304 305 tid, 306 bindRegs); 307 } 308 309 rename.setRenameMap(renameMap); 310 commit.setRenameMap(commitRenameMap); 311 312 // Give renameMap & rename stage access to the freeList; 313 for (int i=0; i < numThreads; i++) { 314 renameMap[i].setFreeList(&freeList); 315 } 316 rename.setFreeList(&freeList); 317 318 // Setup the ROB for whichever stages need it. 319 commit.setROB(&rob); 320 321 lastRunningCycle = curTick; 322 323 lastActivatedCycle = -1; 324 325 contextSwitch = false; 326} 327 328template <class Impl> 329FullO3CPU<Impl>::~FullO3CPU() 330{ 331} 332 333template <class Impl> 334void 335FullO3CPU<Impl>::fullCPURegStats() 336{ 337 BaseO3CPU::regStats(); 338 339 // Register any of the O3CPU's stats here. 340 timesIdled 341 .name(name() + ".timesIdled") 342 .desc("Number of times that the entire CPU went into an idle state and" 343 " unscheduled itself") 344 .prereq(timesIdled); 345 346 idleCycles 347 .name(name() + ".idleCycles") 348 .desc("Total number of cycles that the CPU has spent unscheduled due " 349 "to idling") 350 .prereq(idleCycles); 351 352 // Number of Instructions simulated 353 // -------------------------------- 354 // Should probably be in Base CPU but need templated 355 // MaxThreads so put in here instead 356 committedInsts 357 .init(numThreads) 358 .name(name() + ".committedInsts") 359 .desc("Number of Instructions Simulated"); 360 361 totalCommittedInsts 362 .name(name() + ".committedInsts_total") 363 .desc("Number of Instructions Simulated"); 364 365 cpi 366 .name(name() + ".cpi") 367 .desc("CPI: Cycles Per Instruction") 368 .precision(6); 369 cpi = simTicks / committedInsts; 370 371 totalCpi 372 .name(name() + ".cpi_total") 373 .desc("CPI: Total CPI of All Threads") 374 .precision(6); 375 totalCpi = simTicks / totalCommittedInsts; 376 377 ipc 378 .name(name() + ".ipc") 379 .desc("IPC: Instructions Per Cycle") 380 .precision(6); 381 ipc = committedInsts / simTicks; 382 383 totalIpc 384 .name(name() + ".ipc_total") 385 .desc("IPC: Total IPC of All Threads") 386 .precision(6); 387 totalIpc = totalCommittedInsts / simTicks; 388 389} 390 391template <class Impl> 392Port * 393FullO3CPU<Impl>::getPort(const std::string &if_name, int idx) 394{ 395 if (if_name == "dcache_port") 396 return iew.getDcachePort(); 397 else if (if_name == "icache_port") 398 return fetch.getIcachePort(); 399 else 400 panic("No Such Port\n"); 401} 402 403template <class Impl> 404void 405FullO3CPU<Impl>::tick() 406{ 407 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 408 409 ++numCycles; 410 411// activity = false; 412 413 //Tick each of the stages 414 fetch.tick(); 415 416 decode.tick(); 417 418 rename.tick(); 419 420 iew.tick(); 421 422 commit.tick(); 423 424#if !FULL_SYSTEM 425 doContextSwitch(); 426#endif 427 428 // Now advance the time buffers 429 timeBuffer.advance(); 430 431 fetchQueue.advance(); 432 decodeQueue.advance(); 433 renameQueue.advance(); 434 iewQueue.advance(); 435 436 activityRec.advance(); 437 438 if (removeInstsThisCycle) { 439 cleanUpRemovedInsts(); 440 } 441 442 if (!tickEvent.scheduled()) { 443 if (_status == SwitchedOut || 444 getState() == SimObject::DrainedTiming) { 445 // increment stat 446 lastRunningCycle = curTick; 447 } else if (!activityRec.active()) { 448 lastRunningCycle = curTick; 449 timesIdled++; 450 } else { 451 tickEvent.schedule(curTick + cycles(1)); 452 } 453 } 454 455#if !FULL_SYSTEM 456 updateThreadPriority(); 457#endif 458 459} 460 461template <class Impl> 462void 463FullO3CPU<Impl>::init() 464{ 465 if (!deferRegistration) { 466 registerThreadContexts(); 467 } 468 469 // Set inSyscall so that the CPU doesn't squash when initially 470 // setting up registers. 471 for (int i = 0; i < number_of_threads; ++i) 472 thread[i]->inSyscall = true; 473 474 for (int tid=0; tid < number_of_threads; tid++) { 475#if FULL_SYSTEM 476 ThreadContext *src_tc = threadContexts[tid]; 477#else 478 ThreadContext *src_tc = thread[tid]->getTC(); 479#endif 480 // Threads start in the Suspended State 481 if (src_tc->status() != ThreadContext::Suspended) { 482 continue; 483 } 484 485#if FULL_SYSTEM 486 TheISA::initCPU(src_tc, src_tc->readCpuId()); 487#endif 488 } 489 490 // Clear inSyscall. 491 for (int i = 0; i < number_of_threads; ++i) 492 thread[i]->inSyscall = false; 493 494 // Initialize stages. 495 fetch.initStage(); 496 iew.initStage(); 497 rename.initStage(); 498 commit.initStage(); 499 500 commit.setThreads(thread); 501} 502 503template <class Impl> 504void 505FullO3CPU<Impl>::activateThread(unsigned tid) 506{ 507 list<unsigned>::iterator isActive = find( 508 activeThreads.begin(), activeThreads.end(), tid); 509 510 if (isActive == activeThreads.end()) { 511 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 512 tid); 513 514 activeThreads.push_back(tid); 515 } 516} 517 518template <class Impl> 519void 520FullO3CPU<Impl>::deactivateThread(unsigned tid) 521{ 522 //Remove From Active List, if Active 523 list<unsigned>::iterator thread_it = 524 find(activeThreads.begin(), activeThreads.end(), tid); 525 526 if (thread_it != activeThreads.end()) { 527 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 528 tid); 529 activeThreads.erase(thread_it); 530 } 531} 532 533template <class Impl> 534void 535FullO3CPU<Impl>::activateContext(int tid, int delay) 536{ 537 // Needs to set each stage to running as well. 538 if (delay){ 539 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 540 "on cycle %d\n", tid, curTick + cycles(delay)); 541 scheduleActivateThreadEvent(tid, delay); 542 } else { 543 activateThread(tid); 544 } 545 546 if(lastActivatedCycle < curTick) { 547 scheduleTickEvent(delay); 548 549 // Be sure to signal that there's some activity so the CPU doesn't 550 // deschedule itself. 551 activityRec.activity(); 552 fetch.wakeFromQuiesce(); 553 554 lastActivatedCycle = curTick; 555 556 _status = Running; 557 } 558} 559 560template <class Impl> 561void 562FullO3CPU<Impl>::deallocateContext(int tid, int delay) 563{ 564 // Schedule removal of thread data from CPU 565 if (delay){ 566 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " 567 "on cycle %d\n", tid, curTick + cycles(delay)); 568 scheduleDeallocateContextEvent(tid, delay); 569 } else { 570 deactivateThread(tid); 571 removeThread(tid); 572 } 573} 574 575template <class Impl> 576void 577FullO3CPU<Impl>::suspendContext(int tid) 578{ 579 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 580 unscheduleTickEvent(); 581 _status = Idle; 582/* 583 //Remove From Active List, if Active 584 list<unsigned>::iterator isActive = find( 585 activeThreads.begin(), activeThreads.end(), tid); 586 587 if (isActive != activeThreads.end()) { 588 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 589 tid); 590 activeThreads.erase(isActive); 591 } 592*/ 593} 594 595template <class Impl> 596void 597FullO3CPU<Impl>::haltContext(int tid) 598{ 599 DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid); 600/* 601 //Remove From Active List, if Active 602 list<unsigned>::iterator isActive = find( 603 activeThreads.begin(), activeThreads.end(), tid); 604 605 if (isActive != activeThreads.end()) { 606 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 607 tid); 608 activeThreads.erase(isActive); 609 610 removeThread(tid); 611 } 612*/ 613} 614 615template <class Impl> 616void 617FullO3CPU<Impl>::insertThread(unsigned tid) 618{ 619 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 620 // Will change now that the PC and thread state is internal to the CPU 621 // and not in the ThreadContext. 622#if FULL_SYSTEM 623 ThreadContext *src_tc = system->threadContexts[tid]; 624#else 625 ThreadContext *src_tc = tcBase(tid); 626#endif 627 628 //Bind Int Regs to Rename Map 629 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 630 PhysRegIndex phys_reg = freeList.getIntReg(); 631 632 renameMap[tid].setEntry(ireg,phys_reg); 633 scoreboard.setReg(phys_reg); 634 } 635 636 //Bind Float Regs to Rename Map 637 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 638 PhysRegIndex phys_reg = freeList.getFloatReg(); 639 640 renameMap[tid].setEntry(freg,phys_reg); 641 scoreboard.setReg(phys_reg); 642 } 643 644 //Copy Thread Data Into RegFile 645 //this->copyFromTC(tid); 646 647 //Set PC/NPC/NNPC 648 setPC(src_tc->readPC(), tid); 649 setNextPC(src_tc->readNextPC(), tid); 650#if THE_ISA != ALPHA_ISA 651 setNextNPC(src_tc->readNextNPC(), tid); 652#endif 653 654 src_tc->setStatus(ThreadContext::Active); 655 656 activateContext(tid,1); 657 658 //Reset ROB/IQ/LSQ Entries 659 commit.rob->resetEntries(); 660 iew.resetEntries(); 661} 662 663template <class Impl> 664void 665FullO3CPU<Impl>::removeThread(unsigned tid) 666{ 667 DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid); 668 669 // Copy Thread Data From RegFile 670 // If thread is suspended, it might be re-allocated 671 //this->copyToTC(tid); 672 673 // Unbind Int Regs from Rename Map 674 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 675 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 676 677 scoreboard.unsetReg(phys_reg); 678 freeList.addReg(phys_reg); 679 } 680 681 // Unbind Float Regs from Rename Map 682 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 683 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 684 685 scoreboard.unsetReg(phys_reg); 686 freeList.addReg(phys_reg); 687 } 688 689 // Squash Throughout Pipeline 690 fetch.squash(0,tid); 691 decode.squash(tid); 692 rename.squash(tid); 693 iew.squash(tid); 694 commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid); 695 696 assert(iew.ldstQueue.getCount(tid) == 0); 697 698 // Reset ROB/IQ/LSQ Entries 699 if (activeThreads.size() >= 1) { 700 commit.rob->resetEntries(); 701 iew.resetEntries(); 702 } 703} 704 705 706template <class Impl> 707void 708FullO3CPU<Impl>::activateWhenReady(int tid) 709{ 710 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 711 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 712 tid); 713 714 bool ready = true; 715 716 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 717 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 718 "Phys. Int. Regs.\n", 719 tid); 720 ready = false; 721 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 722 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 723 "Phys. Float. Regs.\n", 724 tid); 725 ready = false; 726 } else if (commit.rob->numFreeEntries() >= 727 commit.rob->entryAmount(activeThreads.size() + 1)) { 728 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 729 "ROB entries.\n", 730 tid); 731 ready = false; 732 } else if (iew.instQueue.numFreeEntries() >= 733 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 734 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 735 "IQ entries.\n", 736 tid); 737 ready = false; 738 } else if (iew.ldstQueue.numFreeEntries() >= 739 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 740 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 741 "LSQ entries.\n", 742 tid); 743 ready = false; 744 } 745 746 if (ready) { 747 insertThread(tid); 748 749 contextSwitch = false; 750 751 cpuWaitList.remove(tid); 752 } else { 753 suspendContext(tid); 754 755 //blocks fetch 756 contextSwitch = true; 757 758 //@todo: dont always add to waitlist 759 //do waitlist 760 cpuWaitList.push_back(tid); 761 } 762} 763 764template <class Impl> 765void 766FullO3CPU<Impl>::serialize(std::ostream &os) 767{ 768 SimObject::State so_state = SimObject::getState(); 769 SERIALIZE_ENUM(so_state); 770 BaseCPU::serialize(os); 771 nameOut(os, csprintf("%s.tickEvent", name())); 772 tickEvent.serialize(os); 773 774 // Use SimpleThread's ability to checkpoint to make it easier to 775 // write out the registers. Also make this static so it doesn't 776 // get instantiated multiple times (causes a panic in statistics). 777 static SimpleThread temp; 778 779 for (int i = 0; i < thread.size(); i++) { 780 nameOut(os, csprintf("%s.xc.%i", name(), i)); 781 temp.copyTC(thread[i]->getTC()); 782 temp.serialize(os); 783 } 784} 785 786template <class Impl> 787void 788FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 789{ 790 SimObject::State so_state; 791 UNSERIALIZE_ENUM(so_state); 792 BaseCPU::unserialize(cp, section); 793 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 794 795 // Use SimpleThread's ability to checkpoint to make it easier to 796 // read in the registers. Also make this static so it doesn't 797 // get instantiated multiple times (causes a panic in statistics). 798 static SimpleThread temp; 799 800 for (int i = 0; i < thread.size(); i++) { 801 temp.copyTC(thread[i]->getTC()); 802 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 803 thread[i]->getTC()->copyArchRegs(temp.getTC()); 804 } 805} 806 807template <class Impl> 808bool 809FullO3CPU<Impl>::drain(Event *drain_event) 810{ 811 drainCount = 0; 812 fetch.drain(); 813 decode.drain(); 814 rename.drain(); 815 iew.drain(); 816 commit.drain(); 817 818 // Wake the CPU and record activity so everything can drain out if 819 // the CPU was not able to immediately drain. 820 if (getState() != SimObject::DrainedTiming) { 821 // A bit of a hack...set the drainEvent after all the drain() 822 // calls have been made, that way if all of the stages drain 823 // immediately, the signalDrained() function knows not to call 824 // process on the drain event. 825 drainEvent = drain_event; 826 827 wakeCPU(); 828 activityRec.activity(); 829 830 return false; 831 } else { 832 return true; 833 } 834} 835 836template <class Impl> 837void 838FullO3CPU<Impl>::resume() 839{ 840 fetch.resume(); 841 decode.resume(); 842 rename.resume(); 843 iew.resume(); 844 commit.resume(); 845 846 if (_status == SwitchedOut || _status == Idle) 847 return; 848 849 if (!tickEvent.scheduled()) 850 tickEvent.schedule(curTick); 851 _status = Running; 852 changeState(SimObject::Timing); 853} 854 855template <class Impl> 856void 857FullO3CPU<Impl>::signalDrained() 858{ 859 if (++drainCount == NumStages) { 860 if (tickEvent.scheduled()) 861 tickEvent.squash(); 862 863 changeState(SimObject::DrainedTiming); 864 865 if (drainEvent) { 866 drainEvent->process(); 867 drainEvent = NULL; 868 } 869 } 870 assert(drainCount <= 5); 871} 872 873template <class Impl> 874void 875FullO3CPU<Impl>::switchOut() 876{ 877 fetch.switchOut(); 878 rename.switchOut(); 879 commit.switchOut(); 880 instList.clear(); 881 while (!removeList.empty()) { 882 removeList.pop(); 883 } 884 885 _status = SwitchedOut; 886#if USE_CHECKER 887 if (checker) 888 checker->switchOut(); 889#endif 890} 891 892template <class Impl> 893void 894FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 895{ 896 // Flush out any old data from the time buffers. 897 for (int i = 0; i < timeBuffer.getSize(); ++i) { 898 timeBuffer.advance(); 899 fetchQueue.advance(); 900 decodeQueue.advance(); 901 renameQueue.advance(); 902 iewQueue.advance(); 903 } 904 905 activityRec.reset(); 906 907 BaseCPU::takeOverFrom(oldCPU); 908 909 fetch.takeOverFrom(); 910 decode.takeOverFrom(); 911 rename.takeOverFrom(); 912 iew.takeOverFrom(); 913 commit.takeOverFrom(); 914 915 assert(!tickEvent.scheduled()); 916 917 // @todo: Figure out how to properly select the tid to put onto 918 // the active threads list. 919 int tid = 0; 920 921 list<unsigned>::iterator isActive = find( 922 activeThreads.begin(), activeThreads.end(), tid); 923 924 if (isActive == activeThreads.end()) { 925 //May Need to Re-code this if the delay variable is the delay 926 //needed for thread to activate 927 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 928 tid); 929 930 activeThreads.push_back(tid); 931 } 932 933 // Set all statuses to active, schedule the CPU's tick event. 934 // @todo: Fix up statuses so this is handled properly 935 for (int i = 0; i < threadContexts.size(); ++i) { 936 ThreadContext *tc = threadContexts[i]; 937 if (tc->status() == ThreadContext::Active && _status != Running) { 938 _status = Running; 939 tickEvent.schedule(curTick); 940 } 941 } 942 if (!tickEvent.scheduled()) 943 tickEvent.schedule(curTick); 944} 945 946template <class Impl> 947uint64_t 948FullO3CPU<Impl>::readIntReg(int reg_idx) 949{ 950 return regFile.readIntReg(reg_idx); 951} 952 953template <class Impl> 954FloatReg 955FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 956{ 957 return regFile.readFloatReg(reg_idx, width); 958} 959 960template <class Impl> 961FloatReg 962FullO3CPU<Impl>::readFloatReg(int reg_idx) 963{ 964 return regFile.readFloatReg(reg_idx); 965} 966 967template <class Impl> 968FloatRegBits 969FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 970{ 971 return regFile.readFloatRegBits(reg_idx, width); 972} 973 974template <class Impl> 975FloatRegBits 976FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 977{ 978 return regFile.readFloatRegBits(reg_idx); 979} 980 981template <class Impl> 982void 983FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 984{ 985 regFile.setIntReg(reg_idx, val); 986} 987 988template <class Impl> 989void 990FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 991{ 992 regFile.setFloatReg(reg_idx, val, width); 993} 994 995template <class Impl> 996void 997FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 998{ 999 regFile.setFloatReg(reg_idx, val); 1000} 1001 1002template <class Impl> 1003void 1004FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 1005{ 1006 regFile.setFloatRegBits(reg_idx, val, width); 1007} 1008 1009template <class Impl> 1010void 1011FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 1012{ 1013 regFile.setFloatRegBits(reg_idx, val); 1014} 1015 1016template <class Impl> 1017uint64_t 1018FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 1019{ 1020 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1021 1022 return regFile.readIntReg(phys_reg); 1023} 1024 1025template <class Impl> 1026float 1027FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 1028{ 1029 int idx = reg_idx + TheISA::FP_Base_DepTag; 1030 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1031 1032 return regFile.readFloatReg(phys_reg); 1033} 1034 1035template <class Impl> 1036double 1037FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 1038{ 1039 int idx = reg_idx + TheISA::FP_Base_DepTag; 1040 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1041 1042 return regFile.readFloatReg(phys_reg, 64); 1043} 1044 1045template <class Impl> 1046uint64_t 1047FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 1048{ 1049 int idx = reg_idx + TheISA::FP_Base_DepTag; 1050 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1051 1052 return regFile.readFloatRegBits(phys_reg); 1053} 1054 1055template <class Impl> 1056void 1057FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1058{ 1059 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1060 1061 regFile.setIntReg(phys_reg, val); 1062} 1063 1064template <class Impl> 1065void 1066FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1067{ 1068 int idx = reg_idx + TheISA::FP_Base_DepTag; 1069 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1070 1071 regFile.setFloatReg(phys_reg, val); 1072} 1073 1074template <class Impl> 1075void 1076FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1077{ 1078 int idx = reg_idx + TheISA::FP_Base_DepTag; 1079 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1080 1081 regFile.setFloatReg(phys_reg, val, 64); 1082} 1083 1084template <class Impl> 1085void 1086FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1087{ 1088 int idx = reg_idx + TheISA::FP_Base_DepTag; 1089 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 1090 1091 regFile.setFloatRegBits(phys_reg, val); 1092} 1093 1094template <class Impl> 1095uint64_t 1096FullO3CPU<Impl>::readPC(unsigned tid) 1097{ 1098 return commit.readPC(tid); 1099} 1100 1101template <class Impl> 1102void 1103FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1104{ 1105 commit.setPC(new_PC, tid); 1106} 1107 1108template <class Impl> 1109uint64_t 1110FullO3CPU<Impl>::readNextPC(unsigned tid) 1111{ 1112 return commit.readNextPC(tid); 1113} 1114 1115template <class Impl> 1116void 1117FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1118{ 1119 commit.setNextPC(val, tid); 1120} 1121 1122#if THE_ISA != ALPHA_ISA 1123template <class Impl> 1124uint64_t 1125FullO3CPU<Impl>::readNextNPC(unsigned tid) 1126{ 1127 return commit.readNextNPC(tid); 1128} 1129 1130template <class Impl> 1131void 1132FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) 1133{ 1134 commit.setNextNPC(val, tid); 1135} 1136#endif 1137 1138template <class Impl> 1139typename FullO3CPU<Impl>::ListIt 1140FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1141{ 1142 instList.push_back(inst); 1143 1144 return --(instList.end()); 1145} 1146 1147template <class Impl> 1148void 1149FullO3CPU<Impl>::instDone(unsigned tid) 1150{ 1151 // Keep an instruction count. 1152 thread[tid]->numInst++; 1153 thread[tid]->numInsts++; 1154 committedInsts[tid]++; 1155 totalCommittedInsts++; 1156 1157 // Check for instruction-count-based events. 1158 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1159} 1160 1161template <class Impl> 1162void 1163FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1164{ 1165 removeInstsThisCycle = true; 1166 1167 removeList.push(inst->getInstListIt()); 1168} 1169 1170template <class Impl> 1171void 1172FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1173{ 1174 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1175 "[sn:%lli]\n", 1176 inst->threadNumber, inst->readPC(), inst->seqNum); 1177 1178 removeInstsThisCycle = true; 1179 1180 // Remove the front instruction. 1181 removeList.push(inst->getInstListIt()); 1182} 1183 1184template <class Impl> 1185void 1186FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1187{ 1188 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1189 " list.\n", tid); 1190 1191 ListIt end_it; 1192 1193 bool rob_empty = false; 1194 1195 if (instList.empty()) { 1196 return; 1197 } else if (rob.isEmpty(/*tid*/)) { 1198 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1199 end_it = instList.begin(); 1200 rob_empty = true; 1201 } else { 1202 end_it = (rob.readTailInst(tid))->getInstListIt(); 1203 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1204 } 1205 1206 removeInstsThisCycle = true; 1207 1208 ListIt inst_it = instList.end(); 1209 1210 inst_it--; 1211 1212 // Walk through the instruction list, removing any instructions 1213 // that were inserted after the given instruction iterator, end_it. 1214 while (inst_it != end_it) { 1215 assert(!instList.empty()); 1216 1217 squashInstIt(inst_it, tid); 1218 1219 inst_it--; 1220 } 1221 1222 // If the ROB was empty, then we actually need to remove the first 1223 // instruction as well. 1224 if (rob_empty) { 1225 squashInstIt(inst_it, tid); 1226 } 1227} 1228 1229template <class Impl> 1230void 1231FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1232 unsigned tid) 1233{ 1234 assert(!instList.empty()); 1235 1236 removeInstsThisCycle = true; 1237 1238 ListIt inst_iter = instList.end(); 1239 1240 inst_iter--; 1241 1242 DPRINTF(O3CPU, "Deleting instructions from instruction " 1243 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1244 tid, seq_num, (*inst_iter)->seqNum); 1245 1246 while ((*inst_iter)->seqNum > seq_num) { 1247 1248 bool break_loop = (inst_iter == instList.begin()); 1249 1250 squashInstIt(inst_iter, tid); 1251 1252 inst_iter--; 1253 1254 if (break_loop) 1255 break; 1256 } 1257} 1258 1259template <class Impl> 1260inline void 1261FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1262{ 1263 if ((*instIt)->threadNumber == tid) { 1264 DPRINTF(O3CPU, "Squashing instruction, " 1265 "[tid:%i] [sn:%lli] PC %#x\n", 1266 (*instIt)->threadNumber, 1267 (*instIt)->seqNum, 1268 (*instIt)->readPC()); 1269 1270 // Mark it as squashed. 1271 (*instIt)->setSquashed(); 1272 1273 // @todo: Formulate a consistent method for deleting 1274 // instructions from the instruction list 1275 // Remove the instruction from the list. 1276 removeList.push(instIt); 1277 } 1278} 1279 1280template <class Impl> 1281void 1282FullO3CPU<Impl>::cleanUpRemovedInsts() 1283{ 1284 while (!removeList.empty()) { 1285 DPRINTF(O3CPU, "Removing instruction, " 1286 "[tid:%i] [sn:%lli] PC %#x\n", 1287 (*removeList.front())->threadNumber, 1288 (*removeList.front())->seqNum, 1289 (*removeList.front())->readPC()); 1290 1291 instList.erase(removeList.front()); 1292 1293 removeList.pop(); 1294 } 1295 1296 removeInstsThisCycle = false; 1297} 1298/* 1299template <class Impl> 1300void 1301FullO3CPU<Impl>::removeAllInsts() 1302{ 1303 instList.clear(); 1304} 1305*/ 1306template <class Impl> 1307void 1308FullO3CPU<Impl>::dumpInsts() 1309{ 1310 int num = 0; 1311 1312 ListIt inst_list_it = instList.begin(); 1313 1314 cprintf("Dumping Instruction List\n"); 1315 1316 while (inst_list_it != instList.end()) { 1317 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1318 "Squashed:%i\n\n", 1319 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1320 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1321 (*inst_list_it)->isSquashed()); 1322 inst_list_it++; 1323 ++num; 1324 } 1325} 1326/* 1327template <class Impl> 1328void 1329FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1330{ 1331 iew.wakeDependents(inst); 1332} 1333*/ 1334template <class Impl> 1335void 1336FullO3CPU<Impl>::wakeCPU() 1337{ 1338 if (activityRec.active() || tickEvent.scheduled()) { 1339 DPRINTF(Activity, "CPU already running.\n"); 1340 return; 1341 } 1342 1343 DPRINTF(Activity, "Waking up CPU\n"); 1344 1345 idleCycles += (curTick - 1) - lastRunningCycle; 1346 1347 tickEvent.schedule(curTick); 1348} 1349 1350template <class Impl> 1351int 1352FullO3CPU<Impl>::getFreeTid() 1353{ 1354 for (int i=0; i < numThreads; i++) { 1355 if (!tids[i]) { 1356 tids[i] = true; 1357 return i; 1358 } 1359 } 1360 1361 return -1; 1362} 1363 1364template <class Impl> 1365void 1366FullO3CPU<Impl>::doContextSwitch() 1367{ 1368 if (contextSwitch) { 1369 1370 //ADD CODE TO DEACTIVE THREAD HERE (???) 1371 1372 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1373 activateWhenReady(tid); 1374 } 1375 1376 if (cpuWaitList.size() == 0) 1377 contextSwitch = true; 1378 } 1379} 1380 1381template <class Impl> 1382void 1383FullO3CPU<Impl>::updateThreadPriority() 1384{ 1385 if (activeThreads.size() > 1) 1386 { 1387 //DEFAULT TO ROUND ROBIN SCHEME 1388 //e.g. Move highest priority to end of thread list 1389 list<unsigned>::iterator list_begin = activeThreads.begin(); 1390 list<unsigned>::iterator list_end = activeThreads.end(); 1391 1392 unsigned high_thread = *list_begin; 1393 1394 activeThreads.erase(list_begin); 1395 1396 activeThreads.push_back(high_thread); 1397 } 1398} 1399 1400// Forward declaration of FullO3CPU. 1401template class FullO3CPU<O3CPUImpl>; 1402