inorder: implement trap handling
This commit is contained in:
parent
061b369d28
commit
7dea79535c
19 changed files with 205 additions and 139 deletions
|
@ -142,7 +142,8 @@ InOrderCPU::CPUEvent::process()
|
||||||
|
|
||||||
case Trap:
|
case Trap:
|
||||||
DPRINTF(InOrderCPU, "Trapping CPU\n");
|
DPRINTF(InOrderCPU, "Trapping CPU\n");
|
||||||
cpu->trapCPU(fault, tid, inst);
|
cpu->trap(fault, tid, inst);
|
||||||
|
cpu->resPool->trap(fault, tid, inst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -451,8 +452,8 @@ InOrderCPU::createBackEndSked(DynInstPtr inst)
|
||||||
if (inst->splitInst)
|
if (inst->splitInst)
|
||||||
M.needs(DCache, CacheUnit::InitSecondSplitRead);
|
M.needs(DCache, CacheUnit::InitSecondSplitRead);
|
||||||
} else if ( inst->isStore() ) {
|
} else if ( inst->isStore() ) {
|
||||||
if ( inst->numSrcRegs() >= 2 ) {
|
for (int i = 1; i < inst->numSrcRegs(); i++ ) {
|
||||||
M.needs(RegManager, UseDefUnit::ReadSrcReg, 1);
|
M.needs(RegManager, UseDefUnit::ReadSrcReg, i);
|
||||||
}
|
}
|
||||||
M.needs(AGEN, AGENUnit::GenerateAddr);
|
M.needs(AGEN, AGENUnit::GenerateAddr);
|
||||||
M.needs(DCache, CacheUnit::InitiateWriteData);
|
M.needs(DCache, CacheUnit::InitiateWriteData);
|
||||||
|
@ -795,14 +796,13 @@ InOrderCPU::updateMemPorts()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
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);
|
scheduleCpuEvent(Trap, fault, tid, inst, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
InOrderCPU::trapCPU(Fault fault, ThreadID tid, DynInstPtr inst)
|
InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst)
|
||||||
{
|
{
|
||||||
fault->invoke(tcBase(tid), inst->staticInst);
|
fault->invoke(tcBase(tid), inst->staticInst);
|
||||||
}
|
}
|
||||||
|
@ -1302,11 +1302,18 @@ InOrderCPU::updateContextSwitchStats()
|
||||||
void
|
void
|
||||||
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
|
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
|
// which can be used when restoring a thread to the CPU after after any
|
||||||
// type of context switching activity (fork, exception, etc.)
|
// 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()) {
|
if (inst->isControl()) {
|
||||||
thread[tid]->lastGradIsBranch = true;
|
thread[tid]->lastGradIsBranch = true;
|
||||||
thread[tid]->lastBranchPC = inst->pcState();
|
thread[tid]->lastBranchPC = inst->pcState();
|
||||||
|
|
|
@ -275,6 +275,9 @@ class InOrderCPU : public BaseCPU
|
||||||
/** Program Counters */
|
/** Program Counters */
|
||||||
TheISA::PCState pc[ThePipeline::MaxThreads];
|
TheISA::PCState pc[ThePipeline::MaxThreads];
|
||||||
|
|
||||||
|
/** Last Committed PC */
|
||||||
|
TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
|
||||||
|
|
||||||
/** The Register File for the CPU */
|
/** The Register File for the CPU */
|
||||||
union {
|
union {
|
||||||
FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
|
FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
|
||||||
|
@ -430,33 +433,45 @@ class InOrderCPU : public BaseCPU
|
||||||
bool validDataAddr(Addr addr) { return true; }
|
bool validDataAddr(Addr addr) { return true; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** trap() - sets up a trap event on the cpuTraps to handle given fault.
|
/** Schedule a trap on the CPU */
|
||||||
* trapCPU() - Traps to handle given fault
|
void trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
|
||||||
*/
|
|
||||||
void trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
|
/** Perform trap to Handle Given Fault */
|
||||||
void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst);
|
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. */
|
/** Add Thread to Active Threads List. */
|
||||||
void activateContext(ThreadID tid, int delay = 0);
|
|
||||||
void activateThread(ThreadID tid);
|
void activateThread(ThreadID tid);
|
||||||
|
|
||||||
|
/** Activate Thread In Each Pipeline Stage */
|
||||||
void activateThreadInPipeline(ThreadID tid);
|
void activateThreadInPipeline(ThreadID tid);
|
||||||
|
|
||||||
/** Add Thread to Active Threads List. */
|
/** Schedule Thread Activation from Ready List */
|
||||||
void activateNextReadyContext(int delay = 0);
|
void activateNextReadyContext(int delay = 0);
|
||||||
|
|
||||||
|
/** Add Thread From Ready List to Active Threads List. */
|
||||||
void activateNextReadyThread();
|
void activateNextReadyThread();
|
||||||
|
|
||||||
/** Remove from Active Thread List */
|
/** Schedule a thread deactivation on the CPU */
|
||||||
void deactivateContext(ThreadID tid, int delay = 0);
|
void deactivateContext(ThreadID tid, int delay = 0);
|
||||||
|
|
||||||
|
/** Remove from Active Thread List */
|
||||||
void deactivateThread(ThreadID tid);
|
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);
|
void suspendContext(ThreadID tid, int delay = 0);
|
||||||
|
|
||||||
|
/** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
|
||||||
void suspendThread(ThreadID tid);
|
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
|
/** Halt Thread, Remove from Active Thread List, Place Thread on Halted
|
||||||
* Threads List
|
* Threads List
|
||||||
*/
|
*/
|
||||||
void haltContext(ThreadID tid, int delay = 0);
|
|
||||||
void haltThread(ThreadID tid);
|
void haltThread(ThreadID tid);
|
||||||
|
|
||||||
/** squashFromMemStall() - sets up a squash event
|
/** squashFromMemStall() - sets up a squash event
|
||||||
|
|
|
@ -54,7 +54,7 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
|
||||||
InstSeqNum seq_num,
|
InstSeqNum seq_num,
|
||||||
ThreadID tid,
|
ThreadID tid,
|
||||||
unsigned _asid)
|
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),
|
virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
|
||||||
thread(state), fault(NoFault), memData(NULL), loadData(0),
|
thread(state), fault(NoFault), memData(NULL), loadData(0),
|
||||||
storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
|
storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
|
||||||
|
@ -319,7 +319,15 @@ void
|
||||||
InOrderDynInst::setSquashInfo(unsigned stage_num)
|
InOrderDynInst::setSquashInfo(unsigned stage_num)
|
||||||
{
|
{
|
||||||
squashingStage = 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 ISA_HAS_DELAY_SLOT
|
||||||
if (isControl()) {
|
if (isControl()) {
|
||||||
|
@ -329,10 +337,9 @@ InOrderDynInst::setSquashInfo(unsigned stage_num)
|
||||||
// Check to see if we should squash after the
|
// Check to see if we should squash after the
|
||||||
// branch or after a branch delay slot.
|
// branch or after a branch delay slot.
|
||||||
if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
|
if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
|
||||||
bdelaySeqNum = seqNum + 1;
|
squashSeqNum = seqNum + 1;
|
||||||
else
|
else
|
||||||
bdelaySeqNum = seqNum;
|
squashSeqNum = seqNum;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,8 +122,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
|
||||||
/** The sequence number of the instruction. */
|
/** The sequence number of the instruction. */
|
||||||
InstSeqNum seqNum;
|
InstSeqNum seqNum;
|
||||||
|
|
||||||
/** The sequence number of the instruction. */
|
/** If this instruction is squashing, the number should we squash behind. */
|
||||||
InstSeqNum bdelaySeqNum;
|
InstSeqNum squashSeqNum;
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
RegDepMapEntry, /// Instruction is entered onto the RegDepMap
|
RegDepMapEntry, /// Instruction is entered onto the RegDepMap
|
||||||
|
|
|
@ -342,43 +342,27 @@ PipelineStage::unblock(ThreadID tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
|
PipelineStage::setupSquash(DynInstPtr inst, ThreadID tid)
|
||||||
{
|
{
|
||||||
if (cpu->squashSeqNum[tid] < inst->seqNum &&
|
if (cpu->lastSquashCycle[tid] == curTick() &&
|
||||||
cpu->lastSquashCycle[tid] == curTick()){
|
cpu->squashSeqNum[tid] < inst->seqNum){
|
||||||
DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to "
|
DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to "
|
||||||
"another stage's squash signal for after [sn:%i].\n",
|
"another stage's squash signal for after [sn:%i].\n",
|
||||||
inst->seqNum, cpu->squashSeqNum[tid]);
|
inst->seqNum, cpu->squashSeqNum[tid]);
|
||||||
} else {
|
} else {
|
||||||
// Send back mispredict information.
|
InstSeqNum squash_seq_num = inst->squashSeqNum;
|
||||||
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].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], "
|
DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
|
||||||
"due to [sn:%i] branch.\n", tid, squash_seq_num,
|
"due to [sn:%i] %s.\n", tid, squash_seq_num,
|
||||||
inst->seqNum);
|
inst->seqNum, inst->instName());
|
||||||
|
|
||||||
// Save squash num for later stage use
|
// Save squash num for later stage use
|
||||||
cpu->squashSeqNum[tid] = squash_seq_num;
|
|
||||||
cpu->lastSquashCycle[tid] = curTick();
|
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++) {
|
for (int i=0; i < insts_from_prev_stage; i++) {
|
||||||
if (prevStage->insts[i]->threadNumber == tid &&
|
if (prevStage->insts[i]->threadNumber == tid &&
|
||||||
prevStage->insts[i]->seqNum > squash_seq_num) {
|
prevStage->insts[i]->seqNum > squash_seq_num) {
|
||||||
// Change Comment to Annulling previous instruction
|
|
||||||
DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
|
DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
|
||||||
"[sn:%i] PC %s.\n",
|
"[sn:%i] PC %s.\n",
|
||||||
tid,
|
tid,
|
||||||
|
@ -676,7 +659,7 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
|
||||||
DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to "
|
DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to "
|
||||||
"squash from stage %u.\n", tid, stage_idx);
|
"squash from stage %u.\n", tid, stage_idx);
|
||||||
InstSeqNum squash_seq_num = fromNextStages->
|
InstSeqNum squash_seq_num = fromNextStages->
|
||||||
stageInfo[stage_idx][tid].bdelayDoneSeqNum;
|
stageInfo[stage_idx][tid].doneSeqNum;
|
||||||
squash(squash_seq_num, tid);
|
squash(squash_seq_num, tid);
|
||||||
break; //return true;
|
break; //return true;
|
||||||
}
|
}
|
||||||
|
@ -989,7 +972,7 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
|
||||||
|
|
||||||
// Remove Thread From Pipeline & Resource Pool
|
// Remove Thread From Pipeline & Resource Pool
|
||||||
inst->squashingStage = stageNum;
|
inst->squashingStage = stageNum;
|
||||||
inst->bdelaySeqNum = inst->seqNum;
|
inst->squashSeqNum = inst->seqNum;
|
||||||
cpu->squashFromMemStall(inst, tid);
|
cpu->squashFromMemStall(inst, tid);
|
||||||
|
|
||||||
// Switch On Cache Miss
|
// Switch On Cache Miss
|
||||||
|
|
|
@ -227,21 +227,17 @@ class PipelineStage
|
||||||
public:
|
public:
|
||||||
void activateThread(ThreadID tid);
|
void activateThread(ThreadID tid);
|
||||||
|
|
||||||
/** Squashes if there is a PC-relative branch that was predicted
|
/** Setup Squashing Information to be passed back thru the pipeline */
|
||||||
* incorrectly. Sends squash information back to fetch.
|
void setupSquash(DynInstPtr inst, ThreadID tid);
|
||||||
*/
|
|
||||||
void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
|
|
||||||
|
|
||||||
virtual void squashDueToMemStall(InstSeqNum seq_num, 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 */
|
/** Squash instructions from stage buffer */
|
||||||
void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
|
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();
|
void dumpInsts();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -290,10 +290,8 @@ Resource::deactivateThread(ThreadID tid)
|
||||||
void
|
void
|
||||||
Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
|
Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
|
||||||
{
|
{
|
||||||
assert(inst->isControl() && "Function Assumes Squash From A Branch");
|
|
||||||
|
|
||||||
// Squash In Pipeline Stage
|
// Squash In Pipeline Stage
|
||||||
cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid);
|
cpu->pipelineStage[stage_num]->setupSquash(inst, tid);
|
||||||
|
|
||||||
// Schedule Squash Through-out Resource Pool
|
// Schedule Squash Through-out Resource Pool
|
||||||
cpu->resPool->scheduleEvent(
|
cpu->resPool->scheduleEvent(
|
||||||
|
|
|
@ -106,6 +106,9 @@ class Resource {
|
||||||
*/
|
*/
|
||||||
virtual void instGraduated(InstSeqNum seq_num, ThreadID tid) { }
|
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
|
/** Request usage of this resource. Returns a ResourceRequest object
|
||||||
* with all the necessary resource information
|
* with all the necessary resource information
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -192,7 +192,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
res_pool_event->setEvent(e_type,
|
res_pool_event->setEvent(e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
inst->readTid());
|
inst->readTid());
|
||||||
res_pool_event->schedule(curTick() + cpu->cycles(delay));
|
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,
|
res_pool_event->setEvent(e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
tid);
|
tid);
|
||||||
|
|
||||||
res_pool_event->schedule(curTick() + cpu->cycles(delay));
|
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,
|
res_pool_event->setEvent(e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
inst->readTid());
|
inst->readTid());
|
||||||
res_pool_event->schedule(curTick() + cpu->cycles(delay));
|
res_pool_event->schedule(curTick() + cpu->cycles(delay));
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,18 @@ ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
|
||||||
tid);
|
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
|
int
|
||||||
ResourcePool::slotsAvail(int res_idx)
|
ResourcePool::slotsAvail(int res_idx)
|
||||||
{
|
{
|
||||||
|
@ -272,7 +284,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
e_type,
|
e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
inst->readTid());
|
inst->readTid());
|
||||||
cpu->schedule(res_pool_event, when);
|
cpu->schedule(res_pool_event, when);
|
||||||
}
|
}
|
||||||
|
@ -289,7 +301,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
e_type,
|
e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
tid);
|
tid);
|
||||||
|
|
||||||
cpu->schedule(res_pool_event, when);
|
cpu->schedule(res_pool_event, when);
|
||||||
|
@ -308,7 +320,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
e_type,
|
e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
tid);
|
tid);
|
||||||
|
|
||||||
cpu->schedule(res_pool_event, sked_tick);
|
cpu->schedule(res_pool_event, sked_tick);
|
||||||
|
@ -337,7 +349,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
new ResPoolEvent(this,e_type,
|
new ResPoolEvent(this,e_type,
|
||||||
inst,
|
inst,
|
||||||
inst->squashingStage,
|
inst->squashingStage,
|
||||||
inst->bdelaySeqNum,
|
inst->squashSeqNum,
|
||||||
inst->readTid());
|
inst->readTid());
|
||||||
cpu->schedule(res_pool_event, when);
|
cpu->schedule(res_pool_event, when);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,6 +182,9 @@ class ResourcePool {
|
||||||
/** Broadcast graduation to all resources */
|
/** Broadcast graduation to all resources */
|
||||||
void instGraduated(InstSeqNum seq_num, ThreadID tid);
|
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
|
/** The number of instructions available that a resource can
|
||||||
* can still process.
|
* can still process.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -78,8 +78,8 @@ AGENUnit::execute(int slot_num)
|
||||||
if (inst->fault == NoFault) {
|
if (inst->fault == NoFault) {
|
||||||
agen_req->done();
|
agen_req->done();
|
||||||
} else {
|
} else {
|
||||||
fatal("%s encountered while calculating address [sn:%i]",
|
fatal("%s encountered while calculating address [sn:%i] %s",
|
||||||
inst->fault->name(), seq_num);
|
inst->fault->name(), seq_num, inst->instName());
|
||||||
}
|
}
|
||||||
|
|
||||||
agens++;
|
agens++;
|
||||||
|
|
|
@ -441,9 +441,10 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||||
|
|
||||||
cache_req->tlbStall = true;
|
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);
|
scheduleEvent(slot_idx, 1);
|
||||||
|
|
||||||
cpu->trap(inst->fault, tid, inst);
|
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
|
DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
|
||||||
"to phys. addr:%08p.\n", tid, inst->seqNum,
|
"to phys. addr:%08p.\n", tid, inst->seqNum,
|
||||||
|
@ -1072,6 +1073,11 @@ CacheUnitEvent::process()
|
||||||
CacheUnit* tlb_res = dynamic_cast<CacheUnit*>(resource);
|
CacheUnit* tlb_res = dynamic_cast<CacheUnit*>(resource);
|
||||||
assert(tlb_res);
|
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->tlbBlocked[tid] = false;
|
||||||
|
|
||||||
tlb_res->cpu->pipelineStage[stage_num]->
|
tlb_res->cpu->pipelineStage[stage_num]->
|
||||||
|
|
|
@ -140,9 +140,10 @@ ExecutionUnit::execute(int slot_num)
|
||||||
// Evaluate Branch
|
// Evaluate Branch
|
||||||
fault = inst->execute();
|
fault = inst->execute();
|
||||||
executions++;
|
executions++;
|
||||||
inst->setExecuted();
|
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
inst->setExecuted();
|
||||||
|
|
||||||
if (inst->mispredicted()) {
|
if (inst->mispredicted()) {
|
||||||
assert(inst->isControl());
|
assert(inst->isControl());
|
||||||
|
|
||||||
|
@ -190,7 +191,8 @@ ExecutionUnit::execute(int slot_num)
|
||||||
|
|
||||||
exec_req->done();
|
exec_req->done();
|
||||||
} else {
|
} 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;
|
inst->fault = fault;
|
||||||
exec_req->done();
|
exec_req->done();
|
||||||
}
|
}
|
||||||
|
@ -210,6 +212,8 @@ ExecutionUnit::execute(int slot_num)
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
|
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
|
||||||
"fault.\n", inst->readTid(), seq_num, fault->name());
|
"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;
|
inst->fault = fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ FetchSeqUnit::execute(int slot_num)
|
||||||
|
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
|
DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
|
||||||
"start from stage %i, after [sn:%i].\n",
|
"start from stage %i, after [sn:%i].\n",
|
||||||
tid, stage_num, inst->bdelaySeqNum);
|
tid, stage_num, inst->squashSeqNum);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Ignoring branch "
|
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(),
|
"stage %i.\n", tid, inst->instName(), inst->pcState(),
|
||||||
squash_stage);
|
squash_stage);
|
||||||
|
|
||||||
if (squashSeqNum[tid] <= squash_seq_num &&
|
if (lastSquashCycle[tid] == curTick() &&
|
||||||
lastSquashCycle[tid] == curTick()) {
|
squashSeqNum[tid] <= squash_seq_num) {
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, "
|
DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, "
|
||||||
"since there is an outstanding squash that is older.\n",
|
"since there is an outstanding squash that is older.\n",
|
||||||
tid, squash_stage);
|
tid, squash_stage);
|
||||||
|
@ -161,6 +161,13 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
|
||||||
squashSeqNum[tid] = squash_seq_num;
|
squashSeqNum[tid] = squash_seq_num;
|
||||||
lastSquashCycle[tid] = curTick();
|
lastSquashCycle[tid] = curTick();
|
||||||
|
|
||||||
|
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;
|
TheISA::PCState nextPC;
|
||||||
assert(inst->staticInst);
|
assert(inst->staticInst);
|
||||||
if (inst->isControl()) {
|
if (inst->isControl()) {
|
||||||
|
@ -212,6 +219,7 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
|
||||||
|
|
||||||
pcValid[tid] = true;
|
pcValid[tid] = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Resource::squash(inst, squash_stage, squash_seq_num, tid);
|
Resource::squash(inst, squash_stage, squash_seq_num, tid);
|
||||||
}
|
}
|
||||||
|
@ -272,6 +280,17 @@ FetchSeqUnit::suspendThread(ThreadID tid)
|
||||||
deactivateThread(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
|
void
|
||||||
FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
|
FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,15 +65,12 @@ class FetchSeqUnit : public Resource {
|
||||||
void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
|
void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
|
||||||
|
|
||||||
|
|
||||||
/** Override default Resource squash sequence. This actually,
|
/** Update to correct PC from a squash */
|
||||||
* looks in the global communication buffer to get squash
|
|
||||||
* info
|
|
||||||
*/
|
|
||||||
void squash(DynInstPtr inst, int squash_stage,
|
void squash(DynInstPtr inst, int squash_stage,
|
||||||
InstSeqNum squash_seq_num, ThreadID tid);
|
InstSeqNum squash_seq_num, ThreadID tid);
|
||||||
|
|
||||||
|
/** Update to correct PC from a trap */
|
||||||
inline void squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid);
|
void trap(Fault fault, ThreadID tid, DynInstPtr inst);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned instSize;
|
unsigned instSize;
|
||||||
|
|
|
@ -111,6 +111,7 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
|
||||||
|
|
||||||
predecoder.setTC(cpu->thread[tid]->getTC());
|
predecoder.setTC(cpu->thread[tid]->getTC());
|
||||||
predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
|
predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
|
||||||
|
assert(predecoder.extMachInstReady());
|
||||||
ext_inst = predecoder.getExtMachInst(instPC);
|
ext_inst = predecoder.getExtMachInst(instPC);
|
||||||
|
|
||||||
inst->pcState(instPC);
|
inst->pcState(instPC);
|
||||||
|
@ -552,3 +553,9 @@ FetchUnit::squashCacheRequest(CacheReqPtr req_ptr)
|
||||||
CacheUnit::squashCacheRequest(req_ptr);
|
CacheUnit::squashCacheRequest(req_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FetchUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
|
||||||
|
{
|
||||||
|
//@todo: per thread?
|
||||||
|
predecoder.reset();
|
||||||
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ class FetchUnit : public CacheUnit
|
||||||
/** Executes one of the commands from the "Command" enum */
|
/** Executes one of the commands from the "Command" enum */
|
||||||
void execute(int slot_num);
|
void execute(int slot_num);
|
||||||
|
|
||||||
|
void trap(Fault fault, ThreadID tid, DynInstPtr inst);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void squashCacheRequest(CacheReqPtr req_ptr);
|
void squashCacheRequest(CacheReqPtr req_ptr);
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,14 @@ GraduationUnit::execute(int slot_num)
|
||||||
|
|
||||||
// Handle Any Faults Before Graduating Instruction
|
// Handle Any Faults Before Graduating Instruction
|
||||||
if (inst->fault != NoFault) {
|
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,
|
DPRINTF(InOrderGraduation,
|
||||||
|
|
Loading…
Reference in a new issue