inorder: fault handling
Maintain all information about an instruction's fault in the DynInst object rather than any cpu-request object. Also, if there is a fault during the execution stage then just save the fault inside the instruction and trap once the instruction tries to graduate
This commit is contained in:
parent
e57613588b
commit
e396a34b01
14 changed files with 39 additions and 85 deletions
|
@ -944,12 +944,7 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
|
|||
"completed.\n", tid, inst->seqNum,
|
||||
cpu->resPool->name(res_num));
|
||||
|
||||
if (req->fault == NoFault) {
|
||||
inst->popSchedEntry();
|
||||
} else {
|
||||
panic("%i: encountered %s fault!\n",
|
||||
curTick(), req->fault->name());
|
||||
}
|
||||
inst->popSchedEntry();
|
||||
|
||||
reqs_processed++;
|
||||
|
||||
|
|
|
@ -277,7 +277,6 @@ Resource::execute(int slot_idx)
|
|||
DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n",
|
||||
reqMap[slot_idx]->getTid(), name());
|
||||
reqMap[slot_idx]->setCompleted(true);
|
||||
reqMap[slot_idx]->fault = NoFault;
|
||||
reqMap[slot_idx]->done();
|
||||
}
|
||||
|
||||
|
|
|
@ -350,9 +350,6 @@ class ResourceRequest
|
|||
/** Not guaranteed to be set, used for debugging */
|
||||
InstSeqNum seqNum;
|
||||
|
||||
/** Fault Associated With This Resource Request */
|
||||
Fault fault;
|
||||
|
||||
/** Command For This Resource */
|
||||
unsigned cmd;
|
||||
|
||||
|
|
|
@ -52,14 +52,11 @@ AGENUnit::execute(int slot_num)
|
|||
{
|
||||
ResourceRequest* agen_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
#if TRACING_ON
|
||||
ThreadID tid = inst->readTid();
|
||||
#endif
|
||||
int seq_num = inst->seqNum;
|
||||
|
||||
agen_req->fault = NoFault;
|
||||
|
||||
switch (agen_req->cmd)
|
||||
{
|
||||
case GenerateAddr:
|
||||
|
@ -70,18 +67,18 @@ AGENUnit::execute(int slot_num)
|
|||
"[tid:%i] Generating Address for [sn:%i] (%s).\n",
|
||||
tid, seq_num, inst->staticInst->getName());
|
||||
|
||||
fault = inst->calcEA();
|
||||
inst->fault = inst->calcEA();
|
||||
inst->setMemAddr(inst->getEA());
|
||||
|
||||
DPRINTF(InOrderAGEN,
|
||||
"[tid:%i] [sn:%i] Effective address calculated as: %#x\n",
|
||||
tid, seq_num, inst->getEA());
|
||||
|
||||
if (fault == NoFault) {
|
||||
if (inst->fault == NoFault) {
|
||||
agen_req->done();
|
||||
} else {
|
||||
fatal("%s encountered while calculating address [sn:%i]",
|
||||
fault->name(), seq_num);
|
||||
inst->fault->name(), seq_num);
|
||||
}
|
||||
|
||||
agens++;
|
||||
|
|
|
@ -67,13 +67,9 @@ BranchPredictor::execute(int slot_num)
|
|||
// After this is working, change this to a reinterpret cast
|
||||
// for performance considerations
|
||||
ResourceRequest* bpred_req = reqMap[slot_num];
|
||||
|
||||
DynInstPtr inst = bpred_req->inst;
|
||||
ThreadID tid = inst->readTid();
|
||||
int seq_num = inst->seqNum;
|
||||
//int stage_num = bpred_req->getStageNum();
|
||||
|
||||
bpred_req->fault = NoFault;
|
||||
|
||||
switch (bpred_req->cmd)
|
||||
{
|
||||
|
|
|
@ -405,7 +405,7 @@ CacheUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req,
|
|||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
void
|
||||
CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||
int flags, TheISA::TLB::Mode tlb_mode)
|
||||
{
|
||||
|
@ -416,13 +416,13 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
|
||||
setupMemRequest(inst, cache_req, acc_size, flags);
|
||||
|
||||
cache_req->fault =
|
||||
inst->fault =
|
||||
_tlb->translateAtomic(cache_req->memReq,
|
||||
cpu->thread[tid]->getTC(), tlb_mode);
|
||||
|
||||
if (cache_req->fault != NoFault) {
|
||||
if (inst->fault != NoFault) {
|
||||
DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating "
|
||||
"addr:%08p for [sn:%i].\n", tid, cache_req->fault->name(),
|
||||
"addr:%08p for [sn:%i].\n", tid, inst->fault->name(),
|
||||
cache_req->memReq->getVaddr(), inst->seqNum);
|
||||
|
||||
cpu->pipelineStage[stage_num]->setResStall(cache_req, tid);
|
||||
|
@ -433,7 +433,7 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
|
||||
scheduleEvent(slot_idx, 1);
|
||||
|
||||
cpu->trap(cache_req->fault, tid, inst);
|
||||
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,
|
||||
|
@ -441,7 +441,6 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
cache_req->memReq->getPaddr());
|
||||
}
|
||||
|
||||
return cache_req->fault;
|
||||
}
|
||||
|
||||
Fault
|
||||
|
@ -531,7 +530,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr,
|
|||
|
||||
doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Read);
|
||||
|
||||
if (cache_req->fault == NoFault) {
|
||||
if (inst->fault == NoFault) {
|
||||
if (!cache_req->splitAccess) {
|
||||
cache_req->reqData = new uint8_t[size];
|
||||
doCacheAccess(inst, NULL);
|
||||
|
@ -546,7 +545,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr,
|
|||
}
|
||||
}
|
||||
|
||||
return cache_req->fault;
|
||||
return inst->fault;
|
||||
}
|
||||
|
||||
Fault
|
||||
|
@ -638,7 +637,7 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
|
|||
|
||||
doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Write);
|
||||
|
||||
if (cache_req->fault == NoFault) {
|
||||
if (inst->fault == NoFault) {
|
||||
if (!cache_req->splitAccess) {
|
||||
// Remove this line since storeData is saved in INST?
|
||||
cache_req->reqData = new uint8_t[size];
|
||||
|
@ -649,7 +648,7 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
|
|||
|
||||
}
|
||||
|
||||
return cache_req->fault;
|
||||
return inst->fault;
|
||||
}
|
||||
|
||||
|
||||
|
@ -672,7 +671,7 @@ CacheUnit::execute(int slot_num)
|
|||
std::string acc_type = "write";
|
||||
#endif
|
||||
|
||||
cache_req->fault = NoFault;
|
||||
inst->fault = NoFault;
|
||||
|
||||
switch (cache_req->cmd)
|
||||
{
|
||||
|
@ -785,7 +784,7 @@ CacheUnit::execute(int slot_num)
|
|||
}
|
||||
|
||||
// @TODO: Split into doCacheRead() and doCacheWrite()
|
||||
Fault
|
||||
void
|
||||
CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res,
|
||||
CacheReqPtr split_req)
|
||||
{
|
||||
|
@ -883,7 +882,6 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res,
|
|||
cache_req->setCompleted(false);
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -161,13 +161,13 @@ class CacheUnit : public Resource
|
|||
Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
|
||||
Addr addr, unsigned flags, uint64_t *res);
|
||||
|
||||
Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||
void doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||
int flags, TheISA::TLB::Mode tlb_mode);
|
||||
|
||||
/** Read/Write on behalf of an instruction.
|
||||
* curResSlot needs to be a valid value in instruction.
|
||||
*/
|
||||
Fault doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL,
|
||||
void doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL,
|
||||
CacheReqPtr split_req=NULL);
|
||||
|
||||
uint64_t getMemData(Packet *packet);
|
||||
|
|
|
@ -51,11 +51,8 @@ DecodeUnit::execute(int slot_num)
|
|||
{
|
||||
ResourceRequest* decode_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
ThreadID tid = inst->readTid();
|
||||
|
||||
decode_req->fault = NoFault;
|
||||
|
||||
switch (decode_req->cmd)
|
||||
{
|
||||
case DecodeInst:
|
||||
|
|
|
@ -84,14 +84,11 @@ ExecutionUnit::execute(int slot_num)
|
|||
{
|
||||
ResourceRequest* exec_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
ThreadID tid = inst->readTid();
|
||||
Fault fault = NoFault;
|
||||
int seq_num = inst->seqNum;
|
||||
|
||||
exec_req->fault = NoFault;
|
||||
|
||||
DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
|
||||
tid, seq_num, inst->pcState(), inst->instName());
|
||||
inst->readTid(), seq_num, inst->pcState(), inst->instName());
|
||||
|
||||
switch (exec_req->cmd)
|
||||
{
|
||||
|
@ -126,7 +123,6 @@ ExecutionUnit::execute(int slot_num)
|
|||
if (inst->mispredicted()) {
|
||||
int stage_num = exec_req->getStageNum();
|
||||
ThreadID tid = inst->readTid();
|
||||
|
||||
// If it's a branch ...
|
||||
if (inst->isDirectCtrl()) {
|
||||
assert(!inst->isIndirectCtrl());
|
||||
|
@ -247,13 +243,13 @@ ExecutionUnit::execute(int slot_num)
|
|||
seq_num,
|
||||
(inst->resultType(0) == InOrderDynInst::Float) ?
|
||||
inst->readFloatResult(0) : inst->readIntResult(0));
|
||||
|
||||
exec_req->done();
|
||||
} else {
|
||||
warn("inst [sn:%i] had a %s fault",
|
||||
seq_num, fault->name());
|
||||
cpu->trap(fault, tid, inst);
|
||||
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
|
||||
"fault.\n", inst->readTid(), seq_num, fault->name());
|
||||
inst->fault = fault;
|
||||
}
|
||||
|
||||
exec_req->done();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -74,8 +74,6 @@ FetchSeqUnit::execute(int slot_num)
|
|||
int stage_num = fs_req->getStageNum();
|
||||
int seq_num = inst->seqNum;
|
||||
|
||||
fs_req->fault = NoFault;
|
||||
|
||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: Current PC is %s\n", tid,
|
||||
pc[tid]);
|
||||
|
||||
|
|
|
@ -227,7 +227,8 @@ FetchUnit::execute(int slot_num)
|
|||
ThreadID tid = inst->readTid();
|
||||
Addr block_addr = cacheBlockAlign(inst->getMemAddr());
|
||||
int asid = cpu->asid[tid];
|
||||
cache_req->fault = NoFault;
|
||||
|
||||
inst->fault = NoFault;
|
||||
|
||||
switch (cache_req->cmd)
|
||||
{
|
||||
|
@ -275,7 +276,7 @@ FetchUnit::execute(int slot_num)
|
|||
|
||||
doTLBAccess(inst, cache_req, cacheBlkSize, 0, TheISA::TLB::Execute);
|
||||
|
||||
if (cache_req->fault == NoFault) {
|
||||
if (inst->fault == NoFault) {
|
||||
DPRINTF(InOrderCachePort,
|
||||
"[tid:%u]: Initiating fetch access to %s for "
|
||||
"addr:%#x (block:%#x)\n", tid, name(),
|
||||
|
|
|
@ -51,31 +51,23 @@ GraduationUnit::execute(int slot_num)
|
|||
{
|
||||
ResourceRequest* grad_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
ThreadID tid = inst->readTid();
|
||||
int stage_num = inst->resSched.top()->stageNum;
|
||||
|
||||
grad_req->fault = NoFault;
|
||||
|
||||
switch (grad_req->cmd)
|
||||
{
|
||||
case GraduateInst:
|
||||
{
|
||||
// @TODO: Instructions should never really get to this point since
|
||||
// this should be handled through the request interface. Check to
|
||||
// make sure this happens and delete this code.
|
||||
if (lastCycleGrad != curTick()) {
|
||||
lastCycleGrad = curTick();
|
||||
numCycleGrad = 0;
|
||||
} else if (numCycleGrad > width) {
|
||||
DPRINTF(InOrderGraduation,
|
||||
"Graduation bandwidth reached for this cycle.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure this is the last thing on the resource schedule
|
||||
assert(inst->resSched.size() == 1);
|
||||
|
||||
// Handle Any Faults Before Graduating Instruction
|
||||
if (inst->fault != NoFault) {
|
||||
cpu->trap(inst->fault, tid, inst);
|
||||
grad_req->setCompleted(false);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(InOrderGraduation,
|
||||
"[tid:%i] Graduating instruction [sn:%i].\n",
|
||||
tid, inst->seqNum);
|
||||
|
@ -97,9 +89,6 @@ GraduationUnit::execute(int slot_num)
|
|||
// Tell CPU that instruction is finished processing
|
||||
cpu->instDone(inst, tid);
|
||||
|
||||
//cpu->pipelineStage[stage_num]->toPrevStages->
|
||||
//stageInfo[stage_num][tid].doneSeqNum = inst->seqNum;
|
||||
|
||||
grad_req->done();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -67,8 +67,6 @@ InstBuffer::execute(int slot_idx)
|
|||
ThreadID tid = inst->readTid();
|
||||
int stage_num = ib_req->getStageNum();
|
||||
|
||||
ib_req->fault = NoFault;
|
||||
|
||||
switch (ib_req->cmd)
|
||||
{
|
||||
case ScheduleOrBypass:
|
||||
|
|
|
@ -204,10 +204,6 @@ MultDivUnit::execute(int slot_num)
|
|||
{
|
||||
ResourceRequest* mult_div_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
|
||||
//ThreadID tid = inst->readTid();
|
||||
//int seq_num = inst->seqNum;
|
||||
|
||||
switch (mult_div_req->cmd)
|
||||
{
|
||||
|
@ -281,11 +277,8 @@ MultDivUnit::exeMulDiv(int slot_num)
|
|||
{
|
||||
ResourceRequest* mult_div_req = reqMap[slot_num];
|
||||
DynInstPtr inst = reqMap[slot_num]->inst;
|
||||
Fault fault = reqMap[slot_num]->fault;
|
||||
ThreadID tid = inst->readTid();
|
||||
int seq_num = inst->seqNum;
|
||||
|
||||
fault = inst->execute();
|
||||
inst->fault = inst->execute();
|
||||
|
||||
if (inst->opClass() == IntMultOp) {
|
||||
multiplies++;
|
||||
|
@ -293,15 +286,15 @@ MultDivUnit::exeMulDiv(int slot_num)
|
|||
divides++;
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
if (inst->fault == NoFault) {
|
||||
inst->setExecuted();
|
||||
mult_div_req->setCompleted();
|
||||
|
||||
DPRINTF(Resource, "[tid:%i]: The result of execution is 0x%x.\n",
|
||||
DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n",
|
||||
inst->readTid(), inst->readIntResult(0));
|
||||
} else {
|
||||
warn("inst [sn:%i] had a %s fault", seq_num, fault->name());
|
||||
cpu->trap(fault, tid, inst);
|
||||
DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s "
|
||||
"fault.\n", inst->readTid(), inst->seqNum, inst->fault->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue