2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
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.
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.
31 #include "config/full_system.hh"
34 #include "sim/system.hh"
36 #include "sim/process.hh"
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"
47 #include "sim/root.hh"
48 #include "sim/stat_control.hh"
51 using namespace TheISA
;
53 BaseFullCPU::BaseFullCPU(Params
*params
)
54 : BaseCPU(params
), cpu_id(0)
59 BaseFullCPU::regStats()
65 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
66 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
72 FullO3CPU
<Impl
>::TickEvent::process()
79 FullO3CPU
<Impl
>::TickEvent::description()
81 return "FullO3CPU tick event";
85 FullO3CPU
<Impl
>::FullO3CPU(Params
*params
)
86 : BaseFullCPU(params
),
88 removeInstsThisCycle(false),
95 regFile(params
->numPhysIntRegs
, params
->numPhysFloatRegs
),
97 freeList(params
->numberOfThreads
,//number of activeThreads
98 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
99 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
),
101 rob(params
->numROBEntries
, params
->squashWidth
,
102 params
->smtROBPolicy
, params
->smtROBThreshold
,
103 params
->numberOfThreads
),
105 scoreboard(params
->numberOfThreads
,//number of activeThreads
106 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
107 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
,
108 TheISA::NumMiscRegs
* number_of_threads
,
111 // For now just have these time buffers be pretty big.
112 // @todo: Make these time buffer sizes parameters or derived
119 activityRec(NumStages
, 10, params
->activity
),
124 system(params
->system
),
125 physmem(system
->physmem
),
126 #endif // FULL_SYSTEM
129 deferRegistration(params
->deferRegistration
),
130 numThreads(number_of_threads
)
134 if (params
->checker
) {
135 BaseCPU
*temp_checker
= params
->checker
;
136 checker
= dynamic_cast<Checker
<DynInstPtr
> *>(temp_checker
);
137 checker
->setMemory(mem
);
139 checker
->setSystem(params
->system
);
146 thread
.resize(number_of_threads
);
147 tids
.resize(number_of_threads
);
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.
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
);
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
);
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
);
180 commit
.setFetchStage(&fetch
);
181 commit
.setIEWStage(&iew
);
182 rename
.setIEWStage(&iew
);
183 rename
.setCommitStage(&commit
);
186 int active_threads
= params
->workload
.size();
188 int active_threads
= 1;
191 //Make Sure That this a Valid Architeture
192 assert(params
->numPhysIntRegs
>= numThreads
* TheISA::NumIntRegs
);
193 assert(params
->numPhysFloatRegs
>= numThreads
* TheISA::NumFloatRegs
);
195 rename
.setScoreboard(&scoreboard
);
196 iew
.setScoreboard(&scoreboard
);
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
202 for (int tid
=0; tid
< numThreads
; tid
++) {
203 bool bindRegs
= (tid
<= active_threads
- 1);
205 commitRenameMap
[tid
].init(TheISA::NumIntRegs
,
206 params
->numPhysIntRegs
,
207 lreg_idx
, //Index for Logical. Regs
209 TheISA::NumFloatRegs
,
210 params
->numPhysFloatRegs
,
211 freg_idx
, //Index for Float Regs
221 renameMap
[tid
].init(TheISA::NumIntRegs
,
222 params
->numPhysIntRegs
,
223 lreg_idx
, //Index for Logical. Regs
225 TheISA::NumFloatRegs
,
226 params
->numPhysFloatRegs
,
227 freg_idx
, //Index for Float Regs
238 rename
.setRenameMap(renameMap
);
239 commit
.setRenameMap(commitRenameMap
);
241 // Give renameMap & rename stage access to the freeList;
242 for (int i
=0; i
< numThreads
; i
++) {
243 renameMap
[i
].setFreeList(&freeList
);
245 rename
.setFreeList(&freeList
);
247 // Setup the ROB for whichever stages need it.
250 lastRunningCycle
= curTick
;
252 contextSwitch
= false;
255 template <class Impl
>
256 FullO3CPU
<Impl
>::~FullO3CPU()
260 template <class Impl
>
262 FullO3CPU
<Impl
>::fullCPURegStats()
264 BaseFullCPU::regStats();
266 // Register any of the FullCPU's stats here.
268 .name(name() + ".timesIdled")
269 .desc("Number of times that the entire CPU went into an idle state and"
270 " unscheduled itself")
274 .name(name() + ".idleCycles")
275 .desc("Total number of cycles that the CPU has spent unscheduled due "
279 // Number of Instructions simulated
280 // --------------------------------
281 // Should probably be in Base CPU but need templated
282 // MaxThreads so put in here instead
285 .name(name() + ".committedInsts")
286 .desc("Number of Instructions Simulated");
289 .name(name() + ".committedInsts_total")
290 .desc("Number of Instructions Simulated");
293 .name(name() + ".cpi")
294 .desc("CPI: Cycles Per Instruction")
296 cpi
= simTicks
/ committedInsts
;
299 .name(name() + ".cpi_total")
300 .desc("CPI: Total CPI of All Threads")
302 totalCpi
= simTicks
/ totalCommittedInsts
;
305 .name(name() + ".ipc")
306 .desc("IPC: Instructions Per Cycle")
308 ipc
= committedInsts
/ simTicks
;
311 .name(name() + ".ipc_total")
312 .desc("IPC: Total IPC of All Threads")
314 totalIpc
= totalCommittedInsts
/ simTicks
;
318 template <class Impl
>
320 FullO3CPU
<Impl
>::tick()
322 DPRINTF(FullCPU
, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
328 //Tick each of the stages
343 // Now advance the time buffers
344 timeBuffer
.advance();
346 fetchQueue
.advance();
347 decodeQueue
.advance();
348 renameQueue
.advance();
351 activityRec
.advance();
353 if (removeInstsThisCycle
) {
354 cleanUpRemovedInsts();
357 if (!tickEvent
.scheduled()) {
358 if (_status
== SwitchedOut
) {
360 lastRunningCycle
= curTick
;
361 } else if (!activityRec
.active()) {
362 lastRunningCycle
= curTick
;
365 tickEvent
.schedule(curTick
+ cycles(1));
370 updateThreadPriority();
375 template <class Impl
>
377 FullO3CPU
<Impl
>::init()
379 if (!deferRegistration
) {
380 registerThreadContexts();
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;
388 for (int tid
=0; tid
< number_of_threads
; tid
++) {
390 ThreadContext
*src_tc
= threadContexts
[tid
];
392 ThreadContext
*src_tc
= thread
[tid
]->getTC();
394 // Threads start in the Suspended State
395 if (src_tc
->status() != ThreadContext::Suspended
) {
400 TheISA::initCPU(src_tc
, src_tc
->readCpuId());
405 for (int i
= 0; i
< number_of_threads
; ++i
)
406 thread
[i
]->inSyscall
= false;
408 // Initialize stages.
414 commit
.setThreads(thread
);
417 template <class Impl
>
419 FullO3CPU
<Impl
>::insertThread(unsigned tid
)
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.
426 ThreadContext
*src_tc
= system
->threadContexts
[tid
];
428 ThreadContext
*src_tc
= thread
[tid
];
431 //Bind Int Regs to Rename Map
432 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
433 PhysRegIndex phys_reg
= freeList
.getIntReg();
435 renameMap
[tid
].setEntry(ireg
,phys_reg
);
436 scoreboard
.setReg(phys_reg
);
439 //Bind Float Regs to Rename Map
440 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
441 PhysRegIndex phys_reg
= freeList
.getFloatReg();
443 renameMap
[tid
].setEntry(freg
,phys_reg
);
444 scoreboard
.setReg(phys_reg
);
447 //Copy Thread Data Into RegFile
448 this->copyFromTC(tid
);
451 regFile
.pc
[tid
] = src_tc
->readPC();
452 regFile
.npc
[tid
] = src_tc
->readNextPC();
454 src_tc
->setStatus(ThreadContext::Active
);
456 activateContext(tid
,1);
458 //Reset ROB/IQ/LSQ Entries
459 commit
.rob
->resetEntries();
464 template <class Impl
>
466 FullO3CPU
<Impl
>::removeThread(unsigned tid
)
468 DPRINTF(FullCPU
,"[tid:%i] Removing thread data");
470 //Unbind Int Regs from Rename Map
471 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
472 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(ireg
);
474 scoreboard
.unsetReg(phys_reg
);
475 freeList
.addReg(phys_reg
);
478 //Unbind Float Regs from Rename Map
479 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
480 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(freg
);
482 scoreboard
.unsetReg(phys_reg
);
483 freeList
.addReg(phys_reg
);
486 //Copy Thread Data From RegFile
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...
492 // this->copyToTC(tid);
494 //Squash Throughout Pipeline
499 assert(iew
.ldstQueue
.getCount(tid
) == 0);
501 //Reset ROB/IQ/LSQ Entries
502 if (activeThreads
.size() >= 1) {
503 commit
.rob
->resetEntries();
510 template <class Impl
>
512 FullO3CPU
<Impl
>::activateWhenReady(int tid
)
514 DPRINTF(FullCPU
,"[tid:%i]: Checking if resources are available for incoming"
515 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
520 if (freeList
.numFreeIntRegs() >= TheISA::NumIntRegs
) {
521 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
522 "Phys. Int. Regs.\n",
525 } else if (freeList
.numFreeFloatRegs() >= TheISA::NumFloatRegs
) {
526 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
527 "Phys. Float. Regs.\n",
530 } else if (commit
.rob
->numFreeEntries() >=
531 commit
.rob
->entryAmount(activeThreads
.size() + 1)) {
532 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
536 } else if (iew
.instQueue
.numFreeEntries() >=
537 iew
.instQueue
.entryAmount(activeThreads
.size() + 1)) {
538 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
542 } else if (iew
.ldstQueue
.numFreeEntries() >=
543 iew
.ldstQueue
.entryAmount(activeThreads
.size() + 1)) {
544 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
553 contextSwitch
= false;
555 cpuWaitList
.remove(tid
);
560 contextSwitch
= true;
563 cpuWaitList
.push_back(tid
);
567 template <class Impl
>
569 FullO3CPU
<Impl
>::activateContext(int tid
, int delay
)
571 // Needs to set each stage to running as well.
572 list
<unsigned>::iterator isActive
= find(
573 activeThreads
.begin(), activeThreads
.end(), tid
);
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",
581 activeThreads
.push_back(tid
);
584 assert(_status
== Idle
|| _status
== SwitchedOut
);
586 scheduleTickEvent(delay
);
588 // Be sure to signal that there's some activity so the CPU doesn't
589 // deschedule itself.
590 activityRec
.activity();
591 fetch
.wakeFromQuiesce();
596 template <class Impl
>
598 FullO3CPU
<Impl
>::suspendContext(int tid
)
600 DPRINTF(FullCPU
,"[tid: %i]: Suspended ...\n", tid
);
601 unscheduleTickEvent();
604 //Remove From Active List, if Active
605 list<unsigned>::iterator isActive = find(
606 activeThreads.begin(), activeThreads.end(), tid);
608 if (isActive != activeThreads.end()) {
609 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
611 activeThreads.erase(isActive);
616 template <class Impl
>
618 FullO3CPU
<Impl
>::deallocateContext(int tid
)
620 DPRINTF(FullCPU
,"[tid:%i]: Deallocating ...", tid
);
622 //Remove From Active List, if Active
623 list<unsigned>::iterator isActive = find(
624 activeThreads.begin(), activeThreads.end(), tid);
626 if (isActive != activeThreads.end()) {
627 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
629 activeThreads.erase(isActive);
636 template <class Impl
>
638 FullO3CPU
<Impl
>::haltContext(int tid
)
640 DPRINTF(FullCPU
,"[tid:%i]: Halted ...", tid
);
642 //Remove From Active List, if Active
643 list<unsigned>::iterator isActive = find(
644 activeThreads.begin(), activeThreads.end(), tid);
646 if (isActive != activeThreads.end()) {
647 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
649 activeThreads.erase(isActive);
656 template <class Impl
>
658 FullO3CPU
<Impl
>::switchOut(Sampler
*_sampler
)
668 // Wake the CPU and record activity so everything can drain out if
669 // the CPU is currently idle.
671 activityRec
.activity();
674 template <class Impl
>
676 FullO3CPU
<Impl
>::signalSwitched()
678 if (++switchCount
== NumStages
) {
680 rename
.doSwitchOut();
681 commit
.doSwitchOut();
683 while (!removeList
.empty()) {
688 checker
->switchOut(sampler
);
690 if (tickEvent
.scheduled())
692 sampler
->signalSwitched();
693 _status
= SwitchedOut
;
695 assert(switchCount
<= 5);
698 template <class Impl
>
700 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
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();
713 BaseCPU::takeOverFrom(oldCPU
);
715 fetch
.takeOverFrom();
716 decode
.takeOverFrom();
717 rename
.takeOverFrom();
719 commit
.takeOverFrom();
721 assert(!tickEvent
.scheduled());
723 // @todo: Figure out how to properly select the tid to put onto
724 // the active threads list.
727 list
<unsigned>::iterator isActive
= find(
728 activeThreads
.begin(), activeThreads
.end(), tid
);
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",
736 activeThreads
.push_back(tid
);
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
) {
745 tickEvent
.schedule(curTick
);
748 if (!tickEvent
.scheduled())
749 tickEvent
.schedule(curTick
);
752 template <class Impl
>
754 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
756 return regFile
.readIntReg(reg_idx
);
759 template <class Impl
>
761 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
, int width
)
763 return regFile
.readFloatReg(reg_idx
, width
);
766 template <class Impl
>
768 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
)
770 return regFile
.readFloatReg(reg_idx
);
773 template <class Impl
>
775 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
, int width
)
777 return regFile
.readFloatRegBits(reg_idx
, width
);
780 template <class Impl
>
782 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
)
784 return regFile
.readFloatRegBits(reg_idx
);
787 template <class Impl
>
789 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
791 regFile
.setIntReg(reg_idx
, val
);
794 template <class Impl
>
796 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
, int width
)
798 regFile
.setFloatReg(reg_idx
, val
, width
);
801 template <class Impl
>
803 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
)
805 regFile
.setFloatReg(reg_idx
, val
);
808 template <class Impl
>
810 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
, int width
)
812 regFile
.setFloatRegBits(reg_idx
, val
, width
);
815 template <class Impl
>
817 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
)
819 regFile
.setFloatRegBits(reg_idx
, val
);
822 template <class Impl
>
824 FullO3CPU
<Impl
>::readArchIntReg(int reg_idx
, unsigned tid
)
826 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
828 return regFile
.readIntReg(phys_reg
);
831 template <class Impl
>
833 FullO3CPU
<Impl
>::readArchFloatRegSingle(int reg_idx
, unsigned tid
)
835 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
836 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
838 return regFile
.readFloatReg(phys_reg
);
841 template <class Impl
>
843 FullO3CPU
<Impl
>::readArchFloatRegDouble(int reg_idx
, unsigned tid
)
845 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
846 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
848 return regFile
.readFloatReg(phys_reg
, 64);
851 template <class Impl
>
853 FullO3CPU
<Impl
>::readArchFloatRegInt(int reg_idx
, unsigned tid
)
855 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
856 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
858 return regFile
.readFloatRegBits(phys_reg
);
861 template <class Impl
>
863 FullO3CPU
<Impl
>::setArchIntReg(int reg_idx
, uint64_t val
, unsigned tid
)
865 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
867 regFile
.setIntReg(phys_reg
, val
);
870 template <class Impl
>
872 FullO3CPU
<Impl
>::setArchFloatRegSingle(int reg_idx
, float val
, unsigned tid
)
874 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
876 regFile
.setFloatReg(phys_reg
, val
);
879 template <class Impl
>
881 FullO3CPU
<Impl
>::setArchFloatRegDouble(int reg_idx
, double val
, unsigned tid
)
883 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
885 regFile
.setFloatReg(phys_reg
, val
, 64);
888 template <class Impl
>
890 FullO3CPU
<Impl
>::setArchFloatRegInt(int reg_idx
, uint64_t val
, unsigned tid
)
892 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
894 regFile
.setFloatRegBits(phys_reg
, val
);
897 template <class Impl
>
899 FullO3CPU
<Impl
>::readPC(unsigned tid
)
901 return commit
.readPC(tid
);
904 template <class Impl
>
906 FullO3CPU
<Impl
>::setPC(Addr new_PC
,unsigned tid
)
908 commit
.setPC(new_PC
, tid
);
911 template <class Impl
>
913 FullO3CPU
<Impl
>::readNextPC(unsigned tid
)
915 return commit
.readNextPC(tid
);
918 template <class Impl
>
920 FullO3CPU
<Impl
>::setNextPC(uint64_t val
,unsigned tid
)
922 commit
.setNextPC(val
, tid
);
925 template <class Impl
>
926 typename FullO3CPU
<Impl
>::ListIt
927 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
929 instList
.push_back(inst
);
931 return --(instList
.end());
934 template <class Impl
>
936 FullO3CPU
<Impl
>::instDone(unsigned tid
)
938 // Keep an instruction count.
939 thread
[tid
]->numInst
++;
940 thread
[tid
]->numInsts
++;
941 committedInsts
[tid
]++;
942 totalCommittedInsts
++;
944 // Check for instruction-count-based events.
945 comInstEventQueue
[tid
]->serviceEvents(thread
[tid
]->numInst
);
948 template <class Impl
>
950 FullO3CPU
<Impl
>::addToRemoveList(DynInstPtr
&inst
)
952 removeInstsThisCycle
= true;
954 removeList
.push(inst
->getInstListIt());
957 template <class Impl
>
959 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
961 DPRINTF(FullCPU
, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
963 inst
->threadNumber
, inst
->readPC(), inst
->seqNum
);
965 removeInstsThisCycle
= true;
967 // Remove the front instruction.
968 removeList
.push(inst
->getInstListIt());
971 template <class Impl
>
973 FullO3CPU
<Impl
>::removeInstsNotInROB(unsigned tid
)
975 DPRINTF(FullCPU
, "FullCPU: Thread %i: Deleting instructions from instruction"
980 bool rob_empty
= false;
982 if (instList
.empty()) {
984 } else if (rob
.isEmpty(/*tid*/)) {
985 DPRINTF(FullCPU
, "FullCPU: ROB is empty, squashing all insts.\n");
986 end_it
= instList
.begin();
989 end_it
= (rob
.readTailInst(tid
))->getInstListIt();
990 DPRINTF(FullCPU
, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
993 removeInstsThisCycle
= true;
995 ListIt inst_it
= instList
.end();
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());
1004 squashInstIt(inst_it
, tid
);
1009 // If the ROB was empty, then we actually need to remove the first
1010 // instruction as well.
1012 squashInstIt(inst_it
, tid
);
1016 template <class Impl
>
1018 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
,
1021 assert(!instList
.empty());
1023 removeInstsThisCycle
= true;
1025 ListIt inst_iter
= instList
.end();
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
);
1033 while ((*inst_iter
)->seqNum
> seq_num
) {
1035 bool break_loop
= (inst_iter
== instList
.begin());
1037 squashInstIt(inst_iter
, tid
);
1046 template <class Impl
>
1048 FullO3CPU
<Impl
>::squashInstIt(const ListIt
&instIt
, const unsigned &tid
)
1050 if ((*instIt
)->threadNumber
== tid
) {
1051 DPRINTF(FullCPU
, "FullCPU: Squashing instruction, "
1052 "[tid:%i] [sn:%lli] PC %#x\n",
1053 (*instIt
)->threadNumber
,
1055 (*instIt
)->readPC());
1057 // Mark it as squashed.
1058 (*instIt
)->setSquashed();
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
);
1067 template <class Impl
>
1069 FullO3CPU
<Impl
>::cleanUpRemovedInsts()
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());
1078 instList
.erase(removeList
.front());
1083 removeInstsThisCycle
= false;
1086 template <class Impl>
1088 FullO3CPU<Impl>::removeAllInsts()
1093 template <class Impl
>
1095 FullO3CPU
<Impl
>::dumpInsts()
1099 ListIt inst_list_it
= instList
.begin();
1101 cprintf("Dumping Instruction List\n");
1103 while (inst_list_it
!= instList
.end()) {
1104 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\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());
1114 template <class Impl>
1116 FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1118 iew.wakeDependents(inst);
1121 template <class Impl
>
1123 FullO3CPU
<Impl
>::wakeCPU()
1125 if (activityRec
.active() || tickEvent
.scheduled()) {
1126 DPRINTF(Activity
, "CPU already running.\n");
1130 DPRINTF(Activity
, "Waking up CPU\n");
1132 idleCycles
+= (curTick
- 1) - lastRunningCycle
;
1134 tickEvent
.schedule(curTick
);
1137 template <class Impl
>
1139 FullO3CPU
<Impl
>::getFreeTid()
1141 for (int i
=0; i
< numThreads
; i
++) {
1151 template <class Impl
>
1153 FullO3CPU
<Impl
>::doContextSwitch()
1155 if (contextSwitch
) {
1157 //ADD CODE TO DEACTIVE THREAD HERE (???)
1159 for (int tid
=0; tid
< cpuWaitList
.size(); tid
++) {
1160 activateWhenReady(tid
);
1163 if (cpuWaitList
.size() == 0)
1164 contextSwitch
= true;
1168 template <class Impl
>
1170 FullO3CPU
<Impl
>::updateThreadPriority()
1172 if (activeThreads
.size() > 1)
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();
1179 unsigned high_thread
= *list_begin
;
1181 activeThreads
.erase(list_begin
);
1183 activeThreads
.push_back(high_thread
);
1187 // Forward declaration of FullO3CPU.
1188 template class FullO3CPU
<AlphaSimpleImpl
>;