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

--- 8 unchanged lines hidden (view full) ---

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
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"
36
37#include "cpu/activity.hh"
38#include "cpu/checker/cpu.hh"
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
48using namespace std;
49using namespace TheISA;
50
48BaseFullCPU::BaseFullCPU(Params &params)
49 : BaseCPU(&params), cpu_id(0)
51BaseFullCPU::BaseFullCPU(Params *params)
52 : BaseCPU(params), cpu_id(0)
53{
54}
55
56void
57BaseFullCPU::regStats()
58{
59 BaseCPU::regStats();
60}
61
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

--- 4 unchanged lines hidden (view full) ---

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
82template <class Impl>
75FullO3CPU<Impl>::FullO3CPU(Params &params)
76#if FULL_SYSTEM
83FullO3CPU<Impl>::FullO3CPU(Params *params)
84 : BaseFullCPU(params),
78#else
79 : BaseFullCPU(params),
80#endif // FULL_SYSTEM
85 tickEvent(this),
86 removeInstsThisCycle(false),
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),
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),
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),
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),
108
101 // What to pass to these time buffers?
109 // For now just have these time buffers be pretty big.
110 // @todo: Make these time buffer sizes parameters or derived
111 // from latencies
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),
118
109 cpuXC(NULL),
110
119 globalSeqNum(1),
120
121#if FULL_SYSTEM
114 system(params.system),
122 system(params->system),
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()),
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
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);
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;
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
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.
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
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);
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
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
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 }
244 rename.setFreeList(&freeList);
189 renameMap.setFreeList(&freeList);
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
252 // Setup the ROB for whichever stages need it.
253 commit.setROB(&rob);
254
255 lastRunningCycle = curTick;
256
257 contextSwitch = false;
258}
259
260template <class Impl>
261FullO3CPU<Impl>::~FullO3CPU()
262{
263}
264
265template <class Impl>
266void
267FullO3CPU<Impl>::fullCPURegStats()
268{
269 BaseFullCPU::regStats();
270
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
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
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
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
378}
379
380template <class Impl>
381void
382FullO3CPU<Impl>::init()
383{
242 if(!deferRegistration)
243 {
244 this->registerExecContexts();
384 if (!deferRegistration) {
385 registerExecContexts();
386 }
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++) {
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];
396#else
252 ExecContext *src_xc = thread[0]->getProxy();
397 ExecContext *src_xc = thread[tid]->getXCProxy();
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;
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
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);
420}
421
422template <class Impl>
423void
280FullO3CPU<Impl>::activateContext(int thread_num, int delay)
424FullO3CPU<Impl>::insertThread(unsigned tid)
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{
576 // Needs to set each stage to running as well.
577 list<unsigned>::iterator isActive = find(
578 activeThreads.begin(), activeThreads.end(), tid);
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
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
598 _status = Running;
599}
600
601template <class Impl>
602void
291FullO3CPU<Impl>::suspendContext(int thread_num)
603FullO3CPU<Impl>::suspendContext(int tid)
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*/
619}
620
621template <class Impl>
622void
298FullO3CPU<Impl>::deallocateContext(int thread_num)
623FullO3CPU<Impl>::deallocateContext(int tid)
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*/
639}
640
641template <class Impl>
642void
305FullO3CPU<Impl>::haltContext(int thread_num)
643FullO3CPU<Impl>::haltContext(int tid)
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*/
659}
660
661template <class Impl>
662void
312FullO3CPU::switchOut()
663FullO3CPU<Impl>::switchOut(Sampler *_sampler)
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();
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
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
718 BaseCPU::takeOverFrom(oldCPU);
719
720 fetch.takeOverFrom();
721 decode.takeOverFrom();
722 rename.takeOverFrom();
723 iew.takeOverFrom();
724 commit.takeOverFrom();
725
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
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);
755}
756
757template <class Impl>
337InstSeqNum
338FullO3CPU<Impl>::getAndIncrementInstSeq()
339{
340 // Hopefully this works right.
341 return globalSeqNum++;
342}
343
344template <class Impl>
758uint64_t
759FullO3CPU<Impl>::readIntReg(int reg_idx)
760{
761 return regFile.readIntReg(reg_idx);
762}
763
764template <class Impl>
765FloatReg

