1/* 2 * Copyright (c) 2004-2006 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 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/full_system.hh" 33#include "config/use_checker.hh" 34 35#if FULL_SYSTEM 36#include "sim/system.hh" 37#else 38#include "sim/process.hh" 39#endif 40 41#include "cpu/activity.hh" 42#include "cpu/simple_thread.hh" 43#include "cpu/thread_context.hh" 44#include "cpu/o3/isa_specific.hh" 45#include "cpu/o3/cpu.hh" 46 47#include "sim/root.hh" 48#include "sim/stat_control.hh" 49 50#if USE_CHECKER 51#include "cpu/checker/cpu.hh" 52#endif 53 54using namespace std; 55using namespace TheISA; 56 57BaseO3CPU::BaseO3CPU(Params *params) 58 : BaseCPU(params), cpu_id(0) 59{ 60} 61 62void 63BaseO3CPU::regStats() 64{ 65 BaseCPU::regStats(); 66} 67 68template <class Impl> 69FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 70 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 71{ 72} 73 74template <class Impl> 75void 76FullO3CPU<Impl>::TickEvent::process() 77{ 78 cpu->tick(); 79} 80 81template <class Impl> 82const char * 83FullO3CPU<Impl>::TickEvent::description() 84{ 85 return "FullO3CPU tick event"; 86} 87 88template <class Impl> 89FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 90 : Event(&mainEventQueue, CPU_Tick_Pri) 91{ 92} 93 94template <class Impl> 95void 96FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 97 FullO3CPU<Impl> *thread_cpu) 98{ 99 tid = thread_num; 100 cpu = thread_cpu; 101} 102 103template <class Impl> 104void 105FullO3CPU<Impl>::ActivateThreadEvent::process() 106{ 107 cpu->activateThread(tid); 108} 109 110template <class Impl> 111const char * 112FullO3CPU<Impl>::ActivateThreadEvent::description() 113{ 114 return "FullO3CPU \"Activate Thread\" event"; 115} 116 117template <class Impl> 118FullO3CPU<Impl>::FullO3CPU(Params *params) 119 : BaseO3CPU(params), 120 tickEvent(this), 121 removeInstsThisCycle(false), 122 fetch(params), 123 decode(params), 124 rename(params), 125 iew(params), 126 commit(params), 127 128 regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 129 130 freeList(params->numberOfThreads, 131 TheISA::NumIntRegs, params->numPhysIntRegs, 132 TheISA::NumFloatRegs, params->numPhysFloatRegs), 133 134 rob(params->numROBEntries, params->squashWidth, 135 params->smtROBPolicy, params->smtROBThreshold, 136 params->numberOfThreads), 137 138 scoreboard(params->numberOfThreads, 139 TheISA::NumIntRegs, params->numPhysIntRegs, 140 TheISA::NumFloatRegs, params->numPhysFloatRegs, 141 TheISA::NumMiscRegs * number_of_threads, 142 TheISA::ZeroReg), 143 144 // For now just have these time buffers be pretty big. 145 // @todo: Make these time buffer sizes parameters or derived 146 // from latencies 147 timeBuffer(5, 5), 148 fetchQueue(5, 5), 149 decodeQueue(5, 5), 150 renameQueue(5, 5), 151 iewQueue(5, 5), 152 activityRec(NumStages, 10, params->activity), 153 154 globalSeqNum(1), 155 156#if FULL_SYSTEM 157 system(params->system), 158 physmem(system->physmem), 159#endif // FULL_SYSTEM 160 mem(params->mem), 161 drainCount(0), 162 deferRegistration(params->deferRegistration), 163 numThreads(number_of_threads) 164{ 165 _status = Idle; 166 167 checker = NULL; 168 169 if (params->checker) { 170#if USE_CHECKER 171 BaseCPU *temp_checker = params->checker; 172 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 173 checker->setMemory(mem); 174#if FULL_SYSTEM 175 checker->setSystem(params->system); 176#endif 177#else 178 panic("Checker enabled but not compiled in!"); 179#endif // USE_CHECKER 180 } 181 182#if !FULL_SYSTEM 183 thread.resize(number_of_threads); 184 tids.resize(number_of_threads); 185#endif 186 187 // The stages also need their CPU pointer setup. However this 188 // must be done at the upper level CPU because they have pointers 189 // to the upper level CPU, and not this FullO3CPU. 190 191 // Set up Pointers to the activeThreads list for each stage 192 fetch.setActiveThreads(&activeThreads); 193 decode.setActiveThreads(&activeThreads); 194 rename.setActiveThreads(&activeThreads); 195 iew.setActiveThreads(&activeThreads); 196 commit.setActiveThreads(&activeThreads); 197 198 // Give each of the stages the time buffer they will use. 199 fetch.setTimeBuffer(&timeBuffer); 200 decode.setTimeBuffer(&timeBuffer); 201 rename.setTimeBuffer(&timeBuffer); 202 iew.setTimeBuffer(&timeBuffer); 203 commit.setTimeBuffer(&timeBuffer); 204 205 // Also setup each of the stages' queues. 206 fetch.setFetchQueue(&fetchQueue); 207 decode.setFetchQueue(&fetchQueue); 208 commit.setFetchQueue(&fetchQueue); 209 decode.setDecodeQueue(&decodeQueue); 210 rename.setDecodeQueue(&decodeQueue); 211 rename.setRenameQueue(&renameQueue); 212 iew.setRenameQueue(&renameQueue); 213 iew.setIEWQueue(&iewQueue); 214 commit.setIEWQueue(&iewQueue); 215 commit.setRenameQueue(&renameQueue); 216 217 commit.setFetchStage(&fetch); 218 commit.setIEWStage(&iew); 219 rename.setIEWStage(&iew); 220 rename.setCommitStage(&commit); 221 222#if !FULL_SYSTEM 223 int active_threads = params->workload.size(); 224 225 if (active_threads > Impl::MaxThreads) { 226 panic("Workload Size too large. Increase the 'MaxThreads'" 227 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 228 "edit your workload size."); 229 } 230#else 231 int active_threads = 1; 232#endif 233 234 //Make Sure That this a Valid Architeture 235 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 236 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 237 238 rename.setScoreboard(&scoreboard); 239 iew.setScoreboard(&scoreboard); 240 241 // Setup the rename map for whichever stages need it. 242 PhysRegIndex lreg_idx = 0; 243 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 244 245 for (int tid=0; tid < numThreads; tid++) { 246 bool bindRegs = (tid <= active_threads - 1); 247 248 commitRenameMap[tid].init(TheISA::NumIntRegs, 249 params->numPhysIntRegs, 250 lreg_idx, //Index for Logical. Regs 251 252 TheISA::NumFloatRegs, 253 params->numPhysFloatRegs, 254 freg_idx, //Index for Float Regs 255 256 TheISA::NumMiscRegs, 257 258 TheISA::ZeroReg, 259 TheISA::ZeroReg, 260 261 tid, 262 false); 263 264 renameMap[tid].init(TheISA::NumIntRegs, 265 params->numPhysIntRegs, 266 lreg_idx, //Index for Logical. Regs 267 268 TheISA::NumFloatRegs, 269 params->numPhysFloatRegs, 270 freg_idx, //Index for Float Regs 271 272 TheISA::NumMiscRegs, 273 274 TheISA::ZeroReg, 275 TheISA::ZeroReg, 276 277 tid, 278 bindRegs); 279 } 280 281 rename.setRenameMap(renameMap); 282 commit.setRenameMap(commitRenameMap); 283 284 // Give renameMap & rename stage access to the freeList; 285 for (int i=0; i < numThreads; i++) { 286 renameMap[i].setFreeList(&freeList); 287 } 288 rename.setFreeList(&freeList); 289 290 // Setup the ROB for whichever stages need it. 291 commit.setROB(&rob); 292 293 lastRunningCycle = curTick; 294 295 lastActivatedCycle = -1; 296 297 contextSwitch = false; 298} 299 300template <class Impl> 301FullO3CPU<Impl>::~FullO3CPU() 302{ 303} 304 305template <class Impl> 306void 307FullO3CPU<Impl>::fullCPURegStats() 308{ 309 BaseO3CPU::regStats(); 310 311 // Register any of the O3CPU's stats here. 312 timesIdled 313 .name(name() + ".timesIdled") 314 .desc("Number of times that the entire CPU went into an idle state and" 315 " unscheduled itself") 316 .prereq(timesIdled); 317 318 idleCycles 319 .name(name() + ".idleCycles") 320 .desc("Total number of cycles that the CPU has spent unscheduled due " 321 "to idling") 322 .prereq(idleCycles); 323 324 // Number of Instructions simulated 325 // -------------------------------- 326 // Should probably be in Base CPU but need templated 327 // MaxThreads so put in here instead 328 committedInsts 329 .init(numThreads) 330 .name(name() + ".committedInsts") 331 .desc("Number of Instructions Simulated"); 332 333 totalCommittedInsts 334 .name(name() + ".committedInsts_total") 335 .desc("Number of Instructions Simulated"); 336 337 cpi 338 .name(name() + ".cpi") 339 .desc("CPI: Cycles Per Instruction") 340 .precision(6); 341 cpi = simTicks / committedInsts; 342 343 totalCpi 344 .name(name() + ".cpi_total") 345 .desc("CPI: Total CPI of All Threads") 346 .precision(6); 347 totalCpi = simTicks / totalCommittedInsts; 348 349 ipc 350 .name(name() + ".ipc") 351 .desc("IPC: Instructions Per Cycle") 352 .precision(6); 353 ipc = committedInsts / simTicks; 354 355 totalIpc 356 .name(name() + ".ipc_total") 357 .desc("IPC: Total IPC of All Threads") 358 .precision(6); 359 totalIpc = totalCommittedInsts / simTicks; 360 361} 362 363template <class Impl> 364void 365FullO3CPU<Impl>::tick() 366{ 367 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 368 369 ++numCycles; 370 371// activity = false; 372 373 //Tick each of the stages 374 fetch.tick(); 375 376 decode.tick(); 377 378 rename.tick(); 379 380 iew.tick(); 381 382 commit.tick(); 383 384#if !FULL_SYSTEM 385 doContextSwitch(); 386#endif 387 388 // Now advance the time buffers 389 timeBuffer.advance(); 390 391 fetchQueue.advance(); 392 decodeQueue.advance(); 393 renameQueue.advance(); 394 iewQueue.advance(); 395 396 activityRec.advance(); 397 398 if (removeInstsThisCycle) { 399 cleanUpRemovedInsts(); 400 } 401 402 if (!tickEvent.scheduled()) {
| 1/* 2 * Copyright (c) 2004-2006 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 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/full_system.hh" 33#include "config/use_checker.hh" 34 35#if FULL_SYSTEM 36#include "sim/system.hh" 37#else 38#include "sim/process.hh" 39#endif 40 41#include "cpu/activity.hh" 42#include "cpu/simple_thread.hh" 43#include "cpu/thread_context.hh" 44#include "cpu/o3/isa_specific.hh" 45#include "cpu/o3/cpu.hh" 46 47#include "sim/root.hh" 48#include "sim/stat_control.hh" 49 50#if USE_CHECKER 51#include "cpu/checker/cpu.hh" 52#endif 53 54using namespace std; 55using namespace TheISA; 56 57BaseO3CPU::BaseO3CPU(Params *params) 58 : BaseCPU(params), cpu_id(0) 59{ 60} 61 62void 63BaseO3CPU::regStats() 64{ 65 BaseCPU::regStats(); 66} 67 68template <class Impl> 69FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) 70 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) 71{ 72} 73 74template <class Impl> 75void 76FullO3CPU<Impl>::TickEvent::process() 77{ 78 cpu->tick(); 79} 80 81template <class Impl> 82const char * 83FullO3CPU<Impl>::TickEvent::description() 84{ 85 return "FullO3CPU tick event"; 86} 87 88template <class Impl> 89FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() 90 : Event(&mainEventQueue, CPU_Tick_Pri) 91{ 92} 93 94template <class Impl> 95void 96FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, 97 FullO3CPU<Impl> *thread_cpu) 98{ 99 tid = thread_num; 100 cpu = thread_cpu; 101} 102 103template <class Impl> 104void 105FullO3CPU<Impl>::ActivateThreadEvent::process() 106{ 107 cpu->activateThread(tid); 108} 109 110template <class Impl> 111const char * 112FullO3CPU<Impl>::ActivateThreadEvent::description() 113{ 114 return "FullO3CPU \"Activate Thread\" event"; 115} 116 117template <class Impl> 118FullO3CPU<Impl>::FullO3CPU(Params *params) 119 : BaseO3CPU(params), 120 tickEvent(this), 121 removeInstsThisCycle(false), 122 fetch(params), 123 decode(params), 124 rename(params), 125 iew(params), 126 commit(params), 127 128 regFile(params->numPhysIntRegs, params->numPhysFloatRegs), 129 130 freeList(params->numberOfThreads, 131 TheISA::NumIntRegs, params->numPhysIntRegs, 132 TheISA::NumFloatRegs, params->numPhysFloatRegs), 133 134 rob(params->numROBEntries, params->squashWidth, 135 params->smtROBPolicy, params->smtROBThreshold, 136 params->numberOfThreads), 137 138 scoreboard(params->numberOfThreads, 139 TheISA::NumIntRegs, params->numPhysIntRegs, 140 TheISA::NumFloatRegs, params->numPhysFloatRegs, 141 TheISA::NumMiscRegs * number_of_threads, 142 TheISA::ZeroReg), 143 144 // For now just have these time buffers be pretty big. 145 // @todo: Make these time buffer sizes parameters or derived 146 // from latencies 147 timeBuffer(5, 5), 148 fetchQueue(5, 5), 149 decodeQueue(5, 5), 150 renameQueue(5, 5), 151 iewQueue(5, 5), 152 activityRec(NumStages, 10, params->activity), 153 154 globalSeqNum(1), 155 156#if FULL_SYSTEM 157 system(params->system), 158 physmem(system->physmem), 159#endif // FULL_SYSTEM 160 mem(params->mem), 161 drainCount(0), 162 deferRegistration(params->deferRegistration), 163 numThreads(number_of_threads) 164{ 165 _status = Idle; 166 167 checker = NULL; 168 169 if (params->checker) { 170#if USE_CHECKER 171 BaseCPU *temp_checker = params->checker; 172 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); 173 checker->setMemory(mem); 174#if FULL_SYSTEM 175 checker->setSystem(params->system); 176#endif 177#else 178 panic("Checker enabled but not compiled in!"); 179#endif // USE_CHECKER 180 } 181 182#if !FULL_SYSTEM 183 thread.resize(number_of_threads); 184 tids.resize(number_of_threads); 185#endif 186 187 // The stages also need their CPU pointer setup. However this 188 // must be done at the upper level CPU because they have pointers 189 // to the upper level CPU, and not this FullO3CPU. 190 191 // Set up Pointers to the activeThreads list for each stage 192 fetch.setActiveThreads(&activeThreads); 193 decode.setActiveThreads(&activeThreads); 194 rename.setActiveThreads(&activeThreads); 195 iew.setActiveThreads(&activeThreads); 196 commit.setActiveThreads(&activeThreads); 197 198 // Give each of the stages the time buffer they will use. 199 fetch.setTimeBuffer(&timeBuffer); 200 decode.setTimeBuffer(&timeBuffer); 201 rename.setTimeBuffer(&timeBuffer); 202 iew.setTimeBuffer(&timeBuffer); 203 commit.setTimeBuffer(&timeBuffer); 204 205 // Also setup each of the stages' queues. 206 fetch.setFetchQueue(&fetchQueue); 207 decode.setFetchQueue(&fetchQueue); 208 commit.setFetchQueue(&fetchQueue); 209 decode.setDecodeQueue(&decodeQueue); 210 rename.setDecodeQueue(&decodeQueue); 211 rename.setRenameQueue(&renameQueue); 212 iew.setRenameQueue(&renameQueue); 213 iew.setIEWQueue(&iewQueue); 214 commit.setIEWQueue(&iewQueue); 215 commit.setRenameQueue(&renameQueue); 216 217 commit.setFetchStage(&fetch); 218 commit.setIEWStage(&iew); 219 rename.setIEWStage(&iew); 220 rename.setCommitStage(&commit); 221 222#if !FULL_SYSTEM 223 int active_threads = params->workload.size(); 224 225 if (active_threads > Impl::MaxThreads) { 226 panic("Workload Size too large. Increase the 'MaxThreads'" 227 "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " 228 "edit your workload size."); 229 } 230#else 231 int active_threads = 1; 232#endif 233 234 //Make Sure That this a Valid Architeture 235 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); 236 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); 237 238 rename.setScoreboard(&scoreboard); 239 iew.setScoreboard(&scoreboard); 240 241 // Setup the rename map for whichever stages need it. 242 PhysRegIndex lreg_idx = 0; 243 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs 244 245 for (int tid=0; tid < numThreads; tid++) { 246 bool bindRegs = (tid <= active_threads - 1); 247 248 commitRenameMap[tid].init(TheISA::NumIntRegs, 249 params->numPhysIntRegs, 250 lreg_idx, //Index for Logical. Regs 251 252 TheISA::NumFloatRegs, 253 params->numPhysFloatRegs, 254 freg_idx, //Index for Float Regs 255 256 TheISA::NumMiscRegs, 257 258 TheISA::ZeroReg, 259 TheISA::ZeroReg, 260 261 tid, 262 false); 263 264 renameMap[tid].init(TheISA::NumIntRegs, 265 params->numPhysIntRegs, 266 lreg_idx, //Index for Logical. Regs 267 268 TheISA::NumFloatRegs, 269 params->numPhysFloatRegs, 270 freg_idx, //Index for Float Regs 271 272 TheISA::NumMiscRegs, 273 274 TheISA::ZeroReg, 275 TheISA::ZeroReg, 276 277 tid, 278 bindRegs); 279 } 280 281 rename.setRenameMap(renameMap); 282 commit.setRenameMap(commitRenameMap); 283 284 // Give renameMap & rename stage access to the freeList; 285 for (int i=0; i < numThreads; i++) { 286 renameMap[i].setFreeList(&freeList); 287 } 288 rename.setFreeList(&freeList); 289 290 // Setup the ROB for whichever stages need it. 291 commit.setROB(&rob); 292 293 lastRunningCycle = curTick; 294 295 lastActivatedCycle = -1; 296 297 contextSwitch = false; 298} 299 300template <class Impl> 301FullO3CPU<Impl>::~FullO3CPU() 302{ 303} 304 305template <class Impl> 306void 307FullO3CPU<Impl>::fullCPURegStats() 308{ 309 BaseO3CPU::regStats(); 310 311 // Register any of the O3CPU's stats here. 312 timesIdled 313 .name(name() + ".timesIdled") 314 .desc("Number of times that the entire CPU went into an idle state and" 315 " unscheduled itself") 316 .prereq(timesIdled); 317 318 idleCycles 319 .name(name() + ".idleCycles") 320 .desc("Total number of cycles that the CPU has spent unscheduled due " 321 "to idling") 322 .prereq(idleCycles); 323 324 // Number of Instructions simulated 325 // -------------------------------- 326 // Should probably be in Base CPU but need templated 327 // MaxThreads so put in here instead 328 committedInsts 329 .init(numThreads) 330 .name(name() + ".committedInsts") 331 .desc("Number of Instructions Simulated"); 332 333 totalCommittedInsts 334 .name(name() + ".committedInsts_total") 335 .desc("Number of Instructions Simulated"); 336 337 cpi 338 .name(name() + ".cpi") 339 .desc("CPI: Cycles Per Instruction") 340 .precision(6); 341 cpi = simTicks / committedInsts; 342 343 totalCpi 344 .name(name() + ".cpi_total") 345 .desc("CPI: Total CPI of All Threads") 346 .precision(6); 347 totalCpi = simTicks / totalCommittedInsts; 348 349 ipc 350 .name(name() + ".ipc") 351 .desc("IPC: Instructions Per Cycle") 352 .precision(6); 353 ipc = committedInsts / simTicks; 354 355 totalIpc 356 .name(name() + ".ipc_total") 357 .desc("IPC: Total IPC of All Threads") 358 .precision(6); 359 totalIpc = totalCommittedInsts / simTicks; 360 361} 362 363template <class Impl> 364void 365FullO3CPU<Impl>::tick() 366{ 367 DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); 368 369 ++numCycles; 370 371// activity = false; 372 373 //Tick each of the stages 374 fetch.tick(); 375 376 decode.tick(); 377 378 rename.tick(); 379 380 iew.tick(); 381 382 commit.tick(); 383 384#if !FULL_SYSTEM 385 doContextSwitch(); 386#endif 387 388 // Now advance the time buffers 389 timeBuffer.advance(); 390 391 fetchQueue.advance(); 392 decodeQueue.advance(); 393 renameQueue.advance(); 394 iewQueue.advance(); 395 396 activityRec.advance(); 397 398 if (removeInstsThisCycle) { 399 cleanUpRemovedInsts(); 400 } 401 402 if (!tickEvent.scheduled()) {
|
403 if (_status == SwitchedOut) {
| 403 if (_status == SwitchedOut || 404 getState() == SimObject::DrainedTiming) {
|
404 // increment stat 405 lastRunningCycle = curTick; 406 } else if (!activityRec.active()) { 407 lastRunningCycle = curTick; 408 timesIdled++; 409 } else { 410 tickEvent.schedule(curTick + cycles(1)); 411 } 412 } 413 414#if !FULL_SYSTEM 415 updateThreadPriority(); 416#endif 417 418} 419 420template <class Impl> 421void 422FullO3CPU<Impl>::init() 423{ 424 if (!deferRegistration) { 425 registerThreadContexts(); 426 } 427 428 // Set inSyscall so that the CPU doesn't squash when initially 429 // setting up registers. 430 for (int i = 0; i < number_of_threads; ++i) 431 thread[i]->inSyscall = true; 432 433 for (int tid=0; tid < number_of_threads; tid++) { 434#if FULL_SYSTEM 435 ThreadContext *src_tc = threadContexts[tid]; 436#else 437 ThreadContext *src_tc = thread[tid]->getTC(); 438#endif 439 // Threads start in the Suspended State 440 if (src_tc->status() != ThreadContext::Suspended) { 441 continue; 442 } 443 444#if FULL_SYSTEM 445 TheISA::initCPU(src_tc, src_tc->readCpuId()); 446#endif 447 } 448 449 // Clear inSyscall. 450 for (int i = 0; i < number_of_threads; ++i) 451 thread[i]->inSyscall = false; 452 453 // Initialize stages. 454 fetch.initStage(); 455 iew.initStage(); 456 rename.initStage(); 457 commit.initStage(); 458 459 commit.setThreads(thread); 460} 461 462template <class Impl> 463void 464FullO3CPU<Impl>::insertThread(unsigned tid) 465{ 466 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 467 // Will change now that the PC and thread state is internal to the CPU 468 // and not in the ThreadContext. 469#if FULL_SYSTEM 470 ThreadContext *src_tc = system->threadContexts[tid]; 471#else 472 ThreadContext *src_tc = tcBase(tid); 473#endif 474 475 //Bind Int Regs to Rename Map 476 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 477 PhysRegIndex phys_reg = freeList.getIntReg(); 478 479 renameMap[tid].setEntry(ireg,phys_reg); 480 scoreboard.setReg(phys_reg); 481 } 482 483 //Bind Float Regs to Rename Map 484 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 485 PhysRegIndex phys_reg = freeList.getFloatReg(); 486 487 renameMap[tid].setEntry(freg,phys_reg); 488 scoreboard.setReg(phys_reg); 489 } 490 491 //Copy Thread Data Into RegFile 492 //this->copyFromTC(tid); 493 494 //Set PC/NPC/NNPC 495 setPC(src_tc->readPC(), tid); 496 setNextPC(src_tc->readNextPC(), tid); 497#if THE_ISA != ALPHA_ISA 498 setNextNPC(src_tc->readNextNPC(), tid); 499#endif 500 501 src_tc->setStatus(ThreadContext::Active); 502 503 activateContext(tid,1); 504 505 //Reset ROB/IQ/LSQ Entries 506 commit.rob->resetEntries(); 507 iew.resetEntries(); 508} 509 510template <class Impl> 511void 512FullO3CPU<Impl>::removeThread(unsigned tid) 513{ 514 DPRINTF(O3CPU,"[tid:%i] Removing thread from CPU."); 515 516 // Copy Thread Data From RegFile 517 // If thread is suspended, it might be re-allocated 518 //this->copyToTC(tid); 519 520 // Unbind Int Regs from Rename Map 521 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 522 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 523 524 scoreboard.unsetReg(phys_reg); 525 freeList.addReg(phys_reg); 526 } 527 528 // Unbind Float Regs from Rename Map 529 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 530 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 531 532 scoreboard.unsetReg(phys_reg); 533 freeList.addReg(phys_reg); 534 } 535 536 // Squash Throughout Pipeline 537 fetch.squash(0,tid); 538 decode.squash(tid); 539 rename.squash(tid); 540 541 assert(iew.ldstQueue.getCount(tid) == 0); 542 543 // Reset ROB/IQ/LSQ Entries 544 if (activeThreads.size() >= 1) { 545 commit.rob->resetEntries(); 546 iew.resetEntries(); 547 } 548} 549 550 551template <class Impl> 552void 553FullO3CPU<Impl>::activateWhenReady(int tid) 554{ 555 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 556 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 557 tid); 558 559 bool ready = true; 560 561 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 562 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 563 "Phys. Int. Regs.\n", 564 tid); 565 ready = false; 566 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 567 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 568 "Phys. Float. Regs.\n", 569 tid); 570 ready = false; 571 } else if (commit.rob->numFreeEntries() >= 572 commit.rob->entryAmount(activeThreads.size() + 1)) { 573 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 574 "ROB entries.\n", 575 tid); 576 ready = false; 577 } else if (iew.instQueue.numFreeEntries() >= 578 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 579 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 580 "IQ entries.\n", 581 tid); 582 ready = false; 583 } else if (iew.ldstQueue.numFreeEntries() >= 584 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 585 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 586 "LSQ entries.\n", 587 tid); 588 ready = false; 589 } 590 591 if (ready) { 592 insertThread(tid); 593 594 contextSwitch = false; 595 596 cpuWaitList.remove(tid); 597 } else { 598 suspendContext(tid); 599 600 //blocks fetch 601 contextSwitch = true; 602 603 //do waitlist 604 cpuWaitList.push_back(tid); 605 } 606} 607 608template <class Impl> 609void 610FullO3CPU<Impl>::activateThread(unsigned int tid) 611{ 612 list<unsigned>::iterator isActive = find( 613 activeThreads.begin(), activeThreads.end(), tid); 614 615 if (isActive == activeThreads.end()) { 616 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 617 tid); 618 619 activeThreads.push_back(tid); 620 } 621} 622 623 624template <class Impl> 625void 626FullO3CPU<Impl>::activateContext(int tid, int delay) 627{ 628 // Needs to set each stage to running as well. 629 if (delay){ 630 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 631 "on cycle %d\n", tid, curTick + cycles(delay)); 632 scheduleActivateThreadEvent(tid, delay); 633 } else { 634 activateThread(tid); 635 } 636 637 if(lastActivatedCycle < curTick) { 638 scheduleTickEvent(delay); 639 640 // Be sure to signal that there's some activity so the CPU doesn't 641 // deschedule itself. 642 activityRec.activity(); 643 fetch.wakeFromQuiesce(); 644 645 lastActivatedCycle = curTick; 646 647 _status = Running; 648 } 649} 650 651template <class Impl> 652void 653FullO3CPU<Impl>::suspendContext(int tid) 654{ 655 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 656 unscheduleTickEvent(); 657 _status = Idle; 658/* 659 //Remove From Active List, if Active 660 list<unsigned>::iterator isActive = find( 661 activeThreads.begin(), activeThreads.end(), tid); 662 663 if (isActive != activeThreads.end()) { 664 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 665 tid); 666 activeThreads.erase(isActive); 667 } 668*/ 669} 670 671template <class Impl> 672void 673FullO3CPU<Impl>::deallocateContext(int tid) 674{ 675 DPRINTF(O3CPU,"[tid:%i]: Deallocating Thread Context", tid); 676 677 //Remove From Active List, if Active 678 list<unsigned>::iterator thread_it = 679 find(activeThreads.begin(), activeThreads.end(), tid); 680 681 if (thread_it != activeThreads.end()) { 682 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 683 tid); 684 activeThreads.erase(thread_it); 685 686 removeThread(tid); 687 } 688} 689 690template <class Impl> 691void 692FullO3CPU<Impl>::haltContext(int tid) 693{ 694 DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid); 695/* 696 //Remove From Active List, if Active 697 list<unsigned>::iterator isActive = find( 698 activeThreads.begin(), activeThreads.end(), tid); 699 700 if (isActive != activeThreads.end()) { 701 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 702 tid); 703 activeThreads.erase(isActive); 704 705 removeThread(tid); 706 } 707*/ 708} 709 710template <class Impl> 711void 712FullO3CPU<Impl>::serialize(std::ostream &os) 713{ 714 SERIALIZE_ENUM(_status); 715 BaseCPU::serialize(os); 716 nameOut(os, csprintf("%s.tickEvent", name())); 717 tickEvent.serialize(os); 718 719 // Use SimpleThread's ability to checkpoint to make it easier to 720 // write out the registers. Also make this static so it doesn't 721 // get instantiated multiple times (causes a panic in statistics). 722 static SimpleThread temp; 723 724 for (int i = 0; i < thread.size(); i++) { 725 nameOut(os, csprintf("%s.xc.%i", name(), i)); 726 temp.copyTC(thread[i]->getTC()); 727 temp.serialize(os); 728 } 729} 730 731template <class Impl> 732void 733FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 734{ 735 UNSERIALIZE_ENUM(_status); 736 BaseCPU::unserialize(cp, section); 737 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 738 739 // Use SimpleThread's ability to checkpoint to make it easier to 740 // read in the registers. Also make this static so it doesn't 741 // get instantiated multiple times (causes a panic in statistics). 742 static SimpleThread temp; 743 744 for (int i = 0; i < thread.size(); i++) { 745 temp.copyTC(thread[i]->getTC()); 746 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 747 thread[i]->getTC()->copyArchRegs(temp.getTC()); 748 } 749} 750 751template <class Impl> 752bool 753FullO3CPU<Impl>::drain(Event *drain_event) 754{ 755 drainCount = 0; 756 fetch.drain(); 757 decode.drain(); 758 rename.drain(); 759 iew.drain(); 760 commit.drain(); 761 762 // Wake the CPU and record activity so everything can drain out if 763 // the CPU was not able to immediately drain. 764 if (getState() != SimObject::DrainedTiming) { 765 // A bit of a hack...set the drainEvent after all the drain() 766 // calls have been made, that way if all of the stages drain 767 // immediately, the signalDrained() function knows not to call 768 // process on the drain event. 769 drainEvent = drain_event; 770 771 wakeCPU(); 772 activityRec.activity(); 773 774 return false; 775 } else { 776 return true; 777 } 778} 779 780template <class Impl> 781void 782FullO3CPU<Impl>::resume() 783{ 784 fetch.resume(); 785 decode.resume(); 786 rename.resume(); 787 iew.resume(); 788 commit.resume(); 789 790 if (_status == SwitchedOut || _status == Idle) 791 return; 792 793 if (!tickEvent.scheduled()) 794 tickEvent.schedule(curTick); 795 _status = Running;
| 405 // increment stat 406 lastRunningCycle = curTick; 407 } else if (!activityRec.active()) { 408 lastRunningCycle = curTick; 409 timesIdled++; 410 } else { 411 tickEvent.schedule(curTick + cycles(1)); 412 } 413 } 414 415#if !FULL_SYSTEM 416 updateThreadPriority(); 417#endif 418 419} 420 421template <class Impl> 422void 423FullO3CPU<Impl>::init() 424{ 425 if (!deferRegistration) { 426 registerThreadContexts(); 427 } 428 429 // Set inSyscall so that the CPU doesn't squash when initially 430 // setting up registers. 431 for (int i = 0; i < number_of_threads; ++i) 432 thread[i]->inSyscall = true; 433 434 for (int tid=0; tid < number_of_threads; tid++) { 435#if FULL_SYSTEM 436 ThreadContext *src_tc = threadContexts[tid]; 437#else 438 ThreadContext *src_tc = thread[tid]->getTC(); 439#endif 440 // Threads start in the Suspended State 441 if (src_tc->status() != ThreadContext::Suspended) { 442 continue; 443 } 444 445#if FULL_SYSTEM 446 TheISA::initCPU(src_tc, src_tc->readCpuId()); 447#endif 448 } 449 450 // Clear inSyscall. 451 for (int i = 0; i < number_of_threads; ++i) 452 thread[i]->inSyscall = false; 453 454 // Initialize stages. 455 fetch.initStage(); 456 iew.initStage(); 457 rename.initStage(); 458 commit.initStage(); 459 460 commit.setThreads(thread); 461} 462 463template <class Impl> 464void 465FullO3CPU<Impl>::insertThread(unsigned tid) 466{ 467 DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU"); 468 // Will change now that the PC and thread state is internal to the CPU 469 // and not in the ThreadContext. 470#if FULL_SYSTEM 471 ThreadContext *src_tc = system->threadContexts[tid]; 472#else 473 ThreadContext *src_tc = tcBase(tid); 474#endif 475 476 //Bind Int Regs to Rename Map 477 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 478 PhysRegIndex phys_reg = freeList.getIntReg(); 479 480 renameMap[tid].setEntry(ireg,phys_reg); 481 scoreboard.setReg(phys_reg); 482 } 483 484 //Bind Float Regs to Rename Map 485 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 486 PhysRegIndex phys_reg = freeList.getFloatReg(); 487 488 renameMap[tid].setEntry(freg,phys_reg); 489 scoreboard.setReg(phys_reg); 490 } 491 492 //Copy Thread Data Into RegFile 493 //this->copyFromTC(tid); 494 495 //Set PC/NPC/NNPC 496 setPC(src_tc->readPC(), tid); 497 setNextPC(src_tc->readNextPC(), tid); 498#if THE_ISA != ALPHA_ISA 499 setNextNPC(src_tc->readNextNPC(), tid); 500#endif 501 502 src_tc->setStatus(ThreadContext::Active); 503 504 activateContext(tid,1); 505 506 //Reset ROB/IQ/LSQ Entries 507 commit.rob->resetEntries(); 508 iew.resetEntries(); 509} 510 511template <class Impl> 512void 513FullO3CPU<Impl>::removeThread(unsigned tid) 514{ 515 DPRINTF(O3CPU,"[tid:%i] Removing thread from CPU."); 516 517 // Copy Thread Data From RegFile 518 // If thread is suspended, it might be re-allocated 519 //this->copyToTC(tid); 520 521 // Unbind Int Regs from Rename Map 522 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { 523 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg); 524 525 scoreboard.unsetReg(phys_reg); 526 freeList.addReg(phys_reg); 527 } 528 529 // Unbind Float Regs from Rename Map 530 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) { 531 PhysRegIndex phys_reg = renameMap[tid].lookup(freg); 532 533 scoreboard.unsetReg(phys_reg); 534 freeList.addReg(phys_reg); 535 } 536 537 // Squash Throughout Pipeline 538 fetch.squash(0,tid); 539 decode.squash(tid); 540 rename.squash(tid); 541 542 assert(iew.ldstQueue.getCount(tid) == 0); 543 544 // Reset ROB/IQ/LSQ Entries 545 if (activeThreads.size() >= 1) { 546 commit.rob->resetEntries(); 547 iew.resetEntries(); 548 } 549} 550 551 552template <class Impl> 553void 554FullO3CPU<Impl>::activateWhenReady(int tid) 555{ 556 DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" 557 "(e.g. PhysRegs/ROB/IQ/LSQ) \n", 558 tid); 559 560 bool ready = true; 561 562 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { 563 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 564 "Phys. Int. Regs.\n", 565 tid); 566 ready = false; 567 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { 568 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 569 "Phys. Float. Regs.\n", 570 tid); 571 ready = false; 572 } else if (commit.rob->numFreeEntries() >= 573 commit.rob->entryAmount(activeThreads.size() + 1)) { 574 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 575 "ROB entries.\n", 576 tid); 577 ready = false; 578 } else if (iew.instQueue.numFreeEntries() >= 579 iew.instQueue.entryAmount(activeThreads.size() + 1)) { 580 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 581 "IQ entries.\n", 582 tid); 583 ready = false; 584 } else if (iew.ldstQueue.numFreeEntries() >= 585 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { 586 DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " 587 "LSQ entries.\n", 588 tid); 589 ready = false; 590 } 591 592 if (ready) { 593 insertThread(tid); 594 595 contextSwitch = false; 596 597 cpuWaitList.remove(tid); 598 } else { 599 suspendContext(tid); 600 601 //blocks fetch 602 contextSwitch = true; 603 604 //do waitlist 605 cpuWaitList.push_back(tid); 606 } 607} 608 609template <class Impl> 610void 611FullO3CPU<Impl>::activateThread(unsigned int tid) 612{ 613 list<unsigned>::iterator isActive = find( 614 activeThreads.begin(), activeThreads.end(), tid); 615 616 if (isActive == activeThreads.end()) { 617 DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n", 618 tid); 619 620 activeThreads.push_back(tid); 621 } 622} 623 624 625template <class Impl> 626void 627FullO3CPU<Impl>::activateContext(int tid, int delay) 628{ 629 // Needs to set each stage to running as well. 630 if (delay){ 631 DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " 632 "on cycle %d\n", tid, curTick + cycles(delay)); 633 scheduleActivateThreadEvent(tid, delay); 634 } else { 635 activateThread(tid); 636 } 637 638 if(lastActivatedCycle < curTick) { 639 scheduleTickEvent(delay); 640 641 // Be sure to signal that there's some activity so the CPU doesn't 642 // deschedule itself. 643 activityRec.activity(); 644 fetch.wakeFromQuiesce(); 645 646 lastActivatedCycle = curTick; 647 648 _status = Running; 649 } 650} 651 652template <class Impl> 653void 654FullO3CPU<Impl>::suspendContext(int tid) 655{ 656 DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); 657 unscheduleTickEvent(); 658 _status = Idle; 659/* 660 //Remove From Active List, if Active 661 list<unsigned>::iterator isActive = find( 662 activeThreads.begin(), activeThreads.end(), tid); 663 664 if (isActive != activeThreads.end()) { 665 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 666 tid); 667 activeThreads.erase(isActive); 668 } 669*/ 670} 671 672template <class Impl> 673void 674FullO3CPU<Impl>::deallocateContext(int tid) 675{ 676 DPRINTF(O3CPU,"[tid:%i]: Deallocating Thread Context", tid); 677 678 //Remove From Active List, if Active 679 list<unsigned>::iterator thread_it = 680 find(activeThreads.begin(), activeThreads.end(), tid); 681 682 if (thread_it != activeThreads.end()) { 683 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 684 tid); 685 activeThreads.erase(thread_it); 686 687 removeThread(tid); 688 } 689} 690 691template <class Impl> 692void 693FullO3CPU<Impl>::haltContext(int tid) 694{ 695 DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid); 696/* 697 //Remove From Active List, if Active 698 list<unsigned>::iterator isActive = find( 699 activeThreads.begin(), activeThreads.end(), tid); 700 701 if (isActive != activeThreads.end()) { 702 DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", 703 tid); 704 activeThreads.erase(isActive); 705 706 removeThread(tid); 707 } 708*/ 709} 710 711template <class Impl> 712void 713FullO3CPU<Impl>::serialize(std::ostream &os) 714{ 715 SERIALIZE_ENUM(_status); 716 BaseCPU::serialize(os); 717 nameOut(os, csprintf("%s.tickEvent", name())); 718 tickEvent.serialize(os); 719 720 // Use SimpleThread's ability to checkpoint to make it easier to 721 // write out the registers. Also make this static so it doesn't 722 // get instantiated multiple times (causes a panic in statistics). 723 static SimpleThread temp; 724 725 for (int i = 0; i < thread.size(); i++) { 726 nameOut(os, csprintf("%s.xc.%i", name(), i)); 727 temp.copyTC(thread[i]->getTC()); 728 temp.serialize(os); 729 } 730} 731 732template <class Impl> 733void 734FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 735{ 736 UNSERIALIZE_ENUM(_status); 737 BaseCPU::unserialize(cp, section); 738 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); 739 740 // Use SimpleThread's ability to checkpoint to make it easier to 741 // read in the registers. Also make this static so it doesn't 742 // get instantiated multiple times (causes a panic in statistics). 743 static SimpleThread temp; 744 745 for (int i = 0; i < thread.size(); i++) { 746 temp.copyTC(thread[i]->getTC()); 747 temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); 748 thread[i]->getTC()->copyArchRegs(temp.getTC()); 749 } 750} 751 752template <class Impl> 753bool 754FullO3CPU<Impl>::drain(Event *drain_event) 755{ 756 drainCount = 0; 757 fetch.drain(); 758 decode.drain(); 759 rename.drain(); 760 iew.drain(); 761 commit.drain(); 762 763 // Wake the CPU and record activity so everything can drain out if 764 // the CPU was not able to immediately drain. 765 if (getState() != SimObject::DrainedTiming) { 766 // A bit of a hack...set the drainEvent after all the drain() 767 // calls have been made, that way if all of the stages drain 768 // immediately, the signalDrained() function knows not to call 769 // process on the drain event. 770 drainEvent = drain_event; 771 772 wakeCPU(); 773 activityRec.activity(); 774 775 return false; 776 } else { 777 return true; 778 } 779} 780 781template <class Impl> 782void 783FullO3CPU<Impl>::resume() 784{ 785 fetch.resume(); 786 decode.resume(); 787 rename.resume(); 788 iew.resume(); 789 commit.resume(); 790 791 if (_status == SwitchedOut || _status == Idle) 792 return; 793 794 if (!tickEvent.scheduled()) 795 tickEvent.schedule(curTick); 796 _status = Running;
|
| 797 changeState(SimObject::Timing);
|
796} 797 798template <class Impl> 799void 800FullO3CPU<Impl>::signalDrained() 801{ 802 if (++drainCount == NumStages) { 803 if (tickEvent.scheduled()) 804 tickEvent.squash(); 805 806 changeState(SimObject::DrainedTiming); 807 808 if (drainEvent) { 809 drainEvent->process(); 810 drainEvent = NULL; 811 } 812 } 813 assert(drainCount <= 5); 814} 815 816template <class Impl> 817void 818FullO3CPU<Impl>::switchOut() 819{ 820 fetch.switchOut(); 821 rename.switchOut(); 822 commit.switchOut(); 823 instList.clear(); 824 while (!removeList.empty()) { 825 removeList.pop(); 826 } 827 828 _status = SwitchedOut; 829#if USE_CHECKER 830 if (checker) 831 checker->switchOut(); 832#endif 833} 834 835template <class Impl> 836void 837FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 838{ 839 // Flush out any old data from the time buffers. 840 for (int i = 0; i < 10; ++i) { 841 timeBuffer.advance(); 842 fetchQueue.advance(); 843 decodeQueue.advance(); 844 renameQueue.advance(); 845 iewQueue.advance(); 846 } 847 848 activityRec.reset(); 849 850 BaseCPU::takeOverFrom(oldCPU); 851 852 fetch.takeOverFrom(); 853 decode.takeOverFrom(); 854 rename.takeOverFrom(); 855 iew.takeOverFrom(); 856 commit.takeOverFrom(); 857 858 assert(!tickEvent.scheduled()); 859 860 // @todo: Figure out how to properly select the tid to put onto 861 // the active threads list. 862 int tid = 0; 863 864 list<unsigned>::iterator isActive = find( 865 activeThreads.begin(), activeThreads.end(), tid); 866 867 if (isActive == activeThreads.end()) { 868 //May Need to Re-code this if the delay variable is the delay 869 //needed for thread to activate 870 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 871 tid); 872 873 activeThreads.push_back(tid); 874 } 875 876 // Set all statuses to active, schedule the CPU's tick event. 877 // @todo: Fix up statuses so this is handled properly 878 for (int i = 0; i < threadContexts.size(); ++i) { 879 ThreadContext *tc = threadContexts[i]; 880 if (tc->status() == ThreadContext::Active && _status != Running) { 881 _status = Running; 882 tickEvent.schedule(curTick); 883 } 884 } 885 if (!tickEvent.scheduled()) 886 tickEvent.schedule(curTick); 887} 888 889template <class Impl> 890uint64_t 891FullO3CPU<Impl>::readIntReg(int reg_idx) 892{ 893 return regFile.readIntReg(reg_idx); 894} 895 896template <class Impl> 897FloatReg 898FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 899{ 900 return regFile.readFloatReg(reg_idx, width); 901} 902 903template <class Impl> 904FloatReg 905FullO3CPU<Impl>::readFloatReg(int reg_idx) 906{ 907 return regFile.readFloatReg(reg_idx); 908} 909 910template <class Impl> 911FloatRegBits 912FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 913{ 914 return regFile.readFloatRegBits(reg_idx, width); 915} 916 917template <class Impl> 918FloatRegBits 919FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 920{ 921 return regFile.readFloatRegBits(reg_idx); 922} 923 924template <class Impl> 925void 926FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 927{ 928 regFile.setIntReg(reg_idx, val); 929} 930 931template <class Impl> 932void 933FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 934{ 935 regFile.setFloatReg(reg_idx, val, width); 936} 937 938template <class Impl> 939void 940FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 941{ 942 regFile.setFloatReg(reg_idx, val); 943} 944 945template <class Impl> 946void 947FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 948{ 949 regFile.setFloatRegBits(reg_idx, val, width); 950} 951 952template <class Impl> 953void 954FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 955{ 956 regFile.setFloatRegBits(reg_idx, val); 957} 958 959template <class Impl> 960uint64_t 961FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 962{ 963 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 964 965 return regFile.readIntReg(phys_reg); 966} 967 968template <class Impl> 969float 970FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 971{ 972 int idx = reg_idx + TheISA::FP_Base_DepTag; 973 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 974 975 return regFile.readFloatReg(phys_reg); 976} 977 978template <class Impl> 979double 980FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 981{ 982 int idx = reg_idx + TheISA::FP_Base_DepTag; 983 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 984 985 return regFile.readFloatReg(phys_reg, 64); 986} 987 988template <class Impl> 989uint64_t 990FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 991{ 992 int idx = reg_idx + TheISA::FP_Base_DepTag; 993 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 994 995 return regFile.readFloatRegBits(phys_reg); 996} 997 998template <class Impl> 999void 1000FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1001{ 1002 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1003 1004 regFile.setIntReg(phys_reg, val); 1005} 1006 1007template <class Impl> 1008void 1009FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1010{ 1011 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1012 1013 regFile.setFloatReg(phys_reg, val); 1014} 1015 1016template <class Impl> 1017void 1018FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1019{ 1020 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1021 1022 regFile.setFloatReg(phys_reg, val, 64); 1023} 1024 1025template <class Impl> 1026void 1027FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1028{ 1029 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1030 1031 regFile.setFloatRegBits(phys_reg, val); 1032} 1033 1034template <class Impl> 1035uint64_t 1036FullO3CPU<Impl>::readPC(unsigned tid) 1037{ 1038 return commit.readPC(tid); 1039} 1040 1041template <class Impl> 1042void 1043FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1044{ 1045 commit.setPC(new_PC, tid); 1046} 1047 1048template <class Impl> 1049uint64_t 1050FullO3CPU<Impl>::readNextPC(unsigned tid) 1051{ 1052 return commit.readNextPC(tid); 1053} 1054 1055template <class Impl> 1056void 1057FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1058{ 1059 commit.setNextPC(val, tid); 1060} 1061 1062#if THE_ISA != ALPHA_ISA 1063template <class Impl> 1064uint64_t 1065FullO3CPU<Impl>::readNextNPC(unsigned tid) 1066{ 1067 return commit.readNextNPC(tid); 1068} 1069 1070template <class Impl> 1071void 1072FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) 1073{ 1074 commit.setNextNPC(val, tid); 1075} 1076#endif 1077 1078template <class Impl> 1079typename FullO3CPU<Impl>::ListIt 1080FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1081{ 1082 instList.push_back(inst); 1083 1084 return --(instList.end()); 1085} 1086 1087template <class Impl> 1088void 1089FullO3CPU<Impl>::instDone(unsigned tid) 1090{ 1091 // Keep an instruction count. 1092 thread[tid]->numInst++; 1093 thread[tid]->numInsts++; 1094 committedInsts[tid]++; 1095 totalCommittedInsts++; 1096 1097 // Check for instruction-count-based events. 1098 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1099} 1100 1101template <class Impl> 1102void 1103FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1104{ 1105 removeInstsThisCycle = true; 1106 1107 removeList.push(inst->getInstListIt()); 1108} 1109 1110template <class Impl> 1111void 1112FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1113{ 1114 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1115 "[sn:%lli]\n", 1116 inst->threadNumber, inst->readPC(), inst->seqNum); 1117 1118 removeInstsThisCycle = true; 1119 1120 // Remove the front instruction. 1121 removeList.push(inst->getInstListIt()); 1122} 1123 1124template <class Impl> 1125void 1126FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1127{ 1128 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1129 " list.\n", tid); 1130 1131 ListIt end_it; 1132 1133 bool rob_empty = false; 1134 1135 if (instList.empty()) { 1136 return; 1137 } else if (rob.isEmpty(/*tid*/)) { 1138 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1139 end_it = instList.begin(); 1140 rob_empty = true; 1141 } else { 1142 end_it = (rob.readTailInst(tid))->getInstListIt(); 1143 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1144 } 1145 1146 removeInstsThisCycle = true; 1147 1148 ListIt inst_it = instList.end(); 1149 1150 inst_it--; 1151 1152 // Walk through the instruction list, removing any instructions 1153 // that were inserted after the given instruction iterator, end_it. 1154 while (inst_it != end_it) { 1155 assert(!instList.empty()); 1156 1157 squashInstIt(inst_it, tid); 1158 1159 inst_it--; 1160 } 1161 1162 // If the ROB was empty, then we actually need to remove the first 1163 // instruction as well. 1164 if (rob_empty) { 1165 squashInstIt(inst_it, tid); 1166 } 1167} 1168 1169template <class Impl> 1170void 1171FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1172 unsigned tid) 1173{ 1174 assert(!instList.empty()); 1175 1176 removeInstsThisCycle = true; 1177 1178 ListIt inst_iter = instList.end(); 1179 1180 inst_iter--; 1181 1182 DPRINTF(O3CPU, "Deleting instructions from instruction " 1183 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1184 tid, seq_num, (*inst_iter)->seqNum); 1185 1186 while ((*inst_iter)->seqNum > seq_num) { 1187 1188 bool break_loop = (inst_iter == instList.begin()); 1189 1190 squashInstIt(inst_iter, tid); 1191 1192 inst_iter--; 1193 1194 if (break_loop) 1195 break; 1196 } 1197} 1198 1199template <class Impl> 1200inline void 1201FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1202{ 1203 if ((*instIt)->threadNumber == tid) { 1204 DPRINTF(O3CPU, "Squashing instruction, " 1205 "[tid:%i] [sn:%lli] PC %#x\n", 1206 (*instIt)->threadNumber, 1207 (*instIt)->seqNum, 1208 (*instIt)->readPC()); 1209 1210 // Mark it as squashed. 1211 (*instIt)->setSquashed(); 1212 1213 // @todo: Formulate a consistent method for deleting 1214 // instructions from the instruction list 1215 // Remove the instruction from the list. 1216 removeList.push(instIt); 1217 } 1218} 1219 1220template <class Impl> 1221void 1222FullO3CPU<Impl>::cleanUpRemovedInsts() 1223{ 1224 while (!removeList.empty()) { 1225 DPRINTF(O3CPU, "Removing instruction, " 1226 "[tid:%i] [sn:%lli] PC %#x\n", 1227 (*removeList.front())->threadNumber, 1228 (*removeList.front())->seqNum, 1229 (*removeList.front())->readPC()); 1230 1231 instList.erase(removeList.front()); 1232 1233 removeList.pop(); 1234 } 1235 1236 removeInstsThisCycle = false; 1237} 1238/* 1239template <class Impl> 1240void 1241FullO3CPU<Impl>::removeAllInsts() 1242{ 1243 instList.clear(); 1244} 1245*/ 1246template <class Impl> 1247void 1248FullO3CPU<Impl>::dumpInsts() 1249{ 1250 int num = 0; 1251 1252 ListIt inst_list_it = instList.begin(); 1253 1254 cprintf("Dumping Instruction List\n"); 1255 1256 while (inst_list_it != instList.end()) { 1257 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1258 "Squashed:%i\n\n", 1259 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1260 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1261 (*inst_list_it)->isSquashed()); 1262 inst_list_it++; 1263 ++num; 1264 } 1265} 1266/* 1267template <class Impl> 1268void 1269FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1270{ 1271 iew.wakeDependents(inst); 1272} 1273*/ 1274template <class Impl> 1275void 1276FullO3CPU<Impl>::wakeCPU() 1277{ 1278 if (activityRec.active() || tickEvent.scheduled()) { 1279 DPRINTF(Activity, "CPU already running.\n"); 1280 return; 1281 } 1282 1283 DPRINTF(Activity, "Waking up CPU\n"); 1284 1285 idleCycles += (curTick - 1) - lastRunningCycle; 1286 1287 tickEvent.schedule(curTick); 1288} 1289 1290template <class Impl> 1291int 1292FullO3CPU<Impl>::getFreeTid() 1293{ 1294 for (int i=0; i < numThreads; i++) { 1295 if (!tids[i]) { 1296 tids[i] = true; 1297 return i; 1298 } 1299 } 1300 1301 return -1; 1302} 1303 1304template <class Impl> 1305void 1306FullO3CPU<Impl>::doContextSwitch() 1307{ 1308 if (contextSwitch) { 1309 1310 //ADD CODE TO DEACTIVE THREAD HERE (???) 1311 1312 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1313 activateWhenReady(tid); 1314 } 1315 1316 if (cpuWaitList.size() == 0) 1317 contextSwitch = true; 1318 } 1319} 1320 1321template <class Impl> 1322void 1323FullO3CPU<Impl>::updateThreadPriority() 1324{ 1325 if (activeThreads.size() > 1) 1326 { 1327 //DEFAULT TO ROUND ROBIN SCHEME 1328 //e.g. Move highest priority to end of thread list 1329 list<unsigned>::iterator list_begin = activeThreads.begin(); 1330 list<unsigned>::iterator list_end = activeThreads.end(); 1331 1332 unsigned high_thread = *list_begin; 1333 1334 activeThreads.erase(list_begin); 1335 1336 activeThreads.push_back(high_thread); 1337 } 1338} 1339 1340// Forward declaration of FullO3CPU. 1341template class FullO3CPU<O3CPUImpl>;
| 798} 799 800template <class Impl> 801void 802FullO3CPU<Impl>::signalDrained() 803{ 804 if (++drainCount == NumStages) { 805 if (tickEvent.scheduled()) 806 tickEvent.squash(); 807 808 changeState(SimObject::DrainedTiming); 809 810 if (drainEvent) { 811 drainEvent->process(); 812 drainEvent = NULL; 813 } 814 } 815 assert(drainCount <= 5); 816} 817 818template <class Impl> 819void 820FullO3CPU<Impl>::switchOut() 821{ 822 fetch.switchOut(); 823 rename.switchOut(); 824 commit.switchOut(); 825 instList.clear(); 826 while (!removeList.empty()) { 827 removeList.pop(); 828 } 829 830 _status = SwitchedOut; 831#if USE_CHECKER 832 if (checker) 833 checker->switchOut(); 834#endif 835} 836 837template <class Impl> 838void 839FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 840{ 841 // Flush out any old data from the time buffers. 842 for (int i = 0; i < 10; ++i) { 843 timeBuffer.advance(); 844 fetchQueue.advance(); 845 decodeQueue.advance(); 846 renameQueue.advance(); 847 iewQueue.advance(); 848 } 849 850 activityRec.reset(); 851 852 BaseCPU::takeOverFrom(oldCPU); 853 854 fetch.takeOverFrom(); 855 decode.takeOverFrom(); 856 rename.takeOverFrom(); 857 iew.takeOverFrom(); 858 commit.takeOverFrom(); 859 860 assert(!tickEvent.scheduled()); 861 862 // @todo: Figure out how to properly select the tid to put onto 863 // the active threads list. 864 int tid = 0; 865 866 list<unsigned>::iterator isActive = find( 867 activeThreads.begin(), activeThreads.end(), tid); 868 869 if (isActive == activeThreads.end()) { 870 //May Need to Re-code this if the delay variable is the delay 871 //needed for thread to activate 872 DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", 873 tid); 874 875 activeThreads.push_back(tid); 876 } 877 878 // Set all statuses to active, schedule the CPU's tick event. 879 // @todo: Fix up statuses so this is handled properly 880 for (int i = 0; i < threadContexts.size(); ++i) { 881 ThreadContext *tc = threadContexts[i]; 882 if (tc->status() == ThreadContext::Active && _status != Running) { 883 _status = Running; 884 tickEvent.schedule(curTick); 885 } 886 } 887 if (!tickEvent.scheduled()) 888 tickEvent.schedule(curTick); 889} 890 891template <class Impl> 892uint64_t 893FullO3CPU<Impl>::readIntReg(int reg_idx) 894{ 895 return regFile.readIntReg(reg_idx); 896} 897 898template <class Impl> 899FloatReg 900FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) 901{ 902 return regFile.readFloatReg(reg_idx, width); 903} 904 905template <class Impl> 906FloatReg 907FullO3CPU<Impl>::readFloatReg(int reg_idx) 908{ 909 return regFile.readFloatReg(reg_idx); 910} 911 912template <class Impl> 913FloatRegBits 914FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) 915{ 916 return regFile.readFloatRegBits(reg_idx, width); 917} 918 919template <class Impl> 920FloatRegBits 921FullO3CPU<Impl>::readFloatRegBits(int reg_idx) 922{ 923 return regFile.readFloatRegBits(reg_idx); 924} 925 926template <class Impl> 927void 928FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) 929{ 930 regFile.setIntReg(reg_idx, val); 931} 932 933template <class Impl> 934void 935FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 936{ 937 regFile.setFloatReg(reg_idx, val, width); 938} 939 940template <class Impl> 941void 942FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) 943{ 944 regFile.setFloatReg(reg_idx, val); 945} 946 947template <class Impl> 948void 949FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) 950{ 951 regFile.setFloatRegBits(reg_idx, val, width); 952} 953 954template <class Impl> 955void 956FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 957{ 958 regFile.setFloatRegBits(reg_idx, val); 959} 960 961template <class Impl> 962uint64_t 963FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid) 964{ 965 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 966 967 return regFile.readIntReg(phys_reg); 968} 969 970template <class Impl> 971float 972FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid) 973{ 974 int idx = reg_idx + TheISA::FP_Base_DepTag; 975 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 976 977 return regFile.readFloatReg(phys_reg); 978} 979 980template <class Impl> 981double 982FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid) 983{ 984 int idx = reg_idx + TheISA::FP_Base_DepTag; 985 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 986 987 return regFile.readFloatReg(phys_reg, 64); 988} 989 990template <class Impl> 991uint64_t 992FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid) 993{ 994 int idx = reg_idx + TheISA::FP_Base_DepTag; 995 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); 996 997 return regFile.readFloatRegBits(phys_reg); 998} 999 1000template <class Impl> 1001void 1002FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid) 1003{ 1004 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1005 1006 regFile.setIntReg(phys_reg, val); 1007} 1008 1009template <class Impl> 1010void 1011FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) 1012{ 1013 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1014 1015 regFile.setFloatReg(phys_reg, val); 1016} 1017 1018template <class Impl> 1019void 1020FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) 1021{ 1022 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1023 1024 regFile.setFloatReg(phys_reg, val, 64); 1025} 1026 1027template <class Impl> 1028void 1029FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) 1030{ 1031 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); 1032 1033 regFile.setFloatRegBits(phys_reg, val); 1034} 1035 1036template <class Impl> 1037uint64_t 1038FullO3CPU<Impl>::readPC(unsigned tid) 1039{ 1040 return commit.readPC(tid); 1041} 1042 1043template <class Impl> 1044void 1045FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid) 1046{ 1047 commit.setPC(new_PC, tid); 1048} 1049 1050template <class Impl> 1051uint64_t 1052FullO3CPU<Impl>::readNextPC(unsigned tid) 1053{ 1054 return commit.readNextPC(tid); 1055} 1056 1057template <class Impl> 1058void 1059FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) 1060{ 1061 commit.setNextPC(val, tid); 1062} 1063 1064#if THE_ISA != ALPHA_ISA 1065template <class Impl> 1066uint64_t 1067FullO3CPU<Impl>::readNextNPC(unsigned tid) 1068{ 1069 return commit.readNextNPC(tid); 1070} 1071 1072template <class Impl> 1073void 1074FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) 1075{ 1076 commit.setNextNPC(val, tid); 1077} 1078#endif 1079 1080template <class Impl> 1081typename FullO3CPU<Impl>::ListIt 1082FullO3CPU<Impl>::addInst(DynInstPtr &inst) 1083{ 1084 instList.push_back(inst); 1085 1086 return --(instList.end()); 1087} 1088 1089template <class Impl> 1090void 1091FullO3CPU<Impl>::instDone(unsigned tid) 1092{ 1093 // Keep an instruction count. 1094 thread[tid]->numInst++; 1095 thread[tid]->numInsts++; 1096 committedInsts[tid]++; 1097 totalCommittedInsts++; 1098 1099 // Check for instruction-count-based events. 1100 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); 1101} 1102 1103template <class Impl> 1104void 1105FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst) 1106{ 1107 removeInstsThisCycle = true; 1108 1109 removeList.push(inst->getInstListIt()); 1110} 1111 1112template <class Impl> 1113void 1114FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 1115{ 1116 DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " 1117 "[sn:%lli]\n", 1118 inst->threadNumber, inst->readPC(), inst->seqNum); 1119 1120 removeInstsThisCycle = true; 1121 1122 // Remove the front instruction. 1123 removeList.push(inst->getInstListIt()); 1124} 1125 1126template <class Impl> 1127void 1128FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) 1129{ 1130 DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" 1131 " list.\n", tid); 1132 1133 ListIt end_it; 1134 1135 bool rob_empty = false; 1136 1137 if (instList.empty()) { 1138 return; 1139 } else if (rob.isEmpty(/*tid*/)) { 1140 DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); 1141 end_it = instList.begin(); 1142 rob_empty = true; 1143 } else { 1144 end_it = (rob.readTailInst(tid))->getInstListIt(); 1145 DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); 1146 } 1147 1148 removeInstsThisCycle = true; 1149 1150 ListIt inst_it = instList.end(); 1151 1152 inst_it--; 1153 1154 // Walk through the instruction list, removing any instructions 1155 // that were inserted after the given instruction iterator, end_it. 1156 while (inst_it != end_it) { 1157 assert(!instList.empty()); 1158 1159 squashInstIt(inst_it, tid); 1160 1161 inst_it--; 1162 } 1163 1164 // If the ROB was empty, then we actually need to remove the first 1165 // instruction as well. 1166 if (rob_empty) { 1167 squashInstIt(inst_it, tid); 1168 } 1169} 1170 1171template <class Impl> 1172void 1173FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num, 1174 unsigned tid) 1175{ 1176 assert(!instList.empty()); 1177 1178 removeInstsThisCycle = true; 1179 1180 ListIt inst_iter = instList.end(); 1181 1182 inst_iter--; 1183 1184 DPRINTF(O3CPU, "Deleting instructions from instruction " 1185 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", 1186 tid, seq_num, (*inst_iter)->seqNum); 1187 1188 while ((*inst_iter)->seqNum > seq_num) { 1189 1190 bool break_loop = (inst_iter == instList.begin()); 1191 1192 squashInstIt(inst_iter, tid); 1193 1194 inst_iter--; 1195 1196 if (break_loop) 1197 break; 1198 } 1199} 1200 1201template <class Impl> 1202inline void 1203FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid) 1204{ 1205 if ((*instIt)->threadNumber == tid) { 1206 DPRINTF(O3CPU, "Squashing instruction, " 1207 "[tid:%i] [sn:%lli] PC %#x\n", 1208 (*instIt)->threadNumber, 1209 (*instIt)->seqNum, 1210 (*instIt)->readPC()); 1211 1212 // Mark it as squashed. 1213 (*instIt)->setSquashed(); 1214 1215 // @todo: Formulate a consistent method for deleting 1216 // instructions from the instruction list 1217 // Remove the instruction from the list. 1218 removeList.push(instIt); 1219 } 1220} 1221 1222template <class Impl> 1223void 1224FullO3CPU<Impl>::cleanUpRemovedInsts() 1225{ 1226 while (!removeList.empty()) { 1227 DPRINTF(O3CPU, "Removing instruction, " 1228 "[tid:%i] [sn:%lli] PC %#x\n", 1229 (*removeList.front())->threadNumber, 1230 (*removeList.front())->seqNum, 1231 (*removeList.front())->readPC()); 1232 1233 instList.erase(removeList.front()); 1234 1235 removeList.pop(); 1236 } 1237 1238 removeInstsThisCycle = false; 1239} 1240/* 1241template <class Impl> 1242void 1243FullO3CPU<Impl>::removeAllInsts() 1244{ 1245 instList.clear(); 1246} 1247*/ 1248template <class Impl> 1249void 1250FullO3CPU<Impl>::dumpInsts() 1251{ 1252 int num = 0; 1253 1254 ListIt inst_list_it = instList.begin(); 1255 1256 cprintf("Dumping Instruction List\n"); 1257 1258 while (inst_list_it != instList.end()) { 1259 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" 1260 "Squashed:%i\n\n", 1261 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, 1262 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), 1263 (*inst_list_it)->isSquashed()); 1264 inst_list_it++; 1265 ++num; 1266 } 1267} 1268/* 1269template <class Impl> 1270void 1271FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 1272{ 1273 iew.wakeDependents(inst); 1274} 1275*/ 1276template <class Impl> 1277void 1278FullO3CPU<Impl>::wakeCPU() 1279{ 1280 if (activityRec.active() || tickEvent.scheduled()) { 1281 DPRINTF(Activity, "CPU already running.\n"); 1282 return; 1283 } 1284 1285 DPRINTF(Activity, "Waking up CPU\n"); 1286 1287 idleCycles += (curTick - 1) - lastRunningCycle; 1288 1289 tickEvent.schedule(curTick); 1290} 1291 1292template <class Impl> 1293int 1294FullO3CPU<Impl>::getFreeTid() 1295{ 1296 for (int i=0; i < numThreads; i++) { 1297 if (!tids[i]) { 1298 tids[i] = true; 1299 return i; 1300 } 1301 } 1302 1303 return -1; 1304} 1305 1306template <class Impl> 1307void 1308FullO3CPU<Impl>::doContextSwitch() 1309{ 1310 if (contextSwitch) { 1311 1312 //ADD CODE TO DEACTIVE THREAD HERE (???) 1313 1314 for (int tid=0; tid < cpuWaitList.size(); tid++) { 1315 activateWhenReady(tid); 1316 } 1317 1318 if (cpuWaitList.size() == 0) 1319 contextSwitch = true; 1320 } 1321} 1322 1323template <class Impl> 1324void 1325FullO3CPU<Impl>::updateThreadPriority() 1326{ 1327 if (activeThreads.size() > 1) 1328 { 1329 //DEFAULT TO ROUND ROBIN SCHEME 1330 //e.g. Move highest priority to end of thread list 1331 list<unsigned>::iterator list_begin = activeThreads.begin(); 1332 list<unsigned>::iterator list_end = activeThreads.end(); 1333 1334 unsigned high_thread = *list_begin; 1335 1336 activeThreads.erase(list_begin); 1337 1338 activeThreads.push_back(high_thread); 1339 } 1340} 1341 1342// Forward declaration of FullO3CPU. 1343template class FullO3CPU<O3CPUImpl>;
|