summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/inst_queue_impl.hh
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2004-10-21 18:02:36 -0400
committerKevin Lim <ktlim@umich.edu>2004-10-21 18:02:36 -0400
commit2fb632dbda1b5db9163322541676cef52a55029f (patch)
tree102f60acd87e237820600070ba485dd6fc14db42 /cpu/beta_cpu/inst_queue_impl.hh
parente3fb9afa79e37cb8c60a48b9ff3976665c2c7675 (diff)
downloadgem5-2fb632dbda1b5db9163322541676cef52a55029f.tar.xz
Check in of various updates to the CPU. Mainly adds in stats, improves
branch prediction, and makes memory dependence work properly. SConscript: Added return address stack, tournament predictor. cpu/base_cpu.cc: Added debug break and print statements. cpu/base_dyn_inst.cc: cpu/base_dyn_inst.hh: Comment out possibly unneeded variables. cpu/beta_cpu/2bit_local_pred.cc: 2bit predictor no longer speculatively updates itself. cpu/beta_cpu/alpha_dyn_inst.hh: Comment formatting. cpu/beta_cpu/alpha_full_cpu.hh: Formatting cpu/beta_cpu/alpha_full_cpu_builder.cc: Added new parameters for branch predictors, and IQ parameters. cpu/beta_cpu/alpha_full_cpu_impl.hh: Register stats. cpu/beta_cpu/alpha_params.hh: Added parameters for IQ, branch predictors, and store sets. cpu/beta_cpu/bpred_unit.cc: Removed one class. cpu/beta_cpu/bpred_unit.hh: Add in RAS, stats. Changed branch predictor unit functionality so that it holds a history of past branches so it can update, and also hold a proper history of the RAS so it can be restored on branch mispredicts. cpu/beta_cpu/bpred_unit_impl.hh: Added in stats, history of branches, RAS. Now bpred unit actually modifies the instruction's predicted next PC. cpu/beta_cpu/btb.cc: Add in sanity checks. cpu/beta_cpu/comm.hh: Add in communication where needed, remove it where it's not. cpu/beta_cpu/commit.hh: cpu/beta_cpu/rename.hh: cpu/beta_cpu/rename_impl.hh: Add in stats. cpu/beta_cpu/commit_impl.hh: Stats, update what is sent back on branch mispredict. cpu/beta_cpu/cpu_policy.hh: Change the bpred unit being used. cpu/beta_cpu/decode.hh: cpu/beta_cpu/decode_impl.hh: Stats. cpu/beta_cpu/fetch.hh: Stats, change squash so it can handle squashes from decode differently than squashes from commit. cpu/beta_cpu/fetch_impl.hh: Add in stats. Change how a cache line is fetched. Update to work with caches. Also have separate functions for different behavior if squash is coming from decode vs commit. cpu/beta_cpu/free_list.hh: Remove some old comments. cpu/beta_cpu/full_cpu.cc: cpu/beta_cpu/full_cpu.hh: Added function to remove instructions from back of instruction list until a certain sequence number. cpu/beta_cpu/iew.hh: Stats, separate squashing behavior due to branches vs memory. cpu/beta_cpu/iew_impl.hh: Stats, separate squashing behavior for branches vs memory. cpu/beta_cpu/inst_queue.cc: Debug stuff cpu/beta_cpu/inst_queue.hh: Stats, change how mem dep unit works, debug stuff cpu/beta_cpu/inst_queue_impl.hh: Stats, change how mem dep unit works, debug stuff. Also add in parameters that used to be hardcoded. cpu/beta_cpu/mem_dep_unit.hh: cpu/beta_cpu/mem_dep_unit_impl.hh: Add in stats, change how memory dependence unit works. It now holds the memory instructions that are waiting for their memory dependences to resolve. It provides which instructions are ready directly to the IQ. cpu/beta_cpu/regfile.hh: Fix up sanity checks. cpu/beta_cpu/rename_map.cc: Fix loop variable type. cpu/beta_cpu/rob_impl.hh: Remove intermediate DynInstPtr cpu/beta_cpu/store_set.cc: Add in debugging statements. cpu/beta_cpu/store_set.hh: Reorder function arguments to match the rest of the calls. --HG-- extra : convert_revision : aabf9b1fecd1d743265dfc3b174d6159937c6f44
Diffstat (limited to 'cpu/beta_cpu/inst_queue_impl.hh')
-rw-r--r--cpu/beta_cpu/inst_queue_impl.hh190
1 files changed, 164 insertions, 26 deletions
diff --git a/cpu/beta_cpu/inst_queue_impl.hh b/cpu/beta_cpu/inst_queue_impl.hh
index 03e3fed33..c688181ed 100644
--- a/cpu/beta_cpu/inst_queue_impl.hh
+++ b/cpu/beta_cpu/inst_queue_impl.hh
@@ -24,15 +24,13 @@ InstructionQueue<Impl>::InstructionQueue(Params &params)
numEntries(params.numIQEntries),
intWidth(params.executeIntWidth),
floatWidth(params.executeFloatWidth),
+ branchWidth(params.executeBranchWidth),
+ memoryWidth(params.executeMemoryWidth),
totalWidth(params.issueWidth),
numPhysIntRegs(params.numPhysIntRegs),
numPhysFloatRegs(params.numPhysFloatRegs),
commitToIEWDelay(params.commitToIEWDelay)
{
- // HACK: HARDCODED NUMBER. REMOVE LATER AND ADD TO PARAMETER.
- branchWidth = 1;
- memoryWidth = 1;
-
DPRINTF(IQ, "IQ: Int width is %i.\n", params.executeIntWidth);
// Initialize the number of free IQ entries.
@@ -68,6 +66,87 @@ InstructionQueue<Impl>::InstructionQueue(Params &params)
template <class Impl>
void
+InstructionQueue<Impl>::regStats()
+{
+ iqInstsAdded
+ .name(name() + ".iqInstsAdded")
+ .desc("Number of instructions added to the IQ (excludes non-spec)")
+ .prereq(iqInstsAdded);
+
+ iqNonSpecInstsAdded
+ .name(name() + ".iqNonSpecInstsAdded")
+ .desc("Number of non-speculative instructions added to the IQ")
+ .prereq(iqNonSpecInstsAdded);
+
+// iqIntInstsAdded;
+
+ iqIntInstsIssued
+ .name(name() + ".iqIntInstsIssued")
+ .desc("Number of integer instructions issued")
+ .prereq(iqIntInstsIssued);
+
+// iqFloatInstsAdded;
+
+ iqFloatInstsIssued
+ .name(name() + ".iqFloatInstsIssued")
+ .desc("Number of float instructions issued")
+ .prereq(iqFloatInstsIssued);
+
+// iqBranchInstsAdded;
+
+ iqBranchInstsIssued
+ .name(name() + ".iqBranchInstsIssued")
+ .desc("Number of branch instructions issued")
+ .prereq(iqBranchInstsIssued);
+
+// iqMemInstsAdded;
+
+ iqMemInstsIssued
+ .name(name() + ".iqMemInstsIssued")
+ .desc("Number of memory instructions issued")
+ .prereq(iqMemInstsIssued);
+
+// iqMiscInstsAdded;
+
+ iqMiscInstsIssued
+ .name(name() + ".iqMiscInstsIssued")
+ .desc("Number of miscellaneous instructions issued")
+ .prereq(iqMiscInstsIssued);
+
+ iqSquashedInstsIssued
+ .name(name() + ".iqSquashedInstsIssued")
+ .desc("Number of squashed instructions issued")
+ .prereq(iqSquashedInstsIssued);
+
+ iqLoopSquashStalls
+ .name(name() + ".iqLoopSquashStalls")
+ .desc("Number of times issue loop had to restart due to squashed "
+ "inst; mainly for profiling")
+ .prereq(iqLoopSquashStalls);
+
+ iqSquashedInstsExamined
+ .name(name() + ".iqSquashedInstsExamined")
+ .desc("Number of squashed instructions iterated over during squash;"
+ " mainly for profiling")
+ .prereq(iqSquashedInstsExamined);
+
+ iqSquashedOperandsExamined
+ .name(name() + ".iqSquashedOperandsExamined")
+ .desc("Number of squashed operands that are examined and possibly "
+ "removed from graph")
+ .prereq(iqSquashedOperandsExamined);
+
+ iqSquashedNonSpecRemoved
+ .name(name() + ".iqSquashedNonSpecRemoved")
+ .desc("Number of squashed non-spec instructions that were removed")
+ .prereq(iqSquashedNonSpecRemoved);
+
+ // Tell mem dependence unit to reg stats as well.
+ memDepUnit.regStats();
+}
+
+template <class Impl>
+void
InstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
{
cpu = cpu_ptr;
@@ -161,10 +240,14 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
// unit.
if (new_inst->isMemRef()) {
memDepUnit.insert(new_inst);
+ // Uh..forgot to look it up and put it on the proper dependency list
+ // if the instruction should not go yet.
+ } else {
+ // If the instruction is ready then add it to the ready list.
+ addIfReady(new_inst);
}
- // If the instruction is ready then add it to the ready list.
- addIfReady(new_inst);
+ ++iqInstsAdded;
assert(freeEntries == (numEntries - countInsts()));
}
@@ -219,13 +302,16 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
// If it's a memory instruction, add it to the memory dependency
// unit.
if (inst->isMemRef()) {
- memDepUnit.insert(inst);
+ memDepUnit.insertNonSpec(inst);
}
+
+ ++iqNonSpecInstsAdded;
}
// Slightly hack function to advance the tail iterator in the case that
// the IEW stage issues an instruction that is not added to the IQ. This
// is needed in case a long chain of such instructions occurs.
+// I don't think this is used anymore.
template <class Impl>
void
InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
@@ -288,7 +374,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
bool insts_available = !readyBranchInsts.empty() ||
!readyIntInsts.empty() ||
!readyFloatInsts.empty() ||
- !readyMemInsts.empty() ||
+ !memDepUnit.empty() ||
!readyMiscInsts.empty() ||
!squashedInsts.empty();
@@ -327,6 +413,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
if (int_head_inst->isSquashed()) {
readyIntInsts.pop();
+
+ ++iqLoopSquashStalls;
+
continue;
}
@@ -344,6 +433,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
if (float_head_inst->isSquashed()) {
readyFloatInsts.pop();
+
+ ++iqLoopSquashStalls;
+
continue;
} else if (float_head_inst->seqNum < oldest_inst) {
oldest_inst = float_head_inst->seqNum;
@@ -361,6 +453,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
if (branch_head_inst->isSquashed()) {
readyBranchInsts.pop();
+
+ ++iqLoopSquashStalls;
+
continue;
} else if (branch_head_inst->seqNum < oldest_inst) {
oldest_inst = branch_head_inst->seqNum;
@@ -370,15 +465,18 @@ InstructionQueue<Impl>::scheduleReadyInsts()
}
- if (!readyMemInsts.empty() &&
+ if (!memDepUnit.empty() &&
memory_issued < memoryWidth) {
insts_available = true;
- mem_head_inst = readyMemInsts.top();
+ mem_head_inst = memDepUnit.top();
if (mem_head_inst->isSquashed()) {
- readyMemInsts.pop();
+ memDepUnit.pop();
+
+ ++iqLoopSquashStalls;
+
continue;
} else if (mem_head_inst->seqNum < oldest_inst) {
oldest_inst = mem_head_inst->seqNum;
@@ -395,6 +493,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
if (misc_head_inst->isSquashed()) {
readyMiscInsts.pop();
+
+ ++iqLoopSquashStalls;
+
continue;
} else if (misc_head_inst->seqNum < oldest_inst) {
oldest_inst = misc_head_inst->seqNum;
@@ -450,9 +551,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
case Memory:
issuing_inst = mem_head_inst;
- memDepUnit.issue(mem_head_inst);
-
- readyMemInsts.pop();
+ memDepUnit.pop();
++memory_issued;
DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
issuing_inst->readPC());
@@ -461,6 +560,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
case Misc:
issuing_inst = misc_head_inst;
readyMiscInsts.pop();
+
+ ++iqMiscInstsIssued;
+
DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
issuing_inst->readPC());
break;
@@ -476,6 +578,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
if (list_with_oldest != None) {
i2e_info->insts[total_issued] = issuing_inst;
+ i2e_info->size++;
issuing_inst->setIssued();
@@ -485,12 +588,21 @@ InstructionQueue<Impl>::scheduleReadyInsts()
assert(freeEntries == (numEntries - countInsts()));
}
+
+ iqIntInstsIssued += int_issued;
+ iqFloatInstsIssued += float_issued;
+ iqBranchInstsIssued += branch_issued;
+ iqMemInstsIssued += memory_issued;
+ iqSquashedInstsIssued += squashed_issued;
}
template <class Impl>
void
InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
{
+ DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
+ "number %i as ready to execute.\n", inst);
+
non_spec_it_t inst_it = nonSpecInsts.find(inst);
assert(inst_it != nonSpecInsts.end());
@@ -499,7 +611,11 @@ InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
(*inst_it).second->setCanIssue();
// Now schedule the instruction.
- addIfReady((*inst_it).second);
+ if (!(*inst_it).second->isMemRef()) {
+ addIfReady((*inst_it).second);
+ } else {
+ memDepUnit.nonSpecInstReady((*inst_it).second);
+ }
nonSpecInsts.erase(inst_it);
}
@@ -552,6 +668,7 @@ InstructionQueue<Impl>::doSquash()
// hasn't already been squashed in the IQ.
if (!squashed_inst->isIssued() &&
!squashed_inst->isSquashedInIQ()) {
+
// Remove the instruction from the dependency list.
// Hack for now: These below don't add themselves to the
// dependency list, so don't try to remove them.
@@ -576,7 +693,15 @@ InstructionQueue<Impl>::doSquash()
src_reg < numPhysRegs) {
dependGraph[src_reg].remove(squashed_inst);
}
+
+ ++iqSquashedOperandsExamined;
}
+
+ // Might want to remove producers as well.
+ } else {
+ nonSpecInsts.erase(squashed_inst->seqNum);
+
+ ++iqSquashedNonSpecRemoved;
}
// Might want to also clear out the head of the dependency graph.
@@ -590,11 +715,8 @@ InstructionQueue<Impl>::doSquash()
squashed_inst->readPC());
}
- if (squashed_inst->isNonSpeculative() || squashed_inst->isStore()) {
- nonSpecInsts.erase(squashed_inst->seqNum);
- }
-
--squashIt;
+ ++iqSquashedInstsExamined;
}
}
@@ -665,6 +787,8 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
dependGraph[dest_reg].next = curr->next;
+ DependencyEntry::mem_alloc_counter--;
+
delete curr;
}
@@ -749,13 +873,9 @@ InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
}
dependGraph[dest_reg].inst = new_inst;
-#if 0
- if (dependGraph[dest_reg].next) {
- panic("Dependency chain of dest reg %i is not empty.\n",
- dest_reg);
- }
-#endif
+
assert(!dependGraph[dest_reg].next);
+
// Mark the scoreboard to say it's not yet ready.
regScoreboard[dest_reg] = false;
}
@@ -776,6 +896,8 @@ InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
// Then actually add it to the chain.
this->next = new_entry;
+
+ ++mem_alloc_counter;
}
template <class Impl>
@@ -805,6 +927,8 @@ InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
// Now remove this instruction from the list.
prev->next = curr->next;
+ --mem_alloc_counter;
+
delete curr;
}
@@ -855,12 +979,26 @@ InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
+ // Message to the mem dependence unit that this instruction has
+ // its registers ready.
+
+ memDepUnit.regsReady(inst);
+
+#if 0
if (memDepUnit.readyToIssue(inst)) {
DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
"putting it onto the ready list, PC %#x.\n",
inst->readPC());
readyMemInsts.push(inst);
+ } else {
+ // Make dependent on the store.
+ // Will need some way to get the store instruction it should
+ // be dependent upon; then when the store issues it can
+ // put the instruction on the ready list.
+ // Yet another tree?
+ assert(0 && "Instruction has no way to actually issue");
}
+#endif
} else if (inst->isInteger()) {
@@ -923,7 +1061,7 @@ InstructionQueue<Impl>::dumpLists()
cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
- cprintf("Ready memory list size: %i\n", readyMemInsts.size());
+// cprintf("Ready memory list size: %i\n", readyMemInsts.size());
cprintf("Ready misc list size: %i\n", readyMiscInsts.size());