inorder: squash and trap behind a tlb fault
This commit is contained in:
parent
e0e387c2a9
commit
5f608dd2e9
6 changed files with 65 additions and 22 deletions
|
@ -847,6 +847,7 @@ void
|
|||
InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst)
|
||||
{
|
||||
fault->invoke(tcBase(tid), inst->staticInst);
|
||||
removePipelineStalls(tid);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1650,6 +1651,7 @@ InOrderCPU::wakeup()
|
|||
void
|
||||
InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
|
||||
{
|
||||
//@todo: squash behind syscall
|
||||
scheduleCpuEvent(Syscall, fault, tid, inst, delay, Syscall_Pri);
|
||||
}
|
||||
|
||||
|
|
|
@ -336,6 +336,25 @@ Resource::squashDueToMemStall(DynInstPtr inst, int stage_num,
|
|||
squash(inst, stage_num, squash_seq_num, tid);
|
||||
}
|
||||
|
||||
void
|
||||
Resource::squashThenTrap(int stage_num, DynInstPtr inst)
|
||||
{
|
||||
ThreadID tid = inst->readTid();
|
||||
|
||||
inst->setSquashInfo(stage_num);
|
||||
setupSquash(inst, stage_num, tid);
|
||||
|
||||
if (inst->traceData && DTRACE(ExecFaulting)) {
|
||||
inst->traceData->setStageCycle(stage_num, curTick());
|
||||
inst->traceData->setFetchSeq(inst->seqNum);
|
||||
inst->traceData->dump();
|
||||
delete inst->traceData;
|
||||
inst->traceData = NULL;
|
||||
}
|
||||
|
||||
cpu->trapContext(inst->fault, tid, inst);
|
||||
}
|
||||
|
||||
Tick
|
||||
Resource::ticks(int num_cycles)
|
||||
{
|
||||
|
|
|
@ -168,6 +168,9 @@ class Resource {
|
|||
virtual void squashDueToMemStall(DynInstPtr inst, int stage_num,
|
||||
InstSeqNum squash_seq_num, ThreadID tid);
|
||||
|
||||
/** Handle Squash & Trap that occured from an instruction in a resource */
|
||||
void squashThenTrap(int stage_num, DynInstPtr inst);
|
||||
|
||||
/** The number of instructions available that this resource can
|
||||
* can still process
|
||||
*/
|
||||
|
|
|
@ -119,6 +119,7 @@ CacheUnit::CacheUnit(string res_name, int res_id, int res_width,
|
|||
|
||||
for (int i=0; i < MaxThreads; i++) {
|
||||
tlbBlocked[i] = false;
|
||||
tlbBlockSeqNum[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,12 +392,8 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
int flags, TheISA::TLB::Mode tlb_mode)
|
||||
{
|
||||
ThreadID tid = inst->readTid();
|
||||
//Addr aligned_addr = inst->getMemAddr();
|
||||
unsigned stage_num = cache_req->getStageNum();
|
||||
unsigned slot_idx = cache_req->getSlot();
|
||||
|
||||
setupMemRequest(inst, cache_req, acc_size, flags);
|
||||
|
||||
inst->fault =
|
||||
_tlb->translateAtomic(cache_req->memReq,
|
||||
cpu->thread[tid]->getTC(), tlb_mode);
|
||||
|
@ -406,16 +403,25 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
"addr:%08p for [sn:%i].\n", tid, inst->fault->name(),
|
||||
cache_req->memReq->getVaddr(), inst->seqNum);
|
||||
|
||||
cpu->pipelineStage[stage_num]->setResStall(cache_req, tid);
|
||||
|
||||
tlbBlocked[tid] = true;
|
||||
tlbBlockSeqNum[tid] = inst->seqNum;
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
unsigned stage_num = cache_req->getStageNum();
|
||||
|
||||
cpu->pipelineStage[stage_num]->setResStall(cache_req, tid);
|
||||
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);
|
||||
unsigned slot_idx = cache_req->getSlot();
|
||||
#endif
|
||||
|
||||
// Mark it as complete so it can pass through next stage.
|
||||
// Fault Handling will happen at commit/graduation
|
||||
cache_req->setCompleted();
|
||||
} else {
|
||||
DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
|
||||
"to phys. addr:%08p.\n", tid, inst->seqNum,
|
||||
|
@ -654,8 +660,6 @@ CacheUnit::execute(int slot_num)
|
|||
std::string acc_type = "write";
|
||||
#endif
|
||||
|
||||
inst->fault = NoFault;
|
||||
|
||||
switch (cache_req->cmd)
|
||||
{
|
||||
|
||||
|
@ -712,6 +716,16 @@ CacheUnit::execute(int slot_num)
|
|||
DPRINTF(InOrderCachePort,
|
||||
"[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n",
|
||||
tid, inst->seqNum);
|
||||
|
||||
if (inst->fault != NoFault) {
|
||||
DPRINTF(InOrderCachePort,
|
||||
"[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
|
||||
"next stage.\n", tid, inst->seqNum, inst->fault->name(),
|
||||
inst->getMemAddr());
|
||||
finishCacheUnitReq(inst, cache_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//@todo: timing translations need to check here...
|
||||
assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes");
|
||||
if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) {
|
||||
|
@ -730,6 +744,15 @@ CacheUnit::execute(int slot_num)
|
|||
"[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n",
|
||||
tid, inst->seqNum);
|
||||
|
||||
if (inst->fault != NoFault) {
|
||||
DPRINTF(InOrderCachePort,
|
||||
"[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to ",
|
||||
"next stage.\n", tid, inst->seqNum, inst->fault->name(),
|
||||
inst->getMemAddr());
|
||||
finishCacheUnitReq(inst, cache_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//@todo: check that timing translation is finished here
|
||||
RequestPtr mem_req = cache_req->memReq;
|
||||
DPRINTF(InOrderCachePort,
|
||||
|
@ -789,7 +812,8 @@ CacheUnit::execute(int slot_num)
|
|||
"[tid:%i]: [sn:%i]: Trying to Complete Split Data Write "
|
||||
"Access\n", tid, inst->seqNum);
|
||||
//@todo: illegal to have a unaligned cond.swap or llsc?
|
||||
assert(!cache_req->memReq->isSwap() && !cache_req->memReq->isCondSwap() && !cache_req->memReq->isLLSC());
|
||||
assert(!cache_req->memReq->isSwap() && !cache_req->memReq->isCondSwap()
|
||||
&& !cache_req->memReq->isLLSC());
|
||||
|
||||
if (cache_req->isMemAccPending()) {
|
||||
cache_req->dataPkt->reqData = cache_req->reqData;
|
||||
|
@ -1224,6 +1248,12 @@ void
|
|||
CacheUnit::squash(DynInstPtr inst, int stage_num,
|
||||
InstSeqNum squash_seq_num, ThreadID tid)
|
||||
{
|
||||
if (tlbBlockSeqNum[tid] > squash_seq_num) {
|
||||
DPRINTF(InOrderCachePort, "Releasing TLB Block due to "
|
||||
" squash after [sn:%i].\n", squash_seq_num);
|
||||
tlbBlocked[tid] = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
ResReqPtr req_ptr = reqs[i];
|
||||
|
||||
|
|
|
@ -203,9 +203,9 @@ class CacheUnit : public Resource
|
|||
}
|
||||
|
||||
bool tlbBlocked[ThePipeline::MaxThreads];
|
||||
InstSeqNum tlbBlockSeqNum[ThePipeline::MaxThreads];
|
||||
|
||||
TheISA::TLB* tlb();
|
||||
|
||||
TheISA::TLB *_tlb;
|
||||
};
|
||||
|
||||
|
|
|
@ -70,18 +70,7 @@ GraduationUnit::execute(int slot_num)
|
|||
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);
|
||||
|
||||
if (inst->traceData && DTRACE(ExecFaulting)) {
|
||||
inst->traceData->setStageCycle(stage_num, curTick());
|
||||
inst->traceData->setFetchSeq(inst->seqNum);
|
||||
inst->traceData->dump();
|
||||
delete inst->traceData;
|
||||
inst->traceData = NULL;
|
||||
}
|
||||
|
||||
cpu->trapContext(inst->fault, tid, inst);
|
||||
squashThenTrap(stage_num, inst);
|
||||
grad_req->done(false);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue