summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2010-01-31 18:26:32 -0500
committerKorey Sewell <ksewell@umich.edu>2010-01-31 18:26:32 -0500
commite1fcc6498017574735362636791f9ad73fb39b04 (patch)
treeda58049ba1b2c6b52dced5aa8928cb6fc27485ab /src/cpu
parent4a945aab1958d39fcfea4608715e77d5112809cf (diff)
downloadgem5-e1fcc6498017574735362636791f9ad73fb39b04.tar.xz
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
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/inorder/cpu.cc78
-rw-r--r--src/cpu/inorder/cpu.hh23
-rw-r--r--src/cpu/inorder/pipeline_stage.cc10
-rw-r--r--src/cpu/inorder/resource_pool.cc34
-rw-r--r--src/cpu/inorder/thread_context.cc6
5 files changed, 128 insertions, 23 deletions
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);
}
@@ -644,9 +663,38 @@ 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
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<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(); }
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());
}