inorder: implement trap handling

This commit is contained in:
Korey Sewell 2011-06-19 21:43:36 -04:00
parent 061b369d28
commit 7dea79535c
19 changed files with 205 additions and 139 deletions

View file

@ -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();

View file

@ -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);
/** 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 activateContext(ThreadID tid, int delay = 0);
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

View file

@ -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
}

View file

@ -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

View file

@ -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;
InstSeqNum squash_seq_num = inst->squashSeqNum;
toPrevStages->stageInfo[stageNum][tid].squash = true;
toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg();
toPrevStages->stageInfo[stageNum][tid].doneSeqNum =
squash_seq_num;
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->bdelaySeqNum;
#else
toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
InstSeqNum squash_seq_num = inst->seqNum;
#endif
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

View file

@ -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:

View file

@ -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(

View file

@ -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
*/

View file

@ -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));

View file

@ -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);
}

View file

@ -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.
*/

View file

@ -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++;

View file

@ -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]->

View file

@ -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;
}

View file

@ -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 (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->pc.instAddr() == nextPC.instAddr()) {
advancePC(nextPC, inst->staticInst);
DPRINTF(Resource, "Advanced PC to %s\n", nextPC);
}
}
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 {
nextPC = inst->pcState();
advancePC(nextPC, inst->staticInst);
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_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);
}
}
} else {
nextPC = inst->pcState();
advancePC(nextPC, inst->staticInst);
}
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;
}
pcValid[tid] = true;
}
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;
}
pcValid[tid] = true;
}
}
Resource::squash(inst, squash_stage, squash_seq_num, tid);
}
@ -272,6 +280,17 @@ FetchSeqUnit::suspendThread(ThreadID tid)
deactivateThread(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)
{

View file

@ -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;

View file

@ -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();
}

View file

@ -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);

View file

@ -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,