diff options
author | Brad Beckmann <Brad.Beckmann@amd.com> | 2011-02-22 11:16:40 -0800 |
---|---|---|
committer | Brad Beckmann <Brad.Beckmann@amd.com> | 2011-02-22 11:16:40 -0800 |
commit | 63a25a56ccc93c24703fec87f830c833974e7060 (patch) | |
tree | a0f12244a32eb7da2963ca974ab49a993aee2cfc /src/cpu/inorder/resources | |
parent | 8ea71c3907a411de9c203b45bfd6eab24e3ad849 (diff) | |
parent | 77eed184f529c4ccbef59ad2018d18ff3fbb54af (diff) | |
download | gem5-63a25a56ccc93c24703fec87f830c833974e7060.tar.xz |
m5: merged in hammer fix
Diffstat (limited to 'src/cpu/inorder/resources')
20 files changed, 332 insertions, 506 deletions
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: |