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