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