diff options
Diffstat (limited to 'src')
28 files changed, 478 insertions, 436 deletions
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 3a705258d..0ec4c9861 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -324,12 +324,7 @@ 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); @@ -361,6 +356,17 @@ 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; @@ -459,13 +465,13 @@ InOrderCPU::createBackEndSked(DynInstPtr inst) W.needs(ExecUnit, ExecutionUnit::ExecuteInst); } + W.needs(Grad, GraduationUnit::GraduateInst); + for (int idx=0; idx < inst->numDestRegs(); idx++) { W.needs(RegManager, UseDefUnit::WriteDestReg, idx); } - W.needs(Grad, GraduationUnit::GraduateInst); - - // Insert Front Schedule into our cache of + // Insert Back Schedule into our cache of // resource schedules addToSkedCache(inst, res_sked); @@ -636,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(); @@ -1436,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 2a5c815e1..2fa6bdc59 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -315,6 +315,7 @@ class InOrderCPU : public BaseCPU 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; } @@ -593,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. */ @@ -626,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/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index bc31a8537..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,8 +946,11 @@ 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)); @@ -948,11 +959,10 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) req->stagePasses++; - bool done_in_pipeline = inst->finishSkedEntry(); + done_in_pipeline = inst->finishSkedEntry(); if (done_in_pipeline) { DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] finished " "in pipeline.\n", tid, inst->seqNum); - break; } } else { DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed." @@ -989,21 +999,18 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) "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()); - } - - + } + + // 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.hh b/src/cpu/inorder/pipeline_traits.hh index 75f01adb1..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 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 72b45dda8..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,6 +182,9 @@ 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->curSkedEntry->stageNum; unsigned cmd = inst->curSkedEntry->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 e1914623a..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,16 +77,16 @@ 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, 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 8cd105493..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->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; @@ -297,6 +293,7 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, int slot_num, unsigned cmd) { 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->curSkedEntry->idx); + cache_req->setRequest(inst, stage_num, id, slot_num, + sched_entry->cmd, pkt_cmd, + inst->curSkedEntry->idx); + return cache_req; } void @@ -651,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); @@ -667,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(); @@ -693,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(), @@ -808,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; } @@ -867,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, @@ -891,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); } } @@ -914,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(); @@ -1059,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); @@ -1073,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 @@ -1124,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(); + 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) { @@ -1145,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; } @@ -1159,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 " @@ -1182,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 42857c783..71d33ab90 100644 --- a/src/cpu/inorder/resources/decode_unit.cc +++ b/src/cpu/inorder/resources/decode_unit.cc @@ -49,8 +49,8 @@ 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) 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 0a5483aff..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) @@ -119,32 +144,23 @@ FetchUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, int slot_num, unsigned cmd) { 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->curSkedEntry->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(); @@ -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 362641b54..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,8 +48,8 @@ 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->curSkedEntry->stageNum; @@ -58,15 +57,18 @@ GraduationUnit::execute(int slot_num) { case GraduateInst: { - // Make sure this is the last thing on the resource schedule - // @todo: replace this check - // 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, @@ -81,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 988fcd4da..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(); diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index 042fb590b..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); @@ -132,7 +136,7 @@ MultDivUnit::getSlot(DynInstPtr inst) // If we have this instruction's request already then return if (slot_num != -1 && - inst->curSkedEntry->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 2e19ea928..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->curSkedEntry->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 538b20246..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->curSkedEntry->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->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: |