From e1fcc6498017574735362636791f9ad73fb39b04 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Sun, 31 Jan 2010 18:26:32 -0500 Subject: 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 --- src/cpu/inorder/cpu.cc | 78 ++++++++++++++++++++++++++++++++++++--- src/cpu/inorder/cpu.hh | 23 +++++++++++- src/cpu/inorder/pipeline_stage.cc | 10 ++++- src/cpu/inorder/resource_pool.cc | 34 +++++++++++------ src/cpu/inorder/thread_context.cc | 6 +-- 5 files changed, 128 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index c0daad207..e52e5935a 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -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::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 diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 1c819638d..854f5167c 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -89,7 +89,7 @@ class InOrderCPU : public BaseCPU typedef TimeBuffer 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 currentThreads; + /** Ready Threads List */ + std::list readyThreads; + /** Suspended Threads List */ std::list 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(); } diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 1fd7150da..30a3733b0 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -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; diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc index 8822715c7..97ba4d087 100644 --- a/src/cpu/inorder/resource_pool.cc +++ b/src/cpu/inorder/resource_pool.cc @@ -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) { } diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 41d16b633..d2f511b9d 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -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()); } -- cgit v1.2.3