std::string InOrderCPU::eventNames[NumCPUEvents] =
{
"ActivateThread",
+ "ActivateNextReadyThread",
+ "DeactivateThread",
"DeallocateThread",
"SuspendThread",
"DisableThreads",
//@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;
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;
}
}
// 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);
}
}
+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);
_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)
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
typedef TimeBuffer<InterStageStruct> StageQueue;
friend class Resource;
-
+
public:
/** Constructs a CPU with the given parameters. */
InOrderCPU(Params *params);
// pool event.
enum CPUEventType {
ActivateThread,
+ ActivateNextReadyThread,
+ DeactivateThread,
DeallocateThread,
SuspendThread,
DisableThreads,
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);
/** Current Threads List */
std::list<ThreadID> currentThreads;
+ /** Ready Threads List */
+ std::list<ThreadID> readyThreads;
+
/** Suspended Threads List */
std::list<ThreadID> suspendedThreads;
/** 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(); }
// 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;
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,
default:
DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n",
InOrderCPU::eventNames[e_type]);
- ; // If Resource Pool doesnt recognize event, we ignore it.
}
}
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();
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
}
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)
{ }
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());
}