summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/rename_impl.hh
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/beta_cpu/rename_impl.hh')
-rw-r--r--cpu/beta_cpu/rename_impl.hh397
1 files changed, 224 insertions, 173 deletions
diff --git a/cpu/beta_cpu/rename_impl.hh b/cpu/beta_cpu/rename_impl.hh
index 2b60c2f50..47464d961 100644
--- a/cpu/beta_cpu/rename_impl.hh
+++ b/cpu/beta_cpu/rename_impl.hh
@@ -2,18 +2,19 @@
#include "cpu/beta_cpu/rename.hh"
-template<class Impl>
+template <class Impl>
SimpleRename<Impl>::SimpleRename(Params &params)
: iewToRenameDelay(params.iewToRenameDelay),
decodeToRenameDelay(params.decodeToRenameDelay),
commitToRenameDelay(params.commitToRenameDelay),
renameWidth(params.renameWidth),
- commitWidth(params.commitWidth)
+ commitWidth(params.commitWidth),
+ numInst(0)
{
_status = Idle;
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
{
@@ -21,7 +22,7 @@ SimpleRename<Impl>::setCPU(FullCPU *cpu_ptr)
cpu = cpu_ptr;
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
@@ -38,7 +39,7 @@ SimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
toDecode = timeBuffer->getWire(0);
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
{
@@ -49,7 +50,7 @@ SimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
toIEW = renameQueue->getWire(0);
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
{
@@ -61,7 +62,7 @@ SimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
{
@@ -69,7 +70,7 @@ SimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr)
renameMap = rm_ptr;
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
{
@@ -77,7 +78,7 @@ SimpleRename<Impl>::setFreeList(FreeList *fl_ptr)
freeList = fl_ptr;
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::dumpHistory()
{
@@ -93,7 +94,7 @@ SimpleRename<Impl>::dumpHistory()
}
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::block()
{
@@ -110,12 +111,12 @@ SimpleRename<Impl>::block()
// the previous stages are expected to check all possible stall signals.
}
-template<class Impl>
+template <class Impl>
inline void
SimpleRename<Impl>::unblock()
{
- DPRINTF(Rename, "Rename: Reading instructions out of skid "
- "buffer.\n");
+ DPRINTF(Rename, "Rename: Read instructions out of skid buffer this "
+ "cycle.\n");
// Remove the now processed instructions from the skid buffer.
skidBuffer.pop();
@@ -130,12 +131,12 @@ SimpleRename<Impl>::unblock()
}
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::doSquash()
{
typename list<RenameHistory>::iterator hb_it = historyBuffer.begin();
- typename list<RenameHistory>::iterator delete_it;
+// typename list<RenameHistory>::iterator delete_it;
InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum;
@@ -166,15 +167,17 @@ SimpleRename<Impl>::doSquash()
freeList->addReg(hb_it->newPhysReg);
}
- delete_it = hb_it;
+// delete_it = hb_it;
+
+// hb_it++;
- hb_it++;
+ historyBuffer.erase(hb_it++);
- historyBuffer.erase(delete_it);
+ assert(hb_it != historyBuffer.end());
}
}
-template<class Impl>
+template <class Impl>
void
SimpleRename<Impl>::squash()
{
@@ -182,6 +185,8 @@ SimpleRename<Impl>::squash()
// Set the status to Squashing.
_status = Squashing;
+ numInst = 0;
+
// Clear the skid buffer in case it has any data in it.
while (!skidBuffer.empty())
{
@@ -199,10 +204,10 @@ void
SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
{
DPRINTF(Rename, "Rename: Removing a committed instruction from the "
- "history buffer, sequence number %lli.\n", inst_seq_num);
+ "history buffer, until sequence number %lli.\n", inst_seq_num);
typename list<RenameHistory>::iterator hb_it = historyBuffer.end();
- hb_it--;
+ --hb_it;
if (hb_it->instSeqNum > inst_seq_num) {
DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure "
@@ -210,7 +215,7 @@ SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
return;
}
- for ( ; hb_it->instSeqNum != inst_seq_num; hb_it--)
+ while ((*hb_it).instSeqNum != inst_seq_num)
{
// Make sure we haven't gone off the end of the list.
assert(hb_it != historyBuffer.end());
@@ -222,10 +227,19 @@ SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
// be the last instruction in the list, as it is the instruction
// that was just committed that is being removed.
assert(hb_it->instSeqNum < inst_seq_num);
- DPRINTF(Rename, "Rename: Committed instruction is not the last "
- "entry in the history buffer.\n");
+ DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence"
+ " number %i.\n",
+ (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
+
+ if (!(*hb_it).placeHolder) {
+ freeList->addReg((*hb_it).prevPhysReg);
+ }
+
+ historyBuffer.erase(hb_it--);
}
+ // Finally free up the previous register of the squashed instruction
+ // itself.
if (!(*hb_it).placeHolder) {
freeList->addReg(hb_it->prevPhysReg);
}
@@ -234,6 +248,113 @@ SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num)
}
+template <class Impl>
+inline void
+SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst)
+{
+ unsigned num_src_regs = inst->numSrcRegs();
+
+ // Get the architectual register numbers from the source and
+ // destination operands, and redirect them to the right register.
+ // Will need to mark dependencies though.
+ for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
+ {
+ RegIndex src_reg = inst->srcRegIdx(src_idx);
+
+ // Look up the source registers to get the phys. register they've
+ // been renamed to, and set the sources to those registers.
+ RegIndex renamed_reg = renameMap->lookup(src_reg);
+
+ DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
+ "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
+
+ inst->renameSrcReg(src_idx, renamed_reg);
+
+ // Either incorporate it into the info passed back,
+ // or make another function call to see if that register is
+ // ready or not.
+ if (renameMap->isReady(renamed_reg)) {
+ DPRINTF(Rename, "Rename: Register is ready.\n");
+
+ inst->markSrcRegReady(src_idx);
+ }
+ }
+}
+
+template <class Impl>
+inline void
+SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst)
+{
+ typename SimpleRenameMap::RenameInfo rename_result;
+
+ unsigned num_dest_regs = inst->numDestRegs();
+
+ // Rename the destination registers.
+ for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
+ {
+ RegIndex dest_reg = inst->destRegIdx(dest_idx);
+
+ // Get the physical register that the destination will be
+ // renamed to.
+ rename_result = renameMap->rename(dest_reg);
+
+ DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
+ "reg %i.\n", (int)dest_reg,
+ (int)rename_result.first);
+
+ // Record the rename information so that a history can be kept.
+ RenameHistory hb_entry(inst->seqNum, dest_reg,
+ rename_result.first,
+ rename_result.second);
+
+ historyBuffer.push_front(hb_entry);
+
+ DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
+ "sequence number %lli.\n",
+ (*historyBuffer.begin()).instSeqNum);
+
+ // Tell the instruction to rename the appropriate destination
+ // register (dest_idx) to the new physical register
+ // (rename_result.first), and record the previous physical
+ // register that the same logical register was renamed to
+ // (rename_result.second).
+ inst->renameDestReg(dest_idx,
+ rename_result.first,
+ rename_result.second);
+ }
+
+ // If it's an instruction with no destination registers, then put
+ // a placeholder within the history buffer. It might be better
+ // to not put it in the history buffer at all (other than branches,
+ // which always need at least a place holder), and differentiate
+ // between instructions with and without destination registers
+ // when getting from commit the instructions that committed.
+ if (num_dest_regs == 0) {
+ RenameHistory hb_entry(inst->seqNum);
+
+ historyBuffer.push_front(hb_entry);
+
+ DPRINTF(Rename, "Rename: Adding placeholder instruction to "
+ "history buffer, sequence number %lli.\n",
+ inst->seqNum);
+ }
+}
+
+template <class Impl>
+inline int
+SimpleRename<Impl>::calcFreeROBEntries()
+{
+ return fromCommit->commitInfo.freeROBEntries -
+ renameWidth * iewToRenameDelay;
+}
+
+template <class Impl>
+inline int
+SimpleRename<Impl>::calcFreeIQEntries()
+{
+ return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;
+}
+
template<class Impl>
void
SimpleRename<Impl>::tick()
@@ -258,12 +379,18 @@ SimpleRename<Impl>::tick()
// buffer were used. Remove those instructions and handle
// the rest of unblocking.
if (_status == Unblocking) {
+ if (fromDecode->size > 0) {
+ // Add the current inputs onto the skid buffer, so they can be
+ // reprocessed when this stage unblocks.
+ skidBuffer.push(*fromDecode);
+ }
+
unblock();
}
} else if (_status == Blocked) {
// If stage is blocked and still receiving valid instructions,
// make sure to store them in the skid buffer.
- if (fromDecode->insts[0] != NULL) {
+ if (fromDecode->size > 0) {
block();
@@ -273,8 +400,9 @@ SimpleRename<Impl>::tick()
if (!fromIEW->iewInfo.stall &&
!fromCommit->commitInfo.stall &&
- fromCommit->commitInfo.freeROBEntries != 0 &&
- fromIEW->iewInfo.freeIQEntries != 0) {
+ calcFreeROBEntries() > 0 &&
+ calcFreeIQEntries() > 0 &&
+ renameMap->numFreeEntries() > 0) {
// Need to be sure to check all blocking conditions above.
// If they have cleared, then start unblocking.
@@ -344,6 +472,7 @@ SimpleRename<Impl>::rename()
// the rename map and the free list.
if (fromCommit->commitInfo.squash ||
fromCommit->commitInfo.robSquashing) {
+ DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");
squash();
return;
}
@@ -368,37 +497,38 @@ SimpleRename<Impl>::rename()
// Check the decode queue to see if instructions are available.
// If there are no available instructions to rename, then do nothing.
// Or, if the stage is currently unblocking, then go ahead and run it.
- if (fromDecode->insts[0] == NULL && _status != Unblocking) {
+ if (fromDecode->size == 0 && _status != Unblocking) {
DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");
// Should I change status to idle?
return;
}
- DynInst *inst;
- unsigned num_inst = 0;
+ ////////////////////////////////////
+ // Actual rename part.
+ ////////////////////////////////////
- bool insts_available = _status == Unblocking ?
- skidBuffer.front().insts[num_inst] != NULL :
- fromDecode->insts[num_inst] != NULL;
+ DynInstPtr inst;
- typename SimpleRenameMap::RenameInfo rename_result;
+ // If we're unblocking, then we may be in the middle of an instruction
+ // group. Subtract off numInst to get the proper number of instructions
+ // left.
+ int insts_available = _status == Unblocking ?
+ skidBuffer.front().size - numInst :
+ fromDecode->size;
- unsigned num_src_regs;
- unsigned num_dest_regs;
+ bool block_this_cycle = false;
// Will have to do a different calculation for the number of free
// entries. Number of free entries recorded on this cycle -
// renameWidth * renameToDecodeDelay
- // Can I avoid a multiply?
- unsigned free_rob_entries =
- fromCommit->commitInfo.freeROBEntries - iewToRenameDelay;
- DPRINTF(Rename, "Rename: ROB has %d free entries.\n",
- free_rob_entries);
- unsigned free_iq_entries =
- fromIEW->iewInfo.freeIQEntries - iewToRenameDelay;
+ int free_rob_entries = calcFreeROBEntries();
+ int free_iq_entries = calcFreeIQEntries();
+ int min_iq_rob = min(free_rob_entries, free_iq_entries);
+
+ unsigned to_iew_index = 0;
// Check if there's any space left.
- if (free_rob_entries == 0 || free_iq_entries == 0) {
+ if (min_iq_rob <= 0) {
DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "
"entries.\n"
"Rename: ROB has %d free entries.\n"
@@ -410,22 +540,40 @@ SimpleRename<Impl>::rename()
toDecode->renameInfo.stall = true;
return;
- }
+ } else if (min_iq_rob < insts_available) {
+ DPRINTF(Rename, "Rename: Will have to block this cycle. Only "
+ "%i insts can be renamed due to IQ/ROB limits.\n",
+ min_iq_rob);
+
+ insts_available = min_iq_rob;
- unsigned min_iq_rob = min(free_rob_entries, free_iq_entries);
- unsigned num_insts_to_rename = min(min_iq_rob, renameWidth);
+ block_this_cycle = true;
+ }
- while (insts_available &&
- num_inst < num_insts_to_rename) {
+ while (insts_available > 0) {
DPRINTF(Rename, "Rename: Sending instructions to iew.\n");
// Get the next instruction either from the skid buffer or the
// decode queue.
- inst = _status == Unblocking ? skidBuffer.front().insts[num_inst] :
- fromDecode->insts[num_inst];
+ inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
+ fromDecode->insts[numInst];
+
+ if (inst->isSquashed()) {
+ DPRINTF(Rename, "Rename: instruction %i with PC %#x is "
+ "squashed, skipping.\n",
+ inst->seqNum, inst->readPC());
+
+ // Go to the next instruction.
+ ++numInst;
+
+ // Decrement how many instructions are available.
+ --insts_available;
+
+ continue;
+ }
DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",
- inst, inst->readPC());
+ inst->seqNum, inst->readPC());
// If it's a trap instruction, then it needs to wait here within
// rename until the ROB is empty. Needs a way to detect that the
@@ -438,156 +586,59 @@ SimpleRename<Impl>::rename()
panic("Rename: Serializing instruction encountered.\n");
DPRINTF(Rename, "Rename: Serializing instruction "
"encountered.\n");
- block();
// Change status over to BarrierStall so that other stages know
// what this is blocked on.
_status = BarrierStall;
- // Tell the previous stage to stall.
- toDecode->renameInfo.stall = true;
-
- break;
- }
-
- // Make sure there's enough room in the ROB and the IQ.
- // This doesn't really need to be done dynamically; consider
- // moving outside of this function.
- if (free_rob_entries == 0 || free_iq_entries == 0) {
- DPRINTF(Rename, "Rename: Blocking due to lack of ROB or IQ "
- "entries.\n");
- // Call some sort of function to handle all the setup of being
- // blocked.
- block();
-
- // Not really sure how to schedule an event properly, but an
- // event must be scheduled such that upon freeing a ROB entry,
- // this stage will restart up. Perhaps add in a ptr to an Event
- // within the ROB that will be able to execute that Event
- // if a free register is added to the freelist.
-
- // Tell the previous stage to stall.
- toDecode->renameInfo.stall = true;
+ block_this_cycle = true;
break;
}
- // Temporary variables to hold number of source and destination regs.
- num_src_regs = inst->numSrcRegs();
- num_dest_regs = inst->numDestRegs();
-
// Check here to make sure there are enough destination registers
// to rename to. Otherwise block.
- if (renameMap->numFreeEntries() < num_dest_regs)
+ if (renameMap->numFreeEntries() < inst->numDestRegs())
{
DPRINTF(Rename, "Rename: Blocking due to lack of free "
"physical registers to rename to.\n");
- // Call function to handle blocking.
- block();
-
// Need some sort of event based on a register being freed.
- // Tell the previous stage to stall.
- toDecode->renameInfo.stall = true;
+ block_this_cycle = true;
- // Break out of rename loop.
break;
}
- // Get the architectual register numbers from the source and
- // destination operands, and redirect them to the right register.
- // Will need to mark dependencies though.
- for (int src_idx = 0; src_idx < num_src_regs; src_idx++)
- {
- RegIndex src_reg = inst->srcRegIdx(src_idx);
-
- // Look up the source registers to get the phys. register they've
- // been renamed to, and set the sources to those registers.
- RegIndex renamed_reg = renameMap->lookup(src_reg);
-
- DPRINTF(Rename, "Rename: Looking up arch reg %i, got "
- "physical reg %i.\n", (int)src_reg, (int)renamed_reg);
-
- inst->renameSrcReg(src_idx, renamed_reg);
-
- // Either incorporate it into the info passed back,
- // or make another function call to see if that register is
- // ready or not.
- if (renameMap->isReady(renamed_reg)) {
- DPRINTF(Rename, "Rename: Register is ready.\n");
-
- inst->markSrcRegReady(src_idx);
- }
- }
-
- // Rename the destination registers.
- for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)
- {
- RegIndex dest_reg = inst->destRegIdx(dest_idx);
-
- // Get the physical register that the destination will be
- // renamed to.
- rename_result = renameMap->rename(dest_reg);
-
- DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "
- "register %i.\n", (int)dest_reg,
- (int)rename_result.first);
-
- // Record the rename information so that a history can be kept.
- RenameHistory hb_entry(inst->seqNum, dest_reg,
- rename_result.first,
- rename_result.second);
-
- historyBuffer.push_front(hb_entry);
-
- DPRINTF(Rename, "Rename: Adding instruction to history buffer, "
- "sequence number %lli.\n", inst->seqNum);
-
- // Tell the instruction to rename the appropriate destination
- // register (dest_idx) to the new physical register
- // (rename_result.first), and record the previous physical
- // register that the same logical register was renamed to
- // (rename_result.second).
- inst->renameDestReg(dest_idx,
- rename_result.first,
- rename_result.second);
- }
-
- // If it's an instruction with no destination registers, then put
- // a placeholder within the history buffer. It might be better
- // to not put it in the history buffer at all (other than branches,
- // which always need at least a place holder), and differentiate
- // between instructions with and without destination registers
- // when getting from commit the instructions that committed.
- if (num_dest_regs == 0) {
- RenameHistory hb_entry(inst->seqNum);
-
- historyBuffer.push_front(hb_entry);
+ renameSrcRegs(inst);
- DPRINTF(Rename, "Rename: Adding placeholder instruction to "
- "history buffer, sequence number %lli.\n",
- inst->seqNum);
- }
+ renameDestRegs(inst);
// Put instruction in rename queue.
- toIEW->insts[num_inst] = inst;
+ toIEW->insts[to_iew_index] = inst;
+ ++(toIEW->size);
// Decrease the number of free ROB and IQ entries.
--free_rob_entries;
--free_iq_entries;
// Increment which instruction we're on.
- ++num_inst;
-
- // Check whether or not there are instructions available.
- // Either need to check within the skid buffer, or the decode
- // queue, depending if this stage is unblocking or not.
- // Hmm, dangerous check. Can touch memory not allocated. Might
- // be better to just do check at beginning of loop. Or better
- // yet actually pass the number of instructions issued.
- insts_available = _status == Unblocking ?
- skidBuffer.front().insts[num_inst] != NULL :
- fromDecode->insts[num_inst] != NULL;
+ ++to_iew_index;
+ ++numInst;
+
+ // Decrement how many instructions are available.
+ --insts_available;
}
+ // Check if there's any instructions left that haven't yet been renamed.
+ // If so then block.
+ if (block_this_cycle) {
+ block();
+
+ toDecode->renameInfo.stall = true;
+ } else {
+ // If we had a successful rename and didn't have to exit early, then
+ // reset numInst so it will refer to the correct instruction on next
+ // run.
+ numInst = 0;
+ }
}