allow the pipeline and resources to use the cached instruction schedule and resource
sked iterator
TraceFlag('ThreadModel')
TraceFlag('RefCount')
TraceFlag('AddrDep')
-
+ TraceFlag('SkedCache')
CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU',
'InOrderMDU', 'InOrderAGEN', 'InOrderFetchSeq', 'InOrderTLB', 'InOrderBPred',
RSkedPtr
InOrderCPU::createFrontEndSked()
{
- RSkedPtr res_sked = NULL;
+ RSkedPtr res_sked = new ResourceSked();
int stage_num = 0;
StageScheduler F(res_sked, stage_num++);
StageScheduler D(res_sked, stage_num++);
D.needs(BPred, BranchPredictor::PredictBranch);
D.needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
+
+ DPRINTF(SkedCache, "Resource Sked created for instruction \"front_end\"\n");
+
return res_sked;
}
{
RSkedPtr res_sked = lookupSked(inst);
if (res_sked != NULL) {
+ DPRINTF(SkedCache, "Found %s in sked cache.\n",
+ inst->instName());
return res_sked;
+ } else {
+ res_sked = new ResourceSked();
}
int stage_num = ThePipeline::BackEndStartStage;
if (!inst->staticInst) {
warn_once("Static Instruction Object Not Set. Can't Create"
" Back End Schedule");
- return false;
+ return NULL;
}
// EXECUTE
W.needs(Grad, GraduationUnit::GraduateInst);
+ // Insert Front Schedule into our cache of
+ // resource schedules
+ addToSkedCache(inst, res_sked);
+
+ DPRINTF(SkedCache, "Back End Sked Created for instruction: %s (%08p)\n",
+ inst->instName(), inst->getMachInst());
+ res_sked->print();
+
return res_sked;
}
inst->setInstListIt(cpu->addInst(inst));
// Create Front-End Resource Schedule For Instruction
- ThePipeline::createFrontEndSchedule(inst);
+ inst->setFrontSked(cpu->frontEndSked);
}
int reqs_processed = 0;
const TheISA::PCState &instPC,
const TheISA::PCState &_predPC,
InstSeqNum seq_num, InOrderCPU *cpu)
- : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu)
+ : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
void
InOrderDynInst::initVars()
{
+ inFrontEnd = true;
+
fetchMemReq = NULL;
dataMemReq = NULL;
splitMemData = NULL;
////////////////////////////////////////////////////////////
std::string instName() { return staticInst->getName(); }
-
void setMachInst(ExtMachInst inst);
+ ExtMachInst getMachInst() { return staticInst->machInst; }
+
/** Sets the StaticInst. */
void setStaticInst(StaticInstPtr &static_inst);
// RESOURCE SCHEDULING
//
/////////////////////////////////////////////
+ typedef ThePipeline::RSkedPtr RSkedPtr;
+ bool inFrontEnd;
+
+ RSkedPtr frontSked;
+ RSkedIt frontSked_end;
+
+ RSkedPtr backSked;
+ RSkedIt backSked_end;
+
+ RSkedIt curSkedEntry;
+
+ void setFrontSked(RSkedPtr front_sked)
+ {
+ frontSked = front_sked;
+ frontSked_end.init(frontSked);
+ frontSked_end = frontSked->end();
+ //DPRINTF(InOrderDynInst, "Set FrontSked End to : %x \n" ,
+ // frontSked_end.getIt()/*, frontSked->end()*/);
+ //assert(frontSked_end == frontSked->end());
+
+ // This initializes instruction to be able
+ // to walk the resource schedule
+ curSkedEntry.init(frontSked);
+ curSkedEntry = frontSked->begin();
+ }
+
+ void setBackSked(RSkedPtr back_sked)
+ {
+ backSked = back_sked;
+ backSked_end.init(backSked);
+ backSked_end = backSked->end();
+ }
+
void setNextStage(int stage_num) { nextStage = stage_num; }
int getNextStage() { return nextStage; }
/** Print Resource Schedule */
- /** @NOTE: DEBUG ONLY */
- void printSched()
+ void printSked()
{
- ThePipeline::ResSchedule tempSched;
- std::cerr << "\tInst. Res. Schedule: ";
- while (!resSched.empty()) {
- std::cerr << '\t' << resSched.top()->stageNum << "-"
- << resSched.top()->resNum << ", ";
-
- tempSched.push(resSched.top());
- resSched.pop();
+ if (frontSked != NULL) {
+ frontSked->print();
}
- std::cerr << std::endl;
- resSched = tempSched;
+ if (backSked != NULL) {
+ backSked->print();
+ }
}
/** Return Next Resource Stage To Be Used */
int nextResStage()
{
- if (resSched.empty())
- return -1;
- else
- return resSched.top()->stageNum;
+ assert((inFrontEnd && curSkedEntry != frontSked_end) ||
+ (!inFrontEnd && curSkedEntry != backSked_end));
+
+ return curSkedEntry->stageNum;
}
/** Return Next Resource To Be Used */
int nextResource()
{
- if (resSched.empty())
- return -1;
- else
- return resSched.top()->resNum;
+ assert((inFrontEnd && curSkedEntry != frontSked_end) ||
+ (!inFrontEnd && curSkedEntry != backSked_end));
+
+ return curSkedEntry->resNum;
}
- /** Remove & Deallocate a schedule entry */
- void popSchedEntry()
+ /** Finish using a schedule entry, increment to next entry */
+ bool finishSkedEntry()
{
- if (!resSched.empty()) {
- ScheduleEntry* sked = resSched.top();
- resSched.pop();
- if (sked != 0) {
- delete sked;
-
- }
+ curSkedEntry++;
+
+ if (inFrontEnd && curSkedEntry == frontSked_end) {
+ assert(backSked != NULL);
+ curSkedEntry.init(backSked);
+ curSkedEntry = backSked->begin();
+ inFrontEnd = false;
+ } else if (!inFrontEnd && curSkedEntry == backSked_end) {
+ return true;
}
+
+ return false;
}
/** Release a Resource Request (Currently Unused) */
"completed.\n", tid, inst->seqNum,
cpu->resPool->name(res_num));
- inst->popSchedEntry();
-
reqs_processed++;
req->stagePasses++;
+
+ bool done_in_pipeline = inst->finishSkedEntry();
+ if (done_in_pipeline) {
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] finished "
+ "in pipeline.\n", tid, inst->seqNum);
+ break;
+ }
} else {
DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed."
"\n", tid, inst->seqNum, cpu->resPool->name(res_num));
// Activate Next Ready Thread at end of cycle
DPRINTF(ThreadModel, "Attempting to activate next ready "
"thread due to cache miss.\n");
- cpu->activateNextReadyContext();
+ cpu->activateNextReadyContext();
}
// Mark request for deletion
if (slot_num != -1) {
// Get Stage # from Schedule Entry
- stage_num = inst->resSched.top()->stageNum;
- unsigned cmd = inst->resSched.top()->cmd;
+ stage_num = inst->curSkedEntry->stageNum;
+ unsigned cmd = inst->curSkedEntry->cmd;
// Generate Resource Request
inst_req = getRequest(inst, stage_num, id, slot_num, cmd);
resources.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2, 4,
0, _cpu, params));
+
}
ResourcePool::~ResourcePool()
return cpu->name() + ".ResourcePool";
}
+void
+ResourcePool::print()
+{
+ for (int i=0; i < resources.size(); i++) {
+ DPRINTF(InOrderDynInst, "Res:%i %s\n",
+ i, resources[i]->name());
+ }
+
+}
+
void
ResourcePool::regStats()
void init();
+ void print();
+
/** Register Statistics in All Resources */
void regStats();
#include <vector>
#include <list>
-#include <stdio.h>
+#include <cstdio>
using namespace std;
using namespace ThePipeline;
ResourceSked::ResourceSked()
{
- sked.resize(NumStages);
+ stages.resize(NumStages);
}
void
ResourceSked::init()
{
- assert(!sked[0].empty());
+ assert(!stages[0].empty());
- curSkedEntry = sked[0].begin();
+ curSkedEntry = stages[0].begin();
}
int
ResourceSked::size()
{
int total = 0;
- for (int i = 0; i < sked.size(); i++) {
- total += sked[i].size();
+ for (int i = 0; i < stages.size(); i++) {
+ total += stages[i].size();
}
return total;
return size() == 0;
}
+
+ResourceSked::SkedIt
+ResourceSked::begin()
+{
+ int num_stages = stages.size();
+ for (int i = 0; i < num_stages; i++) {
+ if (stages[i].size() > 0)
+ return stages[i].begin();
+ }
+
+ return stages[num_stages - 1].end();
+}
+
+ResourceSked::SkedIt
+ResourceSked::end()
+{
+ int num_stages = stages.size();
+ return stages[num_stages - 1].end();
+}
+
ScheduleEntry*
ResourceSked::top()
{
{
int stage_num = (*curSkedEntry)->stageNum;
- sked[stage_num].erase(curSkedEntry);
+ stages[stage_num].erase(curSkedEntry);
- if (!sked[stage_num].empty()) {
- curSkedEntry = sked[stage_num].begin();
+ if (!stages[stage_num].empty()) {
+ curSkedEntry = stages[stage_num].begin();
} else {
int next_stage = stage_num + 1;
while (next_stage < NumStages) {
- if (sked[next_stage].empty()) {
+ if (stages[next_stage].empty()) {
next_stage++;
} else {
- curSkedEntry = sked[next_stage].begin();
+ curSkedEntry = stages[next_stage].begin();
break;
}
}
SkedIt pri_iter = findIterByPriority(sked_entry, stage_num);
- sked[stage_num].insert(pri_iter, sked_entry);
+ stages[stage_num].insert(pri_iter, sked_entry);
}
void
SkedIt pri_iter = findIterByCommand(sked_entry, stage_num,
sked_cmd, sked_cmd_idx);
- assert(pri_iter != sked[stage_num].end() &&
+ assert(pri_iter != stages[stage_num].end() &&
"Could not find command to insert in front of.");
- sked[stage_num].insert(pri_iter, sked_entry);
+ stages[stage_num].insert(pri_iter, sked_entry);
}
ResourceSked::SkedIt
ResourceSked::findIterByPriority(ScheduleEntry* sked_entry, int stage_num)
{
- if (sked[stage_num].empty()) {
- return sked[stage_num].end();
+ if (stages[stage_num].empty()) {
+ return stages[stage_num].end();
}
int priority = sked_entry->priority;
- SkedIt sked_it = sked[stage_num].begin();
- SkedIt sked_end = sked[stage_num].end();
+ SkedIt sked_it = stages[stage_num].begin();
+ SkedIt sked_end = stages[stage_num].end();
while (sked_it != sked_end) {
if ((*sked_it)->priority > priority)
ResourceSked::findIterByCommand(ScheduleEntry* sked_entry, int stage_num,
int sked_cmd, int sked_cmd_idx)
{
- if (sked[stage_num].empty()) {
- return sked[stage_num].end();
+ if (stages[stage_num].empty()) {
+ return stages[stage_num].end();
}
- SkedIt sked_it = sked[stage_num].begin();
- SkedIt sked_end = sked[stage_num].end();
+ SkedIt sked_it = stages[stage_num].begin();
+ SkedIt sked_end = stages[stage_num].end();
while (sked_it != sked_end) {
if ((*sked_it)->cmd == sked_cmd &&
void
ResourceSked::print()
{
- for (int i = 0; i < sked.size(); i++) {
- cprintf("Stage %i\n====\n", i);
- SkedIt sked_it = sked[i].begin();
- SkedIt sked_end = sked[i].end();
+ for (int i = 0; i < stages.size(); i++) {
+ //ccprintf(cerr, "Stage %i\n====\n", i);
+ SkedIt sked_it = stages[i].begin();
+ SkedIt sked_end = stages[i].end();
while (sked_it != sked_end) {
- cprintf("\t res:%i cmd:%i idx:%i\n", (*sked_it)->resNum, (*sked_it)->cmd, (*sked_it)->idx);
+ DPRINTF(SkedCache, "\t stage:%i res:%i cmd:%i idx:%i\n",
+ (*sked_it)->stageNum,
+ (*sked_it)->resNum,
+ (*sked_it)->cmd,
+ (*sked_it)->idx);
sked_it++;
}
}
if (cache_req &&
cache_req->getInst() == inst &&
- cache_req->instIdx == inst->resSched.top()->idx) {
+ cache_req->instIdx == inst->curSkedEntry->idx) {
return cache_req;
}
map_it++;
CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd)
{
- ScheduleEntry* sched_entry = inst->resSched.top();
+ ScheduleEntry* sched_entry = *inst->curSkedEntry;
if (!inst->validMemAddr()) {
panic("Mem. Addr. must be set before requesting cache access\n");
return new CacheRequest(this, inst, stage_num, id, slot_num,
sched_entry->cmd, 0, pkt_cmd,
0/*flags*/, this->cpu->readCpuId(),
- inst->resSched.top()->idx);
+ inst->curSkedEntry->idx);
}
void
// Check to see if this instruction is requesting the same command
// or a different one
- if (cache_req->cmd != inst->resSched.top()->cmd &&
- cache_req->instIdx == inst->resSched.top()->idx) {
+ if (cache_req->cmd != inst->curSkedEntry->cmd &&
+ cache_req->instIdx == inst->curSkedEntry->idx) {
// If different, then update command in the request
- cache_req->cmd = inst->resSched.top()->cmd;
+ cache_req->cmd = inst->curSkedEntry->cmd;
DPRINTF(InOrderCachePort,
"[tid:%i]: [sn:%i]: Updating the command for this "
"instruction\n ", inst->readTid(), inst->seqNum);
service_request = true;
- } else if (inst->resSched.top()->idx != CacheUnit::InitSecondSplitRead &&
- inst->resSched.top()->idx != CacheUnit::InitSecondSplitWrite) {
+ } else if (inst->curSkedEntry->idx != CacheUnit::InitSecondSplitRead &&
+ inst->curSkedEntry->idx != CacheUnit::InitSecondSplitWrite) {
// If same command, just check to see if memory access was completed
// but dont try to re-execute
DPRINTF(InOrderCachePort,
inst->splitMemData = new uint8_t[size];
if (!inst->splitInstSked) {
+ assert(0 && "Split Requests Not Supported for Now...");
+
// Schedule Split Read/Complete for Instruction
// ==============================
int stage_num = cache_req->getStageNum();
inst->splitInst = true;
if (!inst->splitInstSked) {
+ assert(0 && "Split Requests Not Supported for Now...");
+
// Schedule Split Read/Complete for Instruction
// ==============================
int stage_num = cache_req->getStageNum();
{
case DecodeInst:
{
- bool done_sked = ThePipeline::createBackEndSchedule(inst);
+ inst->setBackSked(cpu->createBackEndSked(inst));
- if (done_sked) {
+ if (inst->backSked != NULL) {
DPRINTF(InOrderDecode,
"[tid:%i]: Setting Destination Register(s) for [sn:%i].\n",
tid, inst->seqNum);
regDepMap[tid]->insert(inst);
+
+ //inst->printSked();
+
decode_req->done();
} else {
DPRINTF(Resource,
FetchUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd)
{
- ScheduleEntry* sched_entry = inst->resSched.top();
+ ScheduleEntry* sched_entry = *inst->curSkedEntry;
if (!inst->validMemAddr()) {
panic("Mem. Addr. must be set before requesting cache access\n");
return new CacheRequest(this, inst, stage_num, id, slot_num,
sched_entry->cmd, 0, pkt_cmd,
0/*flags*/, this->cpu->readCpuId(),
- inst->resSched.top()->idx);
+ inst->curSkedEntry->idx);
}
void
short asid = cpu->asid[tid];
assert(!cache_req->isSquashed());
- assert(inst->resSched.top()->cmd == CompleteFetch);
+ assert(inst->curSkedEntry->cmd == CompleteFetch);
DPRINTF(InOrderCachePort,
"[tid:%u]: [sn:%i]: Processing fetch access for block %#x\n",
ResourceRequest* grad_req = reqMap[slot_num];
DynInstPtr inst = reqMap[slot_num]->inst;
ThreadID tid = inst->readTid();
- int stage_num = inst->resSched.top()->stageNum;
+ int stage_num = inst->curSkedEntry->stageNum;
switch (grad_req->cmd)
{
case GraduateInst:
{
// Make sure this is the last thing on the resource schedule
- assert(inst->resSched.size() == 1);
+ // @todo: replace this check
+ // assert(inst->resSched.size() == 1);
// Handle Any Faults Before Graduating Instruction
if (inst->fault != NoFault) {
// Check to see if this instruction is requesting the same command
// or a different one
- if (mult_div_req->cmd != inst->resSched.top()->cmd) {
+ if (mult_div_req->cmd != inst->curSkedEntry->cmd) {
// If different, then update command in the request
- mult_div_req->cmd = inst->resSched.top()->cmd;
+ mult_div_req->cmd = inst->curSkedEntry->cmd;
DPRINTF(InOrderMDU,
"[tid:%i]: [sn:%i]: Updating the command for this "
"instruction\n", inst->readTid(), inst->seqNum);
// If we have this instruction's request already then return
if (slot_num != -1 &&
- inst->resSched.top()->cmd == reqMap[slot_num]->cmd)
+ inst->curSkedEntry->cmd == reqMap[slot_num]->cmd)
return slot_num;
unsigned repeat_rate = 0;
// Effectively NOP the instruction but still allow it
// to commit
//while (!inst->resSched.empty() &&
- // inst->resSched.top()->stageNum != ThePipeline::NumStages - 1) {
+ // inst->curSkedEntry->stageNum != ThePipeline::NumStages - 1) {
//inst->resSched.pop();
//}
}
int slot_num, unsigned cmd)
{
return new UseDefRequest(this, inst, stage_num, id, slot_num, cmd,
- inst->resSched.top()->idx);
+ inst->curSkedEntry->idx);
}
if (ud_req &&
ud_req->getInst() == inst &&
- ud_req->cmd == inst->resSched.top()->cmd &&
- ud_req->useDefIdx == inst->resSched.top()->idx) {
+ ud_req->cmd == inst->curSkedEntry->cmd &&
+ ud_req->useDefIdx == inst->curSkedEntry->idx) {
return ud_req;
}
map_it++;