diff options
author | Kevin Lim <ktlim@umich.edu> | 2004-08-20 14:54:07 -0400 |
---|---|---|
committer | Kevin Lim <ktlim@umich.edu> | 2004-08-20 14:54:07 -0400 |
commit | 04745696b6b523c5e90c335298099600d4a14a76 (patch) | |
tree | 66b578f8c44355ccf8e970fe59b52554dde9d0ce /cpu/beta_cpu/rob_impl.hh | |
parent | 8295a8050c1096dc560f4976724adada810e56e1 (diff) | |
download | gem5-04745696b6b523c5e90c335298099600d4a14a76.tar.xz |
Check in of new CPU. This checkin works under non-Fullsystem mode, with no caches.
SConscript:
Added new CPU files to build.
arch/alpha/isa_desc:
Changed rduniq and wruniq to be nonspeculative because the uniq register is not renamed.
arch/isa_parser.py:
Added new CPU exec method.
base/statistics.hh:
Minor change for namespace conflict. Probably can change back one the new CPU files are cleaned up.
base/traceflags.py:
Added new CPU trace flags.
cpu/static_inst.hh:
Changed static inst to use a file that defines the execute functions.
--HG--
extra : convert_revision : bd4ce34361308280168324817fc1258dd253e519
Diffstat (limited to 'cpu/beta_cpu/rob_impl.hh')
-rw-r--r-- | cpu/beta_cpu/rob_impl.hh | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/cpu/beta_cpu/rob_impl.hh b/cpu/beta_cpu/rob_impl.hh new file mode 100644 index 000000000..308a8010f --- /dev/null +++ b/cpu/beta_cpu/rob_impl.hh @@ -0,0 +1,264 @@ +#ifndef __ROB_IMPL_HH__ +#define __ROB_IMPL_HH__ + +#include "cpu/beta_cpu/rob.hh" + +template<class Impl> +ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) + : numEntries(_numEntries), + squashWidth(_squashWidth), + numInstsInROB(0), + squashedSeqNum(0) +{ + doneSquashing = true; +} + +template<class Impl> +void +ROB<Impl>::setCPU(FullCPU *cpu_ptr) +{ + cpu = cpu_ptr; + + tail = cpu->instList.begin(); + + squashIt = cpu->instList.end(); +} + +template<class Impl> +int +ROB<Impl>::countInsts() +{ +/* + int return_val = 0; + + // Iterate through the ROB from the head to the tail, counting the + // entries. + for (InstIt i = cpu->instList.begin(); i != tail; i++) + { + assert(i != cpu->instList.end()); + return_val++; + } + + return return_val; +*/ + // Because the head won't be tracked properly until the ROB gets the + // first instruction, and any time that the ROB is empty and has not + // yet gotten the instruction, this function doesn't work. + return numInstsInROB; +} + +template<class Impl> +void +ROB<Impl>::insertInst(DynInst *inst) +{ + // Make sure we have the right number of instructions. + assert(numInstsInROB == countInsts()); + // Make sure the instruction is valid. + assert(inst); + + DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); + + // If the ROB is full then exit. + assert(numInstsInROB != numEntries); + + ++numInstsInROB; + + // Increment the tail iterator, moving it one instruction back. + // There is a special case if the ROB was empty prior to this insertion, + // in which case the tail will be pointing at instList.end(). If that + // happens, then reset the tail to the beginning of the list. + if (tail != cpu->instList.end()) { + tail++; + } else { + tail = cpu->instList.begin(); + } + + // Make sure the tail iterator is actually pointing at the instruction + // added. + assert((*tail) == inst); + + DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); + +} + +// Whatever calls this function needs to ensure that it properly frees up +// registers prior to this function. +template<class Impl> +void +ROB<Impl>::retireHead() +{ + assert(numInstsInROB == countInsts()); + + DynInst *head_inst; + + // Get the head ROB instruction. + head_inst = cpu->instList.front(); + + // Make certain this can retire. + assert(head_inst->readyToCommit()); + + DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " + "instruction PC %#x, seq num %i\n", head_inst->readPC(), + head_inst->seqNum); + + // Keep track of how many instructions are in the ROB. + --numInstsInROB; + + // Tell CPU to remove the instruction from the list of instructions. + // A special case is needed if the instruction being retired is the + // only instruction in the ROB; otherwise the tail iterator will become + // invalidated. + if (tail == cpu->instList.begin()) { + cpu->removeFrontInst(head_inst); + tail = cpu->instList.end(); + } else { + cpu->removeFrontInst(head_inst); + } +} + +template<class Impl> +bool +ROB<Impl>::isHeadReady() +{ + if (numInstsInROB != 0) { + DynInst *head_inst = cpu->instList.front(); + + return head_inst->readyToCommit(); + } + + return false; +} + +template<class Impl> +unsigned +ROB<Impl>::numFreeEntries() +{ + assert(numInstsInROB == countInsts()); + + return numEntries - numInstsInROB; +} + +template<class Impl> +void +ROB<Impl>::doSquash() +{ + DPRINTF(ROB, "ROB: Squashing instructions.\n"); + + assert(squashIt != cpu->instList.end()); + + for (int numSquashed = 0; + numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; + ++numSquashed) + { + // Ensure that the instruction is younger. + assert((*squashIt)->seqNum > squashedSeqNum); + + DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", + (*squashIt)->readPC(), (*squashIt)->seqNum); + + // Mark the instruction as squashed, and ready to commit so that + // it can drain out of the pipeline. + (*squashIt)->setSquashed(); + + (*squashIt)->setCanCommit(); + +#ifndef FULL_SYSTEM + if (squashIt == cpu->instList.begin()) { + DPRINTF(ROB, "ROB: Reached head of instruction list while " + "squashing.\n"); + + squashIt = cpu->instList.end(); + + doneSquashing = true; + + return; + } +#endif + + // Move the tail iterator to the next instruction. + squashIt--; + } + + + // Check if ROB is done squashing. + if ((*squashIt)->seqNum == squashedSeqNum) { + DPRINTF(ROB, "ROB: Done squashing instructions.\n"); + + squashIt = cpu->instList.end(); + + doneSquashing = true; + } +} + +template<class Impl> +void +ROB<Impl>::squash(InstSeqNum squash_num) +{ + DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); + doneSquashing = false; + + squashedSeqNum = squash_num; + + assert(tail != cpu->instList.end()); + + squashIt = tail; + + doSquash(); +} + +template<class Impl> +uint64_t +ROB<Impl>::readHeadPC() +{ + assert(numInstsInROB == countInsts()); + + DynInst *head_inst = cpu->instList.front(); + + return head_inst->readPC(); +} + +template<class Impl> +uint64_t +ROB<Impl>::readHeadNextPC() +{ + assert(numInstsInROB == countInsts()); + + DynInst *head_inst = cpu->instList.front(); + + return head_inst->readNextPC(); +} + +template<class Impl> +InstSeqNum +ROB<Impl>::readHeadSeqNum() +{ + // Return the last sequence number that has not been squashed. Other + // stages can use it to squash any instructions younger than the current + // tail. + DynInst *head_inst = cpu->instList.front(); + + return head_inst->seqNum; +} + +template<class Impl> +uint64_t +ROB<Impl>::readTailPC() +{ + assert(numInstsInROB == countInsts()); + + assert(tail != cpu->instList.end()); + + return (*tail)->readPC(); +} + +template<class Impl> +InstSeqNum +ROB<Impl>::readTailSeqNum() +{ + // Return the last sequence number that has not been squashed. Other + // stages can use it to squash any instructions younger than the current + // tail. + return (*tail)->seqNum; +} + +#endif // __ROB_IMPL_HH__ |