inorder: activate thread on cache miss
authorKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:26:32 +0000 (18:26 -0500)
committerKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:26:32 +0000 (18:26 -0500)
-Support ability to activate next ready thread after a cache miss
through the activateNextReadyContext/Thread() functions
-To support this a "readyList" of thread ids is added
-After a cache miss, thread will suspend and then call
activitynextreadythread

src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/pipeline_stage.cc
src/cpu/inorder/resource_pool.cc
src/cpu/inorder/thread_context.cc

index c0daad207686216f1b0629b12f7396d9092a63cb..e52e5935a0a952df93ebe8f31bebb15bc1f5dcd4 100644 (file)
@@ -96,6 +96,8 @@ InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type,
 std::string InOrderCPU::eventNames[NumCPUEvents] =
 {
     "ActivateThread",
+    "ActivateNextReadyThread",
+    "DeactivateThread",
     "DeallocateThread",
     "SuspendThread",
     "DisableThreads",
@@ -119,9 +121,18 @@ InOrderCPU::CPUEvent::process()
 
       //@TODO: Consider Implementing "Suspend Thread" as Separate from 
       //Deallocate
+      case ActivateNextReadyThread:
+        cpu->activateNextReadyThread();
+        break;
+
+      case DeactivateThread:
+        cpu->deactivateThread(tid);
+        break;
+
       case SuspendThread: // Suspend & Deallocate are same for now.
-        //cpu->suspendThread(tid);
-        //break;
+        cpu->suspendThread(tid);
+        break;
+
       case DeallocateThread:
         cpu->deallocateThread(tid);
         break;
@@ -225,6 +236,14 @@ InOrderCPU::InOrderCPU(Params *params)
 
     if (active_threads > 1) {
         threadModel = (InOrderCPU::ThreadModel) params->threadModel;
+
+        if (threadModel == SMT) {
+            DPRINTF(InOrderCPU, "Setting Thread Model to SMT.\n");            
+        } else if (threadModel == SwitchOnCacheMiss) {
+            DPRINTF(InOrderCPU, "Setting Thread Model to "
+                    "Switch On Cache Miss\n");
+        }
+        
     } else {
         threadModel = Single;
     }
@@ -628,8 +647,8 @@ InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
     }
 
     // Broadcast event to the Resource Pool
-    DynInstPtr dummy_inst =
-        new InOrderDynInst(this, NULL, getNextEventNum(), tid);
+    // Need to reset tid just in case this is a dummy instruction
+    inst->setTid(tid);        
     resPool->scheduleEvent(c_event, inst, 0, 0, tid);
 }
 
@@ -643,10 +662,39 @@ InOrderCPU::isThreadActive(ThreadID tid)
 }
 
 
