summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/base_dyn_inst.hh125
-rw-r--r--src/cpu/base_dyn_inst_impl.hh15
-rw-r--r--src/cpu/inorder/SConscript3
-rw-r--r--src/cpu/inorder/cpu.cc173
-rw-r--r--src/cpu/inorder/cpu.hh96
-rw-r--r--src/cpu/inorder/first_stage.cc2
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.cc30
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.hh107
-rw-r--r--src/cpu/inorder/pipeline_stage.cc62
-rw-r--r--src/cpu/inorder/pipeline_stage.hh15
-rw-r--r--src/cpu/inorder/pipeline_traits.cc171
-rw-r--r--src/cpu/inorder/pipeline_traits.hh20
-rw-r--r--src/cpu/inorder/reg_dep_map.cc8
-rw-r--r--src/cpu/inorder/reg_dep_map.hh2
-rw-r--r--src/cpu/inorder/resource.cc253
-rw-r--r--src/cpu/inorder/resource.hh33
-rw-r--r--src/cpu/inorder/resource_pool.cc23
-rw-r--r--src/cpu/inorder/resource_pool.hh2
-rw-r--r--src/cpu/inorder/resource_sked.cc78
-rw-r--r--src/cpu/inorder/resource_sked.hh206
-rw-r--r--src/cpu/inorder/resources/agen_unit.cc4
-rw-r--r--src/cpu/inorder/resources/branch_predictor.cc2
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc161
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh47
-rw-r--r--src/cpu/inorder/resources/decode_unit.cc11
-rw-r--r--src/cpu/inorder/resources/execution_unit.cc47
-rw-r--r--src/cpu/inorder/resources/execution_unit.hh1
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.cc8
-rw-r--r--src/cpu/inorder/resources/fetch_unit.cc71
-rw-r--r--src/cpu/inorder/resources/fetch_unit.hh2
-rw-r--r--src/cpu/inorder/resources/graduation_unit.cc22
-rw-r--r--src/cpu/inorder/resources/graduation_unit.hh4
-rw-r--r--src/cpu/inorder/resources/inst_buffer.cc15
-rw-r--r--src/cpu/inorder/resources/inst_buffer_new.cc158
-rw-r--r--src/cpu/inorder/resources/inst_buffer_new.hh109
-rw-r--r--src/cpu/inorder/resources/mult_div_unit.cc22
-rw-r--r--src/cpu/inorder/resources/tlb_unit.cc56
-rw-r--r--src/cpu/inorder/resources/tlb_unit.hh15
-rw-r--r--src/cpu/inorder/resources/use_def.cc65
-rw-r--r--src/cpu/inorder/resources/use_def.hh18
-rw-r--r--src/cpu/o3/fetch.hh4
-rw-r--r--src/cpu/o3/fetch_impl.hh23
-rw-r--r--src/cpu/o3/iew_impl.hh21
-rw-r--r--src/cpu/o3/inst_queue.hh28
-rw-r--r--src/cpu/o3/inst_queue_impl.hh53
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh10
-rw-r--r--src/cpu/simple/timing.cc12
-rw-r--r--src/cpu/simple/timing.hh7
-rw-r--r--src/cpu/translation.hh32
49 files changed, 1355 insertions, 1097 deletions
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 0c566ec65..8b6662d70 100644
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
@@ -150,6 +162,29 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Finish a DTB address translation. */
void finishTranslation(WholeTranslationState *state);
+ /** True if the DTB address translation has started. */
+ bool translationStarted;
+
+ /** True if the DTB address translation has completed. */
+ bool translationCompleted;
+
+ /**
+ * Returns true if the DTB address translation is being delayed due to a hw
+ * page table walk.
+ */
+ bool isTranslationDelayed() const
+ {
+ return (translationStarted && !translationCompleted);
+ }
+
+ /**
+ * Saved memory requests (needed when the DTB address translation is
+ * delayed due to a hw page table walk).
+ */
+ RequestPtr savedReq;
+ RequestPtr savedSreqLow;
+ RequestPtr savedSreqHigh;
+
/** @todo: Consider making this private. */
public:
/** The sequence number of the instruction. */
@@ -835,33 +870,42 @@ BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
unsigned size, unsigned flags)
{
reqMade = true;
- Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
- thread->contextId(), threadNumber);
-
+ Request *req = NULL;
Request *sreqLow = NULL;
Request *sreqHigh = NULL;
- // Only split the request if the ISA supports unaligned accesses.
- if (TheISA::HasUnalignedMemAcc) {
- splitRequest(req, sreqLow, sreqHigh);
- }
- initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read);
-
- if (fault == NoFault) {
- effAddr = req->getVaddr();
- effAddrValid = true;
- fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
+ if (reqMade && translationStarted) {
+ req = savedReq;
+ sreqLow = savedSreqLow;
+ sreqHigh = savedSreqHigh;
} else {
- // Commit will have to clean up whatever happened. Set this
- // instruction as executed.
- this->setExecuted();
+ req = new Request(asid, addr, size, flags, this->pc.instAddr(),
+ thread->contextId(), threadNumber);
+
+ // Only split the request if the ISA supports unaligned accesses.
+ if (TheISA::HasUnalignedMemAcc) {
+ splitRequest(req, sreqLow, sreqHigh);
+ }
+ initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read);
}
- if (fault != NoFault) {
- // Return a fixed value to keep simulation deterministic even
- // along misspeculated paths.
- if (data)
- bzero(data, size);
+ if (translationCompleted) {
+ if (fault == NoFault) {
+ effAddr = req->getVaddr();
+ effAddrValid = true;
+ fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
+ } else {
+ // Commit will have to clean up whatever happened. Set this
+ // instruction as executed.
+ this->setExecuted();
+ }
+
+ if (fault != NoFault) {
+ // Return a fixed value to keep simulation deterministic even
+ // along misspeculated paths.
+ if (data)
+ bzero(data, size);
+ }
}
if (traceData) {
@@ -897,19 +941,26 @@ BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
}
reqMade = true;
- Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
- thread->contextId(), threadNumber);
-
+ Request *req = NULL;
Request *sreqLow = NULL;
Request *sreqHigh = NULL;
- // Only split the request if the ISA supports unaligned accesses.
- if (TheISA::HasUnalignedMemAcc) {
- splitRequest(req, sreqLow, sreqHigh);
+ if (reqMade && translationStarted) {
+ req = savedReq;
+ sreqLow = savedSreqLow;
+ sreqHigh = savedSreqHigh;
+ } else {
+ req = new Request(asid, addr, size, flags, this->pc.instAddr(),
+ thread->contextId(), threadNumber);
+
+ // Only split the request if the ISA supports unaligned accesses.
+ if (TheISA::HasUnalignedMemAcc) {
+ splitRequest(req, sreqLow, sreqHigh);
+ }
+ initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write);
}
- initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write);
- if (fault == NoFault) {
+ if (fault == NoFault && translationCompleted) {
effAddr = req->getVaddr();
effAddrValid = true;
fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx);
@@ -953,6 +1004,8 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
RequestPtr sreqHigh, uint64_t *res,
BaseTLB::Mode mode)
{
+ translationStarted = true;
+
if (!TheISA::HasUnalignedMemAcc || sreqLow == NULL) {
WholeTranslationState *state =
new WholeTranslationState(req, NULL, res, mode);
@@ -961,6 +1014,12 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
DataTranslation<BaseDynInst<Impl> > *trans =
new DataTranslation<BaseDynInst<Impl> >(this, state);
cpu->dtb->translateTiming(req, thread->getTC(), trans, mode);
+ if (!translationCompleted) {
+ // Save memory requests.
+ savedReq = state->mainReq;
+ savedSreqLow = state->sreqLow;
+ savedSreqHigh = state->sreqHigh;
+ }
} else {
WholeTranslationState *state =
new WholeTranslationState(req, sreqLow, sreqHigh, NULL, res, mode);
@@ -973,6 +1032,12 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode);
cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode);
+ if (!translationCompleted) {
+ // Save memory requests.
+ savedReq = state->mainReq;
+ savedSreqLow = state->sreqLow;
+ savedSreqHigh = state->sreqHigh;
+ }
}
}
@@ -998,6 +1063,8 @@ BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
state->deleteReqs();
}
delete state;
+
+ translationCompleted = true;
}
#endif // __CPU_BASE_DYN_INST_HH__
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
index 74f199d5f..7e4d25322 100644
--- a/src/cpu/base_dyn_inst_impl.hh
+++ b/src/cpu/base_dyn_inst_impl.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -107,6 +119,9 @@ BaseDynInst<Impl>::initVars()
effAddrValid = false;
physEffAddr = 0;
+ translationStarted = false;
+ translationCompleted = false;
+
isUncacheable = false;
reqMade = false;
readyRegs = 0;
diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript
index ae5ec0257..b9c526763 100644
--- a/src/cpu/inorder/SConscript
+++ b/src/cpu/inorder/SConscript
@@ -55,7 +55,7 @@ if 'InOrderCPU' in env['CPU_MODELS']:
TraceFlag('ThreadModel')
TraceFlag('RefCount')
TraceFlag('AddrDep')
-
+ TraceFlag('SkedCache')
CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU',
'InOrderMDU', 'InOrderAGEN', 'InOrderFetchSeq', 'InOrderTLB', 'InOrderBPred',
@@ -63,7 +63,6 @@ if 'InOrderCPU' in env['CPU_MODELS']:
'InOrderGraduation', 'InOrderCachePort', 'RegDepMap', 'Resource',
'ThreadModel', 'AddrDep'])
- Source('pipeline_traits.cc')
Source('inorder_dyn_inst.cc')
Source('inorder_cpu_builder.cc')
Source('inorder_trace.cc')
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index ffdcae7df..0ec4c9861 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -324,19 +324,19 @@ InOrderCPU::InOrderCPU(Params *params)
tid,
asid[tid]);
- dummyReq[tid] = new ResourceRequest(resPool->getResource(0),
- dummyInst[tid],
- 0,
- 0,
- 0,
- 0);
+ dummyReq[tid] = new ResourceRequest(resPool->getResource(0));
}
dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0);
dummyReqInst->setSquashed();
+ dummyReqInst->resetInstCount();
dummyBufferInst = new InOrderDynInst(this, NULL, 0, 0, 0);
dummyBufferInst->setSquashed();
+ dummyBufferInst->resetInstCount();
+
+ endOfSkedIt = skedCache.end();
+ frontEndSked = createFrontEndSked();
lastRunningCycle = curTick();
@@ -348,7 +348,6 @@ InOrderCPU::InOrderCPU(Params *params)
reset();
#endif
- dummyBufferInst->resetInstCount();
// Schedule First Tick Event, CPU will reschedule itself from here on out.
scheduleTickEvent(0);
@@ -357,8 +356,131 @@ InOrderCPU::InOrderCPU(Params *params)
InOrderCPU::~InOrderCPU()
{
delete resPool;
+
+ std::map<SkedID, ThePipeline::RSkedPtr>::iterator sked_it =
+ skedCache.begin();
+ std::map<SkedID, ThePipeline::RSkedPtr>::iterator sked_end =
+ skedCache.end();
+
+ while (sked_it != sked_end) {
+ delete (*sked_it).second;
+ sked_it++;
+ }
+ skedCache.clear();
}
+std::map<InOrderCPU::SkedID, ThePipeline::RSkedPtr> InOrderCPU::skedCache;
+
+RSkedPtr
+InOrderCPU::createFrontEndSked()
+{
+ RSkedPtr res_sked = new ResourceSked();
+ int stage_num = 0;
+ StageScheduler F(res_sked, stage_num++);
+ StageScheduler D(res_sked, stage_num++);
+
+ // FETCH
+ F.needs(FetchSeq, FetchSeqUnit::AssignNextPC);
+ F.needs(ICache, FetchUnit::InitiateFetch);
+
+ // DECODE
+ D.needs(ICache, FetchUnit::CompleteFetch);
+ D.needs(Decode, DecodeUnit::DecodeInst);
+ D.needs(BPred, BranchPredictor::PredictBranch);
+ D.needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
+
+
+ DPRINTF(SkedCache, "Resource Sked created for instruction \"front_end\"\n");
+
+ return res_sked;
+}
+
+RSkedPtr
+InOrderCPU::createBackEndSked(DynInstPtr inst)
+{
+ 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;
+ StageScheduler X(res_sked, stage_num++);
+ StageScheduler M(res_sked, stage_num++);
+ StageScheduler W(res_sked, stage_num++);
+
+ if (!inst->staticInst) {
+ warn_once("Static Instruction Object Not Set. Can't Create"
+ " Back End Schedule");
+ return NULL;
+ }
+
+ // EXECUTE
+ for (int idx=0; idx < inst->numSrcRegs(); idx++) {
+ if (!idx || !inst->isStore()) {
+ X.needs(RegManager, UseDefUnit::ReadSrcReg, idx);
+ }
+ }
+
+ if ( inst->isNonSpeculative() ) {
+ // skip execution of non speculative insts until later
+ } else if ( inst->isMemRef() ) {
+ if ( inst->isLoad() ) {
+ X.needs(AGEN, AGENUnit::GenerateAddr);
+ }
+ } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
+ X.needs(MDU, MultDivUnit::StartMultDiv);
+ } else {
+ X.needs(ExecUnit, ExecutionUnit::ExecuteInst);
+ }
+
+ if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
+ X.needs(MDU, MultDivUnit::EndMultDiv);
+ }
+
+ // MEMORY
+ if ( inst->isLoad() ) {
+ M.needs(DCache, CacheUnit::InitiateReadData);
+ } else if ( inst->isStore() ) {
+ if ( inst->numSrcRegs() >= 2 ) {
+ M.needs(RegManager, UseDefUnit::ReadSrcReg, 1);
+ }
+ M.needs(AGEN, AGENUnit::GenerateAddr);
+ M.needs(DCache, CacheUnit::InitiateWriteData);
+ }
+
+
+ // WRITEBACK
+ if ( inst->isLoad() ) {
+ W.needs(DCache, CacheUnit::CompleteReadData);
+ } else if ( inst->isStore() ) {
+ W.needs(DCache, CacheUnit::CompleteWriteData);
+ }
+
+ if ( inst->isNonSpeculative() ) {
+ if ( inst->isMemRef() ) fatal("Non-Speculative Memory Instruction");
+ W.needs(ExecUnit, ExecutionUnit::ExecuteInst);
+ }
+
+ W.needs(Grad, GraduationUnit::GraduateInst);
+
+ for (int idx=0; idx < inst->numDestRegs(); idx++) {
+ W.needs(RegManager, UseDefUnit::WriteDestReg, idx);
+ }
+
+ // Insert Back 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;
+}
void
InOrderCPU::regStats()
@@ -520,8 +642,7 @@ InOrderCPU::tick()
}
activityRec.advance();
- // Any squashed requests, events, or insts then remove them now
- cleanUpRemovedReqs();
+ // Any squashed events, or insts then remove them now
cleanUpRemovedEvents();
cleanUpRemovedInsts();
@@ -1299,14 +1420,6 @@ InOrderCPU::cleanUpRemovedInsts()
DynInstPtr inst = *removeList.front();
ThreadID tid = inst->threadNumber;
- // Make Sure Resource Schedule Is Emptied Out
- ThePipeline::ResSchedule *inst_sched = &inst->resSched;
- while (!inst_sched->empty()) {
- ScheduleEntry* sch_entry = inst_sched->top();
- inst_sched->pop();
- delete sch_entry;
- }
-
// Remove From Register Dependency Map, If Necessary
archRegDepMap[(*removeList.front())->threadNumber].
remove((*removeList.front()));
@@ -1314,8 +1427,8 @@ InOrderCPU::cleanUpRemovedInsts()
// Clear if Non-Speculative
if (inst->staticInst &&
- inst->seqNum == nonSpecSeqNum[tid] &&
- nonSpecInstActive[tid] == true) {
+ inst->seqNum == nonSpecSeqNum[tid] &&
+ nonSpecInstActive[tid] == true) {
nonSpecInstActive[tid] = false;
}
@@ -1328,28 +1441,6 @@ InOrderCPU::cleanUpRemovedInsts()
}
void
-InOrderCPU::cleanUpRemovedReqs()
-{
- while (!reqRemoveList.empty()) {
- ResourceRequest *res_req = reqRemoveList.front();
-
- DPRINTF(RefCount, "[tid:%i] [sn:%lli]: Removing Request "
- "[stage_num:%i] [res:%s] [slot:%i] [completed:%i].\n",
- res_req->inst->threadNumber,
- res_req->inst->seqNum,
- res_req->getStageNum(),
- res_req->res->name(),
- (res_req->isCompleted()) ?
- res_req->getComplSlot() : res_req->getSlot(),
- res_req->isCompleted());
-
- reqRemoveList.pop();
-
- delete res_req;
- }
-}
-
-void
InOrderCPU::cleanUpRemovedEvents()
{
while (!cpuEventRemoveList.empty()) {
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
index 9ff0f12ce..2fa6bdc59 100644
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -296,6 +296,92 @@ class InOrderCPU : public BaseCPU
TheISA::TLB *getITBPtr();
TheISA::TLB *getDTBPtr();
+ /** Accessor Type for the SkedCache */
+ typedef uint32_t SkedID;
+
+ /** Cache of Instruction Schedule using the instruction's name as a key */
+ static std::map<SkedID, ThePipeline::RSkedPtr> skedCache;
+
+ typedef std::map<SkedID, ThePipeline::RSkedPtr>::iterator SkedCacheIt;
+
+ /** Initialized to last iterator in map, signifying a invalid entry
+ on map searches
+ */
+ SkedCacheIt endOfSkedIt;
+
+ ThePipeline::RSkedPtr frontEndSked;
+
+ /** Add a new instruction schedule to the schedule cache */
+ void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked)
+ {
+ SkedID sked_id = genSkedID(inst);
+ assert(skedCache.find(sked_id) == skedCache.end());
+ skedCache[sked_id] = inst_sked;
+ }
+
+
+ /** Find a instruction schedule */
+ ThePipeline::RSkedPtr lookupSked(DynInstPtr inst)
+ {
+ SkedID sked_id = genSkedID(inst);
+ SkedCacheIt lookup_it = skedCache.find(sked_id);
+
+ if (lookup_it != endOfSkedIt) {
+ return (*lookup_it).second;
+ } else {
+ return NULL;
+ }
+ }
+
+ static const uint8_t INST_OPCLASS = 26;
+ static const uint8_t INST_LOAD = 25;
+ static const uint8_t INST_STORE = 24;
+ static const uint8_t INST_CONTROL = 23;
+ static const uint8_t INST_NONSPEC = 22;
+ static const uint8_t INST_DEST_REGS = 18;
+ static const uint8_t INST_SRC_REGS = 14;
+
+ inline SkedID genSkedID(DynInstPtr inst)
+ {
+ SkedID id = 0;
+ id = (inst->opClass() << INST_OPCLASS) |
+ (inst->isLoad() << INST_LOAD) |
+ (inst->isStore() << INST_STORE) |
+ (inst->isControl() << INST_CONTROL) |
+ (inst->isNonSpeculative() << INST_NONSPEC) |
+ (inst->numDestRegs() << INST_DEST_REGS) |
+ (inst->numSrcRegs() << INST_SRC_REGS);
+ return id;
+ }
+
+ ThePipeline::RSkedPtr createFrontEndSked();
+ ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst);
+
+ class StageScheduler {
+ private:
+ ThePipeline::RSkedPtr rsked;
+ int stageNum;
+ int nextTaskPriority;
+
+ public:
+ StageScheduler(ThePipeline::RSkedPtr _rsked, int stage_num)
+ : rsked(_rsked), stageNum(stage_num),
+ nextTaskPriority(0)
+ { }
+
+ void needs(int unit, int request) {
+ rsked->push(new ScheduleEntry(
+ stageNum, nextTaskPriority++, unit, request
+ ));
+ }
+
+ void needs(int unit, int request, int param) {
+ rsked->push(new ScheduleEntry(
+ stageNum, nextTaskPriority++, unit, request, param
+ ));
+ }
+ };
+
public:
/** Registers statistics. */
@@ -508,10 +594,7 @@ class InOrderCPU : public BaseCPU
/** Cleans up all instructions on the instruction remove list. */
void cleanUpRemovedInsts();
- /** Cleans up all instructions on the request remove list. */
- void cleanUpRemovedReqs();
-
- /** Cleans up all instructions on the CPU event remove list. */
+ /** Cleans up all events on the CPU event remove list. */
void cleanUpRemovedEvents();
/** Debug function to print all instructions on the list. */
@@ -541,11 +624,6 @@ class InOrderCPU : public BaseCPU
*/
std::queue<ListIt> removeList;
- /** List of all the resource requests that will be removed at the end
- * of this cycle.
- */
- std::queue<ResourceRequest*> reqRemoveList;
-
/** List of all the cpu event requests that will be removed at the end of
* the current cycle.
*/
diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc
index 71c6ec3e0..b656ca1c7 100644
--- a/src/cpu/inorder/first_stage.cc
+++ b/src/cpu/inorder/first_stage.cc
@@ -181,7 +181,7 @@ FirstStage::processInsts(ThreadID tid)
inst->setInstListIt(cpu->addInst(inst));
// Create Front-End Resource Schedule For Instruction
- ThePipeline::createFrontEndSchedule(inst);
+ inst->setFrontSked(cpu->frontEndSked);
}
int reqs_processed = 0;
diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc
index 6afe35862..e9deb7625 100644
--- a/src/cpu/inorder/inorder_dyn_inst.cc
+++ b/src/cpu/inorder/inorder_dyn_inst.cc
@@ -51,7 +51,7 @@ InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst,
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;
@@ -108,6 +108,8 @@ InOrderDynInst::setMachInst(ExtMachInst machInst)
void
InOrderDynInst::initVars()
{
+ inFrontEnd = true;
+
fetchMemReq = NULL;
dataMemReq = NULL;
splitMemData = NULL;
@@ -123,7 +125,6 @@ InOrderDynInst::initVars()
readyRegs = 0;
nextStage = 0;
- nextInstStageNum = 0;
for(int i = 0; i < MaxInstDestRegs; i++)
instResult[i].val.integer = 0;
@@ -206,8 +207,6 @@ InOrderDynInst::~InOrderDynInst()
--instcount;
- deleteStages();
-
DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
" (active insts: %i)\n", threadNumber, seqNum, instcount);
}
@@ -282,29 +281,6 @@ InOrderDynInst::completeAcc(Packet *pkt)
return this->fault;
}
-InstStage *InOrderDynInst::addStage()
-{
- this->currentInstStage = new InstStage(this, nextInstStageNum++);
- instStageList.push_back( this->currentInstStage );
- return this->currentInstStage;
-}
-
-InstStage *InOrderDynInst::addStage(int stage_num)
-{
- nextInstStageNum = stage_num;
- return InOrderDynInst::addStage();
-}
-
-void InOrderDynInst::deleteStages() {
- std::list<InstStage*>::iterator list_it = instStageList.begin();
- std::list<InstStage*>::iterator list_end = instStageList.end();
-
- while(list_it != list_end) {
- delete *list_it;
- list_it++;
- }
-}
-
Fault
InOrderDynInst::memAccess()
{
diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh
index 1c0ee4384..0e6be3da2 100644
--- a/src/cpu/inorder/inorder_dyn_inst.hh
+++ b/src/cpu/inorder/inorder_dyn_inst.hh
@@ -210,9 +210,6 @@ class InOrderDynInst : public FastAlloc, public RefCounted
/** Data used for a store for operation. */
uint64_t storeData;
- /** The resource schedule for this inst */
- ThePipeline::ResSchedule resSched;
-
/** List of active resource requests for this instruction */
std::list<ResourceRequest*> reqList;
@@ -304,11 +301,6 @@ class InOrderDynInst : public FastAlloc, public RefCounted
int nextStage;
- /* vars to keep track of InstStage's - used for resource sched defn */
- int nextInstStageNum;
- ThePipeline::InstStage *currentInstStage;
- std::list<ThePipeline::InstStage*> instStageList;
-
private:
/** Function to initialize variables in the constructors. */
void initVars();
@@ -337,9 +329,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted
////////////////////////////////////////////////////////////
std::string instName() { return staticInst->getName(); }
-
void setMachInst(ExtMachInst inst);
+ ExtMachInst getMachInst() { return staticInst->machInst; }
+
/** Sets the StaticInst. */
void setStaticInst(StaticInstPtr &static_inst);
@@ -411,68 +404,88 @@ class InOrderDynInst : public FastAlloc, public RefCounted
// RESOURCE SCHEDULING
//
/////////////////////////////////////////////
+ typedef ThePipeline::RSkedPtr RSkedPtr;
+ bool inFrontEnd;
- void setNextStage(int stage_num) { nextStage = stage_num; }
- int getNextStage() { return nextStage; }
+ RSkedPtr frontSked;
+ RSkedIt frontSked_end;
+
+ RSkedPtr backSked;
+ RSkedIt backSked_end;
- ThePipeline::InstStage *addStage();
- ThePipeline::InstStage *addStage(int stage);
- ThePipeline::InstStage *currentStage() { return currentInstStage; }
- void deleteStages();
+ 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();
+ }
- /** Add A Entry To Reource Schedule */
- void addToSched(ScheduleEntry* sched_entry)
- { resSched.push(sched_entry); }
+ 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) */
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index 744ffd4d2..b267ac00e 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -44,12 +44,17 @@ PipelineStage::PipelineStage(Params *params, unsigned stage_num)
stageBufferMax(params->stageWidth),
prevStageValid(false), nextStageValid(false), idle(false)
{
- switchedOutBuffer.resize(ThePipeline::MaxThreads);
- switchedOutValid.resize(ThePipeline::MaxThreads);
-
init(params);
}
+PipelineStage::~PipelineStage()
+{
+ for(ThreadID tid = 0; tid < numThreads; tid++) {
+ skidBuffer[tid].clear();
+ stalls[tid].resources.clear();
+ }
+}
+
void
PipelineStage::init(Params *params)
{
@@ -66,6 +71,12 @@ PipelineStage::init(Params *params)
else
lastStallingStage[tid] = NumStages - 1;
}
+
+ if ((InOrderCPU::ThreadModel) params->threadModel ==
+ InOrderCPU::SwitchOnCacheMiss) {
+ switchedOutBuffer.resize(ThePipeline::MaxThreads);
+ switchedOutValid.resize(ThePipeline::MaxThreads);
+ }
}
@@ -190,9 +201,6 @@ PipelineStage::takeOverFrom()
stalls[tid].resources.clear();
- while (!insts[tid].empty())
- insts[tid].pop();
-
skidBuffer[tid].clear();
}
wroteToTimeBuffer = false;
@@ -938,17 +946,24 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
"\n", tid, inst->seqNum, cpu->resPool->name(res_num));
ResReqPtr req = cpu->resPool->request(res_num, inst);
+ assert(req->valid);
- if (req->isCompleted()) {
+ bool req_completed = req->isCompleted();
+ bool done_in_pipeline = false;
+ if (req_completed) {
DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s "
"completed.\n", tid, inst->seqNum,
cpu->resPool->name(res_num));
- inst->popSchedEntry();
-
reqs_processed++;
req->stagePasses++;
+
+ done_in_pipeline = inst->finishSkedEntry();
+ if (done_in_pipeline) {
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] finished "
+ "in pipeline.\n", tid, inst->seqNum);
+ }
} else {
DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed."
"\n", tid, inst->seqNum, cpu->resPool->name(res_num));
@@ -982,23 +997,20 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
// Activate Next Ready Thread at end of cycle
DPRINTF(ThreadModel, "Attempting to activate next ready "
"thread due to cache miss.\n");
- cpu->activateNextReadyContext();
- }
-
- // Mark request for deletion
- // if it isnt currently being used by a resource
- if (!req->hasSlot()) {
- DPRINTF(InOrderStage, "[sn:%i] Deleting Request, has no "
- "slot in resource.\n", inst->seqNum);
-
- cpu->reqRemoveList.push(req);
- } else {
- DPRINTF(InOrderStage, "[sn:%i] Ignoring Request Deletion, "
- "in resource [slot:%i].\n", inst->seqNum,
- req->getSlot());
+ cpu->activateNextReadyContext();
}
-
-
+ }
+
+ // If this request is no longer needs to take up bandwidth in the
+ // resource, go ahead and free that bandwidth up
+ if (req->doneInResource) {
+ req->freeSlot();
+ }
+
+ // No longer need to process this instruction if the last
+ // request it had wasn't completed or if there is nothing
+ // else for it to do in the pipeline
+ if (done_in_pipeline || !req_completed) {
break;
}
diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh
index dfa88de87..ec70fefc5 100644
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -91,10 +91,7 @@ class PipelineStage
public:
PipelineStage(Params *params, unsigned stage_num);
- /** MUST use init() function if this constructor is used. */
- PipelineStage() { }
-
- virtual ~PipelineStage() { }
+ virtual ~PipelineStage();
/** PipelineStage initialization. */
void init(Params *params);
@@ -268,16 +265,6 @@ class PipelineStage
*/
unsigned instsProcessed;
- /** Queue of all instructions coming from previous stage on this cycle. */
- std::queue<DynInstPtr> insts[ThePipeline::MaxThreads];
-
- /** Queue of instructions that are finished processing and ready to go
- * next stage. This is used to prevent from processing an instrution more
- * than once on any stage. NOTE: It is up to the PROGRAMMER must manage
- * this as a queue
- */
- std::list<DynInstPtr> instsToNextStage;
-
/** Skid buffer between previous stage and this one. */
std::list<DynInstPtr> skidBuffer[ThePipeline::MaxThreads];
diff --git a/src/cpu/inorder/pipeline_traits.cc b/src/cpu/inorder/pipeline_traits.cc
deleted file mode 100644
index a6fad68f7..000000000
--- a/src/cpu/inorder/pipeline_traits.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2007 MIPS Technologies, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Korey Sewell
- *
- */
-
-#include "cpu/inorder/pipeline_traits.hh"
-#include "cpu/inorder/inorder_dyn_inst.hh"
-#include "cpu/inorder/resources/resource_list.hh"
-
-using namespace std;
-
-namespace ThePipeline {
-
-//@TODO: create my own Instruction Schedule Class
-//that operates as a Priority QUEUE
-int getNextPriority(DynInstPtr &inst, int stage_num)
-{
- int cur_pri = 20;
-
- /*
- std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>,
- entryCompare>::iterator sked_it = inst->resSched.begin();
-
- std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>,
- entryCompare>::iterator sked_end = inst->resSched.end();
-
- while (sked_it != sked_end) {
-
- if (sked_it.top()->stageNum == stage_num) {
- cur_pri = sked_it.top()->priority;
- }
-
- sked_it++;
- }
- */
-
- return cur_pri;
-}
-
-void createFrontEndSchedule(DynInstPtr &inst)
-{
- InstStage *F = inst->addStage();
- InstStage *D = inst->addStage();
-
- // FETCH
- F->needs(FetchSeq, FetchSeqUnit::AssignNextPC);
- F->needs(ICache, FetchUnit::InitiateFetch);
-
- // DECODE
- D->needs(ICache, FetchUnit::CompleteFetch);
- D->needs(Decode, DecodeUnit::DecodeInst);
- D->needs(BPred, BranchPredictor::PredictBranch);
- D->needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
-
- inst->resSched.init();
-}
-
-bool createBackEndSchedule(DynInstPtr &inst)
-{
- if (!inst->staticInst) {
- return false;
- }
-
- InstStage *X = inst->addStage();
- InstStage *M = inst->addStage();
- InstStage *W = inst->addStage();
-
- // EXECUTE
- for (int idx=0; idx < inst->numSrcRegs(); idx++) {
- if (!idx || !inst->isStore()) {
- X->needs(RegManager, UseDefUnit::ReadSrcReg, idx);
- }
- }
-
- if ( inst->isNonSpeculative() ) {
- // skip execution of non speculative insts until later
- } else if ( inst->isMemRef() ) {
- if ( inst->isLoad() ) {
- X->needs(AGEN, AGENUnit::GenerateAddr);
- }
- } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
- X->needs(MDU, MultDivUnit::StartMultDiv);
- } else {
- X->needs(ExecUnit, ExecutionUnit::ExecuteInst);
- }
-
- if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
- X->needs(MDU, MultDivUnit::EndMultDiv);
- }
-
- // MEMORY
- if ( inst->isLoad() ) {
- M->needs(DCache, CacheUnit::InitiateReadData);
- } else if ( inst->isStore() ) {
- if ( inst->numSrcRegs() >= 2 ) {
- M->needs(RegManager, UseDefUnit::ReadSrcReg, 1);
- }
- M->needs(AGEN, AGENUnit::GenerateAddr);
- M->needs(DCache, CacheUnit::InitiateWriteData);
- }
-
-
- // WRITEBACK
- if ( inst->isLoad() ) {
- W->needs(DCache, CacheUnit::CompleteReadData);
- } else if ( inst->isStore() ) {
- W->needs(DCache, CacheUnit::CompleteWriteData);
- }
-
- if ( inst->isNonSpeculative() ) {
- if ( inst->isMemRef() ) fatal("Non-Speculative Memory Instruction");
- W->needs(ExecUnit, ExecutionUnit::ExecuteInst);
- }
-
- for (int idx=0; idx < inst->numDestRegs(); idx++) {
- W->needs(RegManager, UseDefUnit::WriteDestReg, idx);
- }
-
- W->needs(Grad, GraduationUnit::GraduateInst);
-
- return true;
-}
-
-InstStage::InstStage(DynInstPtr inst, int stage_num)
-{
- stageNum = stage_num;
- nextTaskPriority = 0;
- instSched = &inst->resSched;
-}
-
-void
-InstStage::needs(int unit, int request) {
- instSched->push( new ScheduleEntry(
- stageNum, nextTaskPriority++, unit, request
- ));
-}
-
-void
-InstStage::needs(int unit, int request, int param) {
- instSched->push( new ScheduleEntry(
- stageNum, nextTaskPriority++, unit, request, param
- ));
-}
-
-};
diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh
index df964e254..573c0200a 100644
--- a/src/cpu/inorder/pipeline_traits.hh
+++ b/src/cpu/inorder/pipeline_traits.hh
@@ -51,7 +51,7 @@ class ResourceSked;
namespace ThePipeline {
// Pipeline Constants
const unsigned NumStages = 5;
- const ThreadID MaxThreads = 8;
+ const ThreadID MaxThreads = 1;
const unsigned BackEndStartStage = 2;
// List of Resources The Pipeline Uses
@@ -77,23 +77,7 @@ namespace ThePipeline {
// RESOURCE SCHEDULING
//////////////////////////
typedef ResourceSked ResSchedule;
-
- void createFrontEndSchedule(DynInstPtr &inst);
- bool createBackEndSchedule(DynInstPtr &inst);
- int getNextPriority(DynInstPtr &inst, int stage_num);
-
- class InstStage {
- private:
- int nextTaskPriority;
- int stageNum;
- ResSchedule *instSched;
-
- public:
- InstStage(DynInstPtr inst, int stage_num);
-
- void needs(int unit, int request);
- void needs(int unit, int request, int param);
- };
+ typedef ResourceSked* RSkedPtr;
};
diff --git a/src/cpu/inorder/reg_dep_map.cc b/src/cpu/inorder/reg_dep_map.cc
index 98a0727a9..48820b50e 100644
--- a/src/cpu/inorder/reg_dep_map.cc
+++ b/src/cpu/inorder/reg_dep_map.cc
@@ -45,6 +45,14 @@ RegDepMap::RegDepMap(int size)
regMap.resize(size);
}
+RegDepMap::~RegDepMap()
+{
+ for (int i = 0; i < regMap.size(); i++) {
+ regMap[i].clear();
+ }
+ regMap.clear();
+}
+
string
RegDepMap::name()
{
diff --git a/src/cpu/inorder/reg_dep_map.hh b/src/cpu/inorder/reg_dep_map.hh
index fa4fe45f3..047e4d129 100644
--- a/src/cpu/inorder/reg_dep_map.hh
+++ b/src/cpu/inorder/reg_dep_map.hh
@@ -48,7 +48,7 @@ class RegDepMap
public:
RegDepMap(int size = TheISA::TotalNumRegs);
- ~RegDepMap() { }
+ ~RegDepMap();
std::string name();
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
index 51beb5aa0..24211532e 100644
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -31,6 +31,8 @@
#include <vector>
#include <list>
+
+#include "base/str.hh"
#include "cpu/inorder/resource.hh"
#include "cpu/inorder/cpu.hh"
using namespace std;
@@ -40,22 +42,42 @@ Resource::Resource(string res_name, int res_id, int res_width,
: resName(res_name), id(res_id),
width(res_width), latency(res_latency), cpu(_cpu)
{
+ reqs.resize(width);
+
// Use to deny a instruction a resource.
- deniedReq = new ResourceRequest(this, NULL, 0, 0, 0, 0);
+ deniedReq = new ResourceRequest(this);
+ deniedReq->valid = true;
}
Resource::~Resource()
{
- delete [] resourceEvent;
- delete deniedReq;
+ if (resourceEvent) {
+ delete [] resourceEvent;
+ }
+
+ delete deniedReq;
+
+ for (int i = 0; i < width; i++) {
+ delete reqs[i];
+ }
}
void
Resource::init()
{
- // Set Up Resource Events to Appropriate Resource BandWidth
- resourceEvent = new ResourceEvent[width];
+ // If the resource has a zero-cycle (no latency)
+ // function, then no reason to have events
+ // that will process them for the right tick
+ if (latency > 0) {
+ resourceEvent = new ResourceEvent[width];
+ } else {
+ resourceEvent = NULL;
+ }
+
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new ResourceRequest(this);
+ }
initSlots();
}
@@ -66,7 +88,10 @@ Resource::initSlots()
// Add available slot numbers for resource
for (int slot_idx = 0; slot_idx < width; slot_idx++) {
availSlots.push_back(slot_idx);
- resourceEvent[slot_idx].init(this, slot_idx);
+
+ if (resourceEvent) {
+ resourceEvent[slot_idx].init(this, slot_idx);
+ }
}
}
@@ -91,42 +116,34 @@ Resource::slotsInUse()
void
Resource::freeSlot(int slot_idx)
{
+ DPRINTF(Resource, "Deallocating [slot:%i].\n",
+ slot_idx);
+
// Put slot number on this resource's free list
availSlots.push_back(slot_idx);
- // Erase Request Pointer From Request Map
- std::map<int, ResReqPtr>::iterator req_it = reqMap.find(slot_idx);
-
- assert(req_it != reqMap.end());
- reqMap.erase(req_it);
-
+ // Invalidate Request & Reset it's flags
+ reqs[slot_idx]->clearRequest();
}
-// TODO: More efficiently search for instruction's slot within
-// resource.
int
Resource::findSlot(DynInstPtr inst)
{
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
int slot_num = -1;
- while (map_it != map_end) {
- if ((*map_it).second->getInst()->seqNum ==
- inst->seqNum) {
- slot_num = (*map_it).second->getSlot();
+ for (int i = 0; i < width; i++) {
+ if (reqs[i]->valid &&
+ reqs[i]->getInst()->seqNum == inst->seqNum) {
+ slot_num = reqs[i]->getSlot();
}
- map_it++;
}
-
return slot_num;
}
int
Resource::getSlot(DynInstPtr inst)
{
- int slot_num;
+ int slot_num = -1;
if (slotsAvail() != 0) {
slot_num = availSlots[0];
@@ -136,24 +153,6 @@ Resource::getSlot(DynInstPtr inst)
assert(slot_num == *vect_it);
availSlots.erase(vect_it);
- } else {
- DPRINTF(Resource, "[tid:%i]: No slots in resource "
- "available to service [sn:%i].\n", inst->readTid(),
- inst->seqNum);
- slot_num = -1;
-
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
- if ((*map_it).second) {
- DPRINTF(Resource, "Currently Serving request from: "
- "[tid:%i] [sn:%i].\n",
- (*map_it).second->getInst()->readTid(),
- (*map_it).second->getInst()->seqNum);
- }
- map_it++;
- }
}
return slot_num;
@@ -183,9 +182,12 @@ Resource::request(DynInstPtr inst)
slot_num = getSlot(inst);
if (slot_num != -1) {
+ DPRINTF(Resource, "Allocating [slot:%i] for [tid:%i]: [sn:%i]\n",
+ slot_num, inst->readTid(), inst->seqNum);
+
// 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);
@@ -200,10 +202,12 @@ Resource::request(DynInstPtr inst)
inst->readTid());
}
- reqMap[slot_num] = inst_req;
-
try_request = true;
+ } else {
+ DPRINTF(Resource, "No slot available for [tid:%i]: [sn:%i]\n",
+ inst->readTid(), inst->seqNum);
}
+
}
if (try_request) {
@@ -236,32 +240,21 @@ ResReqPtr
Resource::getRequest(DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd)
{
- return new ResourceRequest(this, inst, stage_num, id, slot_num,
- cmd);
+ reqs[slot_num]->setRequest(inst, stage_num, id, slot_num, cmd);
+ return reqs[slot_num];
}
ResReqPtr
Resource::findRequest(DynInstPtr inst)
{
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- bool found = false;
- ResReqPtr req = NULL;
-
- while (map_it != map_end) {
- if ((*map_it).second &&
- (*map_it).second->getInst() == inst) {
- req = (*map_it).second;
- //return (*map_it).second;
- assert(found == false);
- found = true;
+ for (int i = 0; i < width; i++) {
+ if (reqs[i]->valid &&
+ reqs[i]->getInst() == inst) {
+ return reqs[i];
}
- map_it++;
}
- return req;
- //return NULL;
+ return NULL;
}
void
@@ -275,9 +268,9 @@ void
Resource::execute(int slot_idx)
{
DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n",
- reqMap[slot_idx]->getTid(), name());
- reqMap[slot_idx]->setCompleted(true);
- reqMap[slot_idx]->done();
+ reqs[slot_idx]->getTid(), name());
+ reqs[slot_idx]->setCompleted(true);
+ reqs[slot_idx]->done();
}
void
@@ -293,15 +286,10 @@ void
Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
ThreadID tid)
{
- std::vector<int> slot_remove_list;
+ for (int i = 0; i < width; i++) {
+ ResReqPtr req_ptr = reqs[i];
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
- ResReqPtr req_ptr = (*map_it).second;
-
- if (req_ptr &&
+ if (req_ptr->valid &&
req_ptr->getInst()->readTid() == tid &&
req_ptr->getInst()->seqNum > squash_seq_num) {
@@ -316,19 +304,8 @@ Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
if (resourceEvent[req_slot_num].scheduled())
unscheduleEvent(req_slot_num);
- // Mark request for later removal
- cpu->reqRemoveList.push(req_ptr);
-
- // Mark slot for removal from resource
- slot_remove_list.push_back(req_ptr->getSlot());
+ freeSlot(req_slot_num);
}
-
- map_it++;
- }
-
- // Now Delete Slot Entry from Req. Map
- for (int i = 0; i < slot_remove_list.size(); i++) {
- freeSlot(slot_remove_list[i]);
}
}
@@ -350,10 +327,8 @@ Resource::ticks(int num_cycles)
void
Resource::scheduleExecution(int slot_num)
{
- int res_latency = getLatency(slot_num);
-
- if (res_latency >= 1) {
- scheduleEvent(slot_num, res_latency);
+ if (latency >= 1) {
+ scheduleEvent(slot_num, latency);
} else {
execute(slot_num);
}
@@ -363,8 +338,8 @@ void
Resource::scheduleEvent(int slot_idx, int delay)
{
DPRINTF(Resource, "[tid:%i]: Scheduling event for [sn:%i] on tick %i.\n",
- reqMap[slot_idx]->inst->readTid(),
- reqMap[slot_idx]->inst->seqNum,
+ reqs[slot_idx]->inst->readTid(),
+ reqs[slot_idx]->inst->seqNum,
cpu->ticks(delay) + curTick());
resourceEvent[slot_idx].scheduleEvent(delay);
}
@@ -401,32 +376,11 @@ int ResourceRequest::resReqID = 0;
int ResourceRequest::maxReqCount = 0;
-ResourceRequest::ResourceRequest(Resource *_res, DynInstPtr _inst,
- int stage_num, int res_idx, int slot_num,
- unsigned _cmd)
- : res(_res), inst(_inst), cmd(_cmd), stageNum(stage_num),
- resIdx(res_idx), slotNum(slot_num), completed(false),
- squashed(false), processing(false), memStall(false)
+ResourceRequest::ResourceRequest(Resource *_res)
+ : res(_res), inst(NULL), stagePasses(0), valid(false), doneInResource(false),
+ completed(false), squashed(false), processing(false),
+ memStall(false)
{
-#ifdef DEBUG
- reqID = resReqID++;
- res->cpu->resReqCount++;
- DPRINTF(ResReqCount, "Res. Req %i created. resReqCount=%i.\n", reqID,
- res->cpu->resReqCount);
-
- if (res->cpu->resReqCount > 100) {
- fatal("Too many undeleted resource requests. Memory leak?\n");
- }
-
- if (res->cpu->resReqCount > maxReqCount) {
- maxReqCount = res->cpu->resReqCount;
- }
-
-#endif
-
- stagePasses = 0;
- complSlotNum = -1;
-
}
ResourceRequest::~ResourceRequest()
@@ -436,6 +390,46 @@ ResourceRequest::~ResourceRequest()
DPRINTF(ResReqCount, "Res. Req %i deleted. resReqCount=%i.\n", reqID,
res->cpu->resReqCount);
#endif
+ inst = NULL;
+}
+
+std::string
+ResourceRequest::name()
+{
+ return res->name() + "." + to_string(slotNum);
+}
+
+void
+ResourceRequest::setRequest(DynInstPtr _inst, int stage_num,
+ int res_idx, int slot_num, unsigned _cmd)
+{
+ valid = true;
+ inst = _inst;
+ stageNum = stage_num;
+ resIdx = res_idx;
+ slotNum = slot_num;
+ cmd = _cmd;
+}
+
+void
+ResourceRequest::clearRequest()
+{
+ valid = false;
+ inst = NULL;
+ stagePasses = 0;
+ completed = false;
+ doneInResource = false;
+ squashed = false;
+ memStall = false;
+}
+
+void
+ResourceRequest::freeSlot()
+{
+ assert(res);
+
+ // Free Slot So Another Instruction Can Use This Resource
+ res->freeSlot(slotNum);
}
void
@@ -447,25 +441,7 @@ ResourceRequest::done(bool completed)
setCompleted(completed);
- // Used for debugging purposes
- if (completed) {
- complSlotNum = slotNum;
-
- // Would like to start a convention such as all requests deleted in
- // resources/pipeline
- // but a little more complex then it seems...
- // For now, all COMPLETED requests deleted in resource..
- // all FAILED requests deleted in pipeline stage
- // *all SQUASHED requests deleted in resource
- res->cpu->reqRemoveList.push(res->reqMap[slotNum]);
- }
-
- // Free Slot So Another Instruction Can Use This Resource
- res->freeSlot(slotNum);
-
- // change slot # to -1, since we check slotNum to see if request is
- // still valid
- slotNum = -1;
+ doneInResource = true;
}
ResourceEvent::ResourceEvent()
@@ -493,7 +469,8 @@ ResourceEvent::process()
const char *
ResourceEvent::description()
{
- string desc = resource->name() + " event";
+ string desc = resource->name() + "-event:slot[" + to_string(slotIdx)
+ + "]";
return desc.c_str();
}
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
index bd9ec48ca..7899a215f 100644
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -221,8 +221,10 @@ class Resource {
const int latency;
public:
- /** Mapping of slot-numbers to the resource-request pointers */
- std::map<int, ResReqPtr> reqMap;
+ /** List of all Requests the Resource is Servicing. Each request
+ represents part of the resource's bandwidth
+ */
+ std::vector<ResReqPtr> reqs;
/** A list of all the available execution slots for this resource.
* This correlates with the actual resource event idx.
@@ -245,7 +247,7 @@ class Resource {
class ResourceEvent : public Event
{
public:
- /** Pointer to the CPU. */
+ /** Pointer to the Resource this is an event for */
Resource *resource;
@@ -297,21 +299,29 @@ class ResourceRequest
static int maxReqCount;
+ friend class Resource;
+
public:
- ResourceRequest(Resource *_res, DynInstPtr _inst, int stage_num,
- int res_idx, int slot_num, unsigned _cmd);
+ ResourceRequest(Resource *_res);
virtual ~ResourceRequest();
+
+ std::string name();
int reqID;
+ virtual void setRequest(DynInstPtr _inst, int stage_num,
+ int res_idx, int slot_num, unsigned _cmd);
+
+ virtual void clearRequest();
+
/** Acknowledge that this is a request is done and remove
* from resource.
*/
void done(bool completed = true);
-
- short stagePasses;
+ void freeSlot();
+
/////////////////////////////////////////////
//
// GET RESOURCE REQUEST IDENTIFICATION / INFO
@@ -319,11 +329,9 @@ class ResourceRequest
/////////////////////////////////////////////
/** Get Resource Index */
int getResIdx() { return resIdx; }
-
/** Get Slot Number */
int getSlot() { return slotNum; }
- int getComplSlot() { return complSlotNum; }
bool hasSlot() { return slotNum >= 0; }
/** Get Stage Number */
@@ -353,6 +361,12 @@ class ResourceRequest
/** Command For This Resource */
unsigned cmd;
+ short stagePasses;
+
+ bool valid;
+
+ bool doneInResource;
+
////////////////////////////////////////
//
// GET RESOURCE REQUEST STATUS FROM VARIABLES
@@ -380,7 +394,6 @@ class ResourceRequest
int stageNum;
int resIdx;
int slotNum;
- int complSlotNum;
/** Resource Request Status */
bool completed;
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index a037cbe9e..4e2f930ab 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -55,7 +55,7 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
memObjects.push_back(ICache);
resources.push_back(new FetchUnit("icache_port", ICache,
- stage_width * MaxThreads, 0, _cpu,
+ stage_width * 2 + MaxThreads, 0, _cpu,
params));
resources.push_back(new DecodeUnit("Decode-Unit", Decode,
@@ -68,7 +68,7 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
0, _cpu, params));
resources.push_back(new UseDefUnit("RegFile-Manager", RegManager,
- stage_width * MaxThreads, 0, _cpu,
+ stage_width * 3, 0, _cpu,
params));
resources.push_back(new AGENUnit("AGEN-Unit", AGEN,
@@ -77,20 +77,21 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
resources.push_back(new ExecutionUnit("Execution-Unit", ExecUnit,
stage_width, 0, _cpu, params));
- resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu,
- params));
+ resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU,
+ stage_width * 2, 0, _cpu, params));
memObjects.push_back(DCache);
resources.push_back(new CacheUnit("dcache_port", DCache,
- stage_width * MaxThreads, 0, _cpu,
+ stage_width * 2 + MaxThreads, 0, _cpu,
params));
resources.push_back(new GraduationUnit("Graduation-Unit", Grad,
- stage_width * MaxThreads, 0, _cpu,
+ stage_width, 0, _cpu,
params));
resources.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2, 4,
0, _cpu, params));
+
}
ResourcePool::~ResourcePool()
@@ -122,6 +123,16 @@ ResourcePool::name()
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()
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
index e8061d3ff..fde38b4e9 100644
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -130,6 +130,8 @@ class ResourcePool {
void init();
+ void print();
+
/** Register Statistics in All Resources */
void regStats();
diff --git a/src/cpu/inorder/resource_sked.cc b/src/cpu/inorder/resource_sked.cc
index 4104e6989..4cf791228 100644
--- a/src/cpu/inorder/resource_sked.cc
+++ b/src/cpu/inorder/resource_sked.cc
@@ -34,30 +34,30 @@
#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;
@@ -69,6 +69,26 @@ ResourceSked::empty()
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()
{
@@ -82,18 +102,18 @@ ResourceSked::pop()
{
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;
}
}
@@ -108,7 +128,7 @@ ResourceSked::push(ScheduleEntry* sked_entry)
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
@@ -122,23 +142,23 @@ ResourceSked::pushBefore(ScheduleEntry* sked_entry, int sked_cmd,
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)
@@ -154,12 +174,12 @@ ResourceSked::SkedIt
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 &&
@@ -175,12 +195,16 @@ ResourceSked::findIterByCommand(ScheduleEntry* sked_entry, int stage_num,
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++;
}
}
diff --git a/src/cpu/inorder/resource_sked.hh b/src/cpu/inorder/resource_sked.hh
index 22e29d728..bd002e161 100644
--- a/src/cpu/inorder/resource_sked.hh
+++ b/src/cpu/inorder/resource_sked.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 The Regents of The University of Michigan
+ * Copyright (c) 2010-2011 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,19 @@
#include <vector>
#include <list>
+#include <cstdlib>
+/** ScheduleEntry class represents a single function that an instruction
+ wants to do at any pipeline stage. For example, if an instruction
+ needs to be decoded and do a branch prediction all in one stage
+ then each of those tasks would need it's own ScheduleEntry.
+
+ Each schedule entry corresponds to some resource that the instruction
+ wants to interact with.
+
+ The file pipeline_traits.cc shows how a typical instruction schedule is
+ made up of these schedule entries.
+*/
class ScheduleEntry {
public:
ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0,
@@ -43,45 +55,225 @@ class ScheduleEntry {
idx(_idx), priority(_priority)
{ }
- // Stage number to perform this service.
+ /** Stage number to perform this service. */
int stageNum;
- // Resource ID to access
+ /** Resource ID to access */
int resNum;
- // See specific resource for meaning
+ /** See specific resource for meaning */
unsigned cmd;
- // See specific resource for meaning
+ /** See specific resource for meaning */
unsigned idx;
- // Some Resources May Need Priority
+ /** Some Resources May Need Priority */
int priority;
};
+/** The ResourceSked maintains the complete schedule
+ for an instruction. That schedule includes what
+ resources an instruction wants to acquire at each
+ pipeline stage and is represented by a collection
+ of ScheduleEntry objects (described above) that
+ must be executed in-order.
+
+ In every pipeline stage, the InOrder model will
+ process all entries on the resource schedule for
+ that stage and then send the instruction to the next
+ stage if and only if the instruction successfully
+ completed each ScheduleEntry.
+*/
class ResourceSked {
public:
typedef std::list<ScheduleEntry*>::iterator SkedIt;
+ typedef std::vector<std::list<ScheduleEntry*> > StageList;
ResourceSked();
+ /** Initializee the current entry pointer to
+ pipeline stage 0 and the 1st schedule entry
+ */
void init();
+ /** Goes through the remaining stages on the schedule
+ and sums all the remaining entries left to be
+ processed
+ */
int size();
+
+ /** Is the schedule empty? */
bool empty();
+
+ /** Beginning Entry of this schedule */
+ SkedIt begin();
+
+ /** Ending Entry of this schedule */
+ SkedIt end();
+
+ /** What is the next task for this instruction schedule? */
ScheduleEntry* top();
+
+ /** Top() Task is completed, remove it from schedule */
void pop();
+
+ /** Add To Schedule based on stage num and priority of
+ Schedule Entry
+ */
void push(ScheduleEntry* sked_entry);
+
+ /** Add Schedule Entry to be in front of another Entry */
void pushBefore(ScheduleEntry* sked_entry, int sked_cmd, int sked_cmd_idx);
+
+ /** Print what's left on the instruction schedule */
void print();
+ StageList *getStages()
+ {
+ return &stages;
+ }
+
private:
+ /** Current Schedule Entry Pointer */
SkedIt curSkedEntry;
- std::vector<std::list<ScheduleEntry*> > sked;
+ /** The Stage-by-Stage Resource Schedule:
+ Resized to Number of Stages in the constructor
+ */
+ StageList stages;
+
+ /** Find a place to insert the instruction using the
+ schedule entries priority
+ */
SkedIt findIterByPriority(ScheduleEntry *sked_entry, int stage_num);
+
+ /** Find a place to insert the instruction using a particular command
+ to look for.
+ */
SkedIt findIterByCommand(ScheduleEntry *sked_entry, int stage_num,
int sked_cmd, int sked_cmd_idx = -1);
};
+/** Wrapper class around the SkedIt iterator in the Resource Sked so that
+ we can use ++ operator to automatically go to the next available
+ resource schedule entry but otherwise maintain same functionality
+ as a normal iterator.
+*/
+class RSkedIt
+{
+ public:
+ RSkedIt()
+ : curStage(0), numStages(0)
+ { }
+
+
+ /** init() must be called before the use of any other member
+ in the RSkedIt class.
+ */
+ void init(ResourceSked* rsked)
+ {
+ stages = rsked->getStages();
+ numStages = stages->size();
+ }
+
+ /* Update the encapsulated "myIt" iterator, but only
+ update curStage/curStage_end if the iterator is valid.
+ The iterator could be invalid in the case where
+ someone is saving the end of a list (i.e. std::list->end())
+ */
+ RSkedIt operator=(ResourceSked::SkedIt const &rhs)
+ {
+ myIt = rhs;
+ if (myIt != (*stages)[numStages-1].end()) {
+ curStage = (*myIt)->stageNum;
+ curStage_end = (*stages)[curStage].end();
+ }
+ return *this;
+ }
+
+ /** Increment to the next entry in current stage.
+ If no more entries then find the next stage that has
+ resource schedule to complete.
+ If no more stages, then return the end() iterator from
+ the last stage to indicate we are done.
+ */
+ RSkedIt &operator++(int unused)
+ {
+ if (++myIt == curStage_end) {
+ curStage++;
+ while (curStage < numStages) {
+ if ((*stages)[curStage].empty()) {
+ curStage++;
+ } else {
+ myIt = (*stages)[curStage].begin();
+ curStage_end = (*stages)[curStage].end();
+ return *this;
+ }
+ }
+
+ myIt = (*stages)[numStages - 1].end();
+ }
+
+ return *this;
+ }
+
+ /** The "pointer" operator can be used on a RSkedIt and it
+ will use the encapsulated iterator
+ */
+ ScheduleEntry* operator->()
+ {
+ return *myIt;
+ }
+
+ /** Dereferencing a RSKedIt will access the encapsulated
+ iterator
+ */
+ ScheduleEntry* operator*()
+ {
+ return *myIt;
+ }
+
+ /** Equality for RSkedIt only compares the "myIt" iterators,
+ as the other members are just ancillary
+ */
+ bool operator==(RSkedIt const &rhs)
+ {
+ return this->myIt == rhs.myIt;
+ }
+
+ /** Inequality for RSkedIt only compares the "myIt" iterators,
+ as the other members are just ancillary
+ */
+ bool operator!=(RSkedIt const &rhs)
+ {
+ return this->myIt != rhs.myIt;
+ }
+
+ /* The == and != operator overloads should be sufficient
+ here if need otherwise direct access to the schedule
+ iterator, then this can be used */
+ ResourceSked::SkedIt getIt()
+ {
+ return myIt;
+ }
+
+ private:
+ /** Schedule Iterator that this class is encapsulating */
+ ResourceSked::SkedIt myIt;
+
+ /** Ptr to resource schedule that the 'myIt' iterator
+ belongs to
+ */
+ ResourceSked::StageList *stages;
+
+ /** The last iterator in the current stage. */
+ ResourceSked::SkedIt curStage_end;
+
+ /** Current Stage that "myIt" refers to. */
+ int curStage;
+
+ /** Number of stages in the "*stages" object. */
+ int numStages;
+};
+
#endif //__CPU_INORDER_RESOURCE_SKED_HH__
diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc
index f1862b94a..764cd9446 100644
--- a/src/cpu/inorder/resources/agen_unit.cc
+++ b/src/cpu/inorder/resources/agen_unit.cc
@@ -50,8 +50,8 @@ AGENUnit::regStats()
void
AGENUnit::execute(int slot_num)
{
- ResourceRequest* agen_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* agen_req = reqs[slot_num];
+ DynInstPtr inst = reqs[slot_num]->inst;
#if TRACING_ON
ThreadID tid = inst->readTid();
#endif
diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc
index 8ca5a9718..5a22e40eb 100644
--- a/src/cpu/inorder/resources/branch_predictor.cc
+++ b/src/cpu/inorder/resources/branch_predictor.cc
@@ -66,7 +66,7 @@ BranchPredictor::execute(int slot_num)
{
// After this is working, change this to a reinterpret cast
// for performance considerations
- ResourceRequest* bpred_req = reqMap[slot_num];
+ ResourceRequest* bpred_req = reqs[slot_num];
DynInstPtr inst = bpred_req->inst;
ThreadID tid = inst->readTid();
int seq_num = inst->seqNum;
diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc
index 8b4dd4402..b17e5b3da 100644
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -133,6 +133,10 @@ CacheUnit::getPort(const string &if_name, int idx)
void
CacheUnit::init()
{
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new CacheRequest(this);
+ }
+
// Currently Used to Model TLB Latency. Eventually
// Switch to Timing TLB translations.
resourceEvent = new CacheUnitEvent[width];
@@ -250,20 +254,16 @@ CacheUnit::removeAddrDependency(DynInstPtr inst)
ResReqPtr
CacheUnit::findRequest(DynInstPtr inst)
{
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
+ for (int i = 0; i < width; i++) {
CacheRequest* cache_req =
- dynamic_cast<CacheRequest*>((*map_it).second);
+ dynamic_cast<CacheRequest*>(reqs[i]);
assert(cache_req);
- if (cache_req &&
+ if (cache_req->valid &&
cache_req->getInst() == inst &&
- cache_req->instIdx == inst->resSched.top()->idx) {
+ cache_req->instIdx == inst->curSkedEntry->idx) {
return cache_req;
}
- map_it++;
}
return NULL;
@@ -272,20 +272,16 @@ CacheUnit::findRequest(DynInstPtr inst)
ResReqPtr
CacheUnit::findRequest(DynInstPtr inst, int idx)
{
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
+ for (int i = 0; i < width; i++) {
CacheRequest* cache_req =
- dynamic_cast<CacheRequest*>((*map_it).second);
+ dynamic_cast<CacheRequest*>(reqs[i]);
assert(cache_req);
- if (cache_req &&
+ if (cache_req->valid &&
cache_req->getInst() == inst &&
cache_req->instIdx == idx) {
return cache_req;
}
- map_it++;
}
return NULL;
@@ -296,7 +292,8 @@ ResReqPtr
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;
+ CacheRequest* cache_req = dynamic_cast<CacheRequest*>(reqs[slot_num]);
if (!inst->validMemAddr()) {
panic("Mem. Addr. must be set before requesting cache access\n");
@@ -343,10 +340,10 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
sched_entry->cmd, name());
}
- 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);
+ cache_req->setRequest(inst, stage_num, id, slot_num,
+ sched_entry->cmd, pkt_cmd,
+ inst->curSkedEntry->idx);
+ return cache_req;
}
void
@@ -357,17 +354,17 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request)
// 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,
@@ -487,14 +484,20 @@ CacheUnit::read(DynInstPtr inst, Addr addr,
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();
-
- int stage_pri = ThePipeline::getNextPriority(inst, stage_num);
+ RSkedPtr inst_sked = (stage_num >= ThePipeline::BackEndStartStage) ?
+ inst->backSked : inst->frontSked;
+
+ // this is just an arbitrarily high priority to ensure that this
+ // gets pushed to the back of the list
+ int stage_pri = 20;
int isplit_cmd = CacheUnit::InitSecondSplitRead;
- inst->resSched.push(new
+ inst_sked->push(new
ScheduleEntry(stage_num,
stage_pri,
cpu->resPool->getResIdx(DCache),
@@ -502,7 +505,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr,
1));
int csplit_cmd = CacheUnit::CompleteSecondSplitRead;
- inst->resSched.push(new
+ inst_sked->push(new
ScheduleEntry(stage_num + 1,
1/*stage_pri*/,
cpu->resPool->getResIdx(DCache),
@@ -590,27 +593,33 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
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();
+ RSkedPtr inst_sked = (stage_num >= ThePipeline::BackEndStartStage) ?
+ inst->backSked : inst->frontSked;
- int stage_pri = ThePipeline::getNextPriority(inst, stage_num);
+ // this is just an arbitrarily high priority to ensure that this
+ // gets pushed to the back of the list
+ int stage_pri = 20;
int isplit_cmd = CacheUnit::InitSecondSplitWrite;
- inst->resSched.push(new
- ScheduleEntry(stage_num,
- stage_pri,
- cpu->resPool->getResIdx(DCache),
- isplit_cmd,
- 1));
+ inst_sked->push(new
+ ScheduleEntry(stage_num,
+ stage_pri,
+ cpu->resPool->getResIdx(DCache),
+ isplit_cmd,
+ 1));
int csplit_cmd = CacheUnit::CompleteSecondSplitWrite;
- inst->resSched.push(new
- ScheduleEntry(stage_num + 1,
- 1/*stage_pri*/,
- cpu->resPool->getResIdx(DCache),
- csplit_cmd,
- 1));
+ inst_sked->push(new
+ ScheduleEntry(stage_num + 1,
+ 1/*stage_pri*/,
+ cpu->resPool->getResIdx(DCache),
+ csplit_cmd,
+ 1));
inst->splitInstSked = true;
} else {
DPRINTF(InOrderCachePort, "[tid:%i] sn:%i] Retrying Split Read "
@@ -639,8 +648,6 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
if (inst->fault == NoFault) {
if (!cache_req->splitAccess) {
- // Remove this line since storeData is saved in INST?
- cache_req->reqData = new uint8_t[size];
doCacheAccess(inst, write_res);
} else {
doCacheAccess(inst, write_res, cache_req);
@@ -655,16 +662,19 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
void
CacheUnit::execute(int slot_num)
{
- CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqMap[slot_num]);
+ CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqs[slot_num]);
assert(cache_req);
- if (cachePortBlocked) {
+ if (cachePortBlocked &&
+ (cache_req->cmd == InitiateReadData ||
+ cache_req->cmd == InitiateWriteData ||
+ cache_req->cmd == InitSecondSplitRead ||
+ cache_req->cmd == InitSecondSplitWrite)) {
DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n");
- cache_req->setCompleted(false);
+ cache_req->done(false);
return;
}
-
DynInstPtr inst = cache_req->inst;
#if TRACING_ON
ThreadID tid = inst->readTid();
@@ -681,7 +691,12 @@ CacheUnit::execute(int slot_num)
acc_type = "read";
#endif
case InitiateWriteData:
-
+ if (cachePortBlocked) {
+ DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n");
+ cache_req->done(false);
+ return;
+ }
+
DPRINTF(InOrderCachePort,
"[tid:%u]: [sn:%i] Initiating data %s access to %s for "
"addr. %08p\n", tid, inst->seqNum, acc_type, name(),
@@ -796,7 +811,7 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res,
CacheReqPtr cache_req;
if (split_req == NULL) {
- cache_req = dynamic_cast<CacheReqPtr>(reqMap[inst->getCurResSlot()]);
+ cache_req = dynamic_cast<CacheReqPtr>(reqs[inst->getCurResSlot()]);
} else{
cache_req = split_req;
}
@@ -855,7 +870,7 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res,
"[tid:%i] [sn:%i] cannot access cache, because port "
"is blocked. now waiting to retry request\n", tid,
inst->seqNum);
- cache_req->setCompleted(false);
+ cache_req->done(false);
cachePortBlocked = true;
} else {
DPRINTF(InOrderCachePort,
@@ -879,7 +894,7 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res,
// Make cache request again since access due to
// inability to access
DPRINTF(InOrderStall, "STALL: \n");
- cache_req->setCompleted(false);
+ cache_req->done(false);
}
}
@@ -902,7 +917,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
cache_pkt->cacheReq->getTid(),
cache_pkt->cacheReq->seqNum);
- cache_pkt->cacheReq->done();
+ cache_pkt->cacheReq->freeSlot();
delete cache_pkt;
cpu->wakeCPU();
@@ -1047,10 +1062,10 @@ CacheUnitEvent::CacheUnitEvent()
void
CacheUnitEvent::process()
{
- DynInstPtr inst = resource->reqMap[slotIdx]->inst;
- int stage_num = resource->reqMap[slotIdx]->getStageNum();
+ DynInstPtr inst = resource->reqs[slotIdx]->inst;
+ int stage_num = resource->reqs[slotIdx]->getStageNum();
ThreadID tid = inst->threadNumber;
- CacheReqPtr req_ptr = dynamic_cast<CacheReqPtr>(resource->reqMap[slotIdx]);
+ CacheReqPtr req_ptr = dynamic_cast<CacheReqPtr>(resource->reqs[slotIdx]);
DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n",
inst->seqNum);
@@ -1061,13 +1076,15 @@ CacheUnitEvent::process()
tlb_res->tlbBlocked[tid] = false;
tlb_res->cpu->pipelineStage[stage_num]->
- unsetResStall(tlb_res->reqMap[slotIdx], tid);
+ unsetResStall(tlb_res->reqs[slotIdx], tid);
req_ptr->tlbStall = false;
if (req_ptr->isSquashed()) {
- req_ptr->done();
+ req_ptr->freeSlot();
}
+
+ tlb_res->cpu->wakeCPU();
}
void
@@ -1112,15 +1129,10 @@ void
CacheUnit::squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid)
{
- vector<int> slot_remove_list;
-
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
- ResReqPtr req_ptr = (*map_it).second;
+ for (int i = 0; i < width; i++) {
+ ResReqPtr req_ptr = reqs[i];
- if (req_ptr &&
+ if (req_ptr->valid &&
req_ptr->getInst()->readTid() == tid &&
req_ptr->getInst()->seqNum > squash_seq_num) {
@@ -1133,7 +1145,6 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
"squashed, ignoring squash process.\n",
req_ptr->getInst()->readTid(),
req_ptr->getInst()->seqNum);
- map_it++;
continue;
}
@@ -1147,18 +1158,14 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
if (cache_req->tlbStall) {
tlbBlocked[tid] = false;
- int stall_stage = reqMap[req_slot_num]->getStageNum();
+ int stall_stage = reqs[req_slot_num]->getStageNum();
cpu->pipelineStage[stall_stage]->
- unsetResStall(reqMap[req_slot_num], tid);
+ unsetResStall(reqs[req_slot_num], tid);
}
if (!cache_req->tlbStall && !cache_req->isMemAccPending()) {
- // Mark request for later removal
- cpu->reqRemoveList.push(req_ptr);
-
- // Mark slot for removal from resource
- slot_remove_list.push_back(req_ptr->getSlot());
+ freeSlot(req_slot_num);
} else {
DPRINTF(InOrderCachePort,
"[tid:%i] Request from [sn:%i] squashed, but still "
@@ -1170,14 +1177,8 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
req_ptr->getInst()->readTid(), req_ptr->getInst()->seqNum,
req_ptr->getInst()->splitInst);
}
-
}
-
- map_it++;
}
- // Now Delete Slot Entry from Req. Map
- for (int i = 0; i < slot_remove_list.size(); i++)
- freeSlot(slot_remove_list[i]);
}
diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh
index afcb36a24..097b6fa7a 100644
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -219,20 +219,18 @@ class CacheUnitEvent : public ResourceEvent {
void process();
};
+//@todo: Move into CacheUnit Class for private access to "valid" field
class CacheRequest : public ResourceRequest
{
public:
- CacheRequest(CacheUnit *cres, DynInstPtr inst, int stage_num, int res_idx,
- int slot_num, unsigned cmd, int req_size,
- MemCmd::Command pkt_cmd, unsigned flags, int cpu_id, int idx)
- : ResourceRequest(cres, inst, stage_num, res_idx, slot_num, cmd),
- pktCmd(pkt_cmd), memReq(NULL), reqData(NULL), dataPkt(NULL),
- retryPkt(NULL), memAccComplete(false), memAccPending(false),
- tlbStall(false), splitAccess(false), splitAccessNum(-1),
- split2ndAccess(false), instIdx(idx), fetchBufferFill(false)
+ CacheRequest(CacheUnit *cres)
+ : ResourceRequest(cres), memReq(NULL), reqData(NULL),
+ dataPkt(NULL), retryPkt(NULL), memAccComplete(false),
+ memAccPending(false), tlbStall(false), splitAccess(false),
+ splitAccessNum(-1), split2ndAccess(false),
+ fetchBufferFill(false)
{ }
-
virtual ~CacheRequest()
{
if (reqData && !splitAccess) {
@@ -240,6 +238,37 @@ class CacheRequest : public ResourceRequest
}
}
+ void setRequest(DynInstPtr _inst, int stage_num, int res_idx, int slot_num,
+ unsigned _cmd, MemCmd::Command pkt_cmd, int idx)
+ {
+ pktCmd = pkt_cmd;
+ instIdx = idx;
+
+ ResourceRequest::setRequest(_inst, stage_num, res_idx, slot_num, _cmd);
+ }
+
+ void clearRequest()
+ {
+ if (reqData && !splitAccess) {
+ delete [] reqData;
+ }
+
+ memReq = NULL;
+ reqData = NULL;
+ dataPkt = NULL;
+ retryPkt = NULL;
+ memAccComplete = false;
+ memAccPending = false;
+ tlbStall = false;
+ splitAccess = false;
+ splitAccessNum = -1;
+ split2ndAccess = false;
+ instIdx = 0;
+ fetchBufferFill = false;
+
+ ResourceRequest::clearRequest();
+ }
+
virtual PacketDataPtr getData()
{ return reqData; }
diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc
index c2f7ae22d..71d33ab90 100644
--- a/src/cpu/inorder/resources/decode_unit.cc
+++ b/src/cpu/inorder/resources/decode_unit.cc
@@ -49,21 +49,24 @@ DecodeUnit::DecodeUnit(std::string res_name, int res_id, int res_width,
void
DecodeUnit::execute(int slot_num)
{
- ResourceRequest* decode_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* decode_req = reqs[slot_num];
+ DynInstPtr inst = reqs[slot_num]->inst;
ThreadID tid = inst->readTid();
switch (decode_req->cmd)
{
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,
diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc
index 36bf2a4dc..b2540cff8 100644
--- a/src/cpu/inorder/resources/execution_unit.cc
+++ b/src/cpu/inorder/resources/execution_unit.cc
@@ -42,7 +42,7 @@ ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width,
int res_latency, InOrderCPU *_cpu,
ThePipeline::Params *params)
: Resource(res_name, res_id, res_width, res_latency, _cpu),
- lastExecuteTick(0), lastControlTick(0)
+ lastExecuteTick(0), lastControlTick(0), serializeTick(0)
{ }
void
@@ -82,27 +82,52 @@ ExecutionUnit::regStats()
void
ExecutionUnit::execute(int slot_num)
{
- ResourceRequest* exec_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* exec_req = reqs[slot_num];
+ DynInstPtr inst = reqs[slot_num]->inst;
Fault fault = NoFault;
int seq_num = inst->seqNum;
+ Tick cur_tick = curTick();
+
+ if (cur_tick == serializeTick) {
+ DPRINTF(InOrderExecute, "Can not execute [tid:%i][sn:%i][PC:%s] %s. "
+ "All instructions are being serialized this cycle\n",
+ inst->readTid(), seq_num, inst->pcState(), inst->instName());
+ exec_req->done(false);
+ return;
+ }
- DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
- inst->readTid(), seq_num, inst->pcState(), inst->instName());
switch (exec_req->cmd)
{
case ExecuteInst:
{
- if (curTick() != lastExecuteTick) {
- lastExecuteTick = curTick();
+ if (inst->isNop()) {
+ DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] [PC:%s] Ignoring execution"
+ "of %s.\n", inst->readTid(), seq_num, inst->pcState(),
+ inst->instName());
+ inst->setExecuted();
+ exec_req->done();
+ return;
+ } else {
+ DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
+ inst->readTid(), seq_num, inst->pcState(), inst->instName());
}
+ if (cur_tick != lastExecuteTick) {
+ lastExecuteTick = cur_tick;
+ }
+
+ assert(!inst->isMemRef());
+
+ if (inst->isSerializeAfter()) {
+ serializeTick = cur_tick;
+ DPRINTF(InOrderExecute, "Serializing execution after [tid:%i] "
+ "[sn:%i] [PC:%s] %s.\n", inst->readTid(), seq_num,
+ inst->pcState(), inst->instName());
+ }
- if (inst->isMemRef()) {
- panic("%s not configured to handle memory ops.\n", resName);
- } else if (inst->isControl()) {
- if (lastControlTick == curTick()) {
+ if (inst->isControl()) {
+ if (lastControlTick == cur_tick) {
DPRINTF(InOrderExecute, "Can not Execute More than One Control "
"Inst Per Cycle. Blocking Request.\n");
exec_req->done(false);
diff --git a/src/cpu/inorder/resources/execution_unit.hh b/src/cpu/inorder/resources/execution_unit.hh
index a6694ddb5..b03a6655e 100644
--- a/src/cpu/inorder/resources/execution_unit.hh
+++ b/src/cpu/inorder/resources/execution_unit.hh
@@ -76,6 +76,7 @@ class ExecutionUnit : public Resource {
Stats::Scalar executions;
Tick lastExecuteTick;
Tick lastControlTick;
+ Tick serializeTick;
};
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc
index 6f84a333d..d23ea0a82 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc
@@ -62,13 +62,17 @@ FetchSeqUnit::init()
{
resourceEvent = new FetchSeqEvent[width];
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new ResourceRequest(this);
+ }
+
initSlots();
}
void
FetchSeqUnit::execute(int slot_num)
{
- ResourceRequest* fs_req = reqMap[slot_num];
+ ResourceRequest* fs_req = reqs[slot_num];
DynInstPtr inst = fs_req->inst;
ThreadID tid = inst->readTid();
int stage_num = fs_req->getStageNum();
@@ -96,7 +100,7 @@ FetchSeqUnit::execute(int slot_num)
fs_req->done();
} else {
DPRINTF(InOrderStall, "STALL: [tid:%i]: NPC not valid\n", tid);
- fs_req->setCompleted(false);
+ fs_req->done(false);
}
}
break;
diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc
index 0e9866708..a0d830ecf 100644
--- a/src/cpu/inorder/resources/fetch_unit.cc
+++ b/src/cpu/inorder/resources/fetch_unit.cc
@@ -56,6 +56,31 @@ FetchUnit::FetchUnit(string res_name, int res_id, int res_width,
predecoder(NULL)
{ }
+FetchUnit::~FetchUnit()
+{
+ std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin();
+ std::list<FetchBlock*>::iterator end_it = fetchBuffer.end();
+ while (fetch_it != end_it) {
+ delete (*fetch_it)->block;
+ delete *fetch_it;
+ fetch_it++;
+ }
+ fetchBuffer.clear();
+
+
+ std::list<FetchBlock*>::iterator pend_it = pendingFetch.begin();
+ std::list<FetchBlock*>::iterator pend_end = pendingFetch.end();
+ while (pend_it != pend_end) {
+ if ((*pend_it)->block) {
+ delete (*pend_it)->block;
+ }
+
+ delete *pend_it;
+ pend_it++;
+ }
+ pendingFetch.clear();
+}
+
void
FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
DynInstPtr inst)
@@ -118,33 +143,24 @@ ResReqPtr
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;
+ CacheRequest* cache_req = dynamic_cast<CacheRequest*>(reqs[slot_num]);
if (!inst->validMemAddr()) {
panic("Mem. Addr. must be set before requesting cache access\n");
}
- MemCmd::Command pkt_cmd;
-
- switch (sched_entry->cmd)
- {
- case InitiateFetch:
- pkt_cmd = MemCmd::ReadReq;
+ assert(sched_entry->cmd == InitiateFetch);
- DPRINTF(InOrderCachePort,
- "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
- inst->readTid(), inst->seqNum, inst->getMemAddr());
- break;
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
+ inst->readTid(), inst->seqNum, inst->getMemAddr());
- default:
- panic("%i: Unexpected request type (%i) to %s", curTick(),
- sched_entry->cmd, name());
- }
+ cache_req->setRequest(inst, stage_num, id, slot_num,
+ sched_entry->cmd, MemCmd::ReadReq,
+ inst->curSkedEntry->idx);
- 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);
+ return cache_req;
}
void
@@ -214,12 +230,12 @@ FetchUnit::markBlockUsed(std::list<FetchBlock*>::iterator block_it)
void
FetchUnit::execute(int slot_num)
{
- CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqMap[slot_num]);
+ CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqs[slot_num]);
assert(cache_req);
- if (cachePortBlocked) {
+ if (cachePortBlocked && cache_req->cmd == InitiateFetch) {
DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n");
- cache_req->setCompleted(false);
+ cache_req->done(false);
return;
}
@@ -270,7 +286,7 @@ FetchUnit::execute(int slot_num)
// If not, block this request.
if (pendingFetch.size() >= fetchBuffSize) {
DPRINTF(InOrderCachePort, "No room available in fetch buffer.\n");
- cache_req->setCompleted(false);
+ cache_req->done();
return;
}
@@ -337,6 +353,8 @@ FetchUnit::execute(int slot_num)
return;
}
+ delete [] (*repl_it)->block;
+ delete *repl_it;
fetchBuffer.erase(repl_it);
}
@@ -414,6 +432,7 @@ FetchUnit::processCacheCompletion(PacketPtr pkt)
cache_pkt->cacheReq->seqNum);
cache_pkt->cacheReq->done();
+ cache_pkt->cacheReq->freeSlot();
delete cache_pkt;
cpu->wakeCPU();
@@ -447,7 +466,7 @@ FetchUnit::processCacheCompletion(PacketPtr pkt)
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",
@@ -514,6 +533,10 @@ FetchUnit::squashCacheRequest(CacheReqPtr req_ptr)
DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Fetch "
"for block %08p (cnt=%i)\n", inst->seqNum,
block_addr, (*block_it)->cnt);
+ if ((*block_it)->block) {
+ delete [] (*block_it)->block;
+ }
+ delete *block_it;
pendingFetch.erase(block_it);
}
}
diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh
index 035f3f4a1..fa133b9eb 100644
--- a/src/cpu/inorder/resources/fetch_unit.hh
+++ b/src/cpu/inorder/resources/fetch_unit.hh
@@ -55,6 +55,8 @@ class FetchUnit : public CacheUnit
FetchUnit(std::string res_name, int res_id, int res_width,
int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params);
+ virtual ~FetchUnit();
+
typedef ThePipeline::DynInstPtr DynInstPtr;
typedef TheISA::ExtMachInst ExtMachInst;
diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc
index 8ccdaa36a..edc2fb3ff 100644
--- a/src/cpu/inorder/resources/graduation_unit.cc
+++ b/src/cpu/inorder/resources/graduation_unit.cc
@@ -37,8 +37,7 @@ GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width,
int res_latency, InOrderCPU *_cpu,
ThePipeline::Params *params)
: Resource(res_name, res_id, res_width, res_latency, _cpu),
- lastCycleGrad(0), numCycleGrad(0)
-
+ lastNonSpecTick(0)
{
for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) {
nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid];
@@ -49,23 +48,27 @@ GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width,
void
GraduationUnit::execute(int slot_num)
{
- ResourceRequest* grad_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* grad_req = reqs[slot_num];
+ DynInstPtr inst = reqs[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);
+ if (lastNonSpecTick == curTick()) {
+ DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. "
+ "Only 1 nonspec inst. per cycle can graduate.\n");
+ grad_req->done(false);
+ return;
+ }
- // Handle Any Faults Before Graduating Instruction
+ // Handle Any Faults Before Graduating Instruction
if (inst->fault != NoFault) {
cpu->trap(inst->fault, tid, inst);
grad_req->setCompleted(false);
- return;
+ return;
}
DPRINTF(InOrderGraduation,
@@ -80,6 +83,7 @@ GraduationUnit::execute(int slot_num)
DPRINTF(InOrderGraduation,
"[tid:%i] Non-speculative inst [sn:%i] graduated\n",
tid, inst->seqNum);
+ lastNonSpecTick = curTick();
}
if (inst->traceData) {
diff --git a/src/cpu/inorder/resources/graduation_unit.hh b/src/cpu/inorder/resources/graduation_unit.hh
index aae41993f..59631bfcb 100644
--- a/src/cpu/inorder/resources/graduation_unit.hh
+++ b/src/cpu/inorder/resources/graduation_unit.hh
@@ -57,9 +57,7 @@ class GraduationUnit : public Resource {
void execute(int slot_num);
protected:
- Tick lastCycleGrad;
- int numCycleGrad;
-
+ Tick lastNonSpecTick;
bool *nonSpecInstActive[ThePipeline::MaxThreads];
InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads];
diff --git a/src/cpu/inorder/resources/inst_buffer.cc b/src/cpu/inorder/resources/inst_buffer.cc
index 18dd26a78..46f5cce72 100644
--- a/src/cpu/inorder/resources/inst_buffer.cc
+++ b/src/cpu/inorder/resources/inst_buffer.cc
@@ -62,7 +62,7 @@ InstBuffer::regStats()
void
InstBuffer::execute(int slot_idx)
{
- ResReqPtr ib_req = reqMap[slot_idx];
+ ResReqPtr ib_req = reqs[slot_idx];
DynInstPtr inst = ib_req->inst;
ThreadID tid = inst->readTid();
int stage_num = ib_req->getStageNum();
@@ -99,19 +99,22 @@ InstBuffer::execute(int slot_idx)
inst->seqNum, next_stage);
// Add to schedule: Insert into buffer in next stage
- int stage_pri = ThePipeline::getNextPriority(inst,
- next_stage);
+ int stage_pri = 20;
+ RSkedPtr insert_sked = (stage_num >= ThePipeline::BackEndStartStage) ?
+ inst->backSked : inst->frontSked;
- inst->resSched.push(new ScheduleEntry(next_stage,
+ insert_sked->push(new ScheduleEntry(next_stage,
stage_pri,
id,
InstBuffer::InsertInst));
// Add to schedule: Remove from buffer in next next (bypass)
// stage
- stage_pri = ThePipeline::getNextPriority(inst, bypass_stage);
+ stage_pri = 20;
+ RSkedPtr bypass_sked = (stage_num >= ThePipeline::BackEndStartStage) ?
+ inst->backSked : inst->frontSked;
- inst->resSched.push(new ScheduleEntry(bypass_stage,
+ bypass_sked->push(new ScheduleEntry(bypass_stage,
stage_pri,
id,
InstBuffer::RemoveInst));
diff --git a/src/cpu/inorder/resources/inst_buffer_new.cc b/src/cpu/inorder/resources/inst_buffer_new.cc
deleted file mode 100644
index 2e5a9666a..000000000
--- a/src/cpu/inorder/resources/inst_buffer_new.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2007 MIPS Technologies, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Korey Sewell
- *
- */
-
-#include <vector>
-#include <list>
-
-#include "arch/isa_traits.hh"
-#include "config/the_isa.hh"
-#include "cpu/inorder/pipeline_traits.hh"
-#include "cpu/inorder/resources/inst_buffer.hh"
-#include "cpu/inorder/cpu.hh"
-
-using namespace std;
-using namespace TheISA;
-using namespace ThePipeline;
-
-InstBuffer::InstBuffer(string res_name, int res_id, int res_width,
- int res_latency, InOrderCPU *_cpu)
- : Resource(res_name, res_id, res_width, res_latency, _cpu)
-{ }
-
-ResReqPtr
-InstBuffer::getRequest(DynInstPtr inst, int stage_num, int res_idx,
- int slot_num)
-{
- // After this is working, change this to a reinterpret cast
- // for performance considerations
- InstBufferEntry* ib_entry = dynamic_cast<InstBufferEntry*>(inst->resSched.top());
- assert(ib_entry);
-
- return new InstBufferRequest(this, inst, stage_num, id, slot_num,
- ib_entry->cmd);
-}
-
-void
-InstBuffer::execute(int slot_idx)
-{
- // After this is working, change this to a reinterpret cast
- // for performance considerations
- InstBufferRequest* ib_req = dynamic_cast<InstBufferRequest*>(reqMap[slot_idx]);
- assert(ib_req);
-
- DynInstPtr inst = ib_req->inst;
- ThreadID tid = inst->readTid();
- int seq_num = inst->seqNum;
- ib_req->fault = NoFault;
-
- switch (ib_req->cmd)
- {
- case InsertInst:
- {
- DPRINTF(Resource, "[tid:%i]: Inserting [sn:%i] into buffer.\n",
- tid, seq_num);
- insert(inst);
- ib_req->done();
- }
- break;
-
- case RemoveInst:
- {
- DPRINTF(Resource, "[tid:%i]: Removing [sn:%i] from buffer.\n",
- tid, seq_num);
- remove(inst);
- ib_req->done();
- }
- break;
-
- default:
- fatal("Unrecognized command to %s", resName);
- }
-
- DPRINTF(Resource, "Buffer now contains %i insts.\n", instList.size());
-}
-
-void
-InstBuffer::insert(DynInstPtr inst)
-{
- instList.push_back(inst);
-}
-
-void
-InstBuffer::remove(DynInstPtr inst)
-{
- std::list<DynInstPtr>::iterator list_it = instList.begin();
- std::list<DynInstPtr>::iterator list_end = instList.end();
-
- while (list_it != list_end) {
- if((*list_it) == inst) {
- instList.erase(list_it);
- break;
- }
- list_it++;
- }
-}
-
-void
-InstBuffer::pop()
-{ instList.pop_front(); }
-
-ThePipeline::DynInstPtr
-InstBuffer::top()
-{ return instList.front(); }
-
-void
-InstBuffer::squash(InstSeqNum squash_seq_num, ThreadID tid)
-{
- list<DynInstPtr>::iterator list_it = instList.begin();
- list<DynInstPtr>::iterator list_end = instList.end();
- queue<list<DynInstPtr>::iterator> remove_list;
-
- // Collect All Instructions to be Removed in Remove List
- while (list_it != list_end) {
- if((*list_it)->seqNum > squash_seq_num) {
- DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i] in resource.\n",
- tid, (*list_it)->seqNum);
- (*list_it)->setSquashed();
- remove_list.push(list_it);
- }
-
- list_it++;
- }
-
- // Removed Instructions from InstList & Clear Remove List
- while (!remove_list.empty()) {
- instList.erase(remove_list.front());
- remove_list.pop();
- }
-
- Resource::squash(squash_seq_num, tid);
-}
diff --git a/src/cpu/inorder/resources/inst_buffer_new.hh b/src/cpu/inorder/resources/inst_buffer_new.hh
deleted file mode 100644
index b1d5a7b09..000000000
--- a/src/cpu/inorder/resources/inst_buffer_new.hh
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2007 MIPS Technologies, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Korey Sewell
- *
- */
-
-#ifndef __CPU_INORDER_INST_BUFF_UNIT_HH__
-#define __CPU_INORDER_INST_BUFF_UNIT_HH__
-
-#include <vector>
-#include <list>
-#include <string>
-
-#include "cpu/inorder/resource.hh"
-#include "cpu/inorder/inorder_dyn_inst.hh"
-#include "cpu/inorder/pipeline_traits.hh"
-#include "cpu/inorder/cpu.hh"
-
-class InstBuffer : public Resource {
- public:
- typedef InOrderDynInst::DynInstPtr DynInstPtr;
-
- public:
- enum Command {
- InsertInst,
- InsertAddr,
- RemoveInst,
- RemoveAddr
- };
-
- public:
- InstBuffer(std::string res_name, int res_id, int res_width,
- int res_latency, InOrderCPU *_cpu);
- virtual ~InstBuffer() {}
-
- virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
- int res_idx, int slot_num);
-
- virtual void execute(int slot_num);
-
- virtual void insert(DynInstPtr inst);
-
- virtual void remove(DynInstPtr inst);
-
- virtual void pop();
-
- virtual DynInstPtr top();
-
- virtual void squash(InstSeqNum squash_seq_num, ThreadID tid);
-
- protected:
- /** List of instructions this resource is currently
- * processing.
- */
- std::list<DynInstPtr> instList;
-
- /** @todo: Add Resource Stats Here */
-
-};
-
-struct InstBufferEntry : public ThePipeline::ScheduleEntry {
- InstBufferEntry(int stage_num, int res_num, InstBuffer::Command _cmd) :
- ScheduleEntry(stage_num, res_num), cmd(_cmd)
- { }
-
- InstBuffer::Command cmd;
-};
-
-class InstBufferRequest : public ResourceRequest {
- public:
- typedef InOrderDynInst::DynInstPtr DynInstPtr;
-
- public:
- InstBufferRequest(InstBuffer *res, DynInstPtr inst, int stage_num, int res_idx, int slot_num,
- InstBuffer::Command _cmd)
- : ResourceRequest(res, inst, stage_num, res_idx, slot_num),
- cmd(_cmd)
- { }
-
- InstBuffer::Command cmd;
-};
-
-
-#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__
diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc
index 5aa0b0aa1..ad8b2b47b 100644
--- a/src/cpu/inorder/resources/mult_div_unit.cc
+++ b/src/cpu/inorder/resources/mult_div_unit.cc
@@ -76,6 +76,10 @@ MultDivUnit::init()
// Set Up Resource Events to Appropriate Resource BandWidth
resourceEvent = new MDUEvent[width];
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new ResourceRequest(this);
+ }
+
initSlots();
}
@@ -92,7 +96,7 @@ void
MultDivUnit::freeSlot(int slot_idx)
{
DPRINTF(InOrderMDU, "Freeing slot for inst:%i\n | slots-free:%i | "
- "slots-used:%i\n", reqMap[slot_idx]->getInst()->seqNum,
+ "slots-used:%i\n", reqs[slot_idx]->getInst()->seqNum,
slotsAvail(), slotsInUse());
Resource::freeSlot(slot_idx);
@@ -110,9 +114,9 @@ MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request)
// 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);
@@ -132,7 +136,7 @@ MultDivUnit::getSlot(DynInstPtr inst)
// 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 == reqs[slot_num]->cmd)
return slot_num;
unsigned repeat_rate = 0;
@@ -202,8 +206,8 @@ MultDivUnit::getDivOpSize(DynInstPtr inst)
void
MultDivUnit::execute(int slot_num)
{
- ResourceRequest* mult_div_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* mult_div_req = reqs[slot_num];
+ DynInstPtr inst = reqs[slot_num]->inst;
switch (mult_div_req->cmd)
{
@@ -275,8 +279,8 @@ MultDivUnit::execute(int slot_num)
void
MultDivUnit::exeMulDiv(int slot_num)
{
- ResourceRequest* mult_div_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
+ ResourceRequest* mult_div_req = reqs[slot_num];
+ DynInstPtr inst = reqs[slot_num]->inst;
inst->fault = inst->execute();
@@ -310,7 +314,7 @@ MDUEvent::process()
mdu_res->exeMulDiv(slotIdx);
- ResourceRequest* mult_div_req = resource->reqMap[slotIdx];
+ ResourceRequest* mult_div_req = resource->reqs[slotIdx];
mult_div_req->done();
}
diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc
index 59840d15b..37aec2209 100644
--- a/src/cpu/inorder/resources/tlb_unit.cc
+++ b/src/cpu/inorder/resources/tlb_unit.cc
@@ -72,6 +72,10 @@ TLBUnit::init()
{
resourceEvent = new TLBUnitEvent[width];
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new TLBUnitRequest(this);
+ }
+
initSlots();
}
@@ -90,8 +94,9 @@ TLBUnit::getRequest(DynInstPtr _inst, int stage_num,
int res_idx, int slot_num,
unsigned cmd)
{
- return new TLBUnitRequest(this, _inst, stage_num, res_idx, slot_num,
- cmd);
+ TLBUnitRequest *tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_num]);
+ tlb_req->setRequest(inst, stage_num, id, slot_num, cmd);
+ return ud_req;
}
void
@@ -99,7 +104,7 @@ TLBUnit::execute(int slot_idx)
{
// After this is working, change this to a reinterpret cast
// for performance considerations
- TLBUnitRequest* tlb_req = dynamic_cast<TLBUnitRequest*>(reqMap[slot_idx]);
+ TLBUnitRequest* tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_idx]);
assert(tlb_req != 0x0);
DynInstPtr inst = tlb_req->inst;
@@ -200,8 +205,8 @@ TLBUnitEvent::TLBUnitEvent()
void
TLBUnitEvent::process()
{
- DynInstPtr inst = resource->reqMap[slotIdx]->inst;
- int stage_num = resource->reqMap[slotIdx]->getStageNum();
+ DynInstPtr inst = resource->reqs[slotIdx]->inst;
+ int stage_num = resource->reqs[slotIdx]->getStageNum();
ThreadID tid = inst->threadNumber;
DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n",
@@ -212,31 +217,18 @@ TLBUnitEvent::process()
tlb_res->tlbBlocked[tid] = false;
- tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(tlb_res->reqMap[slotIdx], tid);
-
- // Effectively NOP the instruction but still allow it
- // to commit
- //while (!inst->resSched.empty() &&
- // inst->resSched.top()->stageNum != ThePipeline::NumStages - 1) {
- //inst->resSched.pop();
- //}
+ tlb_res->cpu->pipelineStage[stage_num]->
+ unsetResStall(tlb_res->reqs[slotIdx], tid);
}
void
TLBUnit::squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid)
{
- //@TODO: Figure out a way to consolidate common parts
- // of this squash code
- std::vector<int> slot_remove_list;
-
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
- ResReqPtr req_ptr = (*map_it).second;
+ for (int i = 0; i < width; i++) {
+ ResReqPtr req_ptr = reqs[i];
- if (req_ptr &&
+ if (req_ptr->valid &&
req_ptr->getInst()->readTid() == tid &&
req_ptr->getInst()->seqNum > squash_seq_num) {
@@ -250,26 +242,16 @@ TLBUnit::squash(DynInstPtr inst, int stage_num,
tlbBlocked[tid] = false;
- int stall_stage = reqMap[req_slot_num]->getStageNum();
+ int stall_stage = reqs[req_slot_num]->getStageNum();
- cpu->pipelineStage[stall_stage]->unsetResStall(reqMap[req_slot_num], tid);
+ cpu->pipelineStage[stall_stage]->
+ unsetResStall(reqs[req_slot_num], tid);
if (resourceEvent[req_slot_num].scheduled())
unscheduleEvent(req_slot_num);
- // Mark request for later removal
- cpu->reqRemoveList.push(req_ptr);
-
- // Mark slot for removal from resource
- slot_remove_list.push_back(req_ptr->getSlot());
+ freeSlot(req_slot_num);
}
-
- map_it++;
- }
-
- // Now Delete Slot Entry from Req. Map
- for (int i = 0; i < slot_remove_list.size(); i++) {
- freeSlot(slot_remove_list[i]);
}
}
diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh
index eb1bf55f0..904ac3eba 100644
--- a/src/cpu/inorder/resources/tlb_unit.hh
+++ b/src/cpu/inorder/resources/tlb_unit.hh
@@ -99,9 +99,15 @@ class TLBUnitRequest : public ResourceRequest {
typedef ThePipeline::DynInstPtr DynInstPtr;
public:
- TLBUnitRequest(TLBUnit *res, DynInstPtr inst, int stage_num, int res_idx, int slot_num,
- unsigned _cmd)
- : ResourceRequest(res, inst, stage_num, res_idx, slot_num, _cmd)
+ TLBUnitRequest(TLBUnit *res)
+ : ResourceRequest(res), memReq(NULL)
+ {
+ }
+
+ RequestPtr memReq;
+
+ void setRequest(DynInstPtr inst, int stage_num, int res_idx, int slot_num,
+ unsigned _cmd)
{
Addr aligned_addr;
int req_size;
@@ -131,9 +137,10 @@ class TLBUnitRequest : public ResourceRequest {
inst->readTid());
memReq = inst->dataMemReq;
}
+
+ ResourceRequest::setRequest(inst, stage_num, res_idx, slot_num, _cmd);
}
- RequestPtr memReq;
};
diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc
index 743011573..19246a30b 100644
--- a/src/cpu/inorder/resources/use_def.cc
+++ b/src/cpu/inorder/resources/use_def.cc
@@ -88,33 +88,48 @@ UseDefUnit::regStats()
Resource::regStats();
}
+void
+UseDefUnit::init()
+{
+ // Set Up Resource Events to Appropriate Resource BandWidth
+ if (latency > 0) {
+ resourceEvent = new ResourceEvent[width];
+ } else {
+ resourceEvent = NULL;
+ }
+
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new UseDefRequest(this);
+ }
+
+ initSlots();
+}
+
ResReqPtr
UseDefUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd)
{
- return new UseDefRequest(this, inst, stage_num, id, slot_num, cmd,
- inst->resSched.top()->idx);
+ UseDefRequest *ud_req = dynamic_cast<UseDefRequest*>(reqs[slot_num]);
+ ud_req->setRequest(inst, stage_num, id, slot_num, cmd,
+ inst->curSkedEntry->idx);
+ return ud_req;
}
ResReqPtr
UseDefUnit::findRequest(DynInstPtr inst)
{
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
-
- while (map_it != map_end) {
- UseDefRequest* ud_req =
- dynamic_cast<UseDefRequest*>((*map_it).second);
+ for (int i = 0; i < width; i++) {
+ UseDefRequest* ud_req =
+ dynamic_cast<UseDefRequest*>(reqs[i]);
assert(ud_req);
- if (ud_req &&
+ if (ud_req->valid &&
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++;
}
return NULL;
@@ -125,7 +140,7 @@ UseDefUnit::execute(int slot_idx)
{
// After this is working, change this to a reinterpret cast
// for performance considerations
- UseDefRequest* ud_req = dynamic_cast<UseDefRequest*>(reqMap[slot_idx]);
+ UseDefRequest* ud_req = dynamic_cast<UseDefRequest*>(reqs[slot_idx]);
assert(ud_req);
DynInstPtr inst = ud_req->inst;
@@ -408,15 +423,10 @@ UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
DPRINTF(InOrderUseDef, "[tid:%i]: Updating Due To Squash After [sn:%i].\n",
tid, squash_seq_num);
- std::vector<int> slot_remove_list;
-
- map<int, ResReqPtr>::iterator map_it = reqMap.begin();
- map<int, ResReqPtr>::iterator map_end = reqMap.end();
+ for (int i = 0; i < width; i++) {
+ ResReqPtr req_ptr = reqs[i];
- while (map_it != map_end) {
- ResReqPtr req_ptr = (*map_it).second;
-
- if (req_ptr &&
+ if (req_ptr->valid &&
req_ptr->getInst()->readTid() == tid &&
req_ptr->getInst()->seqNum > squash_seq_num) {
@@ -431,20 +441,9 @@ UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
unscheduleEvent(req_slot_num);
}
-
- // Mark request for later removal
- cpu->reqRemoveList.push(req_ptr);
- // Mark slot for removal from resource
- slot_remove_list.push_back(req_ptr->getSlot());
+ freeSlot(req_slot_num);
}
-
- map_it++;
- }
-
- // Now Delete Slot Entry from Req. Map
- for (int i = 0; i < slot_remove_list.size(); i++) {
- freeSlot(slot_remove_list[i]);
}
if (outReadSeqNum[tid] >= squash_seq_num) {
diff --git a/src/cpu/inorder/resources/use_def.hh b/src/cpu/inorder/resources/use_def.hh
index d2cc55315..21770cec6 100644
--- a/src/cpu/inorder/resources/use_def.hh
+++ b/src/cpu/inorder/resources/use_def.hh
@@ -56,6 +56,8 @@ class UseDefUnit : public Resource {
UseDefUnit(std::string res_name, int res_id, int res_width,
int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params);
+ void init();
+
ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
int res_idx, int slot_num,
unsigned cmd);
@@ -96,14 +98,20 @@ class UseDefUnit : public Resource {
typedef ThePipeline::DynInstPtr DynInstPtr;
public:
- UseDefRequest(UseDefUnit *res, DynInstPtr inst, int stage_num,
- int res_idx, int slot_num, unsigned cmd,
- int use_def_idx)
- : ResourceRequest(res, inst, stage_num, res_idx, slot_num, cmd),
- useDefIdx(use_def_idx)
+ UseDefRequest(UseDefUnit *res)
+ : ResourceRequest(res)
{ }
int useDefIdx;
+
+ void setRequest(DynInstPtr _inst, int stage_num, int res_idx,
+ int slot_num, unsigned _cmd, int idx)
+ {
+ useDefIdx = idx;
+
+ ResourceRequest::setRequest(_inst, stage_num, res_idx, slot_num,
+ _cmd);
+ }
};
protected:
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 92691720b..647c48a76 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -137,6 +137,10 @@ class DefaultFetch
{}
void
+ markDelayed()
+ {}
+
+ void
finish(Fault fault, RequestPtr req, ThreadContext *tc,
BaseTLB::Mode mode)
{
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index d0c83d586..d2cde496e 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -604,6 +604,9 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
ThreadID tid = mem_req->threadId();
Addr block_PC = mem_req->getVaddr();
+ // Wake up CPU if it was idle
+ cpu->wakeCPU();
+
// If translation was successful, attempt to read the icache block.
if (fault == NoFault) {
// Build packet here.
@@ -654,6 +657,9 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
instruction->fault = fault;
wroteToTimeBuffer = true;
+ DPRINTF(Activity, "Activity this cycle.\n");
+ cpu->activityThisCycle();
+
fetchStatus[tid] = TrapPending;
DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n", tid);
@@ -1064,6 +1070,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
Addr pcOffset = fetchOffset[tid];
Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask;
+ bool inRom = isRomMicroPC(thisPC.microPC());
+
// If returning from the delay of a cache miss, then update the status
// to running, otherwise do the cache access. Possibly move this up
// to tick() function.
@@ -1077,7 +1085,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
Addr block_PC = icacheBlockAlignPC(fetchAddr);
// Unless buffer already got the block, fetch it from icache.
- if (!cacheDataValid[tid] || block_PC != cacheDataPC[tid]) {
+ if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid]) && !inRom) {
DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
"instruction, starting at PC %s.\n", tid, thisPC);
@@ -1149,7 +1157,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
!predictedBranch) {
// If we need to process more memory, do it now.
- if (!curMacroop && !predecoder.extMachInstReady()) {
+ if (!(curMacroop || inRom) && !predecoder.extMachInstReady()) {
if (ISA_HAS_DELAY_SLOT && pcOffset == 0) {
// Walk past any annulled delay slot instructions.
Addr pcAddr = thisPC.instAddr() & BaseCPU::PCMask;
@@ -1175,7 +1183,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// Extract as many instructions and/or microops as we can from
// the memory we've processed so far.
do {
- if (!curMacroop) {
+ if (!(curMacroop || inRom)) {
if (predecoder.extMachInstReady()) {
ExtMachInst extMachInst;
@@ -1196,8 +1204,13 @@ DefaultFetch<Impl>::fetch(bool &status_change)
break;
}
}
- if (curMacroop) {
- staticInst = curMacroop->fetchMicroop(thisPC.microPC());
+ if (curMacroop || inRom) {
+ if (inRom) {
+ staticInst = cpu->microcodeRom.fetchMicroop(
+ thisPC.microPC(), curMacroop);
+ } else {
+ staticInst = curMacroop->fetchMicroop(thisPC.microPC());
+ }
if (staticInst->isLastMicroop()) {
curMacroop = NULL;
pcOffset = 0;
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 3f3761ff3..03f73c798 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -1241,12 +1241,33 @@ DefaultIEW<Impl>::executeInsts()
// Loads will mark themselves as executed, and their writeback
// event adds the instruction to the queue to commit
fault = ldstQueue.executeLoad(inst);
+
+ if (inst->isTranslationDelayed() &&
+ fault == NoFault) {
+ // A hw page table walk is currently going on; the
+ // instruction must be deferred.
+ DPRINTF(IEW, "Execute: Delayed translation, deferring "
+ "load.\n");
+ instQueue.deferMemInst(inst);
+ continue;
+ }
+
if (inst->isDataPrefetch() || inst->isInstPrefetch()) {
fault = NoFault;
}
} else if (inst->isStore()) {
fault = ldstQueue.executeStore(inst);
+ if (inst->isTranslationDelayed() &&
+ fault == NoFault) {
+ // A hw page table walk is currently going on; the
+ // instruction must be deferred.
+ DPRINTF(IEW, "Execute: Delayed translation, deferring "
+ "store.\n");
+ instQueue.deferMemInst(inst);
+ continue;
+ }
+
// If the store had a fault then it may not have a mem req
if (fault != NoFault || inst->readPredicate() == false ||
!inst->isStoreConditional()) {
diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh
index be936e204..64df35743 100644
--- a/src/cpu/o3/inst_queue.hh
+++ b/src/cpu/o3/inst_queue.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -180,6 +192,11 @@ class InstructionQueue
*/
DynInstPtr getInstToExecute();
+ /** Returns a memory instruction that was referred due to a delayed DTB
+ * translation if it is now ready to execute.
+ */
+ DynInstPtr getDeferredMemInstToExecute();
+
/**
* Records the instruction as the producer of a register without
* adding it to the rest of the IQ.
@@ -223,6 +240,12 @@ class InstructionQueue
/** Completes a memory operation. */
void completeMemInst(DynInstPtr &completed_inst);
+ /**
+ * Defers a memory instruction when its DTB translation incurs a hw
+ * page table walk.
+ */
+ void deferMemInst(DynInstPtr &deferred_inst);
+
/** Indicates an ordering violation between a store and a load. */
void violation(DynInstPtr &store, DynInstPtr &faulting_load);
@@ -284,6 +307,11 @@ class InstructionQueue
/** List of instructions that are ready to be executed. */
std::list<DynInstPtr> instsToExecute;
+ /** List of instructions waiting for their DTB translation to
+ * complete (hw page table walk in progress).
+ */
+ std::list<DynInstPtr> deferredMemInsts;
+
/**
* Struct for comparing entries to be added to the priority queue.
* This gives reverse ordering to the instructions in terms of
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index 91cb2f0c8..aa21a0edc 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -397,6 +409,7 @@ InstructionQueue<Impl>::resetState()
}
nonSpecInsts.clear();
listOrder.clear();
+ deferredMemInsts.clear();
}
template <class Impl>
@@ -733,6 +746,15 @@ InstructionQueue<Impl>::scheduleReadyInsts()
IssueStruct *i2e_info = issueToExecuteQueue->access(0);
+ DynInstPtr deferred_mem_inst;
+ int total_deferred_mem_issued = 0;
+ while (total_deferred_mem_issued < totalWidth &&
+ (deferred_mem_inst = getDeferredMemInstToExecute()) != 0) {
+ issueToExecuteQueue->access(0)->size++;
+ instsToExecute.push_back(deferred_mem_inst);
+ total_deferred_mem_issued++;
+ }
+
// Have iterator to head of the list
// While I haven't exceeded bandwidth or reached the end of the list,
// Try to get a FU that can do what this op needs.
@@ -745,7 +767,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
ListOrderIt order_end_it = listOrder.end();
int total_issued = 0;
- while (total_issued < totalWidth &&
+ while (total_issued < (totalWidth - total_deferred_mem_issued) &&
iewStage->canIssue() &&
order_it != order_end_it) {
OpClass op_class = (*order_it).queueType;
@@ -858,7 +880,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
iqInstsIssued+= total_issued;
// If we issued any instructions, tell the CPU we had activity.
- if (total_issued) {
+ if (total_issued || total_deferred_mem_issued) {
cpu->activityThisCycle();
} else {
DPRINTF(IQ, "Not able to schedule any instructions.\n");
@@ -1021,6 +1043,11 @@ void
InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
{
DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
+
+ // Reset DTB translation state
+ resched_inst->translationStarted = false;
+ resched_inst->translationCompleted = false;
+
resched_inst->clearCanIssue();
memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
}
@@ -1051,6 +1078,28 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
template <class Impl>
void
+InstructionQueue<Impl>::deferMemInst(DynInstPtr &deferred_inst)
+{
+ deferredMemInsts.push_back(deferred_inst);
+}
+
+template <class Impl>
+typename Impl::DynInstPtr
+InstructionQueue<Impl>::getDeferredMemInstToExecute()
+{
+ for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
+ ++it) {
+ if ((*it)->translationCompleted) {
+ DynInstPtr ret = *it;
+ deferredMemInsts.erase(it);
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+template <class Impl>
+void
InstructionQueue<Impl>::violation(DynInstPtr &store,
DynInstPtr &faulting_load)
{
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index dd3604ffe..b5d337935 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -445,12 +445,16 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
Fault load_fault = NoFault;
DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
- inst->pcState(),inst->seqNum);
+ inst->pcState(), inst->seqNum);
assert(!inst->isSquashed());
load_fault = inst->initiateAcc();
+ if (inst->isTranslationDelayed() &&
+ load_fault == NoFault)
+ return load_fault;
+
// If the instruction faulted or predicated false, then we need to send it
// along to commit without the instruction completing.
if (load_fault != NoFault || inst->readPredicate() == false) {
@@ -532,6 +536,10 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
Fault store_fault = store_inst->initiateAcc();
+ if (store_inst->isTranslationDelayed() &&
+ store_fault == NoFault)
+ return store_fault;
+
if (store_inst->readPredicate() == false)
store_inst->forwardOldRegs();
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 453699f84..ab1ff91e8 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -752,6 +752,7 @@ TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc)
} else {
delete req;
// fetch fault: advance directly to next instruction (fault handler)
+ _status = Running;
advanceInst(fault);
}
@@ -805,12 +806,11 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt)
if (curStaticInst && curStaticInst->isMemRef()) {
// load or store: just send to dcache
Fault fault = curStaticInst->initiateAcc(this, traceData);
- if (_status != Running) {
- // instruction will complete in dcache response callback
- assert(_status == DcacheWaitResponse ||
- _status == DcacheRetry || DTBWaitResponse);
- assert(fault == NoFault);
- } else {
+
+ // If we're not running now the instruction will complete in a dcache
+ // response callback or the instruction faulted and has started an
+ // ifetch
+ if (_status == Running) {
if (fault != NoFault && traceData) {
// If there was a fault, we shouldn't trace this instruction.
delete traceData;
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index 2b0c8942a..a7a3eb7c3 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -108,6 +108,13 @@ class TimingSimpleCPU : public BaseSimpleCPU
{}
void
+ markDelayed()
+ {
+ assert(cpu->_status == Running);
+ cpu->_status = ITBWaitResponse;
+ }
+
+ void
finish(Fault fault, RequestPtr req, ThreadContext *tc,
BaseTLB::Mode mode)
{
diff --git a/src/cpu/translation.hh b/src/cpu/translation.hh
index 7db7c381a..60953540f 100644
--- a/src/cpu/translation.hh
+++ b/src/cpu/translation.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
@@ -53,6 +65,7 @@ class WholeTranslationState
Fault faults[2];
public:
+ bool delay;
bool isSplit;
RequestPtr mainReq;
RequestPtr sreqLow;
@@ -67,8 +80,8 @@ class WholeTranslationState
*/
WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res,
BaseTLB::Mode _mode)
- : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL),
- sreqHigh(NULL), data(_data), res(_res), mode(_mode)
+ : outstanding(1), delay(false), isSplit(false), mainReq(_req),
+ sreqLow(NULL), sreqHigh(NULL), data(_data), res(_res), mode(_mode)
{
faults[0] = faults[1] = NoFault;
assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
@@ -82,8 +95,9 @@ class WholeTranslationState
WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow,
RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res,
BaseTLB::Mode _mode)
- : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow),
- sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode)
+ : outstanding(2), delay(false), isSplit(true), mainReq(_req),
+ sreqLow(_sreqLow), sreqHigh(_sreqHigh), data(_data), res(_res),
+ mode(_mode)
{
faults[0] = faults[1] = NoFault;
assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
@@ -221,6 +235,16 @@ class DataTranslation : public BaseTLB::Translation
}
/**
+ * Signal the translation state that the translation has been delayed due
+ * to a hw page table walk. Split requests are transparently handled.
+ */
+ void
+ markDelayed()
+ {
+ state->delay = true;
+ }
+
+ /**
* Finish this part of the translation and indicate that the whole
* translation is complete if the state says so.
*/