: PipelineStage(params, stage_num), numFetchingThreads(1),
fetchPolicy(FirstStage::RoundRobin)
{
- for(int tid=0; tid < this->numThreads; tid++) {
+ for(ThreadID tid = 0; tid < this->numThreads; tid++) {
stageStatus[tid] = Running;
}
}
void
-FirstStage::squash(InstSeqNum squash_seq_num, unsigned tid)
+FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
{
// Set status to squashing.
//stageStatus[tid] = Squashing;
// Clear the instruction list and skid buffer in case they have any
// insts in them.
- DPRINTF(InOrderStage, "Removing instructions from stage instruction list.\n");
+ DPRINTF(InOrderStage, "Removing instructions from stage instruction "
+ "list.\n");
while (!insts[tid].empty()) {
if (insts[tid].front()->seqNum <= squash_seq_num) {
- DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because it's <= "
- "squashing seqNum %i.\n",
+ DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because "
+ "it's <= squashing seqNum %i.\n",
tid,
insts[tid].front()->seqNum,
squash_seq_num);
insts[tid].size());
break;
}
- DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n",
- tid, insts[tid].front()->seqNum, insts[tid].front()->PC);
+ DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+ "PC %08p.\n", tid, insts[tid].front()->seqNum,
+ insts[tid].front()->PC);
insts[tid].pop();
}
cpu->removeInstsUntil(squash_seq_num, tid);
}
+void
+FirstStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+ // Need to preserve the stalling instruction in first-stage
+ // since the squash() from first stage also removes
+ // the instruction from the CPU (removeInstsUntil). If that
+ // functionality gets changed then you can move this offset.
+ // (stalling instruction = seq_num + 1)
+ squash(seq_num+1, tid);
+}
+
+
void
FirstStage::processStage(bool &status_change)
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ list<ThreadID>::iterator threads = activeThreads->begin();
//Check stall and squash signals.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
+ while (threads != activeThreads->end()) {
+ ThreadID tid = *threads++;
status_change = checkSignalsAndUpdate(tid) || status_change;
}
- for (int threadFetched = 0; threadFetched < numFetchingThreads;
- threadFetched++) {
- int tid = getFetchingThread(fetchPolicy);
+ for (int insts_fetched = 0;
+ insts_fetched < stageWidth && canSendInstToStage(1);
+ insts_fetched++) {
+ ThreadID tid = getFetchingThread(fetchPolicy);
if (tid >= 0) {
DPRINTF(InOrderStage, "Processing [tid:%i]\n",tid);
DPRINTF(InOrderStage, "No more threads to fetch from.\n");
}
}
+
+ if (instsProcessed > 0) {
+ ++runCycles;
+ idle = false;
+ } else {
+ ++idleCycles;
+ idle = true;
+ }
+
}
-//@TODO: Note in documentation, that when you make a pipeline stage change, then
-//make sure you change the first stage too
+//@TODO: Note in documentation, that when you make a pipeline stage change,
+//then make sure you change the first stage too
void
-FirstStage::processInsts(unsigned tid)
+FirstStage::processInsts(ThreadID tid)
{
bool all_reqs_completed = true;
- for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToStage(1); insts_fetched++) {
+ for (int insts_fetched = 0;
+ insts_fetched < stageWidth && canSendInstToStage(1);
+ insts_fetched++) {
+
DynInstPtr inst;
bool new_inst = false;
inst->traceData = NULL;
#endif // TRACING_ON
- DPRINTF(RefCount, "creation: [tid:%i]: [sn:%i]: Refcount = %i.\n",
- inst->readTid(),
- inst->seqNum,
- 0/*inst->curCount()*/);
-
// Add instruction to the CPU's list of instructions.
inst->setInstListIt(cpu->addInst(inst));
- DPRINTF(RefCount, "after add to CPU List: [tid:%i]: [sn:%i]: Refcount = %i.\n",
- inst->readTid(),
- inst->seqNum,
- 0/*inst->curCount()*/);
-
// Create Front-End Resource Schedule For Instruction
ThePipeline::createFrontEndSchedule(inst);
}
- // Don't let instruction pass to next stage if it hasnt completed
- // all of it's requests for this stage.
- all_reqs_completed = processInstSchedule(inst);
+ int reqs_processed = 0;
+ all_reqs_completed = processInstSchedule(inst, reqs_processed);
+
+ // If the instruction isnt squashed & we've completed one request
+ // Then we can officially count this instruction toward the stage's
+ // bandwidth count
+ if (reqs_processed > 0)
+ instsProcessed++;
if (!all_reqs_completed) {
if (new_inst) {
}
sendInstToNextStage(inst);
- //++stageProcessedInsts;
}
// Record that stage has written to the time buffer for activity
}
}
-int
+ThreadID
FirstStage::getFetchingThread(FetchPriority &fetch_priority)
{
- if (numThreads > 1) {
- switch (fetch_priority) {
+ ThreadID num_active_threads = cpu->numActiveThreads();
+ if (num_active_threads > 1) {
+ switch (fetch_priority) {
case SingleThread:
- return 0;
+ return cpu->activeThreadId();
case RoundRobin:
return roundRobin();
default:
- return -1;
+ return InvalidThreadID;
}
- } else {
- int tid = *((*activeThreads).begin());
+ } else if (num_active_threads == 1) {
+ ThreadID tid = *activeThreads->begin();
if (stageStatus[tid] == Running ||
stageStatus[tid] == Idle) {
return tid;
} else {
- return -1;
+ return InvalidThreadID;
}
- }
-
+ } else {
+ return InvalidThreadID;
+ }
}
-int
+ThreadID
FirstStage::roundRobin()
{
- list<unsigned>::iterator pri_iter = (*fetchPriorityList).begin();
- list<unsigned>::iterator end = (*fetchPriorityList).end();
+ list<ThreadID>::iterator pri_iter = fetchPriorityList->begin();
+ list<ThreadID>::iterator end = fetchPriorityList->end();
- int high_pri;
+ ThreadID high_pri;
while (pri_iter != end) {
high_pri = *pri_iter;
if (stageStatus[high_pri] == Running ||
stageStatus[high_pri] == Idle) {
- (*fetchPriorityList).erase(pri_iter);
- (*fetchPriorityList).push_back(high_pri);
+ fetchPriorityList->erase(pri_iter);
+ fetchPriorityList->push_back(high_pri);
return high_pri;
}
pri_iter++;
}
- return -1;
+ return InvalidThreadID;
}