From: Korey Sewell Date: Mon, 20 Jun 2011 01:43:39 +0000 (-0400) Subject: inorder: squash and trap behind a tlb fault X-Git-Tag: stable_2012_02_02~225 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5f608dd2e9a760b4280fb03ce82a11a62c6f3af9;p=gem5.git inorder: squash and trap behind a tlb fault --- diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index cc2b72e4e..834e591f8 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -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); } diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc index a21536676..817cc5868 100644 --- a/src/cpu/inorder/resource.cc +++ b/src/cpu/inorder/resource.cc @@ -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) { diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index 91d144a64..78e5af5de 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -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 */ diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 0673d6b9b..d0cdfa3c9 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -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]; diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index dd6fa7638..91a8703f7 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -203,9 +203,9 @@ class CacheUnit : public Resource } bool tlbBlocked[ThePipeline::MaxThreads]; + InstSeqNum tlbBlockSeqNum[ThePipeline::MaxThreads]; TheISA::TLB* tlb(); - TheISA::TLB *_tlb; }; diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc index afa9421a8..4f796e933 100644 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -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; }