# HG changeset patch
# User Korey Sewell <[email protected]>
# Date 1254427253 14400
# Node ID cc0c51c78c1badc7767a664d4375274805781aec
# Parent  93e33fd780edd3a4f1641e446495807d36b9c588
inorder: activate thread on cache miss
-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

diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -95,6 +95,8 @@
 std::string InOrderCPU::eventNames[NumCPUEvents] =
 {
     "ActivateThread",
+    "ActivateNextReadyThread",
+    "DeactivateThread",
     "DeallocateThread",
     "SuspendThread",
     "DisableThreads",
@@ -116,10 +118,18 @@
         cpu->activateThread(tid);
         break;
 
-      //@TODO: Consider Implementing "Suspend Thread" as Separate from 
Deallocate
-      case SuspendThread: // Suspend & Deallocate are same for now.
-        //cpu->suspendThread(tid);
-        //break;
+      case ActivateNextReadyThread:
+        cpu->activateNextReadyThread();
+        break;
+
+      case DeactivateThread:
+        cpu->deactivateThread(tid);
+        break;
+
+      case SuspendThread: 
+        cpu->suspendThread(tid);
+        break;
+
       case DeallocateThread:
         cpu->deallocateThread(tid);
         break;
@@ -220,8 +230,10 @@
         
         if (smt.compare(params->threadModel) == 0) {
             threadModel = SMT;
+            DPRINTF(InOrderCPU, "Setting Thread Model to %s.\n", smt);         
   
         } else {
             threadModel = SwitchOnCacheMiss;
+            DPRINTF(InOrderCPU, "Setting Thread Model to %s.\n", 
switchOnCacheMiss);
         }                     
     }
     
@@ -614,8 +626,8 @@
     }
 
     // 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);
 }
 
@@ -630,9 +642,38 @@
 
 
 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);
@@ -878,6 +919,23 @@
     _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)
@@ -889,8 +947,9 @@
 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
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -88,7 +88,7 @@
     typedef TimeBuffer<InterStageStruct> StageQueue;
 
     friend class Resource;
-
+    
   public:
     /** Constructs a CPU with the given parameters. */
     InOrderCPU(Params *params);
@@ -172,6 +172,8 @@
     // pool event.
     enum CPUEventType {
         ActivateThread,
+        ActivateNextReadyThread,
+        DeactivateThread,
         DeallocateThread,
         SuspendThread,
         DisableThreads,
@@ -356,6 +358,10 @@
     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);
@@ -603,6 +609,9 @@
     /** Current Threads List */
     std::list<ThreadID> currentThreads;
 
+    /** Ready Threads List */
+    std::list<ThreadID> readyThreads;
+
     /** Suspended Threads List */
     std::list<ThreadID> suspendedThreads;
 
@@ -624,6 +633,18 @@
     /** 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(); }
 
diff --git a/src/cpu/inorder/pipeline_stage.cc 
b/src/cpu/inorder/pipeline_stage.cc
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -932,7 +932,15 @@
                     // 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;
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -192,8 +192,8 @@
     {
       case InOrderCPU::ActivateThread:
         {
-            DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event 
for tick %i.\n",
-                    curTick + delay);
+            DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event 
for tick %i, [tid:%i].\n",
+                    curTick + delay, inst->readTid());
             ResPoolEvent *res_pool_event = new ResPoolEvent(this,
                                                             e_type,
                                                             inst,
@@ -264,8 +264,8 @@
         break;
 
       default:
+        // If Resource Pool doesnt recognize event, we ignore it.
         DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
InOrderCPU::eventNames[e_type]);
-        ; // If Resource Pool doesnt recognize event, we ignore it.
     }
 }
 
@@ -280,7 +280,7 @@
                         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);
+            tid, stage_num, done_seq_num);
 
     int num_resources = resources.size();
 
@@ -306,14 +306,26 @@
 void
 ResourcePool::activateAll(ThreadID tid)
 {
-    DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all 
resources.\n",
-            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();
+        int num_resources = resources.size();
 
-    for (int idx = 0; idx < num_resources; idx++) {
-        resources[idx]->activateThread(tid);
+        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
@@ -343,7 +355,7 @@
 }
 
 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)
 { }
 
diff --git a/src/cpu/inorder/thread_context.cc 
b/src/cpu/inorder/thread_context.cc
--- a/src/cpu/inorder/thread_context.cc
+++ b/src/cpu/inorder/thread_context.cc
@@ -241,21 +241,21 @@
 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());
 }
 
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to