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:
parent
4a945aab19
commit
e1fcc64980
5 changed files with 128 additions and 23 deletions
|
@ -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
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{ }
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue