inorder: bug in mdu
authorKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:38 +0000 (21:43 -0400)
committerKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:38 +0000 (21:43 -0400)
segfault was caused by squashed multiply thats in the process of an event.
use isProcessing flag to handle this and cleanup the MDU code

src/cpu/inorder/resource.cc
src/cpu/inorder/resource.hh
src/cpu/inorder/resource_pool.cc
src/cpu/inorder/resources/mult_div_unit.cc
src/cpu/inorder/resources/mult_div_unit.hh

index 8d3f3daace3d7dee73d6df7f5992f57485403cbc..a2153667626b16e9a5b5d2bb0e099257a1837ba0 100644 (file)
@@ -297,16 +297,18 @@ Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
     cpu->resPool->scheduleEvent(
         (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
 }
+
 void
 Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
                  ThreadID tid)
 {
     for (int i = 0; i < width; i++) {
         ResReqPtr req_ptr = reqs[i];
+        DynInstPtr inst = req_ptr->getInst();
 
         if (req_ptr->valid &&
-            req_ptr->getInst()->readTid() == tid &&
-            req_ptr->getInst()->seqNum > squash_seq_num) {
+            inst->readTid() == tid &&
+            inst->seqNum > squash_seq_num) {
 
             DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n",
                     req_ptr->getInst()->readTid(),
index fcf01065a8ba849dc030036dafadfc4e977837a5..91d144a64d6760464c117a7b5e21b0be6b5f950d 100644 (file)
@@ -389,7 +389,7 @@ class ResourceRequest
 
     /** Get/Set IsProcessing variables */
     bool isProcessing() { return processing; }
-    void setProcessing() { processing = true; }
+    void setProcessing(bool cond = true) { processing = cond; }
 
     /** Get/Set IsWaiting variables */
     bool isMemStall() { return memStall; }
index a8a26f51e195ba2997d15e2ff1b29ff5e939f9d2..0e89a7650115683af13f0b04c07ed71d5b4f0382 100644 (file)
@@ -79,7 +79,10 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
                                           stage_width, 0, _cpu, params));
 
     resources.push_back(new MultDivUnit("mult_div_unit", MDU,
-                                        stage_width * 2, 0, _cpu, params));
+                                        stage_width * 2,
+                                        0,
+                                        _cpu,
+                                        params));
 
     memObjects.push_back(DCache);
     resources.push_back(new CacheUnit("dcache_port", DCache, 
index 49df901e30cdd97caa21c628fd63533bf23ec6d7..fc27276d50c241a6c14b4082035b66b19884c46d 100644 (file)
@@ -86,25 +86,6 @@ MultDivUnit::init()
     initSlots();
 }
 
-int
-MultDivUnit::findSlot(DynInstPtr inst)
-{
-    DPRINTF(InOrderMDU, "Finding slot for inst:%i\n | slots-free:%i | "
-            "slots-used:%i\n", inst->seqNum, slotsAvail(), slotsInUse());
-    
-    return Resource::findSlot(inst);    
-}
-
-void
-MultDivUnit::freeSlot(int slot_idx)
-{
-    DPRINTF(InOrderMDU, "Freeing slot for inst:%i\n | slots-free:%i | "
-            "slots-used:%i\n", reqs[slot_idx]->getInst()->seqNum,
-            slotsAvail(), slotsInUse());
-    
-    Resource::freeSlot(slot_idx);    
-}
-
 //@TODO: Should we push this behavior into base-class to generically
 //       accomodate all multicyle resources?
 void
@@ -124,7 +105,7 @@ MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request)
                 "[tid:%i]: [sn:%i]: Updating the command for this "
                 "instruction\n", inst->readTid(), inst->seqNum);
     } else {
-        // If same command, just check to see if memory access was completed
+        // If same command, just check to see if access was completed
         // but dont try to re-execute
         DPRINTF(InOrderMDU,
                 "[tid:%i]: [sn:%i]: requesting this resource again\n",
@@ -212,41 +193,47 @@ MultDivUnit::execute(int slot_num)
     ResourceRequest* mult_div_req = reqs[slot_num];
     DynInstPtr inst = reqs[slot_num]->inst;
  
+    DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num);
+
     switch (mult_div_req->cmd)
     {
       case StartMultDiv:
-        DPRINTF(InOrderMDU, "Start MDU called ...\n");        
-
-        if (inst->opClass() == IntMultOp) {
-            scheduleEvent(slot_num, multLatency);
-        } else if (inst->opClass() == IntDivOp) {
-            int op_size = getDivOpSize(inst);
-
-            switch (op_size)
-            {
-              case 8:
-                scheduleEvent(slot_num, div8Latency);
-                break;
-
-              case 16:
-                scheduleEvent(slot_num, div16Latency);
-                break;
-
-              case 24:
-                scheduleEvent(slot_num, div24Latency);
-                break;
-
-              case 32:
-                scheduleEvent(slot_num, div32Latency);
-                break;
+        {
+            DPRINTF(InOrderMDU, "Start MDU called ...\n");
+
+            OpClass op_class = inst->opClass();
+            if (op_class == IntMultOp) {
+                scheduleEvent(slot_num, multLatency);
+            } else if (op_class == IntDivOp) {
+                int op_size = getDivOpSize(inst);
+
+                switch (op_size)
+                {
+                  case 8:
+                    scheduleEvent(slot_num, div8Latency);
+                    break;
+
+                  case 16:
+                    scheduleEvent(slot_num, div16Latency);
+                    break;
+
+                  case 24:
+                    scheduleEvent(slot_num, div24Latency);
+                    break;
+
+                  case 32:
+                    scheduleEvent(slot_num, div32Latency);
+                    break;
+                }
+
+                lastDivSize = op_size;
             }
 
-            lastDivSize = op_size;
+            // Allow to pass through to next stage while
+            // event processes
+            mult_div_req->setProcessing();
+            mult_div_req->setCompleted();
         }
-
-        // Allow to pass through to next stage while
-        // event processes
-        mult_div_req->setCompleted();
         break;
         
       case MultDiv:
@@ -264,7 +251,7 @@ MultDivUnit::execute(int slot_num)
         //      counting down the time
         {
             DPRINTF(InOrderMDU, "End MDU called ...\n");    
-            if (mult_div_req->getInst()->isExecuted()) {
+            if (!mult_div_req->isProcessing()) {
                 DPRINTF(InOrderMDU, "Mult/Div finished.\n");                    
                 mult_div_req->done();            
             } else {                
@@ -295,7 +282,6 @@ MultDivUnit::exeMulDiv(int slot_num)
 
     if (inst->fault == NoFault) {
         inst->setExecuted();
-        mult_div_req->setCompleted();
 
         DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n",
                 inst->readTid(), inst->readIntResult(0));
@@ -303,8 +289,40 @@ MultDivUnit::exeMulDiv(int slot_num)
         DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s "
                 "fault.\n", inst->readTid(), inst->seqNum, inst->fault->name());
     }    
+
+    mult_div_req->setProcessing(false);
 }
 
+void
+MultDivUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
+                 ThreadID tid)
+{
+    for (int i = 0; i < width; i++) {
+        ResReqPtr req_ptr = reqs[i];
+        DynInstPtr inst = req_ptr->getInst();
+
+        if (req_ptr->valid &&
+            inst->readTid() == tid &&
+            inst->seqNum > squash_seq_num) {
+
+            DPRINTF(InOrderMDU, "[tid:%i]: Squashing [sn:%i].\n",
+                    req_ptr->getInst()->readTid(),
+                    req_ptr->getInst()->seqNum);
+
+            req_ptr->setSquashed();
+
+            int req_slot_num = req_ptr->getSlot();
+
+            if (req_ptr->isProcessing())
+                DPRINTF(InOrderMDU, "[tid:%i]: Squashed [sn:%i], but "
+                        "waiting for MDU operation to complete.\n",
+                        req_ptr->getInst()->readTid(),
+                        req_ptr->getInst()->seqNum);
+            else
+                freeSlot(req_slot_num);
+        }
+    }
+}
 
 MDUEvent::MDUEvent()
     : ResourceEvent()
@@ -319,7 +337,8 @@ MDUEvent::process()
 
     ResourceRequest* mult_div_req = resource->reqs[slotIdx];
 
-    mult_div_req->done();    
+    if (mult_div_req->isSquashed())
+        mdu_res->freeSlot(slotIdx);
 }
 
 
index 753bc64a68ea6e7bb32ddf3061639cb652b34e53..7d179bdcec15451b96a9ca550fcbdca939b1150c 100644 (file)
@@ -64,10 +64,6 @@ class MultDivUnit : public Resource {
      *  valid mult/div sequence is being maintained
      */
     int getSlot(DynInstPtr inst);
-
-    int findSlot(DynInstPtr inst);
-
-    void freeSlot(int slot_idx);
     
     void init();
     
@@ -84,6 +80,9 @@ class MultDivUnit : public Resource {
 
     void requestAgain(DynInstPtr inst, bool &try_request);
 
+    void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
+                ThreadID tid);
+
   protected:
     /** Latency & Repeat Rate for Multiply Insts */
     unsigned multRepeatRate;