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
This commit is contained in:
Korey Sewell 2010-01-31 18:26:32 -05:00
parent 4a945aab19
commit e1fcc64980
5 changed files with 128 additions and 23 deletions

View 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

View 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(); }

View 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;

View 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)
{ }

View 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());
}