+void
+InOrderCPU::activateNextReadyThread()
+{
+    if (readyThreads.size() >= 1) {          
+        ThreadID ready_tid = readyThreads.front();
+        
+        // Activate in Pipeline
+        activateThread(ready_tid);                        
+        
+        // Activate in Resource Pool
+        resPool->activateAll(ready_tid);
+        
+        list<ThreadID>::iterator ready_it =
+            std::find(readyThreads.begin(), readyThreads.end(), ready_tid);
+        readyThreads.erase(ready_it);                        
+    } else {
+        DPRINTF(InOrderCPU,
+                "No Ready Threads to Activate.\n");
+    }        
+}
+
 void
 InOrderCPU::activateThread(ThreadID tid)
 {
-    if (!isThreadActive(tid)) {
+    if (threadModel == SwitchOnCacheMiss &&
+        numActiveThreads() == 1) {
+        DPRINTF(InOrderCPU,
+                "Ignoring Activation of [tid:%i]. Placing on "
+                "ready list\n", tid);        
+
+        readyThreads.push_back(tid);
+        
+    } else if (!isThreadActive(tid)) {
         DPRINTF(InOrderCPU,
                 "Adding Thread %i to active threads list in CPU.\n", tid);
         activeThreads.push_back(tid);
@@ -892,6 +940,23 @@ InOrderCPU::activateContext(ThreadID tid, int delay)
     _status = Running;
 }
 
+void
+InOrderCPU::activateNextReadyContext(int delay)
+{
+    DPRINTF(InOrderCPU,"Activating next ready thread\n");
+
+    // NOTE: Add 5 to the event priority so that we always activate
+    // threads after we've finished deactivating, squashing,etc.
+    // other threads
+    scheduleCpuEvent(ActivateNextReadyThread, NoFault, 0/*tid*/, dummyInst, 
+                     delay, 5);
+
+    // Be sure to signal that there's some activity so the CPU doesn't
+    // deschedule itself.
+    activityRec.activity();
+
+    _status = Running;
+}
 
 void
 InOrderCPU::suspendContext(ThreadID tid, int delay)
@@ -903,8 +968,9 @@ InOrderCPU::suspendContext(ThreadID tid, int delay)
 void
 InOrderCPU::suspendThread(ThreadID tid)
 {
-    DPRINTF(InOrderCPU,"[tid: %i]: Suspended ...\n", tid);
+    DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid);
     deactivateThread(tid);
+    suspendedThreads.push_back(tid);    
 }
 
 void
index 1c819638d21b1e465eb3dd31d02ac4e16de9bb08..854f5167c17f7359f0dce0a75bf51d48179406b0 100644 (file)
@@ -89,7 +89,7 @@ class InOrderCPU : public BaseCPU
     typedef TimeBuffer<InterStageStruct> StageQueue;
 
     friend class Resource;
-
+    
   public:
     /** Constructs a CPU with the given parameters. */
     InOrderCPU(Params *params);
@@ -175,6 +175,8 @@ class InOrderCPU : public BaseCPU
     // pool event.
     enum CPUEventType {
         ActivateThread,
+        ActivateNextReadyThread,
+        DeactivateThread,
         DeallocateThread,
         SuspendThread,
         DisableThreads,
@@ -361,6 +363,10 @@ class InOrderCPU : public BaseCPU
     void activateContext(ThreadID tid, int delay = 0);
     void activateThread(ThreadID tid);
 
+    /** Add Thread to Active Threads List. */
+    void activateNextReadyContext(int delay = 0);
+    void activateNextReadyThread();
+
     /** Remove Thread from Active Threads List */
     void suspendContext(ThreadID tid, int delay = 0);
     void suspendThread(ThreadID tid);
@@ -612,6 +618,9 @@ class InOrderCPU : public BaseCPU
     /** Current Threads List */
     std::list<ThreadID> currentThreads;
 
+    /** Ready Threads List */
+    std::list<ThreadID> readyThreads;
+
     /** Suspended Threads List */
     std::list<ThreadID> suspendedThreads;
 
@@ -633,6 +642,18 @@ class InOrderCPU : public BaseCPU
     /** Number of Active Threads in the CPU */
     ThreadID numActiveThreads() { return activeThreads.size(); }
 
+    /** Thread id of active thread
+     *  Only used for SwitchOnCacheMiss model. Assumes only 1 thread active
+     */
+    ThreadID activeThreadId() 
+    { 
+        if (numActiveThreads() > 0)
+            return activeThreads.front();
+        else
+            return -1;
+    }
+    
+     
     /** Records that there was time buffer activity this cycle. */
     void activityThisCycle() { activityRec.activity(); }
 
index 1fd7150da4df4eed9c38d88d27d483f9c4afb429..30a3733b039f2b8eaab34e08b5081fe04794c55a 100644 (file)
@@ -951,7 +951,15 @@ PipelineStage::processInstSchedule(DynInstPtr inst)
                     // Remove Thread From Pipeline & Resource Pool
                     inst->squashingStage = stageNum;         
                     inst->bdelaySeqNum = inst->seqNum;                               
-                    cpu->squashFromMemStall(inst, tid);                    
+                    cpu->squashFromMemStall(inst, tid);  
+
+                    // Switch On Cache Miss
+                    //=====================
+                    // Suspend Thread at end of cycle
+                    cpu->suspendContext(tid);                    
+
+                    // Activate Next Ready Thread at end of cycle
+                    cpu->activateNextReadyContext();                                                                                               
                 }
                 
                 break;
index 8822715c73ddd21d3efa1ce3562fd8ea336235b5..97ba4d08754549c604b231205522ecdf4ae97437 100644 (file)
@@ -212,7 +212,8 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
       case InOrderCPU::ActivateThread:
         {
             DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event "
-                    "for tick %i.\n", curTick + delay);
+                    "for tick %i, [tid:%i].\n", curTick + delay, 
+                    inst->readTid());
             ResPoolEvent *res_pool_event = 
                 new ResPoolEvent(this,
                                  e_type,
@@ -295,7 +296,6 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
       default:
         DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
                 InOrderCPU::eventNames[e_type]);
