diff options
Diffstat (limited to 'src/cpu/inorder/resource.cc')
-rw-r--r-- | src/cpu/inorder/resource.cc | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc deleted file mode 100644 index c732b8519..000000000 --- a/src/cpu/inorder/resource.cc +++ /dev/null @@ -1,523 +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 <list> -#include <vector> - -#include "base/str.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/ExecFaulting.hh" -#include "debug/RefCount.hh" -#include "debug/ResReqCount.hh" -#include "debug/Resource.hh" - -using namespace std; - -Resource::Resource(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu) - : resName(res_name), id(res_id), - width(res_width), latency(res_latency), cpu(_cpu), - resourceEvent(NULL) -{ - reqs.resize(width); - - // Use to deny a instruction a resource. - deniedReq = new ResourceRequest(this); - deniedReq->valid = true; -} - -Resource::~Resource() -{ - if (resourceEvent) { - delete [] resourceEvent; - } - - delete deniedReq; - - for (int i = 0; i < width; i++) { - delete reqs[i]; - } -} - - -void -Resource::init() -{ - // 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 > Cycles(0)) - resourceEvent = new ResourceEvent[width]; - - - for (int i = 0; i < width; i++) - reqs[i] = new ResourceRequest(this); - - - initSlots(); -} - -void -Resource::initSlots() -{ - // Add available slot numbers for resource - for (int slot_idx = 0; slot_idx < width; slot_idx++) { - availSlots.push_back(slot_idx); - - if (resourceEvent) { - resourceEvent[slot_idx].init(this, slot_idx); - } - } -} - -std::string -Resource::name() -{ - return cpu->name() + "." + resName; -} - -int -Resource::slotsAvail() -{ - return availSlots.size(); -} - -int -Resource::slotsInUse() -{ - return width - availSlots.size(); -} - -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); - - // Invalidate Request & Reset it's flags - reqs[slot_idx]->clearRequest(); -} - -int -Resource::findSlot(DynInstPtr inst) -{ - int slot_num = -1; - - for (int i = 0; i < width; i++) { - if (reqs[i]->valid && - reqs[i]->getInst()->seqNum == inst->seqNum) { - slot_num = reqs[i]->getSlot(); - } - } - return slot_num; -} - -int -Resource::getSlot(DynInstPtr inst) -{ - int slot_num = -1; - - if (slotsAvail() != 0) { - slot_num = availSlots[0]; - - vector<int>::iterator vect_it = availSlots.begin(); - - assert(slot_num == *vect_it); - - availSlots.erase(vect_it); - } - - return slot_num; -} - -ResReqPtr -Resource::request(DynInstPtr inst) -{ - // See if the resource is already serving this instruction. - // If so, use that request; - bool try_request = false; - int slot_num = -1; - int stage_num; - ResReqPtr inst_req = findRequest(inst); - - if (inst_req) { - // If some preprocessing has to be done on instruction - // that has already requested once, then handle it here. - // update the 'try_request' variable if we should - // re-execute the request. - requestAgain(inst, try_request); - - slot_num = inst_req->getSlot(); - stage_num = inst_req->getStageNum(); - } else { - // Get new slot # for instruction - 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; - - // Generate Resource Request - inst_req = getRequest(inst, stage_num, id, slot_num, cmd); - - if (inst->staticInst) { - DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this " - "resource.\n", - inst->readTid(), inst->seqNum); - } else { - DPRINTF(Resource, "[tid:%i]: instruction requesting this " - "resource.\n", - inst->readTid()); - } - - try_request = true; - } else { - DPRINTF(Resource, "No slot available for [tid:%i]: [sn:%i]\n", - inst->readTid(), inst->seqNum); - } - - } - - if (try_request) { - // Schedule execution of resource - scheduleExecution(slot_num); - } else { - inst_req = deniedReq; - rejectRequest(inst); - } - - return inst_req; -} - -void -Resource::requestAgain(DynInstPtr inst, bool &do_request) -{ - do_request = true; - - if (inst->staticInst) { - DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this resource " - "again.\n", - inst->readTid(), inst->seqNum); - } else { - DPRINTF(Resource, "[tid:%i]: requesting this resource again.\n", - inst->readTid()); - } -} - -ResReqPtr -Resource::getRequest(DynInstPtr inst, int stage_num, int res_idx, - int slot_num, unsigned cmd) -{ - reqs[slot_num]->setRequest(inst, stage_num, id, slot_num, cmd); - return reqs[slot_num]; -} - -ResReqPtr -Resource::findRequest(DynInstPtr inst) -{ - for (int i = 0; i < width; i++) { - if (reqs[i]->valid && - reqs[i]->getInst() == inst) { - return reqs[i]; - } - } - - return NULL; -} - -void -Resource::rejectRequest(DynInstPtr inst) -{ - DPRINTF(RefCount, "[tid:%i]: Unable to grant request for [sn:%i].\n", - inst->readTid(), inst->seqNum); -} - -void -Resource::execute(int slot_idx) -{ - //@todo: have each resource print out command their executing - DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n", - reqs[slot_idx]->getTid(), name()); - reqs[slot_idx]->setCompleted(true); - reqs[slot_idx]->done(); -} - -void -Resource::deactivateThread(ThreadID tid) -{ - // In the most basic case, deactivation means squashing everything - // from a particular thread - DynInstPtr dummy_inst = new InOrderDynInst(cpu, NULL, 0, tid, tid); - squash(dummy_inst, 0, 0, tid); -} - -void -Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid) -{ - // Squash In Pipeline Stage - cpu->pipelineStage[stage_num]->setupSquash(inst, tid); - - // Schedule Squash Through-out Resource Pool - cpu->resPool->scheduleEvent( - (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, - Cycles(0)); -} - -void -Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, - ThreadID tid) -{ - //@todo: check squash seq num before squashing. can save time going - // through this function. - for (int i = 0; i < width; i++) { - ResReqPtr req_ptr = reqs[i]; - DynInstPtr inst = req_ptr->getInst(); - - if (req_ptr->valid && - inst->readTid() == tid && - inst->seqNum > squash_seq_num) { - - DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n", - req_ptr->getInst()->readTid(), - req_ptr->getInst()->seqNum); - - req_ptr->setSquashed(); - - int req_slot_num = req_ptr->getSlot(); - - if (latency > Cycles(0)) { - if (resourceEvent[req_slot_num].scheduled()) - unscheduleEvent(req_slot_num); - } - - freeSlot(req_slot_num); - } - } -} - -void -Resource::squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, - ThreadID tid) -{ - squash(inst, stage_num, squash_seq_num, tid); -} - -void -Resource::squashThenTrap(int stage_num, DynInstPtr inst) -{ - ThreadID tid = inst->readTid(); - - inst->setSquashInfo(stage_num); - setupSquash(inst, stage_num, tid); - - if (inst->traceData) { - if (inst->staticInst && - inst->fault != NoFault && DTRACE(ExecFaulting)) { - inst->traceData->setStageCycle(stage_num, curTick()); - inst->traceData->setFetchSeq(inst->seqNum); - inst->traceData->dump(); - } - - delete inst->traceData; - inst->traceData = NULL; - } - - cpu->trapContext(inst->fault, tid, inst); -} - -void -Resource::scheduleExecution(int slot_num) -{ - if (latency > Cycles(0)) { - scheduleEvent(slot_num, latency); - } else { - execute(slot_num); - } -} - -void -Resource::scheduleEvent(int slot_idx, Cycles delay) -{ - DPRINTF(Resource, "[tid:%i]: Scheduling event for [sn:%i] on tick %i.\n", - reqs[slot_idx]->inst->readTid(), - reqs[slot_idx]->inst->seqNum, - cpu->clockEdge(delay)); - resourceEvent[slot_idx].scheduleEvent(delay); -} - -bool -Resource::scheduleEvent(DynInstPtr inst, Cycles delay) -{ - int slot_idx = findSlot(inst); - - if(slot_idx != -1) - resourceEvent[slot_idx].scheduleEvent(delay); - - return slot_idx; -} - -void -Resource::unscheduleEvent(int slot_idx) -{ - resourceEvent[slot_idx].unscheduleEvent(); -} - -bool -Resource::unscheduleEvent(DynInstPtr inst) -{ - int slot_idx = findSlot(inst); - - if(slot_idx != -1) - resourceEvent[slot_idx].unscheduleEvent(); - - return slot_idx; -} - -int ResourceRequest::resReqID = 0; - -int ResourceRequest::maxReqCount = 0; - -ResourceRequest::ResourceRequest(Resource *_res) - : res(_res), inst(NULL), stagePasses(0), valid(false), doneInResource(false), - completed(false), squashed(false), processing(false), - memStall(false) -{ -} - -ResourceRequest::~ResourceRequest() -{ -#ifdef DEBUG - res->cpu->resReqCount--; - DPRINTF(ResReqCount, "Res. Req %i deleted. resReqCount=%i.\n", reqID, - res->cpu->resReqCount); -#endif - inst = NULL; -} - -std::string -ResourceRequest::name() -{ - return csprintf("%s[slot:%i]:", res->name(), 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 -ResourceRequest::done(bool completed) -{ - DPRINTF(Resource, "done with request from " - "[sn:%i] [tid:%i].\n", - inst->seqNum, inst->readTid()); - - setCompleted(completed); - - doneInResource = true; -} - -ResourceEvent::ResourceEvent() - : Event((Event::Priority)Resource_Event_Pri) -{ } - -ResourceEvent::ResourceEvent(Resource *res, int slot_idx) - : Event((Event::Priority)Resource_Event_Pri), resource(res), - slotIdx(slot_idx) -{ } - -void -ResourceEvent::init(Resource *res, int slot_idx) -{ - resource = res; - slotIdx = slot_idx; -} - -void -ResourceEvent::process() -{ - resource->execute(slotIdx); -} - -const char * -ResourceEvent::description() const -{ - string desc = resource->name() + "-event:slot[" + to_string(slotIdx) - + "]"; - - return desc.c_str(); -} - -void -ResourceEvent::scheduleEvent(Cycles delay) -{ - assert(!scheduled() || squashed()); - resource->cpu->reschedule(this, - resource->cpu->clockEdge(delay), true); -} |