1/*
|
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
|
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan |
3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27 * 28 * 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
|
38#include "sim/root.hh" |
39
|
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
|
45#include "sim/root.hh"
46#include "sim/stat_control.hh"
47
|
46using namespace std; 47
|
50BaseFullCPU::BaseFullCPU(Params *params)
51 : BaseCPU(params), cpu_id(0)
|
48BaseFullCPU::BaseFullCPU(Params ¶ms) 49 : BaseCPU(¶ms), cpu_id(0) |
50{ 51} 52
|
55void
56BaseFullCPU::regStats()
57{
58 BaseCPU::regStats();
59}
60
|
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
|
73//Call constructor to all the pipeline stages here |
74template <class Impl>
|
82FullO3CPU<Impl>::FullO3CPU(Params *params)
|
75FullO3CPU<Impl>::FullO3CPU(Params ¶ms) 76#if FULL_SYSTEM |
77 : BaseFullCPU(params),
|
78#else 79 : BaseFullCPU(params), 80#endif // FULL_SYSTEM |
81 tickEvent(this),
|
85 removeInstsThisCycle(false),
|
82 fetch(params), 83 decode(params), 84 rename(params), 85 iew(params), 86 commit(params), 87
|
92 regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
|
88 regFile(params.numPhysIntRegs, params.numPhysFloatRegs), |
89
|
94 freeList(params->numberOfThreads,//number of activeThreads
95 TheISA::NumIntRegs, params->numPhysIntRegs,
96 TheISA::NumFloatRegs, params->numPhysFloatRegs),
|
90 freeList(TheISA::NumIntRegs, params.numPhysIntRegs, 91 TheISA::NumFloatRegs, params.numPhysFloatRegs), |
92
|
98 rob(params->numROBEntries, params->squashWidth,
99 params->smtROBPolicy, params->smtROBThreshold,
100 params->numberOfThreads),
|
93 renameMap(TheISA::NumIntRegs, params.numPhysIntRegs, 94 TheISA::NumFloatRegs, params.numPhysFloatRegs, 95 TheISA::NumMiscRegs, 96 TheISA::ZeroReg, 97 TheISA::ZeroReg + TheISA::NumIntRegs), |
98
|
102 scoreboard(params->numberOfThreads,//number of activeThreads
103 TheISA::NumIntRegs, params->numPhysIntRegs,
104 TheISA::NumFloatRegs, params->numPhysFloatRegs,
105 TheISA::NumMiscRegs * number_of_threads,
106 TheISA::ZeroReg),
|
99 rob(params.numROBEntries, params.squashWidth), |
100
|
101 // What to pass to these time buffers? |
102 // For now just have these time buffers be pretty big.
|
109 // @todo: Make these time buffer sizes parameters or derived
110 // from latencies
|
103 timeBuffer(5, 5), 104 fetchQueue(5, 5), 105 decodeQueue(5, 5), 106 renameQueue(5, 5), 107 iewQueue(5, 5),
|
116 activityRec(NumStages, 10, params->activity),
|
108
|
109 cpuXC(NULL), 110 |
111 globalSeqNum(1), 112 113#if FULL_SYSTEM
|
121 system(params->system),
|
114 system(params.system), |
115 memCtrl(system->memctrl), 116 physmem(system->physmem),
|
124 mem(params->mem),
|
117 itb(params.itb), 118 dtb(params.dtb), 119 mem(params.mem), |
120#else
|
126// pTable(params->pTable),
127 mem(params->workload[0]->getMemory()),
|
121 // Hardcoded for a single thread!! 122 mem(params.workload[0]->getMemory()), |
123#endif // FULL_SYSTEM
|
129 switchCount(0),
130 icacheInterface(params->icacheInterface),
131 dcacheInterface(params->dcacheInterface),
132 deferRegistration(params->deferRegistration),
133 numThreads(number_of_threads)
|
124 125 icacheInterface(params.icacheInterface), 126 dcacheInterface(params.dcacheInterface), 127 deferRegistration(params.defReg), 128 numInsts(0), 129 funcExeInst(0) |
130{ 131 _status = Idle; 132
|
137 if (params->checker) {
138 BaseCPU *temp_checker = params->checker;
139 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
140 checker->setMemory(mem);
141#if FULL_SYSTEM
142 checker->setSystem(params->system);
143#endif
144 } else {
145 checker = NULL;
146 }
147
|
133#if !FULL_SYSTEM
|
149 thread.resize(number_of_threads);
150 tids.resize(number_of_threads);
|
134 thread.resize(this->number_of_threads); |
135#endif 136
|
153 // The stages also need their CPU pointer setup. However this
154 // must be done at the upper level CPU because they have pointers
155 // to the upper level CPU, and not this FullO3CPU.
|
137 for (int i = 0; i < this->number_of_threads; ++i) { 138#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
|
157 // Set up Pointers to the activeThreads list for each stage
158 fetch.setActiveThreads(&activeThreads);
159 decode.setActiveThreads(&activeThreads);
160 rename.setActiveThreads(&activeThreads);
161 iew.setActiveThreads(&activeThreads);
162 commit.setActiveThreads(&activeThreads);
|
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 155 } |
156
|
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]; 160 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. 164 |
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);
|
174 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
|
183 commit.setFetchStage(&fetch);
184 commit.setIEWStage(&iew);
185 rename.setIEWStage(&iew);
186 rename.setCommitStage(&commit);
187
188#if !FULL_SYSTEM
189 int active_threads = params->workload.size();
190#else
191 int active_threads = 1;
192#endif
193
194 //Make Sure That this a Valid Architeture
195 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
196 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
197
198 rename.setScoreboard(&scoreboard);
199 iew.setScoreboard(&scoreboard);
200
|
183 // Setup the rename map for whichever stages need it.
|
202 PhysRegIndex lreg_idx = 0;
203 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
|
184 rename.setRenameMap(&renameMap); 185 iew.setRenameMap(&renameMap); |
186
|
205 for (int tid=0; tid < numThreads; tid++) {
206 bool bindRegs = (tid <= active_threads - 1);
207
208 commitRenameMap[tid].init(TheISA::NumIntRegs,
209 params->numPhysIntRegs,
210 lreg_idx, //Index for Logical. Regs
211
212 TheISA::NumFloatRegs,
213 params->numPhysFloatRegs,
214 freg_idx, //Index for Float Regs
215
216 TheISA::NumMiscRegs,
217
218 TheISA::ZeroReg,
219 TheISA::ZeroReg,
220
221 tid,
222 false);
223
224 renameMap[tid].init(TheISA::NumIntRegs,
225 params->numPhysIntRegs,
226 lreg_idx, //Index for Logical. Regs
227
228 TheISA::NumFloatRegs,
229 params->numPhysFloatRegs,
230 freg_idx, //Index for Float Regs
231
232 TheISA::NumMiscRegs,
233
234 TheISA::ZeroReg,
235 TheISA::ZeroReg,
236
237 tid,
238 bindRegs);
239 }
240
241 rename.setRenameMap(renameMap);
242 commit.setRenameMap(commitRenameMap);
243
244 // Give renameMap & rename stage access to the freeList;
245 for (int i=0; i < numThreads; i++) {
246 renameMap[i].setFreeList(&freeList);
247 }
|
187 // Setup the free list for whichever stages need it. |
188 rename.setFreeList(&freeList);
|
189 renameMap.setFreeList(&freeList); |
190
|
250 // Setup the page table for whichever stages need it.
251#if !FULL_SYSTEM
252// fetch.setPageTable(pTable);
253// iew.setPageTable(pTable);
254#endif
255
|
191 // Setup the ROB for whichever stages need it. 192 commit.setROB(&rob);
|
258
259 lastRunningCycle = curTick;
260
261 contextSwitch = false;
|
193} 194 195template <class Impl> 196FullO3CPU<Impl>::~FullO3CPU() 197{ 198} 199 200template <class Impl> 201void 202FullO3CPU<Impl>::fullCPURegStats() 203{
|
273 BaseFullCPU::regStats();
274
|
204 // Register any of the FullCPU's stats here.
|
276 timesIdled
277 .name(name() + ".timesIdled")
278 .desc("Number of times that the entire CPU went into an idle state and"
279 " unscheduled itself")
280 .prereq(timesIdled);
281
282 idleCycles
283 .name(name() + ".idleCycles")
284 .desc("Total number of cycles that the CPU has spent unscheduled due "
285 "to idling")
286 .prereq(idleCycles);
287
288 // Number of Instructions simulated
289 // --------------------------------
290 // Should probably be in Base CPU but need templated
291 // MaxThreads so put in here instead
292 committedInsts
293 .init(numThreads)
294 .name(name() + ".committedInsts")
295 .desc("Number of Instructions Simulated");
296
297 totalCommittedInsts
298 .name(name() + ".committedInsts_total")
299 .desc("Number of Instructions Simulated");
300
301 cpi
302 .name(name() + ".cpi")
303 .desc("CPI: Cycles Per Instruction")
304 .precision(6);
305 cpi = simTicks / committedInsts;
306
307 totalCpi
308 .name(name() + ".cpi_total")
309 .desc("CPI: Total CPI of All Threads")
310 .precision(6);
311 totalCpi = simTicks / totalCommittedInsts;
312
313 ipc
314 .name(name() + ".ipc")
315 .desc("IPC: Instructions Per Cycle")
316 .precision(6);
317 ipc = committedInsts / simTicks;
318
319 totalIpc
320 .name(name() + ".ipc_total")
321 .desc("IPC: Total IPC of All Threads")
322 .precision(6);
323 totalIpc = totalCommittedInsts / simTicks;
324
|
205} 206 207template <class Impl> 208void 209FullO3CPU<Impl>::tick() 210{ 211 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n"); 212
|
333 ++numCycles;
334
335// activity = false;
336
337 //Tick each of the stages
|
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. |
216 fetch.tick(); 217 218 decode.tick(); 219 220 rename.tick(); 221 222 iew.tick(); 223 224 commit.tick(); 225
|
348#if !FULL_SYSTEM
349 doContextSwitch();
350#endif
351
352 // Now advance the time buffers
|
226 // Now advance the time buffers, unless the stage is stalled. |
227 timeBuffer.advance(); 228 229 fetchQueue.advance(); 230 decodeQueue.advance(); 231 renameQueue.advance(); 232 iewQueue.advance(); 233
|
360 activityRec.advance();
361
362 if (removeInstsThisCycle) {
363 cleanUpRemovedInsts();
364 }
365
366 if (!tickEvent.scheduled()) {
367 if (_status == SwitchedOut) {
368 // increment stat
369 lastRunningCycle = curTick;
370 } else if (!activityRec.active()) {
371 lastRunningCycle = curTick;
372 timesIdled++;
373 } else {
374 tickEvent.schedule(curTick + cycles(1));
375 }
376 }
377
378#if !FULL_SYSTEM
379 updateThreadPriority();
380#endif
381
|
234 if (_status == Running && !tickEvent.scheduled()) 235 tickEvent.schedule(curTick + 1); |
236} 237 238template <class Impl> 239void 240FullO3CPU<Impl>::init() 241{
|
388 if (!deferRegistration) {
389 registerExecContexts();
390 }
|
242 if(!deferRegistration) 243 { 244 this->registerExecContexts(); |
245
|
392 // Set inSyscall so that the CPU doesn't squash when initially
393 // setting up registers.
394 for (int i = 0; i < number_of_threads; ++i)
395 thread[i]->inSyscall = true;
396
397 for (int tid=0; tid < number_of_threads; tid++) {
|
246 // Need to do a copy of the xc->regs into the CPU's regfile so 247 // that it can start properly. |
248#if FULL_SYSTEM
|
399 ExecContext *src_xc = execContexts[tid];
|
249 ExecContext *src_xc = system->execContexts[0]; 250 TheISA::initCPU(src_xc, src_xc->readCpuId()); |
251#else
|
401 ExecContext *src_xc = thread[tid]->getXCProxy();
|
252 ExecContext *src_xc = thread[0]->getProxy(); |
253#endif
|
403 // Threads start in the Suspended State
404 if (src_xc->status() != ExecContext::Suspended) {
405 continue;
|
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); |
258 } 259
|
408#if FULL_SYSTEM
409 TheISA::initCPU(src_xc, src_xc->readCpuId());
410#endif
|
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(); |
275 }
|
412
413 // Clear inSyscall.
414 for (int i = 0; i < number_of_threads; ++i)
415 thread[i]->inSyscall = false;
416
417 // Initialize stages.
418 fetch.initStage();
419 iew.initStage();
420 rename.initStage();
421 commit.initStage();
422
423 commit.setThreads(thread);
|
276} 277 278template <class Impl> 279void
|
428FullO3CPU<Impl>::insertThread(unsigned tid)
|
280FullO3CPU<Impl>::activateContext(int thread_num, int delay) |
281{
|
430 DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
431 // Will change now that the PC and thread state is internal to the CPU
432 // and not in the CPUExecContext.
433#if 0
434#if FULL_SYSTEM
435 ExecContext *src_xc = system->execContexts[tid];
436#else
437 CPUExecContext *src_xc = thread[tid];
438#endif
439
440 //Bind Int Regs to Rename Map
441 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
442 PhysRegIndex phys_reg = freeList.getIntReg();
443
444 renameMap[tid].setEntry(ireg,phys_reg);
445 scoreboard.setReg(phys_reg);
446 }
447
448 //Bind Float Regs to Rename Map
449 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
450 PhysRegIndex phys_reg = freeList.getFloatReg();
451
452 renameMap[tid].setEntry(freg,phys_reg);
453 scoreboard.setReg(phys_reg);
454 }
455
456 //Copy Thread Data Into RegFile
457 this->copyFromXC(tid);
458
459 //Set PC/NPC
460 regFile.pc[tid] = src_xc->readPC();
461 regFile.npc[tid] = src_xc->readNextPC();
462
463 src_xc->setStatus(ExecContext::Active);
464
465 activateContext(tid,1);
466
467 //Reset ROB/IQ/LSQ Entries
468 commit.rob->resetEntries();
469 iew.resetEntries();
470#endif
471}
472
473template <class Impl>
474void
475FullO3CPU<Impl>::removeThread(unsigned tid)
476{
477 DPRINTF(FullCPU,"[tid:%i] Removing thread data");
478#if 0
479 //Unbind Int Regs from Rename Map
480 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
481 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
482
483 scoreboard.unsetReg(phys_reg);
484 freeList.addReg(phys_reg);
485 }
486
487 //Unbind Float Regs from Rename Map
488 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
489 PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
490
491 scoreboard.unsetReg(phys_reg);
492 freeList.addReg(phys_reg);
493 }
494
495 //Copy Thread Data From RegFile
496 /* Fix Me:
497 * Do we really need to do this if we are removing a thread
498 * in the sense that it's finished (exiting)? If the thread is just
499 * being suspended we might...
500 */
501// this->copyToXC(tid);
502
503 //Squash Throughout Pipeline
504 fetch.squash(0,tid);
505 decode.squash(tid);
506 rename.squash(tid);
507
508 assert(iew.ldstQueue.getCount(tid) == 0);
509
510 //Reset ROB/IQ/LSQ Entries
511 if (activeThreads.size() >= 1) {
512 commit.rob->resetEntries();
513 iew.resetEntries();
514 }
515#endif
516}
517
518
519template <class Impl>
520void
521FullO3CPU<Impl>::activateWhenReady(int tid)
522{
523 DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
524 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
525 tid);
526
527 bool ready = true;
528
529 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
530 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
531 "Phys. Int. Regs.\n",
532 tid);
533 ready = false;
534 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
535 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
536 "Phys. Float. Regs.\n",
537 tid);
538 ready = false;
539 } else if (commit.rob->numFreeEntries() >=
540 commit.rob->entryAmount(activeThreads.size() + 1)) {
541 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
542 "ROB entries.\n",
543 tid);
544 ready = false;
545 } else if (iew.instQueue.numFreeEntries() >=
546 iew.instQueue.entryAmount(activeThreads.size() + 1)) {
547 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
548 "IQ entries.\n",
549 tid);
550 ready = false;
551 } else if (iew.ldstQueue.numFreeEntries() >=
552 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
553 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
554 "LSQ entries.\n",
555 tid);
556 ready = false;
557 }
558
559 if (ready) {
560 insertThread(tid);
561
562 contextSwitch = false;
563
564 cpuWaitList.remove(tid);
565 } else {
566 suspendContext(tid);
567
568 //blocks fetch
569 contextSwitch = true;
570
571 //do waitlist
572 cpuWaitList.push_back(tid);
573 }
574}
575
576template <class Impl>
577void
578FullO3CPU<Impl>::activateContext(int tid, int delay)
579{
|
282 // Needs to set each stage to running as well.
|
581 list<unsigned>::iterator isActive = find(
582 activeThreads.begin(), activeThreads.end(), tid);
|
283
|
584 if (isActive == activeThreads.end()) {
585 //May Need to Re-code this if the delay variable is the
586 //delay needed for thread to activate
587 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
588 tid);
589
590 activeThreads.push_back(tid);
591 }
592
593 assert(_status == Idle || _status == SwitchedOut);
594
|
284 scheduleTickEvent(delay); 285
|
597 // Be sure to signal that there's some activity so the CPU doesn't
598 // deschedule itself.
599 activityRec.activity();
600 fetch.wakeFromQuiesce();
601
|
286 _status = Running; 287} 288 289template <class Impl> 290void
|
607FullO3CPU<Impl>::suspendContext(int tid)
|
291FullO3CPU<Impl>::suspendContext(int thread_num) |
292{
|
609 DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
610 unscheduleTickEvent();
611 _status = Idle;
612/*
613 //Remove From Active List, if Active
614 list<unsigned>::iterator isActive = find(
615 activeThreads.begin(), activeThreads.end(), tid);
616
617 if (isActive != activeThreads.end()) {
618 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
619 tid);
620 activeThreads.erase(isActive);
621 }
622*/
|
293 panic("suspendContext unimplemented!"); |
294} 295 296template <class Impl> 297void
|
627FullO3CPU<Impl>::deallocateContext(int tid)
|
298FullO3CPU<Impl>::deallocateContext(int thread_num) |
299{
|
629 DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
630/*
631 //Remove From Active List, if Active
632 list<unsigned>::iterator isActive = find(
633 activeThreads.begin(), activeThreads.end(), tid);
634
635 if (isActive != activeThreads.end()) {
636 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
637 tid);
638 activeThreads.erase(isActive);
639
640 removeThread(tid);
641 }
642*/
|
300 panic("deallocateContext unimplemented!"); |
301} 302 303template <class Impl> 304void
|
647FullO3CPU<Impl>::haltContext(int tid)
|
305FullO3CPU<Impl>::haltContext(int thread_num) |
306{
|
649 DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
650/*
651 //Remove From Active List, if Active
652 list<unsigned>::iterator isActive = find(
653 activeThreads.begin(), activeThreads.end(), tid);
654
655 if (isActive != activeThreads.end()) {
656 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
657 tid);
658 activeThreads.erase(isActive);
659
660 removeThread(tid);
661 }
662*/
|
307 panic("haltContext unimplemented!"); |
308} 309 310template <class Impl> 311void
|
667FullO3CPU<Impl>::switchOut(Sampler *_sampler)
|
312FullO3CPU::switchOut() |
313{
|
669 sampler = _sampler;
670 switchCount = 0;
671 fetch.switchOut();
672 decode.switchOut();
673 rename.switchOut();
674 iew.switchOut();
675 commit.switchOut();
676
677 // Wake the CPU and record activity so everything can drain out if
678 // the CPU is currently idle.
679 wakeCPU();
680 activityRec.activity();
|
314 panic("FullO3CPU does not have a switch out function.\n"); |
315} 316 317template <class Impl> 318void
|
685FullO3CPU<Impl>::signalSwitched()
686{
687 if (++switchCount == NumStages) {
688 fetch.doSwitchOut();
689 rename.doSwitchOut();
690 commit.doSwitchOut();
691 instList.clear();
692 while (!removeList.empty()) {
693 removeList.pop();
694 }
695
696 if (checker)
697 checker->switchOut(sampler);
698
699 if (tickEvent.scheduled())
700 tickEvent.squash();
701 sampler->signalSwitched();
702 _status = SwitchedOut;
703 }
704 assert(switchCount <= 5);
705}
706
707template <class Impl>
708void
|
319FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) 320{
|
711 // Flush out any old data from the time buffers.
712 for (int i = 0; i < 10; ++i) {
713 timeBuffer.advance();
714 fetchQueue.advance();
715 decodeQueue.advance();
716 renameQueue.advance();
717 iewQueue.advance();
718 }
719
720 activityRec.reset();
721
|
321 BaseCPU::takeOverFrom(oldCPU); 322
|
724 fetch.takeOverFrom();
725 decode.takeOverFrom();
726 rename.takeOverFrom();
727 iew.takeOverFrom();
728 commit.takeOverFrom();
729
|
323 assert(!tickEvent.scheduled()); 324
|
732 // @todo: Figure out how to properly select the tid to put onto
733 // the active threads list.
734 int tid = 0;
735
736 list<unsigned>::iterator isActive = find(
737 activeThreads.begin(), activeThreads.end(), tid);
738
739 if (isActive == activeThreads.end()) {
740 //May Need to Re-code this if the delay variable is the delay
741 //needed for thread to activate
742 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
743 tid);
744
745 activeThreads.push_back(tid);
746 }
747
748 // Set all statuses to active, schedule the CPU's tick event.
749 // @todo: Fix up statuses so this is handled properly
|
325 // Set all status's to active, schedule the 326 // CPU's tick event. |
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 }
|
757 if (!tickEvent.scheduled())
758 tickEvent.schedule(curTick);
|
334} 335 336template <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
|
832FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
|
416FullO3CPU<Impl>::readPC() |
417{
|
834 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
835
836 return regFile.readIntReg(phys_reg);
|
418 return regFile.readPC(); |
419} 420 421template <class Impl>
|
840float
841FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
842{
843 int idx = reg_idx + TheISA::FP_Base_DepTag;
844 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
845
846 return regFile.readFloatRegSingle(phys_reg);
847}
848
849template <class Impl>
850double
851FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
852{
853 int idx = reg_idx + TheISA::FP_Base_DepTag;
854 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
855
856 return regFile.readFloatRegDouble(phys_reg);
857}
858
859template <class Impl>
860uint64_t
861FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
862{
863 int idx = reg_idx + TheISA::FP_Base_DepTag;
864 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
865
866 return regFile.readFloatRegInt(phys_reg);
867}
868
869template <class Impl>
|
422void
|
871FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
|
423FullO3CPU<Impl>::setNextPC(uint64_t val) |
424{
|
873 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
874
875 regFile.setIntReg(phys_reg, val);
|
425 regFile.setNextPC(val); |
426} 427 428template <class Impl> 429void
|
880FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
|
430FullO3CPU<Impl>::setPC(Addr new_PC) |
431{
|
882 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
883
884 regFile.setFloatRegSingle(phys_reg, val);
|
432 regFile.setPC(new_PC); |
433} 434 435template <class Impl> 436void
|
889FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
|
437FullO3CPU<Impl>::addInst(DynInstPtr &inst) |
438{
|
891 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
892
893 regFile.setFloatRegDouble(phys_reg, val);
|
439 instList.push_back(inst); |
440} 441 442template <class Impl> 443void
|
898FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
|
444FullO3CPU<Impl>::instDone() |
445{
|
900 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
|
446 // Keep an instruction count. 447 numInsts++; |
448
|
902 regFile.setFloatRegInt(phys_reg, val);
|
449 // Check for instruction-count-based events. 450 comInstEventQueue[0]->serviceEvents(numInsts); |
451} 452 453template <class Impl>
|
906uint64_t
907FullO3CPU<Impl>::readPC(unsigned tid)
908{
909 return commit.readPC(tid);
910}
911
912template <class Impl>
|
454void
|
914FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
|
455FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst) |
456{
|
916 commit.setPC(new_PC, tid);
917}
|
457 DynInstPtr inst_to_delete; |
458
|
919template <class Impl>
920uint64_t
921FullO3CPU<Impl>::readNextPC(unsigned tid)
922{
923 return commit.readNextPC(tid);
924}
|
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()); |
464
|
926template <class Impl>
927void
928FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
929{
930 commit.setNextPC(val, tid);
931}
|
465 // Obtain the pointer to the instruction. 466 inst_to_delete = instList.back(); |
467
|
933template <class Impl>
934typename FullO3CPU<Impl>::ListIt
935FullO3CPU<Impl>::addInst(DynInstPtr &inst)
936{
937 instList.push_back(inst);
|
468 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", 469 inst_to_delete->seqNum, inst_to_delete->readPC()); |
470
|
939 return --(instList.end());
940}
|
471 // Remove the instruction from the list. 472 instList.pop_back(); |
473
|
942template <class Impl>
943void
944FullO3CPU<Impl>::instDone(unsigned tid)
945{
946 // Keep an instruction count.
947 thread[tid]->numInst++;
948 thread[tid]->numInsts++;
949 committedInsts[tid]++;
950 totalCommittedInsts++;
951
952 // Check for instruction-count-based events.
953 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
|
474 // Mark it as squashed. 475 inst_to_delete->setSquashed(); 476 } |
477} 478 479template <class Impl> 480void
|
958FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
959{
960 removeInstsThisCycle = true;
961
962 removeList.push(inst->getInstListIt());
963}
964
965template <class Impl>
966void
|
481FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) 482{
|
969 DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
970 "[sn:%lli]\n",
971 inst->threadNumber, inst->readPC(), inst->seqNum);
|
483 DynInstPtr inst_to_remove; |
484
|
973 removeInstsThisCycle = true;
|
485 // The front instruction should be the same one being asked to be removed. 486 assert(instList.front() == inst); |
487 488 // Remove the front instruction.
|
976 removeList.push(inst->getInstListIt());
|
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()); |
494} 495 496template <class Impl> 497void
|
981FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
|
498FullO3CPU::removeInstsNotInROB() |
499{
|
983 DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
984 " list.\n", tid);
|
500 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " 501 "list.\n"); |
502
|
986 ListIt end_it;
|
503 DynInstPtr rob_tail = rob.readTailInst(); |
504
|
988 bool rob_empty = false;
989
990 if (instList.empty()) {
991 return;
992 } else if (rob.isEmpty(/*tid*/)) {
993 DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
994 end_it = instList.begin();
995 rob_empty = true;
996 } else {
997 end_it = (rob.readTailInst(tid))->getInstListIt();
998 DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
999 }
1000
1001 removeInstsThisCycle = true;
1002
1003 ListIt inst_it = instList.end();
1004
1005 inst_it--;
1006
1007 // Walk through the instruction list, removing any instructions
1008 // that were inserted after the given instruction iterator, end_it.
1009 while (inst_it != end_it) {
1010 assert(!instList.empty());
1011
1012 squashInstIt(inst_it, tid);
1013
1014 inst_it--;
1015 }
1016
1017 // If the ROB was empty, then we actually need to remove the first
1018 // instruction as well.
1019 if (rob_empty) {
1020 squashInstIt(inst_it, tid);
1021 }
|
505 removeBackInst(rob_tail); |
506} 507 508template <class Impl> 509void
|
1026FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1027 unsigned tid)
|
510FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num) |
511{
|
1029 assert(!instList.empty());
1030
1031 removeInstsThisCycle = true;
1032
1033 ListIt inst_iter = instList.end();
1034
1035 inst_iter--;
1036
|
512 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
|
1038 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1039 tid, seq_num, (*inst_iter)->seqNum);
|
513 "list.\n"); |
514
|
1041 while ((*inst_iter)->seqNum > seq_num) {
|
515 DynInstPtr inst_to_delete; |
516
|
1043 bool break_loop = (inst_iter == instList.begin());
|
517 while (instList.back()->seqNum > seq_num) { 518 assert(!instList.empty()); |
519
|
1045 squashInstIt(inst_iter, tid);
|
520 // Obtain the pointer to the instruction. 521 inst_to_delete = instList.back(); |
522
|
1047 inst_iter--;
|
523 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", 524 inst_to_delete->seqNum, inst_to_delete->readPC()); |
525
|
1049 if (break_loop)
1050 break;
1051 }
1052}
|
526 // Remove the instruction from the list. 527 instList.back() = NULL; 528 instList.pop_back(); |
529
|
1054template <class Impl>
1055inline void
1056FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1057{
1058 if ((*instIt)->threadNumber == tid) {
1059 DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
1060 "[tid:%i] [sn:%lli] PC %#x\n",
1061 (*instIt)->threadNumber,
1062 (*instIt)->seqNum,
1063 (*instIt)->readPC());
1064
|
530 // Mark it as squashed.
|
1066 (*instIt)->setSquashed();
1067
1068 // @todo: Formulate a consistent method for deleting
1069 // instructions from the instruction list
1070 // Remove the instruction from the list.
1071 removeList.push(instIt);
|
531 inst_to_delete->setSquashed(); |
532 }
|
533 |
534} 535 536template <class Impl> 537void
|
1077FullO3CPU<Impl>::cleanUpRemovedInsts()
1078{
1079 while (!removeList.empty()) {
1080 DPRINTF(FullCPU, "FullCPU: Removing instruction, "
1081 "[tid:%i] [sn:%lli] PC %#x\n",
1082 (*removeList.front())->threadNumber,
1083 (*removeList.front())->seqNum,
1084 (*removeList.front())->readPC());
1085
1086 instList.erase(removeList.front());
1087
1088 removeList.pop();
1089 }
1090
1091 removeInstsThisCycle = false;
1092}
1093/*
1094template <class Impl>
1095void
|
538FullO3CPU<Impl>::removeAllInsts() 539{ 540 instList.clear(); 541}
|
1100*/
|
542 |
543template <class Impl> 544void 545FullO3CPU<Impl>::dumpInsts() 546{ 547 int num = 0;
|
548 typename list<DynInstPtr>::iterator inst_list_it = instList.begin(); |
549
|
1107 ListIt inst_list_it = instList.begin();
1108
1109 cprintf("Dumping Instruction List\n");
1110
1111 while (inst_list_it != instList.end()) {
1112 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1113 "Squashed:%i\n\n",
1114 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1115 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1116 (*inst_list_it)->isSquashed());
|
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()); |
555 inst_list_it++; 556 ++num; 557 } 558}
|
1121/*
|
559 |
560template <class Impl> 561void 562FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst) 563{ 564 iew.wakeDependents(inst); 565}
|
1128*/
1129template <class Impl>
1130void
1131FullO3CPU<Impl>::wakeCPU()
1132{
1133 if (activityRec.active() || tickEvent.scheduled()) {
1134 DPRINTF(Activity, "CPU already running.\n");
1135 return;
1136 }
|
566
|
1138 DPRINTF(Activity, "Waking up CPU\n");
1139
1140 idleCycles += (curTick - 1) - lastRunningCycle;
1141
1142 tickEvent.schedule(curTick);
1143}
1144
1145template <class Impl>
1146int
1147FullO3CPU<Impl>::getFreeTid()
1148{
1149 for (int i=0; i < numThreads; i++) {
1150 if (!tids[i]) {
1151 tids[i] = true;
1152 return i;
1153 }
1154 }
1155
1156 return -1;
1157}
1158
1159template <class Impl>
1160void
1161FullO3CPU<Impl>::doContextSwitch()
1162{
1163 if (contextSwitch) {
1164
1165 //ADD CODE TO DEACTIVE THREAD HERE (???)
1166
1167 for (int tid=0; tid < cpuWaitList.size(); tid++) {
1168 activateWhenReady(tid);
1169 }
1170
1171 if (cpuWaitList.size() == 0)
1172 contextSwitch = true;
1173 }
1174}
1175
1176template <class Impl>
1177void
1178FullO3CPU<Impl>::updateThreadPriority()
1179{
1180 if (activeThreads.size() > 1)
1181 {
1182 //DEFAULT TO ROUND ROBIN SCHEME
1183 //e.g. Move highest priority to end of thread list
1184 list<unsigned>::iterator list_begin = activeThreads.begin();
1185 list<unsigned>::iterator list_end = activeThreads.end();
1186
1187 unsigned high_thread = *list_begin;
1188
1189 activeThreads.erase(list_begin);
1190
1191 activeThreads.push_back(high_thread);
1192 }
1193}
1194
|
567// Forward declaration of FullO3CPU. 568template class FullO3CPU<AlphaSimpleImpl>;
|