summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2011-06-19 21:43:36 -0400
committerKorey Sewell <ksewell@umich.edu>2011-06-19 21:43:36 -0400
commit7dea79535c87b68b5fc6143190d09b8fc364f2aa (patch)
tree3f30f0716de709f86b9adaa746f0b3e312203cef /src
parent061b369d288ba4e3fdb145c025fb4d80378cb851 (diff)
downloadgem5-7dea79535c87b68b5fc6143190d09b8fc364f2aa.tar.xz
inorder: implement trap handling
Diffstat (limited to 'src')
-rw-r--r--src/cpu/inorder/cpu.cc23
-rw-r--r--src/cpu/inorder/cpu.hh35
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.cc17
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.hh4
-rw-r--r--src/cpu/inorder/pipeline_stage.cc41
-rw-r--r--src/cpu/inorder/pipeline_stage.hh14
-rw-r--r--src/cpu/inorder/resource.cc4
-rw-r--r--src/cpu/inorder/resource.hh3
-rw-r--r--src/cpu/inorder/resource_pool.9stage.cc6
-rw-r--r--src/cpu/inorder/resource_pool.cc20
-rw-r--r--src/cpu/inorder/resource_pool.hh3
-rw-r--r--src/cpu/inorder/resources/agen_unit.cc4
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc10
-rw-r--r--src/cpu/inorder/resources/execution_unit.cc8
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.cc109
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.hh11
-rw-r--r--src/cpu/inorder/resources/fetch_unit.cc7
-rw-r--r--src/cpu/inorder/resources/fetch_unit.hh2
-rw-r--r--src/cpu/inorder/resources/graduation_unit.cc9
19 files changed, 198 insertions, 132 deletions
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index 2e3b0188b..e0e4d9a15 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -142,7 +142,8 @@ InOrderCPU::CPUEvent::process()
case Trap:
DPRINTF(InOrderCPU, "Trapping CPU\n");
- cpu->trapCPU(fault, tid, inst);
+ cpu->trap(fault, tid, inst);
+ cpu->resPool->trap(fault, tid, inst);
break;
default:
@@ -451,8 +452,8 @@ InOrderCPU::createBackEndSked(DynInstPtr inst)
if (inst->splitInst)
M.needs(DCache, CacheUnit::InitSecondSplitRead);
} else if ( inst->isStore() ) {
- if ( inst->numSrcRegs() >= 2 ) {
- M.needs(RegManager, UseDefUnit::ReadSrcReg, 1);
+ for (int i = 1; i < inst->numSrcRegs(); i++ ) {
+ M.needs(RegManager, UseDefUnit::ReadSrcReg, i);
}
M.needs(AGEN, AGENUnit::GenerateAddr);
M.needs(DCache, CacheUnit::InitiateWriteData);
@@ -795,14 +796,13 @@ InOrderCPU::updateMemPorts()
#endif
void
-InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
+InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
{
- //@ Squash Pipeline during TRAP
scheduleCpuEvent(Trap, fault, tid, inst, delay);
}
void
-InOrderCPU::trapCPU(Fault fault, ThreadID tid, DynInstPtr inst)
+InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst)
{
fault->invoke(tcBase(tid), inst->staticInst);
}
@@ -1302,11 +1302,18 @@ InOrderCPU::updateContextSwitchStats()
void
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
{
- // Set the CPU's PCs - This contributes to the precise state of the CPU
+ // Set the nextPC to be fetched if this is the last instruction
+ // committed
+ // ========
+ // This contributes to the precise state of the CPU
// which can be used when restoring a thread to the CPU after after any
// type of context switching activity (fork, exception, etc.)
- pcState(inst->pcState(), tid);
+ TheISA::PCState comm_pc = inst->pcState();
+ lastCommittedPC[tid] = comm_pc;
+ TheISA::advancePC(comm_pc, inst->staticInst);
+ pcState(comm_pc, tid);
+ //@todo: may be unnecessary with new-ISA-specific branch handling code
if (inst->isControl()) {
thread[tid]->lastGradIsBranch = true;
thread[tid]->lastBranchPC = inst->pcState();
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
index aad701ff4..f60258c96 100644
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -275,6 +275,9 @@ class InOrderCPU : public BaseCPU
/** Program Counters */
TheISA::PCState pc[ThePipeline::MaxThreads];
+ /** Last Committed PC */
+ TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
+
/** The Register File for the CPU */
union {
FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
@@ -430,33 +433,45 @@ class InOrderCPU : public BaseCPU
bool validDataAddr(Addr addr) { return true; }
#endif
- /** trap() - sets up a trap event on the cpuTraps to handle given fault.
- * trapCPU() - Traps to handle given fault
- */
- void trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
- void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst);
+ /** Schedule a trap on the CPU */
+ void trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
- /** Add Thread to Active Threads List. */
+ /** Perform trap to Handle Given Fault */
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
+ /** Schedule thread activation on the CPU */
void activateContext(ThreadID tid, int delay = 0);
+
+ /** Add Thread to Active Threads List. */
void activateThread(ThreadID tid);
+
+ /** Activate Thread In Each Pipeline Stage */
void activateThreadInPipeline(ThreadID tid);
- /** Add Thread to Active Threads List. */
+ /** Schedule Thread Activation from Ready List */
void activateNextReadyContext(int delay = 0);
+
+ /** Add Thread From Ready List to Active Threads List. */
void activateNextReadyThread();
- /** Remove from Active Thread List */
+ /** Schedule a thread deactivation on the CPU */
void deactivateContext(ThreadID tid, int delay = 0);
+
+ /** Remove from Active Thread List */
void deactivateThread(ThreadID tid);
- /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
+ /** Schedule a thread suspension on the CPU */
void suspendContext(ThreadID tid, int delay = 0);
+
+ /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
void suspendThread(ThreadID tid);
+ /** Schedule a thread halt on the CPU */
+ void haltContext(ThreadID tid, int delay = 0);
+
/** Halt Thread, Remove from Active Thread List, Place Thread on Halted
* Threads List
*/
- void haltContext(ThreadID tid, int delay = 0);
void haltThread(ThreadID tid);
/** squashFromMemStall() - sets up a squash event
diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc
index d8bfbacc7..d42e84016 100644
--- a/src/cpu/inorder/inorder_dyn_inst.cc
+++ b/src/cpu/inorder/inorder_dyn_inst.cc
@@ -54,7 +54,7 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
InstSeqNum seq_num,
ThreadID tid,
unsigned _asid)
- : seqNum(seq_num), bdelaySeqNum(0), threadNumber(tid), asid(_asid),
+ : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid),
virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
thread(state), fault(NoFault), memData(NULL), loadData(0),
storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
@@ -319,7 +319,15 @@ void
InOrderDynInst::setSquashInfo(unsigned stage_num)
{
squashingStage = stage_num;
- bdelaySeqNum = seqNum;
+
+ // If it's a fault, then we need to squash
+ // the faulting instruction too. Squash
+ // functions squash above a seqNum, so we
+ // decrement here for that case
+ if (fault != NoFault)
+ squashSeqNum = seqNum - 1;
+ else
+ squashSeqNum = seqNum;
#if ISA_HAS_DELAY_SLOT
if (isControl()) {
@@ -329,10 +337,9 @@ InOrderDynInst::setSquashInfo(unsigned stage_num)
// Check to see if we should squash after the
// branch or after a branch delay slot.
if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
- bdelaySeqNum = seqNum + 1;
+ squashSeqNum = seqNum + 1;
else
- bdelaySeqNum = seqNum;
-
+ squashSeqNum = seqNum;
}
#endif
}
diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh
index 73e723312..0776dc5aa 100644
--- a/src/cpu/inorder/inorder_dyn_inst.hh
+++ b/src/cpu/inorder/inorder_dyn_inst.hh
@@ -122,8 +122,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
/** The sequence number of the instruction. */
InstSeqNum seqNum;
- /** The sequence number of the instruction. */
- InstSeqNum bdelaySeqNum;
+ /** If this instruction is squashing, the number should we squash behind. */
+ InstSeqNum squashSeqNum;
enum Status {
RegDepMapEntry, /// Instruction is entered onto the RegDepMap
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index 51e16b6c4..d37779ce8 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -342,43 +342,27 @@ PipelineStage::unblock(ThreadID tid)
}
void
-PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
+PipelineStage::setupSquash(DynInstPtr inst, ThreadID tid)
{
- if (cpu->squashSeqNum[tid] < inst->seqNum &&
- cpu->lastSquashCycle[tid] == curTick()){
+ if (cpu->lastSquashCycle[tid] == curTick() &&
+ cpu->squashSeqNum[tid] < inst->seqNum){
DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to "
"another stage's squash signal for after [sn:%i].\n",
inst->seqNum, cpu->squashSeqNum[tid]);
} else {
- // Send back mispredict information.
- toPrevStages->stageInfo[stageNum][tid].branchMispredict = true;
- toPrevStages->stageInfo[stageNum][tid].predIncorrect = true;
- toPrevStages->stageInfo[stageNum][tid].doneSeqNum = inst->seqNum;
- toPrevStages->stageInfo[stageNum][tid].squash = true;
- toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg();
-
- toPrevStages->stageInfo[stageNum][tid].branchTaken =
- inst->pcState().branching();
-
-#if ISA_HAS_DELAY_SLOT
- toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
- inst->bdelaySeqNum;
+ InstSeqNum squash_seq_num = inst->squashSeqNum;
- InstSeqNum squash_seq_num = inst->bdelaySeqNum;
-#else
- toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
- InstSeqNum squash_seq_num = inst->seqNum;
-#endif
+ toPrevStages->stageInfo[stageNum][tid].squash = true;
+ toPrevStages->stageInfo[stageNum][tid].doneSeqNum =
+ squash_seq_num;
- DPRINTF(InOrderStage, "Target being re-set to %08p\n",
- inst->predInstAddr());
DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
- "due to [sn:%i] branch.\n", tid, squash_seq_num,
- inst->seqNum);
+ "due to [sn:%i] %s.\n", tid, squash_seq_num,
+ inst->seqNum, inst->instName());
// Save squash num for later stage use
- cpu->squashSeqNum[tid] = squash_seq_num;
cpu->lastSquashCycle[tid] = curTick();
+ cpu->squashSeqNum[tid] = squash_seq_num;
}
}
@@ -398,7 +382,6 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
for (int i=0; i < insts_from_prev_stage; i++) {
if (prevStage->insts[i]->threadNumber == tid &&
prevStage->insts[i]->seqNum > squash_seq_num) {
- // Change Comment to Annulling previous instruction
DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
"[sn:%i] PC %s.\n",
tid,
@@ -676,7 +659,7 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to "
"squash from stage %u.\n", tid, stage_idx);
InstSeqNum squash_seq_num = fromNextStages->
- stageInfo[stage_idx][tid].bdelayDoneSeqNum;
+ stageInfo[stage_idx][tid].doneSeqNum;
squash(squash_seq_num, tid);
break; //return true;
}
@@ -989,7 +972,7 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
// Remove Thread From Pipeline & Resource Pool
inst->squashingStage = stageNum;
- inst->bdelaySeqNum = inst->seqNum;
+ inst->squashSeqNum = inst->seqNum;
cpu->squashFromMemStall(inst, tid);
// Switch On Cache Miss
diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh
index d0d9112c0..963d96afb 100644
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -227,21 +227,17 @@ class PipelineStage
public:
void activateThread(ThreadID tid);
- /** Squashes if there is a PC-relative branch that was predicted
- * incorrectly. Sends squash information back to fetch.
- */
- void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
+ /** Setup Squashing Information to be passed back thru the pipeline */
+ void setupSquash(DynInstPtr inst, ThreadID tid);
virtual void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
+ /** Perform squash of instructions above seq_num */
+ virtual void squash(InstSeqNum squash_num, ThreadID tid);
+
/** Squash instructions from stage buffer */
void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
- /** Squashes due to commit signalling a squash. Changes status to
- * squashing and clears block/unblock signals as needed.
- */
- virtual void squash(InstSeqNum squash_num, ThreadID tid);
-
void dumpInsts();
protected:
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
index 23d33afbe..836335510 100644
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -290,10 +290,8 @@ Resource::deactivateThread(ThreadID tid)
void
Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
{
- assert(inst->isControl() && "Function Assumes Squash From A Branch");
-
// Squash In Pipeline Stage
- cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid);
+ cpu->pipelineStage[stage_num]->setupSquash(inst, tid);
// Schedule Squash Through-out Resource Pool
cpu->resPool->scheduleEvent(
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
index 097497362..fcf01065a 100644
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -106,6 +106,9 @@ class Resource {
*/
virtual void instGraduated(InstSeqNum seq_num, ThreadID tid) { }
+ /** Post-processsing for Trap Generated from this instruction */
+ virtual void trap(Fault fault, ThreadID tid, DynInstPtr inst) { }
+
/** Request usage of this resource. Returns a ResourceRequest object
* with all the necessary resource information
*/
diff --git a/src/cpu/inorder/resource_pool.9stage.cc b/src/cpu/inorder/resource_pool.9stage.cc
index 78a7d4b88..e0a00ee0f 100644
--- a/src/cpu/inorder/resource_pool.9stage.cc
+++ b/src/cpu/inorder/resource_pool.9stage.cc
@@ -192,7 +192,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
res_pool_event->setEvent(e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
inst->readTid());
res_pool_event->schedule(curTick() + cpu->cycles(delay));
@@ -208,7 +208,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
res_pool_event->setEvent(e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
tid);
res_pool_event->schedule(curTick() + cpu->cycles(delay));
@@ -238,7 +238,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
res_pool_event->setEvent(e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
inst->readTid());
res_pool_event->schedule(curTick() + cpu->cycles(delay));
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index 1800aac37..d5b3a5115 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -234,6 +234,18 @@ ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
tid);
}
+void
+ResourcePool::trap(Fault fault, ThreadID tid, DynInstPtr inst)
+{
+ DPRINTF(Resource, "[tid:%i] Broadcasting Trap to all "
+ "resources.\n", tid);
+
+ int num_resources = resources.size();
+
+ for (int idx = 0; idx < num_resources; idx++)
+ resources[idx]->trap(fault, tid, inst);
+}
+
int
ResourcePool::slotsAvail(int res_idx)
{
@@ -272,7 +284,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
inst->readTid());
cpu->schedule(res_pool_event, when);
}
@@ -289,7 +301,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
tid);
cpu->schedule(res_pool_event, when);
@@ -308,7 +320,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
tid);
cpu->schedule(res_pool_event, sked_tick);
@@ -337,7 +349,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
new ResPoolEvent(this,e_type,
inst,
inst->squashingStage,
- inst->bdelaySeqNum,
+ inst->squashSeqNum,
inst->readTid());
cpu->schedule(res_pool_event, when);
}
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
index b42011091..85c0f70f6 100644
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -182,6 +182,9 @@ class ResourcePool {
/** Broadcast graduation to all resources */
void instGraduated(InstSeqNum seq_num, ThreadID tid);
+ /** Broadcast trap to all resources */
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
/** The number of instructions available that a resource can
* can still process.
*/
diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc
index d87ca364d..64f6d7544 100644
--- a/src/cpu/inorder/resources/agen_unit.cc
+++ b/src/cpu/inorder/resources/agen_unit.cc
@@ -78,8 +78,8 @@ AGENUnit::execute(int slot_num)
if (inst->fault == NoFault) {
agen_req->done();
} else {
- fatal("%s encountered while calculating address [sn:%i]",
- inst->fault->name(), seq_num);
+ fatal("%s encountered while calculating address [sn:%i] %s",
+ inst->fault->name(), seq_num, inst->instName());
}
agens++;
diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc
index c1a3590be..760fdb134 100644
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -441,9 +441,10 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
cache_req->tlbStall = true;
+ // schedule a time to process the tlb miss.
+ // latency hardcoded to 1 (for now), but will be updated
+ // when timing translation gets added in
scheduleEvent(slot_idx, 1);
-
- cpu->trap(inst->fault, tid, inst);
} else {
DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
"to phys. addr:%08p.\n", tid, inst->seqNum,
@@ -1072,6 +1073,11 @@ CacheUnitEvent::process()
CacheUnit* tlb_res = dynamic_cast<CacheUnit*>(resource);
assert(tlb_res);
+ //@todo: eventually, we should do a timing translation w/
+ // hw page table walk on tlb miss
+ DPRINTF(Fault, "Handling Fault %s\n", inst->fault->name());
+ inst->fault->invoke(tlb_res->cpu->tcBase(tid), inst->staticInst);
+
tlb_res->tlbBlocked[tid] = false;
tlb_res->cpu->pipelineStage[stage_num]->
diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc
index 4363f125d..d7151add1 100644
--- a/src/cpu/inorder/resources/execution_unit.cc
+++ b/src/cpu/inorder/resources/execution_unit.cc
@@ -140,9 +140,10 @@ ExecutionUnit::execute(int slot_num)
// Evaluate Branch
fault = inst->execute();
executions++;
- inst->setExecuted();
if (fault == NoFault) {
+ inst->setExecuted();
+
if (inst->mispredicted()) {
assert(inst->isControl());
@@ -190,7 +191,8 @@ ExecutionUnit::execute(int slot_num)
exec_req->done();
} else {
- warn("inst [sn:%i] had a %s fault", seq_num, fault->name());
+ DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n",
+ inst->readTid(), inst->seqNum, fault->name());
inst->fault = fault;
exec_req->done();
}
@@ -210,6 +212,8 @@ ExecutionUnit::execute(int slot_num)
} else {
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
"fault.\n", inst->readTid(), seq_num, fault->name());
+ DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n",
+ inst->readTid(), inst->seqNum, fault->name());
inst->fault = fault;
}
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc
index 62dbb452a..024f38fdd 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc
@@ -127,7 +127,7 @@ FetchSeqUnit::execute(int slot_num)
DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
"start from stage %i, after [sn:%i].\n",
- tid, stage_num, inst->bdelaySeqNum);
+ tid, stage_num, inst->squashSeqNum);
}
} else {
DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Ignoring branch "
@@ -152,8 +152,8 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
"stage %i.\n", tid, inst->instName(), inst->pcState(),
squash_stage);
- if (squashSeqNum[tid] <= squash_seq_num &&
- lastSquashCycle[tid] == curTick()) {
+ if (lastSquashCycle[tid] == curTick() &&
+ squashSeqNum[tid] <= squash_seq_num) {
DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, "
"since there is an outstanding squash that is older.\n",
tid, squash_stage);
@@ -161,57 +161,65 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
squashSeqNum[tid] = squash_seq_num;
lastSquashCycle[tid] = curTick();
- TheISA::PCState nextPC;
- assert(inst->staticInst);
- if (inst->isControl()) {
- nextPC = inst->readPredTarg();
-
- // If we are already fetching this PC then advance to next PC
- // =======
- // This should handle ISAs w/delay slots and annulled delay
- // slots to figure out which is the next PC to fetch after
- // a mispredict
- DynInstPtr bdelay_inst = NULL;
- ListIt bdelay_it;
- if (inst->onInstList) {
- bdelay_it = inst->getInstListIt();
- bdelay_it++;
- } else {
- InstSeqNum branch_delay_num = inst->seqNum + 1;
- bdelay_it = cpu->findInst(branch_delay_num, tid);
- }
+ if (inst->fault != NoFault) {
+ // A Trap Caused This Fault and will update the pc state
+ // when done trapping
+ DPRINTF(InOrderFetchSeq, "[tid:%i] Blocking due to fault @ "
+ "[sn:%i].\n", inst->seqNum);
+ pcValid[tid] = false;
+ } else {
+ TheISA::PCState nextPC;
+ assert(inst->staticInst);
+ if (inst->isControl()) {
+ nextPC = inst->readPredTarg();
+
+ // If we are already fetching this PC then advance to next PC
+ // =======
+ // This should handle ISAs w/delay slots and annulled delay
+ // slots to figure out which is the next PC to fetch after
+ // a mispredict
+ DynInstPtr bdelay_inst = NULL;
+ ListIt bdelay_it;
+ if (inst->onInstList) {
+ bdelay_it = inst->getInstListIt();
+ bdelay_it++;
+ } else {
+ InstSeqNum branch_delay_num = inst->seqNum + 1;
+ bdelay_it = cpu->findInst(branch_delay_num, tid);
+ }
- if (bdelay_it != cpu->instList[tid].end()) {
- bdelay_inst = (*bdelay_it);
- }
+ if (bdelay_it != cpu->instList[tid].end()) {
+ bdelay_inst = (*bdelay_it);
+ }
- if (bdelay_inst) {
- DPRINTF(Resource, "Evaluating %s v. %s\n",
- bdelay_inst->pc, nextPC);
+ if (bdelay_inst) {
+ DPRINTF(Resource, "Evaluating %s v. %s\n",
+ bdelay_inst->pc, nextPC);
- if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) {
- advancePC(nextPC, inst->staticInst);
- DPRINTF(Resource, "Advanced PC to %s\n", nextPC);
+ if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) {
+ advancePC(nextPC, inst->staticInst);
+ DPRINTF(Resource, "Advanced PC to %s\n", nextPC);
+ }
}
+ } else {
+ nextPC = inst->pcState();
+ advancePC(nextPC, inst->staticInst);
}
- } else {
- nextPC = inst->pcState();
- advancePC(nextPC, inst->staticInst);
- }
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
- tid, nextPC);
- pc[tid] = nextPC;
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
+ tid, nextPC);
+ pc[tid] = nextPC;
- // Unblock Any Stages Waiting for this information to be updated ...
- if (!pcValid[tid]) {
- cpu->pipelineStage[pcBlockStage[tid]]->
- toPrevStages->stageUnblock[pcBlockStage[tid]][tid] = true;
- }
+ // Unblock Any Stages Waiting for this information to be updated ...
+ if (!pcValid[tid]) {
+ cpu->pipelineStage[pcBlockStage[tid]]->
+ toPrevStages->stageUnblock[pcBlockStage[tid]][tid] = true;
+ }
- pcValid[tid] = true;
- }
+ pcValid[tid] = true;
+ }
+ }
Resource::squash(inst, squash_stage, squash_seq_num, tid);
}
@@ -273,6 +281,17 @@ FetchSeqUnit::suspendThread(ThreadID tid)
}
void
+FetchSeqUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
+{
+ pcValid[tid] = true;
+ pc[tid] = cpu->pcState(tid);
+ DPRINTF(Fault, "[tid:%i]: Trap updating to PC: "
+ "%s.\n", tid, pc[tid]);
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: "
+ "%s.\n", tid, pc[tid]);
+}
+
+void
FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
{
pcValid[tid] = true;
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh
index 7c57fa17b..1cd0047e2 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.hh
+++ b/src/cpu/inorder/resources/fetch_seq_unit.hh
@@ -65,15 +65,12 @@ class FetchSeqUnit : public Resource {
void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
- /** Override default Resource squash sequence. This actually,
- * looks in the global communication buffer to get squash
- * info
- */
+ /** Update to correct PC from a squash */
void squash(DynInstPtr inst, int squash_stage,
- InstSeqNum squash_seq_num, ThreadID tid);
+ InstSeqNum squash_seq_num, ThreadID tid);
-
- inline void squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid);
+ /** Update to correct PC from a trap */
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
protected:
unsigned instSize;
diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc
index 692f78c7b..60452bacd 100644
--- a/src/cpu/inorder/resources/fetch_unit.cc
+++ b/src/cpu/inorder/resources/fetch_unit.cc
@@ -111,6 +111,7 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
predecoder.setTC(cpu->thread[tid]->getTC());
predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
+ assert(predecoder.extMachInstReady());
ext_inst = predecoder.getExtMachInst(instPC);
inst->pcState(instPC);
@@ -552,3 +553,9 @@ FetchUnit::squashCacheRequest(CacheReqPtr req_ptr)
CacheUnit::squashCacheRequest(req_ptr);
}
+void
+FetchUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
+{
+ //@todo: per thread?
+ predecoder.reset();
+}
diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh
index 3075e726d..d6e36419a 100644
--- a/src/cpu/inorder/resources/fetch_unit.hh
+++ b/src/cpu/inorder/resources/fetch_unit.hh
@@ -88,6 +88,8 @@ class FetchUnit : public CacheUnit
/** Executes one of the commands from the "Command" enum */
void execute(int slot_num);
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
private:
void squashCacheRequest(CacheReqPtr req_ptr);
diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc
index 826ed8e03..9c17db945 100644
--- a/src/cpu/inorder/resources/graduation_unit.cc
+++ b/src/cpu/inorder/resources/graduation_unit.cc
@@ -67,7 +67,14 @@ GraduationUnit::execute(int slot_num)
// Handle Any Faults Before Graduating Instruction
if (inst->fault != NoFault) {
- cpu->trap(inst->fault, tid, inst);
+ DPRINTF(Fault, "[sn:%i]: fault %s found for %s\n",
+ inst->seqNum, inst->fault->name(),
+ inst->instName());
+ inst->setSquashInfo(stage_num);
+ setupSquash(inst, stage_num, tid);
+ cpu->trapContext(inst->fault, tid, inst);
+ grad_req->done(false);
+ return;
}
DPRINTF(InOrderGraduation,