-        ; // If Resource Pool doesnt recognize event, we ignore it.
     }
 }
 
@@ -310,7 +310,7 @@ ResourcePool::squashAll(DynInstPtr inst, int stage_num,
                         InstSeqNum done_seq_num, ThreadID tid)
 {
     DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above "
-            "[sn:%i].\n", stage_num, tid, done_seq_num);
+            "[sn:%i].\n", tid, stage_num, done_seq_num);
 
     int num_resources = resources.size();
 
@@ -337,14 +337,24 @@ ResourcePool::squashDueToMemStall(DynInstPtr inst, int stage_num,
 void
 ResourcePool::activateAll(ThreadID tid)
 {
-    DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all "
-            "resources.\n", tid);
-
-    int num_resources = resources.size();
-
-    for (int idx = 0; idx < num_resources; idx++) {
-        resources[idx]->activateThread(tid);
-    }
+    bool do_activate = cpu->threadModel != InOrderCPU::SwitchOnCacheMiss ||
+        cpu->numActiveThreads() < 1 ||
+        cpu->activeThreadId() == tid;
+    
+        
+    if (do_activate) {
+        DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all "
+                    "resources.\n", tid);
+        int num_resources = resources.size();
+        for (int idx = 0; idx < num_resources; idx++) {
+            resources[idx]->activateThread(tid);
+        }
+    } else {
+        DPRINTF(Resource, "[tid:%i] Ignoring Thread Activation to all "
+                    "resources.\n", tid);
+     }
 }
 
 void
@@ -374,7 +384,7 @@ ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
 }
 
 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
-    : Event(CPU_Tick_Pri), resPool(_resPool),
+    : Event((Event::Priority)((unsigned)CPU_Tick_Pri+5)), resPool(_resPool),
       eventType((InOrderCPU::CPUEventType) Default)
 { }
 
index 41d16b633fa62e8644bf671eca69933a232c5188..d2f511b9daa7d59818182a3048f87e83ef2ed411 100644 (file)
@@ -242,21 +242,21 @@ InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val,
 void
 InOrderThreadContext::setPC(uint64_t val)
 {
-    DPRINTF(InOrderCPU, "Setting PC to %08p\n", val);
+    DPRINTF(InOrderCPU, "[tid:%i] Setting PC to %08p\n", thread->readTid(), val);
     cpu->setPC(val, thread->readTid());
 }
 
 void
 InOrderThreadContext::setNextPC(uint64_t val)
 {
-    DPRINTF(InOrderCPU, "Setting NPC to %08p\n", val);
+    DPRINTF(InOrderCPU, "[tid:%i] Setting NPC to %08p\n", thread->readTid(), val);
     cpu->setNextPC(val, thread->readTid());
 }
 
 void
 InOrderThreadContext::setNextNPC(uint64_t val)
 {
-    DPRINTF(InOrderCPU, "Setting NNPC to %08p\n", val);
+    DPRINTF(InOrderCPU, "[tid:%i] Setting NNPC to %08p\n", thread->readTid(), val);
     cpu->setNextNPC(val, thread->readTid());
 }