summaryrefslogtreecommitdiff
path: root/src/cpu/inorder/resources
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/cpu/inorder/resources
parent061b369d288ba4e3fdb145c025fb4d80378cb851 (diff)
downloadgem5-7dea79535c87b68b5fc6143190d09b8fc364f2aa.tar.xz
inorder: implement trap handling
Diffstat (limited to 'src/cpu/inorder/resources')
-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
8 files changed, 101 insertions, 59 deletions
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,