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