--- 55 unchanged lines hidden (view full) ---

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)
830{
418 return regFile.readPC();
831 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
832
833 return regFile.readIntReg(phys_reg);
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>
867void
423FullO3CPU<Impl>::setNextPC(uint64_t val)
868FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
869{
425 regFile.setNextPC(val);
870 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
871
872 regFile.setIntReg(phys_reg, val);
873}
874
875template <class Impl>
876void
430FullO3CPU<Impl>::setPC(Addr new_PC)
877FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
878{
432 regFile.setPC(new_PC);
879 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
880
881 regFile.setFloatReg(phys_reg, val);
882}
883
884template <class Impl>
885void
437FullO3CPU<Impl>::addInst(DynInstPtr &inst)
886FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
887{
439 instList.push_back(inst);
888 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
889
890 regFile.setFloatReg(phys_reg, val, 64);
891}
892
893template <class Impl>
894void
444FullO3CPU<Impl>::instDone()
895FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
896{
446 // Keep an instruction count.
447 numInsts++;
897 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
898
449 // Check for instruction-count-based events.
450 comInstEventQueue[0]->serviceEvents(numInsts);
899 regFile.setFloatRegBits(phys_reg, val);
900}
901
902template <class Impl>
903uint64_t
904FullO3CPU<Impl>::readPC(unsigned tid)
905{
906 return commit.readPC(tid);
907}
908
909template <class Impl>
910void
455FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst)
911FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
912{
457 DynInstPtr inst_to_delete;
913 commit.setPC(new_PC, tid);
914}
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}
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}
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);
935
471 // Remove the instruction from the list.
472 instList.pop_back();
936 return --(instList.end());
937}
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);
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
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);
969
485 // The front instruction should be the same one being asked to be removed.
486 assert(instList.front() == inst);
970 removeInstsThisCycle = true;
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());
974}
975
976template <class Impl>
977void
498FullO3CPU::removeInstsNotInROB()
978FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
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);
982
503 DynInstPtr rob_tail = rob.readTailInst();
983 ListIt end_it;
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 }
1019}
1020
1021template <class Impl>
1022void
510FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num)
1023FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1024 unsigned tid)
1025{
1026 assert(!instList.empty());
1027
1028 removeInstsThisCycle = true;
1029
1030 ListIt inst_iter = instList.end();
1031
1032 inst_iter--;
1033
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);
1037
515 DynInstPtr inst_to_delete;
1038 while ((*inst_iter)->seqNum > seq_num) {
1039
517 while (instList.back()->seqNum > seq_num) {
518 assert(!instList.empty());
1040 bool break_loop = (inst_iter == instList.begin());
1041
520 // Obtain the pointer to the instruction.
521 inst_to_delete = instList.back();
1042 squashInstIt(inst_iter, tid);
1043
523 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
524 inst_to_delete->seqNum, inst_to_delete->readPC());
1044 inst_iter--;
1045
526 // Remove the instruction from the list.
527 instList.back() = NULL;
528 instList.pop_back();
1046 if (break_loop)
1047 break;
1048 }
1049}
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
1062 // Mark it as squashed.
531 inst_to_delete->setSquashed();
532 }
1063 (*instIt)->setSquashed();
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 }
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
1093FullO3CPU<Impl>::removeAllInsts()
1094{
1095 instList.clear();
1096}
542
1097*/
1098template <class Impl>
1099void
1100FullO3CPU<Impl>::dumpInsts()
1101{
1102 int num = 0;
548 typename list<DynInstPtr>::iterator inst_list_it = instList.begin();
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());
1114 inst_list_it++;
1115 ++num;
1116 }
1117}
559
1118/*
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 }
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
1192// Forward declaration of FullO3CPU.
1193template class FullO3CPU<AlphaSimpleImpl>;