summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/iew_impl.hh
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2004-09-23 14:06:03 -0400
committerKevin Lim <ktlim@umich.edu>2004-09-23 14:06:03 -0400
commite3fb9afa79e37cb8c60a48b9ff3976665c2c7675 (patch)
treea2f252590b6e68659c4b97c6478463eb8d8591ab /cpu/beta_cpu/iew_impl.hh
parent04745696b6b523c5e90c335298099600d4a14a76 (diff)
downloadgem5-e3fb9afa79e37cb8c60a48b9ff3976665c2c7675.tar.xz
Update to make multiple instruction issue and different latencies work.
Also change to ref counted DynInst. SConscript: Add branch predictor, BTB, load store queue, and storesets. arch/isa_parser.py: Specify the template parameter for AlphaDynInst base/traceflags.py: Add load store queue, store set, and mem dependence unit to the list of trace flags. cpu/base_dyn_inst.cc: Change formating, add in debug statement. cpu/base_dyn_inst.hh: Change DynInst to be RefCounted, add flag to clear whether or not this instruction can commit. This is likely to be removed in the future. cpu/beta_cpu/alpha_dyn_inst.cc: AlphaDynInst has been changed to be templated, so now this CC file is just used to force instantiations of AlphaDynInst. cpu/beta_cpu/alpha_dyn_inst.hh: Changed AlphaDynInst to be templated on Impl. Removed some unnecessary functions. cpu/beta_cpu/alpha_full_cpu.cc: AlphaFullCPU has been changed to be templated, so this CC file is now just used to force instantation of AlphaFullCPU. cpu/beta_cpu/alpha_full_cpu.hh: Change AlphaFullCPU to be templated on Impl. cpu/beta_cpu/alpha_impl.hh: Update it to reflect AlphaDynInst and AlphaFullCPU being templated on Impl. Also removed time buffers from here, as they are really a part of the CPU and are thus in the CPU policy now. cpu/beta_cpu/alpha_params.hh: Make AlphaSimpleParams inherit from the BaseFullCPU so that it doesn't need to specifically declare any parameters that are already in the BaseFullCPU. cpu/beta_cpu/comm.hh: Changed the structure of the time buffer communication structs. Now they include the size of the packet of instructions it is sending. Added some parameters to the backwards communication struct, mainly for squashing. cpu/beta_cpu/commit.hh: Update typenames to reflect change in location of time buffer structs. Update DynInst to DynInstPtr (it is refcounted now). cpu/beta_cpu/commit_impl.hh: Formatting changes mainly. Also sends back proper information on branch mispredicts so that the bpred unit can update itself. Updated behavior for non-speculative instructions (stores, any other non-spec instructions): once they reach the head of the ROB, the ROB signals back to the IQ that it can go ahead and issue the non-speculative instruction. The instruction itself is updated so that commit won't try to commit it again until it is done executing. cpu/beta_cpu/cpu_policy.hh: Added branch prediction unit, mem dependence prediction unit, load store queue. Moved time buffer structs from AlphaSimpleImpl to here. cpu/beta_cpu/decode.hh: Changed typedefs to reflect change in location of time buffer structs and also the change from DynInst to ref counted DynInstPtr. cpu/beta_cpu/decode_impl.hh: Continues to buffer instructions even while unblocking now. Changed how it loops through groups of instructions so it can properly block during the middle of a group of instructions. cpu/beta_cpu/fetch.hh: Changed typedefs to reflect change in location of time buffer structs and the change to ref counted DynInsts. Also added in branch brediction unit. cpu/beta_cpu/fetch_impl.hh: Add in branch prediction. Changed how fetch checks inputs and its current state to make for easier logic. cpu/beta_cpu/free_list.cc: Changed int regs and float regs to logically use one flat namespace. Future change will be moving them to a single scoreboard to conserve space. cpu/beta_cpu/free_list.hh: Mostly debugging statements. Might be removed for performance in future. cpu/beta_cpu/full_cpu.cc: Added in some debugging statements. Updated BaseFullCPU to take a params object. cpu/beta_cpu/full_cpu.hh: Added params class within BaseCPU that other param classes will be able to inherit from. Updated typedefs to reflect change in location of time buffer structs and ref counted DynInst. cpu/beta_cpu/iew.hh: Updated typedefs to reflect change in location of time buffer structs and use of ref counted DynInsts. cpu/beta_cpu/iew_impl.hh: Added in load store queue, updated iew to be able to execute non- speculative instructions, instead of having them execute in commit. cpu/beta_cpu/inst_queue.hh: Updated change to ref counted DynInsts. Changed inst queue to hold non-speculative instructions as well, which are issued only when commit signals backwards that a nonspeculative instruction is at the head of the ROB. cpu/beta_cpu/inst_queue_impl.hh: Updated to allow for non-speculative instructions to be in the inst queue. Also added some debug functions. cpu/beta_cpu/regfile.hh: Added debugging statements, changed formatting. cpu/beta_cpu/rename.hh: Updated typedefs, added some functions to clean up code. cpu/beta_cpu/rename_impl.hh: Moved some code into functions to make it easier to read. cpu/beta_cpu/rename_map.cc: Changed int and float reg behavior to use a single flat namespace. In the future, the rename maps can be combined to a single rename map to save space. cpu/beta_cpu/rename_map.hh: Added destructor. cpu/beta_cpu/rob.hh: Updated it with change from DynInst to ref counted DynInst. cpu/beta_cpu/rob_impl.hh: Formatting, updated to use ref counted DynInst. cpu/static_inst.hh: Updated forward declaration for AlphaDynInst now that it is templated. --HG-- extra : convert_revision : 1045f240ee9b6a4bd368e1806aca029ebbdc6dd3
Diffstat (limited to 'cpu/beta_cpu/iew_impl.hh')
-rw-r--r--cpu/beta_cpu/iew_impl.hh156
1 files changed, 114 insertions, 42 deletions
diff --git a/cpu/beta_cpu/iew_impl.hh b/cpu/beta_cpu/iew_impl.hh
index b198220f5..521ce77f6 100644
--- a/cpu/beta_cpu/iew_impl.hh
+++ b/cpu/beta_cpu/iew_impl.hh
@@ -3,8 +3,8 @@
// communication happens simultaneously. Might not be that bad really...
// it might skew stats a bit though. Issue would otherwise try to issue
// instructions that would never be executed if there were a delay; without
-// it issue will simply squash. Make this stage block properly. Make this
-// stage delay after a squash properly. Update the statuses for each stage.
+// it issue will simply squash. Make this stage block properly.
+// Update the statuses for each stage.
// Actually read instructions out of the skid buffer.
#include <queue>
@@ -15,8 +15,9 @@
template<class Impl, class IQ>
SimpleIEW<Impl, IQ>::SimpleIEW(Params &params)
: // Just make this time buffer really big for now
- issueToExecQueue(20, 20),
+ issueToExecQueue(5, 5),
instQueue(params),
+ ldstQueue(params),
commitToIEWDelay(params.commitToIEWDelay),
renameToIEWDelay(params.renameToIEWDelay),
issueToExecuteDelay(params.issueToExecuteDelay),
@@ -45,6 +46,7 @@ SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr)
cpu = cpu_ptr;
instQueue.setCPU(cpu_ptr);
+ ldstQueue.setCPU(cpu_ptr);
}
template<class Impl, class IQ>
@@ -96,7 +98,7 @@ SimpleIEW<Impl, IQ>::setRenameMap(RenameMap *rm_ptr)
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::wakeDependents(DynInst *inst)
+SimpleIEW<Impl, IQ>::wakeDependents(DynInstPtr &inst)
{
instQueue.wakeDependents(inst);
}
@@ -150,17 +152,15 @@ SimpleIEW<Impl, IQ>::squash()
// Tell the IQ to start squashing.
instQueue.squash();
- // Tell rename to squash through the time buffer.
- // This communication may be redundant depending upon where squash()
- // is called.
-// toRename->iewInfo.squash = true;
+ // Tell the LDSTQ to start squashing.
+ ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
}
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::squash(DynInst *inst)
+SimpleIEW<Impl, IQ>::squash(DynInstPtr &inst)
{
- DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC:%#x.\n",
+ DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
inst->PC);
// Perhaps leave the squashing up to the ROB stage to tell it when to
// squash?
@@ -170,8 +170,11 @@ SimpleIEW<Impl, IQ>::squash(DynInst *inst)
toRename->iewInfo.squash = true;
// Also send PC update information back to prior stages.
toRename->iewInfo.squashedSeqNum = inst->seqNum;
+ toRename->iewInfo.mispredPC = inst->readPC();
toRename->iewInfo.nextPC = inst->readCalcTarg();
- toRename->iewInfo.predIncorrect = true;
+ toRename->iewInfo.branchMispredict = true;
+ // Prediction was incorrect, so send back inverse.
+ toRename->iewInfo.branchTaken = !(inst->predTaken());
}
template<class Impl, class IQ>
@@ -229,7 +232,7 @@ SimpleIEW<Impl, IQ>::tick()
// If there's still instructions coming from rename, continue to
// put them on the skid buffer.
- if (fromRename->insts[0] != NULL) {
+ if (fromRename->insts[0]) {
block();
}
@@ -244,6 +247,19 @@ SimpleIEW<Impl, IQ>::tick()
// Write back number of free IQ entries here.
toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
+ // Check the committed load/store signals to see if there's a load
+ // or store to commit. Also check if it's being told to execute a
+ // nonspeculative instruction.
+ if (fromCommit->commitInfo.commitIsStore) {
+ ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
+ } else if (fromCommit->commitInfo.commitIsLoad) {
+ ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
+ }
+
+ if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
+ instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
+ }
+
DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
instQueue.numFreeEntries());
}
@@ -265,7 +281,7 @@ SimpleIEW<Impl, IQ>::iew()
}
////////////////////////////////////////
- //ISSUE stage
+ // DISPATCH/ISSUE stage
////////////////////////////////////////
//Put into its own function?
@@ -273,16 +289,16 @@ SimpleIEW<Impl, IQ>::iew()
// Check if there are any instructions coming from rename, and we're.
// not squashing.
- if (fromRename->insts[0] != NULL && _status != Squashing) {
+ if (fromRename->insts[0] && _status != Squashing) {
// Loop through the instructions, putting them in the instruction
// queue.
for (int inst_num = 0; inst_num < issueReadWidth; ++inst_num)
{
- DynInst *inst = fromRename->insts[inst_num];
+ DynInstPtr inst = fromRename->insts[inst_num];
// Make sure there's a valid instruction there.
- if (inst == NULL)
+ if (!inst)
break;
DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
@@ -294,25 +310,38 @@ SimpleIEW<Impl, IQ>::iew()
// Be sure to mark these instructions as ready so that the
// commit stage can go ahead and execute them, and mark
// them as issued so the IQ doesn't reprocess them.
- if (inst->isMemRef()) {
+ if (inst->isSquashed()) {
+ continue;
+ } else if (inst->isLoad()) {
DPRINTF(IEW, "IEW: Issue: Memory instruction "
- "encountered, skipping.\n");
+ "encountered, adding to LDSTQ.\n");
- inst->setIssued();
- inst->setExecuted();
+ // Reserve a spot in the load store queue for this
+ // memory access.
+ ldstQueue.insertLoad(inst);
+
+ } else if (inst->isStore()) {
+ ldstQueue.insertStore(inst);
+
+ // A bit of a hack. Set that it can commit so that
+ // the commit stage will try committing it, and then
+ // once commit realizes it's a store it will send back
+ // a signal to this stage to issue and execute that
+ // store.
inst->setCanCommit();
- instQueue.advanceTail(inst);
+ instQueue.insertNonSpec(inst);
continue;
} else if (inst->isNonSpeculative()) {
DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
"encountered, skipping.\n");
- inst->setIssued();
- inst->setExecuted();
+ // Same hack as with stores.
inst->setCanCommit();
- instQueue.advanceTail(inst);
+ // Specificall insert it as nonspeculative.
+ instQueue.insertNonSpec(inst);
+
continue;
} else if (inst->isNop()) {
DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
@@ -355,6 +384,7 @@ SimpleIEW<Impl, IQ>::iew()
// @todo: Move to the FU pool used in the current full cpu.
int fu_usage = 0;
+ bool fetch_redirect = false;
// Execute/writeback any instructions that are available.
for (int inst_num = 0;
@@ -365,26 +395,48 @@ SimpleIEW<Impl, IQ>::iew()
DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
// Get instruction from issue's queue.
- DynInst *inst = fromIssue->insts[inst_num];
+ DynInstPtr inst = fromIssue->insts[inst_num];
DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
- inst->setExecuted();
-
// Check if the instruction is squashed; if so then skip it
// and don't count it towards the FU usage.
if (inst->isSquashed()) {
DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
+
+ // Consider this instruction executed so that commit can go
+ // ahead and retire the instruction.
+ inst->setExecuted();
+
+ toCommit->insts[inst_num] = inst;
+
continue;
}
+ inst->setExecuted();
+
// If an instruction is executed, then count it towards FU usage.
++fu_usage;
// Execute instruction.
// Note that if the instruction faults, it will be handled
// at the commit stage.
- inst->execute();
+ if (inst->isMemRef()) {
+ DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
+ "reference.\n");
+
+ // Tell the LDSTQ to execute this instruction (if it is a load).
+ if (inst->isLoad()) {
+ ldstQueue.executeLoad(inst);
+ } else if (inst->isStore()) {
+ ldstQueue.executeStore();
+ } else {
+ panic("IEW: Unexpected memory type!\n");
+ }
+
+ } else {
+ inst->execute();
+ }
// First check the time slot that this instruction will write
// to. If there are free write ports at the time, then go ahead
@@ -401,16 +453,34 @@ SimpleIEW<Impl, IQ>::iew()
// Check if branch was correct. This check happens after the
// instruction is added to the queue because even if the branch
// is mispredicted, the branch instruction itself is still valid.
- if (inst->mispredicted()) {
- DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
- DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextPC);
+ // Only handle this if there hasn't already been something that
+ // redirects fetch in this group of instructions.
+ if (!fetch_redirect) {
+ if (inst->mispredicted()) {
+ fetch_redirect = true;
+
+ DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
+ DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
+ inst->nextPC);
+
+ // If incorrect, then signal the ROB that it must be squashed.
+ squash(inst);
+ } else if (ldstQueue.violation()) {
+ fetch_redirect = true;
+
+ DynInstPtr violator = ldstQueue.getMemDepViolator();
- // If incorrect, then signal the ROB that it must be squashed.
- squash(inst);
+ DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: "
+ "%#x, inst PC: %#x. Addr is: %#x.\n",
+ violator->readPC(), inst->readPC(), inst->physEffAddr);
- // Not sure it really needs to break.
-// break;
+ instQueue.violation(inst, violator);
+
+ squash(inst);
+ // Otherwise check if there was a memory ordering violation.
+ // If there was, then signal ROB that it must be squashed. Also
+ // signal IQ that there was a violation.
+ }
}
}
@@ -422,18 +492,20 @@ SimpleIEW<Impl, IQ>::iew()
// Either have IEW have direct access to rename map, or have this as
// part of backwards communication.
for (int inst_num = 0; inst_num < executeWidth &&
- toCommit->insts[inst_num] != NULL; inst_num++)
+ toCommit->insts[inst_num]; inst_num++)
{
- DynInst *inst = toCommit->insts[inst_num];
+ DynInstPtr inst = toCommit->insts[inst_num];
DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
inst->readPC());
- instQueue.wakeDependents(inst);
+ if(!inst->isSquashed()) {
+ instQueue.wakeDependents(inst);
- for (int i = 0; i < inst->numDestRegs(); i++)
- {
- renameMap->markAsReady(inst->renamedDestRegIdx(i));
+ for (int i = 0; i < inst->numDestRegs(); i++)
+ {
+ renameMap->markAsReady(inst->renamedDestRegIdx(i));
+ }
}
}