inorder: squash and trap behind a tlb fault
authorKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:39 +0000 (21:43 -0400)
committerKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:39 +0000 (21:43 -0400)
src/cpu/inorder/cpu.cc
src/cpu/inorder/resource.cc
src/cpu/inorder/resource.hh
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/cache_unit.hh
src/cpu/inorder/resources/graduation_unit.cc

index cc2b72e4e93b89ca19a72450649d08e705bb3b4e..834e591f8a0d19b9196502dee2555e4c6ecf157e 100644 (file)
@@ -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);
 }
 
index a2153667626b16e9a5b5d2bb0e099257a1837ba0..817cc58686ead167d44f4c2a70315eee307c588c 100644 (file)
@@ -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)
 {
index 91d144a64d6760464c117a7b5e21b0be6b5f950d..78e5af5de917bc75ee6056c088da0b8c06689ccd 100644 (file)
@@ -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
      */
index 0673d6b9b8190c1b284ae7e044e698f27e63c5e0..d0cdfa3c94c05e43f605809067e88c2d5995ca10 100644 (file)
@@ -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];
 
index dd6fa763878173a4b757d593675ca8bc9e95ada6..91a8703f73dc3f56093afc649289499f81a2b215 100644 (file)
@@ -203,9 +203,9 @@ class CacheUnit : public Resource
     }
 
     bool tlbBlocked[ThePipeline::MaxThreads];
+    InstSeqNum tlbBlockSeqNum[ThePipeline::MaxThreads];
 
     TheISA::TLB* tlb();
-
     TheISA::TLB *_tlb;
 };
 
index afa9421a8327843699d5bcfef31c187513391239..4f796e9331b680c2284fd4312aa97e78f1a13fad 100644 (file)
@@ -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;
             }