diff options
Diffstat (limited to 'src/cpu/inorder/resources')
26 files changed, 0 insertions, 5870 deletions
diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc deleted file mode 100644 index f978b2fa7..000000000 --- a/src/cpu/inorder/resources/agen_unit.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Korey Sewell - * - */ - -#include "cpu/inorder/resources/agen_unit.hh" -#include "debug/InOrderAGEN.hh" - -AGENUnit::AGENUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ } - -void -AGENUnit::regStats() -{ - agens - .name(name() + ".agens") - .desc("Number of Address Generations"); - - Resource::regStats(); -} - -void -AGENUnit::execute(int slot_num) -{ - ResourceRequest* agen_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; -#if TRACING_ON - ThreadID tid = inst->readTid(); -#endif - InstSeqNum seq_num = inst->seqNum; - - if (inst->fault != NoFault) { - DPRINTF(InOrderAGEN, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - inst->pcState()); - agen_req->done(); - return; - } - - switch (agen_req->cmd) - { - case GenerateAddr: - { - // Load/Store Instruction - if (inst->isMemRef()) { - DPRINTF(InOrderAGEN, - "[tid:%i] Generating Address for [sn:%i] (%s).\n", - tid, seq_num, inst->staticInst->getName()); - - inst->fault = inst->calcEA(); - inst->setMemAddr(inst->getEA()); - - DPRINTF(InOrderAGEN, - "[tid:%i] [sn:%i] Effective address calculated as: %#x\n", - tid, seq_num, inst->getEA()); - - if (inst->fault == NoFault) { - agen_req->done(); - } else { - fatal("%s encountered while calculating address [sn:%i] %s", - inst->fault->name(), seq_num, inst->instName()); - } - - agens++; - } else { - DPRINTF(InOrderAGEN, - "[tid:] Ignoring non-memory instruction [sn:%i]\n", - tid, seq_num); - agen_req->done(); - } - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} diff --git a/src/cpu/inorder/resources/agen_unit.hh b/src/cpu/inorder/resources/agen_unit.hh deleted file mode 100644 index 72c8a1339..000000000 --- a/src/cpu/inorder/resources/agen_unit.hh +++ /dev/null @@ -1,64 +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_AGEN_UNIT_HH__ -#define __CPU_INORDER_AGEN_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class AGENUnit : public Resource { - public: - typedef InOrderDynInst::DynInstPtr DynInstPtr; - - public: - AGENUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - enum Command { - GenerateAddr - }; - - virtual void execute(int slot_num); - void regStats(); - - protected: - Stats::Scalar agens; -}; - -#endif //__CPU_INORDER_DECODE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc deleted file mode 100644 index 50d3847ba..000000000 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ /dev/null @@ -1,181 +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 "config/the_isa.hh" -#include "cpu/inorder/resources/branch_predictor.hh" -#include "debug/InOrderBPred.hh" -#include "debug/InOrderStage.hh" -#include "debug/Resource.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -BranchPredictor::BranchPredictor(std::string res_name, int res_id, - int res_width, Cycles res_latency, - InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - branchPred(params->branchPred) -{ - instSize = sizeof(MachInst); -} - -void -BranchPredictor::regStats() -{ - predictedTaken - .name(name() + ".predictedTaken") - .desc("Number of Branches Predicted As Taken (True)."); - - predictedNotTaken - .name(name() + ".predictedNotTaken") - .desc("Number of Branches Predicted As Not Taken (False)."); - - Resource::regStats(); -} - -void -BranchPredictor::execute(int slot_num) -{ - ResourceRequest* bpred_req = reqs[slot_num]; - DynInstPtr inst = bpred_req->inst; - if (inst->fault != NoFault) { - DPRINTF(InOrderBPred, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->pcState()); - bpred_req->done(); - return; - } - - if (!inst->isControl()) { - DPRINTF(Resource, "Ignoring %s, not a control inst.\n", - inst->instName()); - bpred_req->done(); - return; - } - - ThreadID tid = inst->readTid(); - InstSeqNum seq_num = inst->seqNum; - switch (bpred_req->cmd) - { - case PredictBranch: - { - if (inst->seqNum > cpu->squashSeqNum[tid] && - curTick() == cpu->lastSquashCycle[tid]) { - DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, " - "skipping prediction \n", tid, inst->seqNum); - } else { - TheISA::PCState instPC = inst->pcState(); - TheISA::PCState pred_PC = inst->pcState(); - TheISA::advancePC(pred_PC, inst->staticInst); - - if (inst->isControl()) { - // If not, the pred_PC be updated to pc+8 - // If predicted, the pred_PC will be updated to new target - // value - bool predict_taken = branchPred->predictInOrder( - inst->staticInst, inst->seqNum, - inst->asid, instPC, pred_PC, tid); - - if (predict_taken) { - DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " - "predicted true.\n", tid, seq_num); - predictedTaken++; - } else { - DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " - "predicted false.\n", tid, seq_num); - predictedNotTaken++; - } - - inst->setBranchPred(predict_taken); - } - - //@todo: Check to see how hw_rei is handled here...how does - //PC,NPC get updated to compare mispredict against??? - inst->setPredTarg(pred_PC); - DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: %s Predicted PC is " - "%s.\n", tid, seq_num, inst->instName(), pred_PC); - } - - bpred_req->done(); - } - break; - - case UpdatePredictor: - { - if (inst->seqNum > cpu->squashSeqNum[tid] && - curTick() == cpu->lastSquashCycle[tid]) { - DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, " - "skipping branch predictor update \n", - tid, inst->seqNum); - } else { - DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Updating " - "Branch Predictor.\n", - tid, seq_num); - - - branchPred->update(seq_num, tid); - } - - bpred_req->done(); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -BranchPredictor::squash(DynInstPtr inst, int squash_stage, - InstSeqNum squash_seq_num, ThreadID tid) -{ - InstSeqNum bpred_squash_num = inst->seqNum; - DPRINTF(InOrderBPred, "[tid:%i][sn:%i] Squashing...\n", tid, - bpred_squash_num); - - // update due to branch resolution - if (squash_stage >= ThePipeline::BackEndStartStage) { - branchPred->squash(bpred_squash_num, inst->pcState(), - inst->pcState().branching(), tid); - } else { - // update due to predicted taken branch - branchPred->squash(bpred_squash_num, tid); - } -} - -void -BranchPredictor::instGraduated(InstSeqNum seq_num, ThreadID tid) -{ - branchPred->update(seq_num, tid); -} diff --git a/src/cpu/inorder/resources/branch_predictor.hh b/src/cpu/inorder/resources/branch_predictor.hh deleted file mode 100644 index e2b7fba52..000000000 --- a/src/cpu/inorder/resources/branch_predictor.hh +++ /dev/null @@ -1,87 +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_BRANCH_PREDICTOR_HH__ -#define __CPU_INORDER_BRANCH_PREDICTOR_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/pred/bpred_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class BranchPredictor : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - enum Command { - PredictBranch, - UpdatePredictor - }; - - public: - BranchPredictor(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - void regStats(); - - void execute(int slot_num); - - void squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - - void instGraduated(InstSeqNum seq_num, ThreadID tid); - - protected: - /** List of instructions this resource is currently - * processing. - */ - BPredUnit *branchPred; - - int instSize; - - ///////////////////////////////////////////////////////////////// - // - // RESOURCE STATISTICS - // - ///////////////////////////////////////////////////////////////// - Stats::Scalar predictedTaken; - Stats::Scalar predictedNotTaken; - -}; - -#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__ diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc deleted file mode 100644 index 78b803501..000000000 --- a/src/cpu/inorder/resources/cache_unit.cc +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Copyright (c) 2013 ARM Limited - * All rights reserved - * - * The license below extends only to copyright in the software and shall - * not be construed as granting a license to any other intellectual - * property including but not limited to intellectual property relating - * to a hardware implementation of the functionality of the software - * licensed hereunder. You may use the software subject to the license - * terms below provided that you ensure that this notice is replicated - * unmodified and in its entirety in all distributions of the software, - * modified or unmodified, in source code or in binary form. - * - * Copyright (c) 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 "arch/isa_traits.hh" -#include "arch/locked_mem.hh" -#include "arch/utility.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/cache_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/Activity.hh" -#include "debug/AddrDep.hh" -#include "debug/InOrderCachePort.hh" -#include "debug/InOrderStall.hh" -#include "debug/InOrderTLB.hh" -#include "debug/LLSC.hh" -#include "debug/RefCount.hh" -#include "debug/ThreadModel.hh" -#include "mem/request.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -#if TRACING_ON -static std::string -printMemData(const uint8_t *data, unsigned size) -{ - std::stringstream dataStr; - for (unsigned pos = 0; pos < size; pos++) { - ccprintf(dataStr, "%02x", data[pos]); - } - return dataStr.str(); -} -#endif - -CacheUnit::CacheUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - cachePort(NULL), cachePortBlocked(false) -{ - // Hard-Code Selection For Now - if (res_id == ICache) - _tlb = params->itb; - else if (res_id == DCache) - _tlb = params->dtb; - else - fatal("Unrecognized TLB name passed by user"); - - // Note that the CPU port is not yet instantiated (as it is done - // after the resource pool), we delay setting the cachePort - // pointer until init(). - - for (int i=0; i < MaxThreads; i++) { - tlbBlocked[i] = false; - tlbBlockSeqNum[i] = 0; - } -} - -TheISA::TLB* -CacheUnit::tlb() -{ - return _tlb; - -} - -void -CacheUnit::init() -{ - // Get the appropriate port from the CPU based on the resource name. - if (id == ICache) { - cachePort = &cpu->getInstPort(); - } else if (id == DCache) { - cachePort = &cpu->getDataPort(); - } - assert(cachePort != NULL); - - for (int i = 0; i < width; i++) { - reqs[i] = new CacheRequest(this); - } - - cacheBlkSize = cpu->cacheLineSize(); - cacheBlkMask = cacheBlkSize - 1; - - initSlots(); -} - -int -CacheUnit::getSlot(DynInstPtr inst) -{ - ThreadID tid = inst->readTid(); - if (tlbBlocked[tid]) { - return -1; - } - - // For a Split-Load, the instruction would have processed once already - // causing the address to be unset. - if (!inst->validMemAddr() && !inst->splitInst) { - panic("[tid:%i][sn:%i] Mem. Addr. must be set before requesting " - "cache access\n", inst->readTid(), inst->seqNum); - } - - int new_slot = Resource::getSlot(inst); - inst->memTime = curTick(); - //@note: add back in if you want speculative loads/store capability - //setAddrDependency(inst); - return new_slot; -} - -void -CacheUnit::setAddrDependency(DynInstPtr inst) -{ - Addr req_addr = inst->getMemAddr(); - ThreadID tid = inst->readTid(); - - addrList[tid].push_back(req_addr); - addrMap[tid][req_addr] = inst->seqNum; - - DPRINTF(AddrDep, - "[tid:%i]: [sn:%i]: Address %08p added to dependency list (size=%i)\n", - inst->readTid(), inst->seqNum, req_addr, addrList[tid].size()); - - //@NOTE: 10 is an arbitrarily "high" number, but to be exact - // we would need to know the # of outstanding accesses - // a priori. Information like fetch width, stage width, - // fetch buffer, and the branch resolution stage would be - // useful for the icache_port. For the dcache port, the # - // of outstanding cache accesses (mshrs) would be a good - // sanity check here. - //assert(addrList[tid].size() < 10); -} - -void -CacheUnit::removeAddrDependency(DynInstPtr inst) -{ - ThreadID tid = inst->readTid(); - - Addr mem_addr = inst->getMemAddr(); - - inst->unsetMemAddr(); - - // Erase from Address List - std::list<Addr>::iterator list_it = find(addrList[tid].begin(), - addrList[tid].end(), - mem_addr); - assert(list_it != addrList[tid].end() || inst->splitInst); - - if (list_it != addrList[tid].end()) { - DPRINTF(AddrDep, - "[tid:%i]: [sn:%i] Address %08p removed from dependency " - "list\n", inst->readTid(), inst->seqNum, (*list_it)); - - addrList[tid].erase(list_it); - - // Erase From Address Map (Used for Debugging) - addrMap[tid].erase(addrMap[tid].find(mem_addr)); - } - - -} - -ResReqPtr -CacheUnit::findRequest(DynInstPtr inst) -{ - for (int i = 0; i < width; i++) { - CacheRequest* cache_req = - dynamic_cast<CacheRequest*>(reqs[i]); - assert(cache_req); - - if (cache_req->valid && - cache_req->getInst() == inst && - cache_req->instIdx == inst->curSkedEntry->idx) { - return cache_req; - } - } - - return NULL; -} - -ResReqPtr -CacheUnit::findRequest(DynInstPtr inst, int idx) -{ - for (int i = 0; i < width; i++) { - CacheRequest* cache_req = - dynamic_cast<CacheRequest*>(reqs[i]); - assert(cache_req); - - if (cache_req->valid && - cache_req->getInst() == inst && - cache_req->instIdx == idx) { - return cache_req; - } - } - - return NULL; -} - - -ResReqPtr -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"); - } - - MemCmd::Command pkt_cmd; - - switch (sched_entry->cmd) - { - case InitSecondSplitRead: - pkt_cmd = MemCmd::ReadReq; - - DPRINTF(InOrderCachePort, - "[tid:%i]: Read request from [sn:%i] for addr %08p\n", - inst->readTid(), inst->seqNum, inst->split2ndAddr); - break; - - case InitiateReadData: - pkt_cmd = MemCmd::ReadReq; - - DPRINTF(InOrderCachePort, - "[tid:%i]: Read request from [sn:%i] for addr %08p\n", - inst->readTid(), inst->seqNum, inst->getMemAddr()); - break; - - case InitSecondSplitWrite: - pkt_cmd = MemCmd::WriteReq; - - DPRINTF(InOrderCachePort, - "[tid:%i]: Write request from [sn:%i] for addr %08p\n", - inst->readTid(), inst->seqNum, inst->split2ndAddr); - break; - - case InitiateWriteData: - pkt_cmd = MemCmd::WriteReq; - - DPRINTF(InOrderCachePort, - "[tid:%i]: Write request from [sn:%i] for addr %08p\n", - inst->readTid(), inst->seqNum, inst->getMemAddr()); - break; - - 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, pkt_cmd, - inst->curSkedEntry->idx); - return cache_req; -} - -void -CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) -{ - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst)); - assert(cache_req); - - // Check to see if this instruction is requesting the same command - // or a different one - 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->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->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, - "[tid:%i]: [sn:%i]: requesting this resource again\n", - inst->readTid(), inst->seqNum); - - service_request = true; - } -} - -void -CacheUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req, - int acc_size, int flags) -{ - ThreadID tid = inst->readTid(); - Addr aligned_addr = inst->getMemAddr(); - - if (!cache_req->is2ndSplit()) { - if (cache_req->memReq == NULL) { - cache_req->memReq = - new Request(cpu->asid[tid], aligned_addr, acc_size, flags, - cpu->dataMasterId(), - inst->instAddr(), - cpu->readCpuId(), //@todo: use context id - tid); - } - } else { - assert(inst->splitInst); - - if (inst->splitMemReq == NULL) { - inst->splitMemReq = new Request(cpu->asid[tid], - inst->split2ndAddr, - acc_size, - flags, - cpu->dataMasterId(), - inst->instAddr(), - cpu->readCpuId(), - tid); - } - - cache_req->memReq = inst->splitMemReq; - } -} - -void -CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, - int flags, TheISA::TLB::Mode tlb_mode) -{ - ThreadID tid = inst->readTid(); - - setupMemRequest(inst, cache_req, acc_size, flags); - - //@todo: HACK: the DTB expects the correct PC in the ThreadContext - // but how if the memory accesses are speculative? Shouldn't - // we send along the requestor's PC to the translate functions? - ThreadContext *tc = cpu->thread[tid]->getTC(); - PCState old_pc = tc->pcState(); - tc->pcState() = inst->pcState(); - - inst->fault = - _tlb->translateAtomic(cache_req->memReq, tc, tlb_mode); - tc->pcState() = old_pc; - - if (inst->fault != NoFault) { - DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " - "addr:%08p for [sn:%i].\n", tid, inst->fault->name(), - cache_req->memReq->getVaddr(), inst->seqNum); - - tlbBlocked[tid] = true; - tlbBlockSeqNum[tid] = inst->seqNum; - - // Make sure nothing gets executed until after this faulting - // instruction gets handled. - inst->setSerializeAfter(); - - // Mark it as complete so it can pass through next stage. - // Fault Handling will happen at commit/graduation - cache_req->setCompleted(); - } else { - DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " - "to phys. addr:%08p.\n", tid, inst->seqNum, - cache_req->memReq->getVaddr(), - cache_req->memReq->getPaddr()); - } -} - -void -CacheUnit::trap(const Fault &fault, ThreadID tid, DynInstPtr inst) -{ - tlbBlocked[tid] = false; -} - -Fault -CacheUnit::read(DynInstPtr inst, Addr addr, - uint8_t *data, unsigned size, unsigned flags) -{ - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst)); - assert(cache_req && "Can't Find Instruction for Read!"); - - // The block size of our peer - unsigned blockSize = cacheBlkSize; - - //The size of the data we're trying to read. - int fullSize = size; - inst->totalSize = size; - - if (inst->traceData) { - inst->traceData->setMem(addr, size, flags); - } - - if (inst->split2ndAccess) { - size = inst->split2ndSize; - cache_req->splitAccess = true; - cache_req->split2ndAccess = true; - - DPRINTF(InOrderCachePort, "[sn:%i] Split Read Access (2 of 2) for " - "(%#x, %#x).\n", inst->seqNum, inst->getMemAddr(), - inst->split2ndAddr); - } - - - //The address of the second part of this access if it needs to be split - //across a cache line boundary. - Addr secondAddr = roundDown(addr + size - 1, blockSize); - - - if (secondAddr > addr && !inst->split2ndAccess) { - - if (!inst->splitInst) { - DPRINTF(InOrderCachePort, "%i: sn[%i] Split Read Access (1 of 2) for " - "(%#x, %#x).\n", curTick(), inst->seqNum, addr, secondAddr); - - unsigned stage_num = cache_req->getStageNum(); - unsigned cmd = inst->curSkedEntry->cmd; - - // 1. Make A New Inst. Schedule w/Split Read/Complete Entered on - // the schedule - // ============================== - // 2. Reassign curSkedPtr to current command (InitiateRead) on new - // schedule - // ============================== - inst->splitInst = true; - inst->setBackSked(cpu->createBackEndSked(inst)); - inst->curSkedEntry = inst->backSked->find(stage_num, cmd); - } else { - DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] Retrying Split Read " - "Access (1 of 2) for (%#x, %#x).\n", inst->readTid(), - inst->seqNum, addr, secondAddr); - } - - // Save All "Total" Split Information - // ============================== - inst->splitMemData = new uint8_t[size]; - - // Split Information for First Access - // ============================== - size = secondAddr - addr; - cache_req->splitAccess = true; - - // Split Information for Second Access - // ============================== - inst->split2ndSize = addr + fullSize - secondAddr; - inst->split2ndAddr = secondAddr; - inst->split2ndDataPtr = inst->splitMemData + size; - inst->split2ndFlags = flags; - } - - doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Read); - - if (inst->fault == NoFault) { - if (!cache_req->splitAccess) { - cache_req->reqData = new uint8_t[size]; - doCacheAccess(inst, NULL); - } else { - if (!inst->split2ndAccess) { - cache_req->reqData = inst->splitMemData; - } else { - cache_req->reqData = inst->split2ndDataPtr; - } - - doCacheAccess(inst, NULL, cache_req); - } - } - - return inst->fault; -} - -Fault -CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *write_res) -{ - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst)); - assert(cache_req && "Can't Find Instruction for Write!"); - - // The block size of our peer - unsigned blockSize = cacheBlkSize; - - //The size of the data we're trying to write. - int fullSize = size; - inst->totalSize = size; - - if (inst->traceData) - inst->traceData->setMem(addr, size, flags); - - if (inst->split2ndAccess) { - size = inst->split2ndSize; - cache_req->splitAccess = true; - cache_req->split2ndAccess = true; - - DPRINTF(InOrderCachePort, "[sn:%i] Split Write Access (2 of 2) for " - "(%#x, %#x).\n", inst->seqNum, inst->getMemAddr(), - inst->split2ndAddr); - } - - //The address of the second part of this access if it needs to be split - //across a cache line boundary. - Addr secondAddr = roundDown(addr + size - 1, blockSize); - - if (secondAddr > addr && !inst->split2ndAccess) { - - DPRINTF(InOrderCachePort, "[sn:%i] Split Write Access (1 of 2) for " - "(%#x, %#x).\n", inst->seqNum, addr, secondAddr); - - // Save All "Total" Split Information - // ============================== - 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; - - // 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_sked->push(new - ScheduleEntry(stage_num, - stage_pri, - cpu->resPool->getResIdx(DCache), - isplit_cmd, - 1)); - - int csplit_cmd = CacheUnit::CompleteSecondSplitWrite; - 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 " - "Access (1 of 2) for (%#x, %#x).\n", - inst->readTid(), inst->seqNum, addr, secondAddr); - } - - - - // Split Information for First Access - // ============================== - size = secondAddr - addr; - cache_req->splitAccess = true; - - // Split Information for Second Access - // ============================== - inst->split2ndSize = addr + fullSize - secondAddr; - inst->split2ndAddr = secondAddr; - inst->split2ndFlags = flags; - inst->splitInstSked = true; - } - - doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Write); - - if (inst->fault == NoFault) { - if (!cache_req->splitAccess) { - cache_req->reqData = new uint8_t[size]; - memcpy(cache_req->reqData, data, size); - - //inst->split2ndStoreDataPtr = cache_req->reqData; - //inst->split2ndStoreDataPtr += size; - - doCacheAccess(inst, write_res); - } else { - doCacheAccess(inst, write_res, cache_req); - } - - } - - return inst->fault; -} - - -void -CacheUnit::execute(int slot_num) -{ - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqs[slot_num]); - assert(cache_req); - - 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->done(false); - return; - } - - DynInstPtr inst = cache_req->inst; - if (inst->fault != NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->getMemAddr()); - finishCacheUnitReq(inst, cache_req); - return; - } - - if (inst->isSquashed()) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected squashed instruction " - "next stage.\n", inst->readTid(), inst->seqNum); - finishCacheUnitReq(inst, cache_req); - return; - } - -#if TRACING_ON - ThreadID tid = inst->readTid(); - std::string acc_type = "write"; -#endif - - switch (cache_req->cmd) - { - - case InitiateReadData: -#if TRACING_ON - 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(), - cache_req->inst->getMemAddr()); - - inst->setCurResSlot(slot_num); - - if (inst->isDataPrefetch() || inst->isInstPrefetch()) { - inst->execute(); - } else { - inst->initiateAcc(); - } - - break; - - case InitSecondSplitRead: - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i] Initiating split data read access to %s " - "for addr. %08p\n", tid, inst->seqNum, name(), - cache_req->inst->split2ndAddr); - inst->split2ndAccess = true; - assert(inst->split2ndAddr != 0); - read(inst, inst->split2ndAddr, &inst->split2ndData, - inst->totalSize, inst->split2ndFlags); - break; - - case InitSecondSplitWrite: - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i] Initiating split data write access to %s " - "for addr. %08p\n", tid, inst->seqNum, name(), - cache_req->inst->getMemAddr()); - - inst->split2ndAccess = true; - assert(inst->split2ndAddr != 0); - write(inst, &inst->split2ndData, inst->totalSize, - inst->split2ndAddr, inst->split2ndFlags, NULL); - break; - - case CompleteReadData: - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n", - tid, inst->seqNum); - - - //@todo: timing translations need to check here... - assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); - if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) { - finishCacheUnitReq(inst, cache_req); - } else { - DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", - tid, cache_req->inst->getMemAddr()); - cache_req->setCompleted(false); - cache_req->setMemStall(true); - } - break; - - case CompleteWriteData: - { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n", - tid, inst->seqNum); - - - //@todo: check that timing translation is finished here - RequestPtr mem_req = cache_req->memReq; - if (mem_req->isCondSwap() || mem_req->isLLSC() || mem_req->isSwap()) { - DPRINTF(InOrderCachePort, "Detected Conditional Store Inst.\n"); - - if (!cache_req->isMemAccComplete()) { - DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", - tid, cache_req->inst->getMemAddr()); - cache_req->setCompleted(false); - cache_req->setMemStall(true); - return; - } else { - DPRINTF(InOrderStall, "Mem Acc Completed\n"); - } - } - - if (cache_req->isMemAccPending()) { - DPRINTF(InOrderCachePort, "Store Instruction Pending Completion.\n"); - cache_req->dataPkt->reqData = cache_req->reqData; - cache_req->dataPkt->memReq = cache_req->memReq; - } else - DPRINTF(InOrderCachePort, "Store Instruction Finished Completion.\n"); - - //@todo: if split inst save data - finishCacheUnitReq(inst, cache_req); - } - break; - - case CompleteSecondSplitRead: - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read " - "Access\n", tid, inst->seqNum); - - //@todo: check that timing translation is finished here - assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); - if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) { - finishCacheUnitReq(inst, cache_req); - } else { - DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", - tid, cache_req->inst->split2ndAddr); - cache_req->setCompleted(false); - cache_req->setMemStall(true); - } - break; - - case CompleteSecondSplitWrite: - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Trying to Complete Split Data Write " - "Access\n", tid, inst->seqNum); - //@todo: illegal to have a unaligned cond.swap or llsc? - assert(!cache_req->memReq->isSwap() && !cache_req->memReq->isCondSwap() - && !cache_req->memReq->isLLSC()); - - if (cache_req->isMemAccPending()) { - cache_req->dataPkt->reqData = cache_req->reqData; - cache_req->dataPkt->memReq = cache_req->memReq; - } - - //@todo: check that timing translation is finished here - finishCacheUnitReq(inst, cache_req); - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -CacheUnit::finishCacheUnitReq(DynInstPtr inst, CacheRequest *cache_req) -{ - //@note: add back in for speculative load/store capability - //removeAddrDependency(inst); - cache_req->setMemStall(false); - cache_req->done(); -} - -void -CacheUnit::buildDataPacket(CacheRequest *cache_req) -{ - MemCmd cmd; - - if (cache_req->pktCmd == MemCmd::ReadReq) { - cmd = Packet::makeReadCmd(cache_req->memReq); - } else { - assert(cache_req->pktCmd == MemCmd::WriteReq); - cmd = Packet::makeWriteCmd(cache_req->memReq); - } - - cache_req->dataPkt = new CacheReqPacket(cache_req, cmd, - cache_req->instIdx); - - DPRINTF(InOrderCachePort, "[slot:%i]: Slot marked for %x\n", - cache_req->getSlot(), - cache_req->dataPkt->getAddr()); - - cache_req->dataPkt->hasSlot = true; - cache_req->dataPkt->dataStatic(cache_req->reqData); -} - -void -CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res, - CacheReqPtr split_req) -{ - Fault fault = NoFault; -#if TRACING_ON - ThreadID tid = inst->readTid(); -#endif - bool do_access = true; // flag to suppress cache access - - // Special Handling if this is a split request - CacheReqPtr cache_req; - if (split_req == NULL) - cache_req = dynamic_cast<CacheReqPtr>(reqs[inst->getCurResSlot()]); - else { - cache_req = split_req; - assert(0); - } - - // Make a new packet inside the CacheRequest object - assert(cache_req); - buildDataPacket(cache_req); - - // Special Handling for LL/SC or Compare/Swap - bool is_write = cache_req->dataPkt->isWrite(); - RequestPtr mem_req = cache_req->dataPkt->req; - if (is_write) { - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Storing data: %s\n", - tid, inst->seqNum, - printMemData(cache_req->dataPkt->getConstPtr<uint8_t>(), - cache_req->dataPkt->getSize())); - - if (mem_req->isCondSwap()) { - assert(write_res); - cache_req->memReq->setExtraData(*write_res); - } - if (mem_req->isLLSC()) { - assert(cache_req->inst->isStoreConditional()); - DPRINTF(InOrderCachePort, "Evaluating Store Conditional access\n"); - do_access = TheISA::handleLockedWrite(inst.get(), mem_req, cacheBlkSize); - } - } - - // Finally, go ahead and make the access if we can... - DPRINTF(InOrderCachePort, - "[tid:%i] [sn:%i] attempting to access cache for addr %08p\n", - tid, inst->seqNum, cache_req->dataPkt->getAddr()); - - if (do_access) { - if (!cachePort->sendTimingReq(cache_req->dataPkt)) { - DPRINTF(InOrderCachePort, - "[tid:%i] [sn:%i] cannot access cache, because port " - "is blocked. now waiting to retry request\n", tid, - inst->seqNum); - delete cache_req->dataPkt; - cache_req->dataPkt = NULL; - - delete cache_req->memReq; - cache_req->memReq = NULL; - - cache_req->done(false); - cachePortBlocked = true; - } else { - DPRINTF(InOrderCachePort, - "[tid:%i] [sn:%i] is now waiting for cache response\n", - tid, inst->seqNum); - cache_req->setCompleted(); - cache_req->setMemAccPending(); - cachePortBlocked = false; - } - } else if (mem_req->isLLSC()){ - // Store-Conditional instructions complete even if they "failed" - assert(cache_req->inst->isStoreConditional()); - cache_req->setCompleted(true); - - DPRINTF(LLSC, - "[tid:%i]: T%i Ignoring Failed Store Conditional Access\n", - tid, tid); - - processCacheCompletion(cache_req->dataPkt); - } else { - delete cache_req->dataPkt; - cache_req->dataPkt = NULL; - - delete cache_req->memReq; - cache_req->memReq = NULL; - - // Make cache request again since access due to - // inability to access - DPRINTF(InOrderStall, "STALL: \n"); - cache_req->done(false); - } - -} - -bool -CacheUnit::processSquash(CacheReqPacket *cache_pkt) -{ - // The resource may no longer be actively servicing this - // packet. Scenarios like a store that has been sent to the - // memory system or access that's been squashed. If that's - // the case, we can't access the request slot because it - // will be either invalid or servicing another request. - if (!cache_pkt->hasSlot) { - DPRINTF(InOrderCachePort, - "%x does not have a slot in unit, ignoring.\n", - cache_pkt->getAddr()); - - if (cache_pkt->reqData) { - delete [] cache_pkt->reqData; - cache_pkt->reqData = NULL; - } - - if (cache_pkt->memReq) { - delete cache_pkt->memReq; - cache_pkt->memReq = NULL; - } - - delete cache_pkt; - cache_pkt = NULL; - cpu->wakeCPU(); - return true; - } else { - DPRINTF(InOrderCachePort, "%x has slot %i\n", - cache_pkt->getAddr(), cache_pkt->cacheReq->getSlot()); - } - - - // It's possible that the request is squashed but the - // packet is still acknowledged by the resource. Squashes - // should happen at the end of the cycles and trigger the - // code above, but if not, this would handle any timing - // variations due to diff. user parameters. - if (cache_pkt->cacheReq->isSquashed()) { - DPRINTF(InOrderCachePort, - "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n", - cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum); - - cache_pkt->cacheReq->setMemAccPending(false); - cache_pkt->cacheReq->freeSlot(); - delete cache_pkt; - cache_pkt = NULL; - cpu->wakeCPU(); - return true; - } - - - return false; -} - -void -CacheUnit::processCacheCompletion(PacketPtr pkt) -{ - //@todo: use packet sender state instead of deriving from packet class to - // get special state - CacheReqPacket* cache_pkt = dynamic_cast<CacheReqPacket*>(pkt); - assert(cache_pkt); - - DPRINTF(InOrderCachePort, "Finished request for %x\n", pkt->getAddr()); - - if (processSquash(cache_pkt)) - return; - - CacheRequest *cache_req = dynamic_cast<CacheReqPtr>( - findRequest(cache_pkt->cacheReq->getInst(), cache_pkt->instIdx)); - - if (!cache_req) { - panic("[tid:%u]: [sn:%i]: Can't find slot for cache access to " - "addr. %08p\n", cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum, - cache_pkt->cacheReq->getInst()->getMemAddr()); - } - - assert(cache_req); - assert(cache_req == cache_pkt->cacheReq); - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: [slot:%i] Waking from cache access (vaddr.%08p, paddr:%08p)\n", - cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum, - cache_req->getSlot(), - cache_pkt->req->getVaddr(), - cache_pkt->req->getPaddr()); - - // Get resource request info - unsigned stage_num = cache_req->getStageNum(); - DynInstPtr inst = cache_req->inst; - ThreadID tid = cache_req->inst->readTid(); - - assert(!cache_req->isSquashed()); - assert(inst->staticInst && inst->isMemRef()); - - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Processing cache access\n", - tid, inst->seqNum); - - PacketPtr split_pkt = NULL; - if (inst->splitInst) { - inst->splitFinishCnt++; - - if (inst->splitFinishCnt == 2) { - cache_req->memReq->setVirt(0/*inst->tid*/, - inst->getMemAddr(), - inst->totalSize, - 0, - cpu->dataMasterId(), - 0); - - split_pkt = new Packet(cache_req->memReq, cache_req->pktCmd); - split_pkt->dataStatic(inst->splitMemData); - - DPRINTF(InOrderCachePort, "Completing Split Access.\n"); - inst->completeAcc(split_pkt); - } - } else { - inst->completeAcc(cache_pkt); - } - - inst->setExecuted(); - - if (inst->isLoad()) { - assert(cache_pkt->isRead()); - - if (cache_pkt->req->isLLSC()) { - DPRINTF(InOrderCachePort, - "[tid:%u]: Handling Load-Linked for [sn:%u]\n", - tid, inst->seqNum); - TheISA::handleLockedRead(inst.get(), cache_pkt->req); - } - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Bytes loaded were: %s\n", - tid, inst->seqNum, - (split_pkt) ? printMemData(split_pkt->getConstPtr<uint8_t>(), - split_pkt->getSize()) : - printMemData(cache_pkt->getConstPtr<uint8_t>(), - cache_pkt->getSize())); - } else if(inst->isStore()) { - assert(cache_pkt->isWrite()); - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Bytes stored were: %s\n", - tid, inst->seqNum, - (split_pkt) ? printMemData(split_pkt->getConstPtr<uint8_t>(), - split_pkt->getSize()) : - printMemData(cache_pkt->getConstPtr<uint8_t>(), - cache_pkt->getSize())); - } - - - if (split_pkt) { - delete split_pkt; - split_pkt = NULL; - } - - cache_req->setMemAccPending(false); - cache_req->setMemAccCompleted(); - - if (cache_req->isMemStall() && - cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) { - DPRINTF(InOrderCachePort, "[tid:%u] Waking up from Cache Miss.\n", - tid); - - cpu->activateContext(tid); - - DPRINTF(ThreadModel, "Activating [tid:%i] after return from cache" - "miss.\n", tid); - } - - // Wake up the CPU (if it went to sleep and was waiting on this - // completion event). - cpu->wakeCPU(); - - DPRINTF(Activity, "[tid:%u] Activating %s due to cache completion\n", - tid, cpu->pipelineStage[stage_num]->name()); - - cpu->switchToActive(stage_num); -} - -void -CacheUnit::recvRetry() -{ - DPRINTF(InOrderCachePort, "Unblocking Cache Port. \n"); - - assert(cachePortBlocked); - - // Clear the cache port for use again - cachePortBlocked = false; - - cpu->wakeCPU(); -} - -CacheUnitEvent::CacheUnitEvent() - : ResourceEvent() -{ } - -void -CacheUnitEvent::process() -{ - DynInstPtr inst = resource->reqs[slotIdx]->inst; - int stage_num = resource->reqs[slotIdx]->getStageNum(); - ThreadID tid = inst->threadNumber; - CacheReqPtr req_ptr = dynamic_cast<CacheReqPtr>(resource->reqs[slotIdx]); - - DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n", - inst->seqNum); - - CacheUnit* tlb_res = dynamic_cast<CacheUnit*>(resource); - assert(tlb_res); - - //@todo: eventually, we should do a timing translation w/ - // hw page table walk on tlb miss - DPRINTF(InOrderTLB, "Handling Fault %s : [sn:%i] %x\n", inst->fault->name(), inst->seqNum, inst->getMemAddr()); - inst->fault->invoke(tlb_res->cpu->tcBase(tid), inst->staticInst); - - tlb_res->tlbBlocked[tid] = false; - - tlb_res->cpu->pipelineStage[stage_num]-> - unsetResStall(tlb_res->reqs[slotIdx], tid); - - req_ptr->tlbStall = false; - - //@todo: timing translation needs to have some type of independent - // info regarding if it's squashed or not so we can - // free up the resource if a request gets squashed in the middle - // of a table walk - if (req_ptr->isSquashed()) { - req_ptr->freeSlot(); - } - - tlb_res->cpu->wakeCPU(); -} - -void -CacheUnit::squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid) -{ - // If squashing due to memory stall, then we do NOT want to - // squash the instruction that caused the stall so we - // increment the sequence number here to prevent that. - // - // NOTE: This is only for the SwitchOnCacheMiss Model - // NOTE: If you have multiple outstanding misses from the same - // thread then you need to reevaluate this code - // NOTE: squash should originate from - // pipeline_stage.cc:processInstSchedule - DPRINTF(InOrderCachePort, "Squashing above [sn:%u]\n", - squash_seq_num + 1); - - squash(inst, stage_num, squash_seq_num + 1, tid); -} - -void -CacheUnit::squashCacheRequest(CacheReqPtr req_ptr) -{ - DynInstPtr inst = req_ptr->getInst(); - req_ptr->setSquashed(); - inst->setSquashed(); - - //@note: add back in for speculative load/store capability - /*if (inst->validMemAddr()) { - DPRINTF(AddrDep, "Squash of [tid:%i] [sn:%i], attempting to " - "remove addr. %08p dependencies.\n", - inst->readTid(), - inst->seqNum, - inst->getMemAddr()); - - removeAddrDependency(inst); - }*/ -} - - -void -CacheUnit::squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid) -{ - if (tlbBlocked[tid] && - tlbBlockSeqNum[tid] > squash_seq_num) { - DPRINTF(InOrderCachePort, "Releasing TLB Block due to " - " squash after [sn:%i].\n", squash_seq_num); - tlbBlocked[tid] = false; - } - - for (int i = 0; i < width; i++) { - ResReqPtr req_ptr = reqs[i]; - - if (req_ptr->valid && - req_ptr->getInst()->readTid() == tid && - req_ptr->getInst()->seqNum > squash_seq_num) { - - DPRINTF(InOrderCachePort, - "[tid:%i] Squashing request from [sn:%i]\n", - req_ptr->getInst()->readTid(), req_ptr->getInst()->seqNum); - - if (req_ptr->isSquashed()) { - DPRINTF(AddrDep, "Request for [tid:%i] [sn:%i] already " - "squashed, ignoring squash process.\n", - req_ptr->getInst()->readTid(), - req_ptr->getInst()->seqNum); - continue; - } - - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(req_ptr); - assert(cache_req); - - squashCacheRequest(cache_req); - - int req_slot_num = req_ptr->getSlot(); - - if (cache_req->tlbStall) { - tlbBlocked[tid] = false; - - int stall_stage = reqs[req_slot_num]->getStageNum(); - - cpu->pipelineStage[stall_stage]-> - unsetResStall(reqs[req_slot_num], tid); - } - - if (cache_req->isMemAccPending()) { - cache_req->dataPkt->reqData = cache_req->reqData; - cache_req->dataPkt->memReq = cache_req->memReq; - } - - if (!cache_req->tlbStall) - freeSlot(req_slot_num); - } - } - -} - -void -CacheRequest::clearRequest() -{ - if (!memAccPending) { - if (reqData && !splitAccess) - delete [] reqData; - - if (memReq) - delete memReq; - - if (dataPkt) - delete dataPkt; - } else { - if (dataPkt) - dataPkt->hasSlot = false; - } - - memReq = NULL; - reqData = NULL; - dataPkt = NULL; - memAccComplete = false; - memAccPending = false; - tlbStall = false; - splitAccess = false; - splitAccessNum = -1; - split2ndAccess = false; - instIdx = 0; - fetchBufferFill = false; - - ResourceRequest::clearRequest(); -} diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh deleted file mode 100644 index 11eb9ddad..000000000 --- a/src/cpu/inorder/resources/cache_unit.hh +++ /dev/null @@ -1,269 +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_CACHE_UNIT_HH__ -#define __CPU_INORDER_CACHE_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "arch/tlb.hh" -#include "base/hashmap.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" -#include "mem/packet.hh" -#include "mem/packet_access.hh" -#include "mem/port.hh" -#include "params/InOrderCPU.hh" -#include "sim/sim_object.hh" - -class CacheReqPacket; -typedef CacheReqPacket* CacheReqPktPtr; - -class CacheUnit : public Resource -{ - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - CacheUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - enum Command { - InitiateReadData, - CompleteReadData, - InitiateWriteData, - CompleteWriteData, - InitSecondSplitRead, - InitSecondSplitWrite, - CompleteSecondSplitRead, - CompleteSecondSplitWrite - }; - - public: - - void init(); - - ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd); - - ResReqPtr findRequest(DynInstPtr inst); - ResReqPtr findRequest(DynInstPtr inst, int idx); - - void requestAgain(DynInstPtr inst, bool &try_request); - - virtual int getSlot(DynInstPtr inst); - - /** Executes one of the commands from the "Command" enum */ - virtual void execute(int slot_num); - - virtual void squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - - void squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - - virtual void squashCacheRequest(CacheReqPtr req_ptr); - - /** After memory request is completedd in the cache, then do final - processing to complete the request in the CPU. - */ - virtual void processCacheCompletion(PacketPtr pkt); - - /** Create request that will interface w/TLB and Memory objects */ - virtual void setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req, - int acc_size, int flags); - - void finishCacheUnitReq(DynInstPtr inst, CacheRequest *cache_req); - - void buildDataPacket(CacheRequest *cache_req); - - bool processSquash(CacheReqPacket *cache_pkt); - - void trap(const Fault &fault, ThreadID tid, DynInstPtr inst); - - void recvRetry(); - - Fault read(DynInstPtr inst, Addr addr, - uint8_t *data, unsigned size, unsigned flags); - - Fault write(DynInstPtr inst, uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res); - - void doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, - int flags, TheISA::TLB::Mode tlb_mode); - - /** Read/Write on behalf of an instruction. - * curResSlot needs to be a valid value in instruction. - */ - void doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL, - CacheReqPtr split_req=NULL); - - uint64_t getMemData(Packet *packet); - - void setAddrDependency(DynInstPtr inst); - virtual void removeAddrDependency(DynInstPtr inst); - - protected: - /** Cache interface. */ - MasterPort *cachePort; - - bool cachePortBlocked; - - std::list<Addr> addrList[ThePipeline::MaxThreads]; - - m5::hash_map<Addr, InstSeqNum> addrMap[ThePipeline::MaxThreads]; - - public: - int cacheBlkSize; - - int cacheBlkMask; - - /** Align a PC to the start of the Cache block. */ - Addr cacheBlockAlign(Addr addr) - { - return (addr & ~(cacheBlkMask)); - } - - bool tlbBlocked[ThePipeline::MaxThreads]; - InstSeqNum tlbBlockSeqNum[ThePipeline::MaxThreads]; - - TheISA::TLB* tlb(); - TheISA::TLB *_tlb; -}; - -class CacheUnitEvent : public ResourceEvent { - public: - const std::string name() const - { - return "CacheUnitEvent"; - } - - - /** Constructs a resource event. */ - CacheUnitEvent(); - virtual ~CacheUnitEvent() {} - - /** Processes a resource event. */ - void process(); -}; - -//@todo: Move into CacheUnit Class for private access to "valid" field -class CacheRequest : public ResourceRequest -{ - public: - CacheRequest(CacheUnit *cres) - : ResourceRequest(cres), memReq(NULL), reqData(NULL), - dataPkt(NULL), memAccComplete(false), - memAccPending(false), tlbStall(false), splitAccess(false), - splitAccessNum(-1), split2ndAccess(false), - fetchBufferFill(false) - { } - - virtual ~CacheRequest() - { - if (reqData && !splitAccess) - delete [] reqData; - } - - 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(); - - virtual PacketDataPtr getData() - { return reqData; } - - void - setMemAccCompleted(bool completed = true) - { - memAccComplete = completed; - } - - bool is2ndSplit() - { - return split2ndAccess; - } - - bool isMemAccComplete() { return memAccComplete; } - - void setMemAccPending(bool pending = true) { memAccPending = pending; } - bool isMemAccPending() { return memAccPending; } - - //Make this data private/protected! - MemCmd pktCmd; - RequestPtr memReq; - PacketDataPtr reqData; - CacheReqPacket *dataPkt; - - bool memAccComplete; - bool memAccPending; - bool tlbStall; - - bool splitAccess; - int splitAccessNum; - bool split2ndAccess; - int instIdx; - - /** Should we expect block from cache access or fetch buffer? */ - bool fetchBufferFill; -}; - -class CacheReqPacket : public Packet -{ - public: - CacheReqPacket(CacheRequest *_req, - MemCmd _cmd, int _idx = 0) - : Packet(&(*_req->memReq), _cmd), cacheReq(_req), - instIdx(_idx), hasSlot(false), reqData(NULL), memReq(NULL) - { - - } - - CacheRequest *cacheReq; - int instIdx; - bool hasSlot; - PacketDataPtr reqData; - RequestPtr memReq; -}; - -#endif //__CPU_CACHE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc deleted file mode 100644 index 7b7eccd0a..000000000 --- a/src/cpu/inorder/resources/decode_unit.cc +++ /dev/null @@ -1,97 +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 "config/the_isa.hh" -#include "cpu/inorder/resources/decode_unit.hh" -#include "debug/InOrderDecode.hh" -#include "debug/InOrderStall.hh" -#include "debug/Resource.hh" - -using namespace TheISA; -using namespace ThePipeline; -using namespace std; - -DecodeUnit::DecodeUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ - for (ThreadID tid = 0; tid < MaxThreads; tid++) { - regDepMap[tid] = &cpu->archRegDepMap[tid]; - } -} - -void -DecodeUnit::execute(int slot_num) -{ - ResourceRequest* decode_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - - switch (decode_req->cmd) - { - case DecodeInst: - { - - if (inst->fault != NoFault) { - inst->setBackSked(cpu->faultSked); - DPRINTF(InOrderDecode,"[tid:%i]: Fault found for instruction [sn:%i]\n", - inst->readTid(), inst->seqNum); - } else { - assert(!inst->staticInst->isMacroop()); - inst->setBackSked(cpu->createBackEndSked(inst)); - DPRINTF(InOrderDecode,"Decoded instruction [sn:%i]: %s : 0x%x\n", - inst->seqNum, inst->instName(), - inst->staticInst->machInst); - } - - if (inst->backSked != NULL) { - DPRINTF(InOrderDecode, - "[tid:%i]: Back End Schedule created for %s [sn:%i].\n", - inst->readTid(), inst->instName(), inst->seqNum); - decode_req->done(); - } else { - DPRINTF(Resource, - "[tid:%i] Static Inst not available to decode.\n", - inst->readTid()); - DPRINTF(Resource, - "Unable to create schedule for instruction [sn:%i] \n", - inst->seqNum); - DPRINTF(InOrderStall, "STALL: \n"); - decode_req->done(false); - } - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - diff --git a/src/cpu/inorder/resources/decode_unit.hh b/src/cpu/inorder/resources/decode_unit.hh deleted file mode 100644 index 65f82a94b..000000000 --- a/src/cpu/inorder/resources/decode_unit.hh +++ /dev/null @@ -1,66 +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_DECODE_UNIT_HH__ -#define __CPU_INORDER_DECODE_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/reg_dep_map.hh" -#include "cpu/inorder/resource.hh" - -class DecodeUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - DecodeUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - enum Command { - DecodeInst - }; - - void execute(int slot_num); - - RegDepMap *regDepMap[ThePipeline::MaxThreads]; - - protected: - /** @todo: Add Resource Stats Here */ -}; - -#endif //__CPU_INORDER_DECODE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc deleted file mode 100644 index 296d5126f..000000000 --- a/src/cpu/inorder/resources/execution_unit.cc +++ /dev/null @@ -1,249 +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 "cpu/inorder/resources/execution_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/Fault.hh" -#include "debug/InOrderExecute.hh" -#include "debug/InOrderStall.hh" -#include "sim/full_system.hh" - -using namespace std; -using namespace ThePipeline; - -ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - lastExecuteTick(0), lastControlTick(0) -{ } - -void -ExecutionUnit::regStats() -{ - predictedTakenIncorrect - .name(name() + ".predictedTakenIncorrect") - .desc("Number of Branches Incorrectly Predicted As Taken."); - - predictedNotTakenIncorrect - .name(name() + ".predictedNotTakenIncorrect") - .desc("Number of Branches Incorrectly Predicted As Not Taken)."); - - executions - .name(name() + ".executions") - .desc("Number of Instructions Executed."); - - - predictedIncorrect - .name(name() + ".mispredicted") - .desc("Number of Branches Incorrectly Predicted"); - - predictedCorrect - .name(name() + ".predicted") - .desc("Number of Branches Incorrectly Predicted"); - - mispredictPct - .name(name() + ".mispredictPct") - .desc("Percentage of Incorrect Branches Predicts") - .precision(6); - mispredictPct = (predictedIncorrect / - (predictedCorrect + predictedIncorrect)) * 100; - - Resource::regStats(); -} - -void -ExecutionUnit::execute(int slot_num) -{ - ResourceRequest* exec_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - if (inst->fault != NoFault) { - DPRINTF(InOrderExecute, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->pcState()); - exec_req->done(); - return; - } - - Fault fault = NoFault; - Tick cur_tick = curTick(); - unsigned stage_num = exec_req->getStageNum(); - ThreadID tid = inst->readTid(); -#if TRACING_ON - InstSeqNum seq_num = inst->seqNum; -#endif - - switch (exec_req->cmd) - { - case ExecuteInst: - { - 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; - } - - //@todo: handle address generation here - assert(!inst->isMemRef()); - - 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); - return; - } - lastControlTick = curTick(); - - // Evaluate Branch - fault = inst->execute(); - - // Should unconditional control , pc relative count as an - // execution??? Probably not. - executions++; - - if (fault == NoFault) { - inst->setExecuted(); - - if (inst->mispredicted()) { - assert(inst->isControl()); - - // Set up Squash Generated By this Misprediction - TheISA::PCState pc = inst->pcState(); - TheISA::advancePC(pc, inst->staticInst); - inst->setPredTarg(pc); - inst->setSquashInfo(stage_num); - setupSquash(inst, stage_num, tid); - - DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i] Squashing from " - "stage %i. Redirecting fetch to %s.\n", tid, - inst->seqNum, stage_num, pc); - DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch" - " misprediction at %s\n", tid, inst->pcState()); - - if (inst->predTaken()) { - predictedTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." - "PC %s ... Mispredicts! " - "(Prediction: Taken)\n", - tid, inst->seqNum, - inst->staticInst->disassemble( - inst->instAddr()), - inst->pcState()); - } else { - predictedNotTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." - "PC %s ... Mispredicts! " - "(Prediction: Not Taken)\n", - tid, inst->seqNum, - inst->staticInst->disassemble( - inst->instAddr()), - inst->pcState()); - } - predictedIncorrect++; - } else { - DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Prediction" - "Correct.\n", inst->readTid(), seq_num); - predictedCorrect++; - } - - exec_req->done(); - } else { - DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n", - inst->readTid(), inst->seqNum, fault->name()); - inst->fault = fault; - exec_req->done(); - } - } else { - // Regular ALU instruction - fault = inst->execute(); - executions++; - - if (fault == NoFault) { - inst->setExecuted(); - -#if TRACING_ON - for (int didx = 0; didx < inst->numDestRegs(); didx++) - if (inst->resultType(didx) == InOrderDynInst::Float || - inst->resultType(didx) == InOrderDynInst::FloatBits || - inst->resultType(didx) == InOrderDynInst::Double) - DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i " - "of FP execution is %08f (%x).\n", inst->readTid(), - seq_num, didx, inst->readFloatResult(didx), - inst->readFloatBitsResult(didx)); - else - DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i " - "of Int execution is 0x%x.\n", inst->readTid(), - seq_num, didx, inst->readIntResult(didx)); -#endif - - if (!FullSystem) { - // The Syscall might change the PC, so conservatively - // squash everything behing it - if (inst->isSyscall()) { - inst->setSquashInfo(stage_num); - setupSquash(inst, stage_num, tid); - } - } - } else { - DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s " - "fault.\n", inst->readTid(), seq_num, fault->name()); - DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n", - inst->readTid(), inst->seqNum, fault->name()); - inst->fault = fault; - } - - exec_req->done(); - } - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - - diff --git a/src/cpu/inorder/resources/execution_unit.hh b/src/cpu/inorder/resources/execution_unit.hh deleted file mode 100644 index e87a05c27..000000000 --- a/src/cpu/inorder/resources/execution_unit.hh +++ /dev/null @@ -1,83 +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_EXECUTION_UNIT_HH__ -#define __CPU_INORDER_EXECUTION_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/func_unit.hh" - -class ExecutionUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - enum Command { - ExecuteInst - }; - - public: - ExecutionUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - public: - void regStats(); - - /** Execute the function of this resource. The Default is action - * is to do nothing. More specific models will derive from this - * class and define their own execute function. - */ - void execute(int slot_num); - - protected: - ///////////////////////////////////////////////////////////////// - // - // RESOURCE STATISTICS - // - ///////////////////////////////////////////////////////////////// - Stats::Scalar predictedTakenIncorrect; - Stats::Scalar predictedNotTakenIncorrect; - Stats::Scalar predictedIncorrect; - Stats::Scalar predictedCorrect; - Stats::Formula mispredictPct; - Stats::Scalar executions; - Tick lastExecuteTick; - Tick lastControlTick; -}; - - -#endif //__CPU_INORDER_EXCUTION_UNIT_HH__ diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc deleted file mode 100644 index ead4953fb..000000000 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ /dev/null @@ -1,335 +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 "config/the_isa.hh" -#include "cpu/inorder/resources/fetch_seq_unit.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/InOrderFetchSeq.hh" -#include "debug/InOrderStall.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - instSize(sizeof(MachInst)) -{ - for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - pcValid[tid] = false; - pcBlockStage[tid] = 0; - - //@todo: Use CPU's squashSeqNum here instead of maintaining our own - // state - squashSeqNum[tid] = (InstSeqNum)-1; - lastSquashCycle[tid] = 0; - } -} - -FetchSeqUnit::~FetchSeqUnit() -{ - delete [] resourceEvent; -} - -void -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 = reqs[slot_num]; - DynInstPtr inst = fs_req->inst; - ThreadID tid = inst->readTid(); - int stage_num = fs_req->getStageNum(); - - if (inst->fault != NoFault) { - DPRINTF(InOrderFetchSeq, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - inst->pcState()); - fs_req->done(); - return; - } - - switch (fs_req->cmd) - { - case AssignNextPC: - { - DPRINTF(InOrderFetchSeq, "[tid:%i]: Current PC is %s\n", tid, - pc[tid]); - - if (pcValid[tid]) { - inst->pcState(pc[tid]); - inst->setMemAddr(pc[tid].instAddr()); - - // Advance to next PC (typically PC + 4) - pc[tid].advance(); - - inst->setSeqNum(cpu->getAndIncrementInstSeq(tid)); - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to " - "PC %s\n", tid, inst->seqNum, inst->pcState()); - - fs_req->done(); - } else { - DPRINTF(InOrderStall, "STALL: [tid:%i]: NPC not valid\n", tid); - fs_req->done(false); - } - } - break; - - case UpdateTargetPC: - { - assert(!inst->isCondDelaySlot() && - "Not Handling Conditional Delay Slot"); - - if (inst->isControl()) { - if (inst->isReturn() && !inst->predTaken()) { - // If it's a return, then we must wait for resolved address. - // The Predictor will mark a return a false as "not taken" - // if there is no RAS entry - DPRINTF(InOrderFetchSeq, "[tid:%d]: Setting block signal " - "for stage %i.\n", - tid, stage_num); - cpu->pipelineStage[stage_num]-> - toPrevStages->stageBlock[stage_num][tid] = true; - pcValid[tid] = false; - pcBlockStage[tid] = stage_num; - } else if (inst->predTaken()) { - // Taken Control - inst->setSquashInfo(stage_num); - setupSquash(inst, stage_num, tid); - - DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " - "start from stage %i, after [sn:%i].\n", - tid, stage_num, inst->squashSeqNum); - } - } else { - DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Ignoring branch " - "target update since then is not a control " - "instruction.\n", tid, inst->seqNum); - } - - fs_req->done(); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, - InstSeqNum squash_seq_num, ThreadID tid) -{ - DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating due to squash from %s (%s) " - "stage %i.\n", tid, inst->instName(), inst->pcState(), - squash_stage); - - if (lastSquashCycle[tid] == curTick() && - squashSeqNum[tid] <= squash_seq_num) { - DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, " - "since there is an outstanding squash that is older.\n", - tid, squash_stage); - } else { - squashSeqNum[tid] = squash_seq_num; - lastSquashCycle[tid] = curTick(); - - if (inst->staticInst) { - if (inst->fault != NoFault) { - // A Trap Caused This Fault and will update the pc state - // when done trapping - DPRINTF(InOrderFetchSeq, "[tid:%i] Blocking due to fault @ " - "[sn:%i].%s %s \n", tid, inst->seqNum, - inst->instName(), inst->pcState()); - pcValid[tid] = false; - } else { - TheISA::PCState nextPC; - assert(inst->staticInst); - if (inst->isControl()) { - nextPC = inst->readPredTarg(); - - // If we are already fetching this PC then advance to next PC - // ======= - // This should handle ISAs w/delay slots and annulled delay - // slots to figure out which is the next PC to fetch after - // a mispredict - DynInstPtr bdelay_inst = NULL; - ListIt bdelay_it; - if (inst->onInstList) { - bdelay_it = inst->getInstListIt(); - bdelay_it++; - } else { - InstSeqNum branch_delay_num = inst->seqNum + 1; - bdelay_it = cpu->findInst(branch_delay_num, tid); - } - - if (bdelay_it != cpu->instList[tid].end()) { - bdelay_inst = (*bdelay_it); - } - - if (bdelay_inst) { - if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) { - bdelay_inst->pc = nextPC; - advancePC(nextPC, inst->staticInst); - DPRINTF(InOrderFetchSeq, "Advanced PC to %s\n", nextPC); - } - } - } else { - nextPC = inst->pcState(); - advancePC(nextPC, inst->staticInst); - } - - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n", - tid, nextPC); - pc[tid] = nextPC; - - // Unblock Any Stages Waiting for this information to be updated ... - if (!pcValid[tid]) { - DPRINTF(InOrderFetchSeq, "[tid:%d]: Setting unblock signal " - "for stage %i.\n", - tid, pcBlockStage[tid]); - - // Need to use "fromNextStages" instead of "toPrevStages" - // because the timebuffer will have already have advanced - // in the tick function and this squash function will happen after - // the tick - cpu->pipelineStage[pcBlockStage[tid]]-> - fromNextStages->stageUnblock[pcBlockStage[tid]][tid] = true; - } - - pcValid[tid] = true; - } - } - } - - Resource::squash(inst, squash_stage, squash_seq_num, tid); -} - -FetchSeqUnit::FetchSeqEvent::FetchSeqEvent() - : ResourceEvent() -{ } - -void -FetchSeqUnit::FetchSeqEvent::process() -{ - FetchSeqUnit* fs_res = dynamic_cast<FetchSeqUnit*>(resource); - assert(fs_res); - - for (int i = 0; i < MaxThreads; i++) { - fs_res->pc[i] = fs_res->cpu->pcState(i); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC: %s.\n", - fs_res->pc[i]); - - fs_res->pcValid[i] = true; - } -} - - -void -FetchSeqUnit::activateThread(ThreadID tid) -{ - pcValid[tid] = true; - - pc[tid] = cpu->pcState(tid); - - cpu->fetchPriorityList.push_back(tid); - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC: %s.\n", - tid, pc[tid]); -} - -void -FetchSeqUnit::deactivateThread(ThreadID tid) -{ - pcValid[tid] = false; - pcBlockStage[tid] = 0; - - squashSeqNum[tid] = (InstSeqNum)-1; - lastSquashCycle[tid] = 0; - - list<ThreadID>::iterator thread_it = find(cpu->fetchPriorityList.begin(), - cpu->fetchPriorityList.end(), - tid); - - if (thread_it != cpu->fetchPriorityList.end()) - cpu->fetchPriorityList.erase(thread_it); -} - -void -FetchSeqUnit::suspendThread(ThreadID tid) -{ - deactivateThread(tid); -} - -void -FetchSeqUnit::trap(const Fault &fault, ThreadID tid, DynInstPtr inst) -{ - pcValid[tid] = true; - pc[tid] = cpu->pcState(tid); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: " - "%s.\n", tid, pc[tid]); -} - -void -FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) -{ - pcValid[tid] = true; - - if (cpu->thread[tid]->lastGradIsBranch) { - /** This function assumes that the instruction causing the context - * switch was right after the branch. Thus, if it's not, then - * we are updating incorrectly here - */ - assert(cpu->nextInstAddr(tid) == inst->instAddr()); - pc[tid] = cpu->thread[tid]->lastBranchPC; - } else { - pc[tid] = inst->pcState(); - } - assert(inst->staticInst); - advancePC(pc[tid], inst->staticInst); - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch." - "Assigning PC: %s.\n", tid, pc[tid]); -} diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh deleted file mode 100644 index a8db85b06..000000000 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ /dev/null @@ -1,105 +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_FETCH_SEQ_UNIT_HH__ -#define __CPU_INORDER_FETCH_SEQ_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "config/the_isa.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class FetchSeqUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - typedef std::list<DynInstPtr>::iterator ListIt; - - enum Command { - AssignNextPC, - UpdateTargetPC - }; - - public: - FetchSeqUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - ~FetchSeqUnit(); - - void init(); - void activateThread(ThreadID tid); - void deactivateThread(ThreadID tid); - void suspendThread(ThreadID tid); - void execute(int slot_num); - void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid); - - - /** Update to correct PC from a squash */ - void squash(DynInstPtr inst, int squash_stage, - InstSeqNum squash_seq_num, ThreadID tid); - - /** Update to correct PC from a trap */ - void trap(const Fault &fault, ThreadID tid, DynInstPtr inst); - - protected: - unsigned instSize; - - bool pcValid[ThePipeline::MaxThreads]; - int pcBlockStage[ThePipeline::MaxThreads]; - - TheISA::PCState pc[ThePipeline::MaxThreads]; - - /** Squash Seq. Nums*/ - InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; - - /** Squash Seq. Nums*/ - Tick lastSquashCycle[ThePipeline::MaxThreads]; - - /** @todo: Add Resource Stats Here */ - - public: - class FetchSeqEvent : public ResourceEvent { - public: - /** Constructs a resource event. */ - FetchSeqEvent(); - ~FetchSeqEvent() {} - - /** Processes a resource event. */ - void process(); - }; - -}; - -#endif diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc deleted file mode 100644 index 13864e589..000000000 --- a/src/cpu/inorder/resources/fetch_unit.cc +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 2011 The Regents of The University of Michigan - * 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 "arch/isa_traits.hh" -#include "arch/locked_mem.hh" -#include "arch/utility.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/cache_unit.hh" -#include "cpu/inorder/resources/fetch_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/Activity.hh" -#include "debug/InOrderCachePort.hh" -#include "debug/InOrderStall.hh" -#include "debug/RefCount.hh" -#include "debug/ThreadModel.hh" -#include "mem/request.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -FetchUnit::FetchUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : CacheUnit(res_name, res_id, res_width, res_latency, _cpu, params), - instSize(sizeof(TheISA::MachInst)), fetchBuffSize(params->fetchBuffSize) -{ - for (int tid = 0; tid < MaxThreads; tid++) - decoder[tid] = new Decoder; -} - -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) -{ - Addr block_addr = cacheBlockAlign(inst->getMemAddr()); - Addr fetch_addr = inst->getMemAddr(); - unsigned fetch_offset = (fetch_addr - block_addr) / instSize; - ThreadID tid = inst->readTid(); - TheISA::PCState instPC = inst->pcState(); - - - DPRINTF(InOrderCachePort, "Creating instruction [sn:%i] w/fetch data @" - "addr:%08p block:%08p\n", inst->seqNum, fetch_addr, block_addr); - - assert((*fetch_it)->valid); - - TheISA::MachInst *fetchInsts = - reinterpret_cast<TheISA::MachInst *>((*fetch_it)->block); - - MachInst mach_inst = - TheISA::gtoh(fetchInsts[fetch_offset]); - - decoder[tid]->moreBytes(instPC, inst->instAddr(), mach_inst); - assert(decoder[tid]->instReady()); - inst->setStaticInst(decoder[tid]->decode(instPC)); - inst->pcState(instPC); -} - -void -FetchUnit::removeAddrDependency(DynInstPtr inst) -{ - inst->unsetMemAddr(); -} - -ResReqPtr -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"); - } - - assert(sched_entry->cmd == InitiateFetch); - - DPRINTF(InOrderCachePort, - "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n", - inst->readTid(), inst->seqNum, inst->getMemAddr()); - - cache_req->setRequest(inst, stage_num, id, slot_num, - sched_entry->cmd, MemCmd::ReadReq, - inst->curSkedEntry->idx); - - return cache_req; -} - -void -FetchUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req, - int acc_size, int flags) -{ - ThreadID tid = inst->readTid(); - Addr aligned_addr = cacheBlockAlign(inst->getMemAddr()); - if (cache_req->memReq == NULL) { - cache_req->memReq = - new Request(tid, aligned_addr, acc_size, flags, - cpu->instMasterId(), inst->instAddr(), cpu->readCpuId(), - tid); - DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n", - inst->seqNum, &cache_req->memReq, cache_req->memReq); - } -} - -std::list<FetchUnit::FetchBlock*>::iterator -FetchUnit::findBlock(std::list<FetchBlock*> &fetch_blocks, int asid, - Addr block_addr) -{ - std::list<FetchBlock*>::iterator fetch_it = fetch_blocks.begin(); - std::list<FetchBlock*>::iterator end_it = fetch_blocks.end(); - - while (fetch_it != end_it) { - if ((*fetch_it)->asid == asid && - (*fetch_it)->addr == block_addr) { - return fetch_it; - } - - fetch_it++; - } - - return fetch_it; -} - -std::list<FetchUnit::FetchBlock*>::iterator -FetchUnit::findReplacementBlock() -{ - std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin(); - std::list<FetchBlock*>::iterator end_it = fetchBuffer.end(); - - while (fetch_it != end_it) { - if ((*fetch_it)->cnt == 0) { - return fetch_it; - } else { - DPRINTF(InOrderCachePort, "Block %08p has %i insts pending.\n", - (*fetch_it)->addr, (*fetch_it)->cnt); - } - fetch_it++; - } - - return fetch_it; -} - -void -FetchUnit::markBlockUsed(std::list<FetchBlock*>::iterator block_it) -{ - // Move block from whatever location it is in fetch buffer - // to the back (represents most-recently-used location) - if (block_it != fetchBuffer.end()) { - FetchBlock *mru_blk = *block_it; - fetchBuffer.erase(block_it); - fetchBuffer.push_back(mru_blk); - } -} - -int -FetchUnit::blocksInUse() -{ - std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin(); - std::list<FetchBlock*>::iterator end_it = fetchBuffer.end(); - - int cnt = 0; - while (fetch_it != end_it) { - if ((*fetch_it)->cnt > 0) - cnt++; - - fetch_it++; - } - - return cnt; -} - -void -FetchUnit::clearFetchBuffer() -{ - std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin(); - std::list<FetchBlock*>::iterator end_it = fetchBuffer.end(); - - while (fetch_it != end_it) { - if ((*fetch_it)->block) { - delete [] (*fetch_it)->block; - } - delete *fetch_it; - fetch_it++; - } - fetchBuffer.clear(); -} - -void -FetchUnit::execute(int slot_num) -{ - CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqs[slot_num]); - assert(cache_req); - - if (cachePortBlocked && cache_req->cmd == InitiateFetch) { - DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n"); - cache_req->done(false); - return; - } - - DynInstPtr inst = cache_req->inst; - ThreadID tid = inst->readTid(); - Addr block_addr = cacheBlockAlign(inst->getMemAddr()); - int asid = cpu->asid[tid]; - - if (inst->fault != NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - cacheBlockAlign(inst->getMemAddr())); - finishCacheUnitReq(inst, cache_req); - return; - } - - switch (cache_req->cmd) - { - case InitiateFetch: - { - // Check to see if we've already got this request buffered - // or pending to be buffered - bool do_fetch = true; - int total_pending = pendingFetch.size() + blocksInUse(); - - std::list<FetchBlock*>::iterator pending_it; - pending_it = findBlock(pendingFetch, asid, block_addr); - if (pending_it != pendingFetch.end()) { - (*pending_it)->cnt++; - do_fetch = false; - - DPRINTF(InOrderCachePort, "%08p is a pending fetch block " - "(pending:%i).\n", block_addr, - (*pending_it)->cnt); - } else if (total_pending < fetchBuffSize) { - std::list<FetchBlock*>::iterator buff_it; - buff_it = findBlock(fetchBuffer, asid, block_addr); - if (buff_it != fetchBuffer.end()) { - (*buff_it)->cnt++; - do_fetch = false; - - DPRINTF(InOrderCachePort, "%08p is in fetch buffer " - "(pending:%i).\n", block_addr, (*buff_it)->cnt); - } - } - - if (!do_fetch) { - DPRINTF(InOrderCachePort, "Inst. [sn:%i] marked to be filled " - "through fetch buffer.\n", inst->seqNum); - cache_req->fetchBufferFill = true; - cache_req->setCompleted(true); - return; - } - - // Check to see if there is room in the fetchbuffer for this instruction. - // If not, block this request. - if (total_pending >= fetchBuffSize) { - DPRINTF(InOrderCachePort, "No room available in fetch buffer.\n"); - cache_req->done(false); - return; - } - - doTLBAccess(inst, cache_req, cacheBlkSize, Request::INST_FETCH, TheISA::TLB::Execute); - - if (inst->fault == NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%u]: Initiating fetch access to %s for " - "addr:%#x (block:%#x)\n", tid, name(), - cache_req->inst->getMemAddr(), block_addr); - - cache_req->reqData = new uint8_t[cacheBlkSize]; - - inst->setCurResSlot(slot_num); - - doCacheAccess(inst); - - if (cache_req->isMemAccPending()) { - pendingFetch.push_back(new FetchBlock(asid, block_addr)); - - // mark replacement block - } - } - - break; - } - - case CompleteFetch: - if (inst->fault != NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - inst->getMemAddr()); - finishCacheUnitReq(inst, cache_req); - return; - } - - if (cache_req->fetchBufferFill) { - // Block request if it's depending on a previous fetch, but it hasnt made it yet - std::list<FetchBlock*>::iterator fetch_it = findBlock(fetchBuffer, asid, block_addr); - if (fetch_it == fetchBuffer.end()) { - DPRINTF(InOrderCachePort, "%#x not available yet\n", - block_addr); - cache_req->setCompleted(false); - return; - } - - // Make New Instruction - createMachInst(fetch_it, inst); - if (inst->traceData) { - inst->traceData->setStaticInst(inst->staticInst); - inst->traceData->setPC(inst->pcState()); - } - - // FetchBuffer Book-Keeping - (*fetch_it)->cnt--; - assert((*fetch_it)->cnt >= 0); - markBlockUsed(fetch_it); - - cache_req->done(); - return; - } - - if (cache_req->isMemAccComplete()) { - if (fetchBuffer.size() >= fetchBuffSize) { - // If there is no replacement block, then we'll just have - // to wait till that gets cleared before satisfying the fetch - // for this instruction - std::list<FetchBlock*>::iterator repl_it = - findReplacementBlock(); - if (repl_it == fetchBuffer.end()) { - DPRINTF(InOrderCachePort, "Unable to find replacement block" - " and complete fetch.\n"); - cache_req->setCompleted(false); - return; - } - - delete [] (*repl_it)->block; - delete *repl_it; - fetchBuffer.erase(repl_it); - } - - DPRINTF(InOrderCachePort, - "[tid:%i]: Completing Fetch Access for [sn:%i]\n", - tid, inst->seqNum); - - // Make New Instruction - std::list<FetchBlock*>::iterator fetch_it = - findBlock(pendingFetch, asid, block_addr); - - assert(fetch_it != pendingFetch.end()); - assert((*fetch_it)->valid); - - createMachInst(fetch_it, inst); - if (inst->traceData) { - inst->traceData->setStaticInst(inst->staticInst); - inst->traceData->setPC(inst->pcState()); - } - - - // Update instructions waiting on new fetch block - FetchBlock *new_block = (*fetch_it); - new_block->cnt--; - assert(new_block->cnt >= 0); - - // Finally, update FetchBuffer w/Pending Block into the - // MRU location - pendingFetch.erase(fetch_it); - fetchBuffer.push_back(new_block); - - DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n", - tid, inst->seqNum, - inst->staticInst->disassemble(inst->instAddr())); - - inst->unsetMemAddr(); - - cache_req->done(); - } else { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n", - tid, inst->seqNum); - DPRINTF(InOrderStall, - "STALL: [tid:%i]: Fetch miss from %08p\n", - tid, cache_req->inst->instAddr()); - cache_req->setCompleted(false); - // NOTE: For SwitchOnCacheMiss ThreadModel, we *don't* switch on - // fetch miss, but we could ... - // cache_req->setMemStall(true); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -FetchUnit::processCacheCompletion(PacketPtr pkt) -{ - // Cast to correct packet type - // @todo: use pkt Sender state here to be consistent with other - // cpu models - CacheReqPacket* cache_pkt = dynamic_cast<CacheReqPacket*>(pkt); - assert(cache_pkt); - - DPRINTF(InOrderCachePort, "Finished request for %x\n", - cache_pkt->getAddr()); - - if (processSquash(cache_pkt)) - return; - - Addr block_addr = cacheBlockAlign(cache_pkt->cacheReq-> - getInst()->getMemAddr()); - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Waking from fetch access to addr:%#x(phys:%#x), size:%i\n", - cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum, - block_addr, cache_pkt->getAddr(), cache_pkt->getSize()); - - // Cast to correct request type - CacheRequest *cache_req = dynamic_cast<CacheReqPtr>( - findRequest(cache_pkt->cacheReq->getInst(), cache_pkt->instIdx)); - - if (!cache_req) { - panic("[tid:%u]: [sn:%i]: Can't find slot for fetch access to " - "addr. %08p\n", cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum, - block_addr); - } - - // Get resource request info - unsigned stage_num = cache_req->getStageNum(); - DynInstPtr inst = cache_req->inst; - ThreadID tid = cache_req->inst->readTid(); - short asid = cpu->asid[tid]; - - assert(!cache_req->isSquashed()); - assert(inst->curSkedEntry->cmd == CompleteFetch); - - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Processing fetch access for block %#x\n", - tid, inst->seqNum, block_addr); - - std::list<FetchBlock*>::iterator pend_it = findBlock(pendingFetch, asid, - block_addr); - assert(pend_it != pendingFetch.end()); - - // Copy Data to pendingFetch queue... - (*pend_it)->block = new uint8_t[cacheBlkSize]; - memcpy((*pend_it)->block, cache_pkt->getConstPtr<uint8_t>(), cacheBlkSize); - (*pend_it)->valid = true; - - cache_req->setMemAccPending(false); - cache_req->setMemAccCompleted(); - - if (cache_req->isMemStall() && - cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) { - DPRINTF(InOrderCachePort, "[tid:%u] Waking up from Cache Miss.\n", - tid); - - cpu->activateContext(tid); - - DPRINTF(ThreadModel, "Activating [tid:%i] after return from cache" - "miss.\n", tid); - } - - // Wake up the CPU (if it went to sleep and was waiting on this - // completion event). - cpu->wakeCPU(); - - DPRINTF(Activity, "[tid:%u] Activating %s due to cache completion\n", - tid, cpu->pipelineStage[stage_num]->name()); - - cpu->switchToActive(stage_num); -} - -void -FetchUnit::squashCacheRequest(CacheReqPtr req_ptr) -{ - DynInstPtr inst = req_ptr->getInst(); - ThreadID tid = inst->readTid(); - Addr block_addr = cacheBlockAlign(inst->getMemAddr()); - int asid = cpu->asid[tid]; - - // Check Fetch Buffer (or pending fetch) for this block and - // update pending counts - std::list<FetchBlock*>::iterator buff_it = findBlock(fetchBuffer, - asid, - block_addr); - if (buff_it != fetchBuffer.end()) { - (*buff_it)->cnt--; - DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Access " - "for Fetch Buffer block %08p (cnt=%i)\n", inst->seqNum, - block_addr, (*buff_it)->cnt); - assert((*buff_it)->cnt >= 0); - } else { - std::list<FetchBlock*>::iterator block_it = findBlock(pendingFetch, - asid, - block_addr); - if (block_it != pendingFetch.end()) { - (*block_it)->cnt--; - DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Access " - "for Pending Buffer Block %08p (cnt=%i)\n", - inst->seqNum, - block_addr, (*block_it)->cnt); - assert((*block_it)->cnt >= 0); - if ((*block_it)->cnt == 0) { - if ((*block_it)->block) { - delete [] (*block_it)->block; - } - delete *block_it; - pendingFetch.erase(block_it); - } - } - } - - CacheUnit::squashCacheRequest(req_ptr); -} - -void -FetchUnit::trap(const Fault &fault, ThreadID tid, DynInstPtr inst) -{ - //@todo: per thread? - decoder[tid]->reset(); - - //@todo: squash using dummy inst seq num - squash(NULL, NumStages - 1, 0, tid); - - //@todo: make sure no blocks are in use - assert(blocksInUse() == 0); - assert(pendingFetch.size() == 0); - - //@todo: clear pendingFetch and fetchBuffer - clearFetchBuffer(); -} diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh deleted file mode 100644 index d72721009..000000000 --- a/src/cpu/inorder/resources/fetch_unit.hh +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2011 The Regents of The University of Michigan - * 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_FETCH_UNIT_HH__ -#define __CPU_INORDER_FETCH_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "arch/decoder.hh" -#include "arch/tlb.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/cache_unit.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" -#include "mem/packet.hh" -#include "mem/packet_access.hh" -#include "mem/port.hh" -#include "params/InOrderCPU.hh" -#include "sim/sim_object.hh" - -class FetchUnit : public CacheUnit -{ - public: - FetchUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - virtual ~FetchUnit(); - - typedef ThePipeline::DynInstPtr DynInstPtr; - typedef TheISA::ExtMachInst ExtMachInst; - - struct FetchBlock { - int asid; - Addr addr; - uint8_t *block; - short cnt; - bool valid; - - FetchBlock(int _asid, Addr _addr) - : asid(_asid), addr(_addr), block(NULL), cnt(1), valid(false) - { } - }; - - /** Actions that this resource can take on an instruction */ - enum Command { - InitiateFetch, - CompleteFetch - }; - - - ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd); - - /** Executes one of the commands from the "Command" enum */ - void execute(int slot_num); - - void trap(const Fault &fault, ThreadID tid, DynInstPtr inst); - - TheISA::Decoder *decoder[ThePipeline::MaxThreads]; - - private: - void squashCacheRequest(CacheReqPtr req_ptr); - - void createMachInst(std::list<FetchBlock*>::iterator fetch_it, - DynInstPtr inst); - - /** After memory request is completed, then turn the fetched data - into an instruction. - */ - void processCacheCompletion(PacketPtr pkt); - - /** Create request that will interface w/TLB and Memory objects */ - virtual void setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req, - int acc_size, int flags); - - /** Align a PC to the start of an I-cache block. */ - Addr cacheBlockAlignPC(Addr addr) - { - return (addr & ~(cacheBlkMask)); - } - - void removeAddrDependency(DynInstPtr inst); - - std::list<FetchBlock*>::iterator findReplacementBlock(); - std::list<FetchBlock*>::iterator findBlock(std::list<FetchBlock*> - &fetch_blocks, int asid, - Addr block_addr); - - void markBlockUsed(std::list<FetchBlock*>::iterator block_it); - - int blocksInUse(); - - void clearFetchBuffer(); - - int instSize; - - int fetchBuffSize; - - /** Valid Cache Blocks*/ - std::list<FetchBlock*> fetchBuffer; - - /** Cache lines that are pending */ - std::list<FetchBlock*> pendingFetch; -}; - -#endif //__CPU_FETCH_UNIT_HH__ diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc deleted file mode 100644 index ea63527b6..000000000 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Korey Sewell - * - */ - -#include "cpu/inorder/resources/graduation_unit.hh" -#include "debug/InOrderGraduation.hh" - -using namespace ThePipeline; - -GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ - for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; - nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; - lastNonSpecTick[tid] = 0; - lastFaultTick[tid] = 0; - } -} - -void -GraduationUnit::execute(int slot_num) -{ - ResourceRequest* grad_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - ThreadID tid = inst->readTid(); - int stage_num = inst->curSkedEntry->stageNum; - Tick cur_tick = curTick(); - - //@todo: not the common case, anyway we can move this - // check to the stage and just ignore instructions - // after? - if (lastNonSpecTick[tid] == cur_tick) { - DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. " - "Only 1 nonspec inst. per cycle can graduate.\n"); - grad_req->done(false); - return; - } - - //@todo: use trap Pending - if (cpu->trapPending[tid]) { - //if (lastFaultTick[tid] == cur_tick) { - DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. " - "Only 1 fault can be handled per tick.\n"); - grad_req->done(false); - return; - } - - - switch (grad_req->cmd) - { - case CheckFault: - { - // Handle Any Faults Before Graduating Instruction - if (inst->fault != NoFault) { - DPRINTF(InOrderGraduation, "[tid:%i]: [sn:%i]: fault %s found for %s\n", - tid, inst->seqNum, inst->fault->name(), - inst->instName()); - squashThenTrap(stage_num, inst); - lastFaultTick[tid] = cur_tick; - grad_req->done(false); - return; - } - - DPRINTF(InOrderGraduation, "[tid:%i] [sn:%i]: No fault found for %s\n", - tid, inst->seqNum, inst->instName()); - grad_req->done(); - } - break; - - case GraduateInst: - { - DPRINTF(InOrderGraduation, - "[tid:%i]:[sn:%i]: Graduating instruction %s.\n", - tid, inst->seqNum, inst->staticInst->disassemble(inst->instAddr())); - - // Release Non-Speculative "Block" on instructions that could not - // execute because there was a non-speculative inst. active. - // @TODO: Fix this functionality. Probably too conservative. - // Maybe it should be, non-spec. insts should block other - // non-spec insts because they can potentially be reading - // system state that will be changed by the 1st non-spec inst. - if (inst->isNonSpeculative()) { - *nonSpecInstActive[tid] = false; - DPRINTF(InOrderGraduation, - "[tid:%i] Non-speculative inst [sn:%i] graduated\n", - tid, inst->seqNum); - lastNonSpecTick[tid] = cur_tick; - } - - if (inst->traceData) { - inst->traceData->setStageCycle(stage_num, cur_tick); - } - - // Tell CPU that instruction is finished processing - cpu->instDone(inst, tid); - - grad_req->done(); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } - -} diff --git a/src/cpu/inorder/resources/graduation_unit.hh b/src/cpu/inorder/resources/graduation_unit.hh deleted file mode 100644 index 69d3322fe..000000000 --- a/src/cpu/inorder/resources/graduation_unit.hh +++ /dev/null @@ -1,67 +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_GRAD_UNIT_HH__ -#define __CPU_INORDER_GRAD_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class GraduationUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - enum Command { - CheckFault, - GraduateInst - }; - - public: - GraduationUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - void execute(int slot_num); - - protected: - Tick lastNonSpecTick[ThePipeline::MaxThreads]; - Tick lastFaultTick[ThePipeline::MaxThreads]; - bool *nonSpecInstActive[ThePipeline::MaxThreads]; - InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; -}; - -#endif //__CPU_INORDER_GRAD_UNIT_HH__ diff --git a/src/cpu/inorder/resources/inst_buffer.cc b/src/cpu/inorder/resources/inst_buffer.cc deleted file mode 100644 index 19011059f..000000000 --- a/src/cpu/inorder/resources/inst_buffer.cc +++ /dev/null @@ -1,241 +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 "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/inst_buffer.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "debug/InOrderInstBuffer.hh" -#include "debug/Resource.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -InstBuffer::InstBuffer(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ } - -void -InstBuffer::regStats() -{ - instsBypassed - .name(name() + ".instsBypassed") - .desc("Number of Instructions Bypassed.") - .prereq(instsBypassed); - - Resource::regStats(); -} - -void -InstBuffer::execute(int slot_idx) -{ - ResReqPtr ib_req = reqs[slot_idx]; - DynInstPtr inst = ib_req->inst; - ThreadID tid = inst->readTid(); - int stage_num = ib_req->getStageNum(); - - switch (ib_req->cmd) - { - case ScheduleOrBypass: - { - int next_stage = stage_num + 1; - int bypass_stage = stage_num + 2; - bool do_bypass = true; - - if (!instList.empty()) { - DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i " - "because buffer isn't empty.\n", - inst->seqNum, next_stage); - do_bypass = false; - } else if(cpu->pipelineStage[bypass_stage]->isBlocked(tid)) { - DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i " - "because stage %i is blocking.\n", - inst->seqNum, next_stage); - do_bypass = false; - } else if(cpu->pipelineStage[bypass_stage]-> - stageBufferAvail() <= 0) { - DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i " - "because there is no room in stage %i incoming stage " - "buffer.\n", inst->seqNum, next_stage); - do_bypass = false; - } - - if (!do_bypass) { // SCHEDULE USAGE OF BUFFER - DPRINTF(InOrderInstBuffer, "Scheduling [sn:%i] for buffer " - "insertion in stage %i\n", - inst->seqNum, next_stage); - - // Add to schedule: Insert into buffer in next stage - int stage_pri = 20; - RSkedPtr insert_sked = (stage_num >= ThePipeline::BackEndStartStage) ? - inst->backSked : inst->frontSked; - - 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 = 20; - RSkedPtr bypass_sked = (stage_num >= ThePipeline::BackEndStartStage) ? - inst->backSked : inst->frontSked; - - bypass_sked->push(new ScheduleEntry(bypass_stage, - stage_pri, - id, - InstBuffer::RemoveInst)); - } else { // BYPASS BUFFER & NEXT STAGE - DPRINTF(InOrderInstBuffer, "Setting [sn:%i] to bypass stage " - "%i and enter stage %i.\n", inst->seqNum, next_stage, - bypass_stage); - inst->setNextStage(bypass_stage); - instsBypassed++; - } - - ib_req->done(); - } - break; - - case InsertInst: - { - bool inserted = false; - - if (instList.size() < width) { - DPRINTF(InOrderInstBuffer, "[tid:%i]: Inserting [sn:%i] into " - "buffer.\n", tid, inst->seqNum); - insert(inst); - inserted = true; - } else { - DPRINTF(InOrderInstBuffer, "[tid:%i]: Denying [sn:%i] request " - "because buffer is full.\n", tid, inst->seqNum); - - - std::list<DynInstPtr>::iterator list_it = instList.begin(); - std::list<DynInstPtr>::iterator list_end = instList.end(); - - while (list_it != list_end) { - DPRINTF(Resource,"Serving [tid:%i] [sn:%i].\n", - (*list_it)->readTid(), (*list_it)->seqNum); - list_it++; - } - } - - ib_req->done(inserted); - } - break; - - case RemoveInst: - { - DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing [sn:%i] from " - "buffer.\n", tid, inst->seqNum); - remove(inst); - ib_req->done(); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } - - DPRINTF(InOrderInstBuffer, "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(ThreadID tid) -{ - instList.pop_front(); -} - -ThePipeline::DynInstPtr -InstBuffer::top(ThreadID tid) -{ - return instList.front(); -} - -void -InstBuffer::squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid) -{ - queue<list<DynInstPtr>::iterator> remove_list; - list<DynInstPtr>::iterator list_it = instList.begin(); - list<DynInstPtr>::iterator list_end = instList.end(); - - // Collect All Instructions to be Removed in Remove List - while (list_it != list_end) { - if((*list_it)->readTid() == tid && - (*list_it)->seqNum > squash_seq_num) { - (*list_it)->setSquashed(); - remove_list.push(list_it); - } - - list_it++; - } - - // Removed Instructions from InstList & Clear Remove List - while (!remove_list.empty()) { - DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing squashed [sn:%i] from " - "buffer.\n", tid, (*remove_list.front())->seqNum); - instList.erase(remove_list.front()); - remove_list.pop(); - } - - Resource::squash(inst, stage_num, squash_seq_num, tid); -} diff --git a/src/cpu/inorder/resources/inst_buffer.hh b/src/cpu/inorder/resources/inst_buffer.hh deleted file mode 100644 index 78ef900c6..000000000 --- a/src/cpu/inorder/resources/inst_buffer.hh +++ /dev/null @@ -1,93 +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 <list> -#include <string> -#include <vector> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class InstBuffer : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - enum Command { - InsertInst, - InsertAddr, - RemoveInst, - RemoveAddr, - ScheduleOrBypass - }; - - public: - InstBuffer(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - void regStats(); - - void execute(int slot_num); - - void insert(DynInstPtr inst); - - void remove(DynInstPtr inst); - - void pop(ThreadID tid); - - DynInstPtr top(ThreadID tid); - - void squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - protected: - /** List of instructions this resource is currently - * processing. - */ - std::list<DynInstPtr> instList; - - public: - ///////////////////////////////////////////////////////////////// - // - // RESOURCE STATISTICS - // - ///////////////////////////////////////////////////////////////// - /** Number of Instruction Requests the Resource Processes */ - Stats::Scalar instsBypassed; - -}; - -#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__ diff --git a/src/cpu/inorder/resources/mem_dep_unit.hh b/src/cpu/inorder/resources/mem_dep_unit.hh deleted file mode 100644 index 4e512de58..000000000 --- a/src/cpu/inorder/resources/mem_dep_unit.hh +++ /dev/null @@ -1,66 +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_MEM_DEP_UNIT_HH__ -#define __CPU_INORDER_MEM_DEP_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" - -class MemDepUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - MemDepUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu); - virtual ~MemDepUnit() {} - - virtual void execute(int slot_num); - - protected: - Tick lastCycleGrad; - int numCycleGrad; - - bool *nonSpecInstActive[ThePipeline::MaxThreads]; - - InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; - - /** @todo: Add Resource Stats Here */ -}; - -#endif //__CPU_INORDER_GRAD_UNIT_HH__ diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc deleted file mode 100644 index 5a4d4bb55..000000000 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ /dev/null @@ -1,353 +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 "cpu/inorder/resources/mult_div_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/resource_pool.hh" -#include "cpu/op_class.hh" -#include "debug/InOrderMDU.hh" -#include "debug/Resource.hh" - -using namespace std; -using namespace ThePipeline; - -MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - multRepeatRate(params->multRepeatRate), - multLatency(params->multLatency), - div8RepeatRate(params->div8RepeatRate), - div8Latency(params->div8Latency), - div16RepeatRate(params->div16RepeatRate), - div16Latency(params->div16Latency), - div24RepeatRate(params->div24RepeatRate), - div24Latency(params->div24Latency), - div32RepeatRate(params->div32RepeatRate), - div32Latency(params->div32Latency), - lastMDUCycle(0), lastOpType(No_OpClass) -{ } - -void -MultDivUnit::regStats() -{ - multiplies - .name(name() + ".multiplies") - .desc("Number of Multipy Operations Executed"); - - divides - .name(name() + ".divides") - .desc("Number of Divide Operations Executed"); - - Resource::regStats(); -} - -void -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(); -} - -//@TODO: Should we push this behavior into base-class to generically -// accomodate all multicyle resources? -void -MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request) -{ - ResReqPtr mult_div_req = findRequest(inst); - assert(mult_div_req); - - service_request = true; - - // Check to see if this instruction is requesting the same command - // or a different one - if (mult_div_req->cmd != inst->curSkedEntry->cmd) { - // If different, then update command in the request - mult_div_req->cmd = inst->curSkedEntry->cmd; - DPRINTF(InOrderMDU, - "[tid:%i]: [sn:%i]: Updating the command for this " - "instruction\n", inst->readTid(), inst->seqNum); - } else { - // If same command, just check to see if access was completed - // but dont try to re-execute - DPRINTF(InOrderMDU, - "[tid:%i]: [sn:%i]: requesting this resource again\n", - inst->readTid(), inst->seqNum); - } -} -int -MultDivUnit::getSlot(DynInstPtr inst) -{ - // If MDU already has instruction, return current slot. - int slot_num = findSlot(inst); - - // If we have this instruction's request already then return - if (slot_num != -1 && - inst->curSkedEntry->cmd == reqs[slot_num]->cmd) - return slot_num; - - unsigned repeat_rate = 0; - - /** Enforce MDU dependencies after a multiply is seen last */ - if (lastOpType == IntMultOp) { - repeat_rate = multRepeatRate; - } - - /** Enforce dependencies after a divide is seen last */ - if (lastOpType == IntDivOp) { - switch (lastDivSize) { - case 8: - repeat_rate = div8RepeatRate; - break; - - case 16: - repeat_rate = div16RepeatRate; - break; - - case 24: - repeat_rate = div24RepeatRate; - break; - - case 32: - repeat_rate = div32RepeatRate; - break; - } - } - - if (lastMDUCycle + repeat_rate > curTick()) { - DPRINTF(InOrderMDU, "MDU not ready to process another inst. until %i, " - "denying request.\n", lastMDUCycle + repeat_rate); - return -1; - } else { - int rval = Resource::getSlot(inst); - DPRINTF(InOrderMDU, "MDU request should pass: %i.\n", - rval); - - if (rval != -1) { - lastMDUCycle = curTick(); - lastOpType = inst->opClass(); - lastInstName = inst->staticInst->getName(); - } - - return rval; - } -} - -int -MultDivUnit::getDivOpSize(DynInstPtr inst) -{ - // Get RT Register from instruction (index #1) - uint32_t div_op = inst->readIntSrc(1); - - if (div_op <= 0xFF) { - return 8; - } else if (div_op <= 0xFFFF) { - return 16; - } else if (div_op <= 0xFFFFFF) { - return 24; - } else { - return 32; - } -} - -void -MultDivUnit::execute(int slot_num) -{ - ResourceRequest* mult_div_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - if (inst->fault != NoFault) { - DPRINTF(InOrderMDU, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->pcState()); - mult_div_req->done(); - return; - } - - DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num); - - switch (mult_div_req->cmd) - { - case StartMultDiv: - { - DPRINTF(InOrderMDU, "Start MDU called ...\n"); - - OpClass op_class = inst->opClass(); - if (op_class == IntMultOp) { - scheduleEvent(slot_num, multLatency); - } else if (op_class == IntDivOp) { - int op_size = getDivOpSize(inst); - - switch (op_size) - { - case 8: - scheduleEvent(slot_num, div8Latency); - break; - - case 16: - scheduleEvent(slot_num, div16Latency); - break; - - case 24: - scheduleEvent(slot_num, div24Latency); - break; - - case 32: - scheduleEvent(slot_num, div32Latency); - break; - } - - lastDivSize = op_size; - } - - // Allow to pass through to next stage while - // event processes - mult_div_req->setProcessing(); - mult_div_req->setCompleted(); - } - break; - - case MultDiv: - DPRINTF(InOrderMDU, "Execute MDU called ...\n"); - exeMulDiv(slot_num); - mult_div_req->done(); - break; - - - case EndMultDiv: - //@TODO: Why not allow high-latency requests to sleep - // within stage until event wakes up???? - // Seems wasteful to continually check to see if - // this is done when we have a event in parallel - // counting down the time - { - DPRINTF(InOrderMDU, "End MDU called ...\n"); - if (!mult_div_req->isProcessing()) { - DPRINTF(InOrderMDU, "Mult/Div finished.\n"); - mult_div_req->done(); - } else { - mult_div_req->setCompleted(false); - } - - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -MultDivUnit::exeMulDiv(int slot_num) -{ - ResourceRequest* mult_div_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - - inst->fault = inst->execute(); - - if (inst->opClass() == IntMultOp) { - multiplies++; - } else if (inst->opClass() == IntDivOp) { - divides++; - } - - if (inst->fault == NoFault) { - inst->setExecuted(); - - DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n", - inst->readTid(), inst->readIntResult(0)); - } else { - DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s " - "fault.\n", inst->readTid(), inst->seqNum, inst->fault->name()); - } - - mult_div_req->setProcessing(false); - cpu->wakeCPU(); -} - -void -MultDivUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, - ThreadID tid) -{ - 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(InOrderMDU, "[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 (req_ptr->isProcessing()) - DPRINTF(InOrderMDU, "[tid:%i]: Squashed [sn:%i], but " - "waiting for MDU operation to complete.\n", - req_ptr->getInst()->readTid(), - req_ptr->getInst()->seqNum); - else - freeSlot(req_slot_num); - } - } -} - -MDUEvent::MDUEvent() - : ResourceEvent() -{ } - -void -MDUEvent::process() -{ - MultDivUnit* mdu_res = reinterpret_cast<MultDivUnit*>(resource); - - mdu_res->exeMulDiv(slotIdx); - - ResourceRequest* mult_div_req = resource->reqs[slotIdx]; - - if (mult_div_req->isSquashed()) - mdu_res->freeSlot(slotIdx); -} - - diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh deleted file mode 100644 index d855dbb9d..000000000 --- a/src/cpu/inorder/resources/mult_div_unit.hh +++ /dev/null @@ -1,139 +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_MULT_DIV_UNIT_HH__ -#define __CPU_INORDER_MULT_DIV_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/func_unit.hh" -#include "cpu/op_class.hh" - -class MDUEvent; - -class MultDivUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - enum Command { - StartMultDiv, - EndMultDiv, - MultDiv - }; - - public: - MultDivUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - public: - /** Override default Resource getSlot(). Will only getSlot if - * valid mult/div sequence is being maintained - */ - int getSlot(DynInstPtr inst); - - void init(); - - /** Get Operand Size For A Division Operation */ - int getDivOpSize(DynInstPtr inst); - - /** Override default Resource execute */ - void execute(int slot_num); - - void exeMulDiv(int slot_num); - - /** Register extra resource stats */ - void regStats(); - - void requestAgain(DynInstPtr inst, bool &try_request); - - void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, - ThreadID tid); - - protected: - /** Latency & Repeat Rate for Multiply Insts */ - unsigned multRepeatRate; - Cycles multLatency; - - /** Latency & Repeat Rate for 8-bit Divide Insts */ - unsigned div8RepeatRate; - Cycles div8Latency; - - /** Latency & Repeat Rate for 16-bit Divide Insts */ - unsigned div16RepeatRate; - Cycles div16Latency; - - /** Latency & Repeat Rate for 24-bit Divide Insts */ - unsigned div24RepeatRate; - Cycles div24Latency; - - /** Latency & Repeat Rate for 32-bit Divide Insts */ - unsigned div32RepeatRate; - Cycles div32Latency; - - /** Last cycle that MDU was used */ - Tick lastMDUCycle; - - /** Last type of instruction MDU started processing */ - OpClass lastOpType; - - /** Last Division Operand of instruction MDU was processing */ - uint32_t lastDivSize; - - /** Last instruction name the MDU used */ - std::string lastInstName; - - /** Number of Multiplies */ - Stats::Scalar multiplies; - - /** Number of Divides */ - Stats::Scalar divides; - - MDUEvent *mduEvent; -}; - -class MDUEvent : public ResourceEvent -{ - public: - MDUEvent(); - ~MDUEvent() { } - - - void process(); -}; - - -#endif //__CPU_INORDER_MULT_DIV_UNIT_HH__ diff --git a/src/cpu/inorder/resources/resource_list.hh b/src/cpu/inorder/resources/resource_list.hh deleted file mode 100644 index a3876d80f..000000000 --- a/src/cpu/inorder/resources/resource_list.hh +++ /dev/null @@ -1,50 +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_RESOURCE_LIST_HH -#define CPU_INORDER_RESOURCE_LIST_HH - -#include "cpu/inorder/resources/agen_unit.hh" -#include "cpu/inorder/resources/branch_predictor.hh" -#include "cpu/inorder/resources/cache_unit.hh" -#include "cpu/inorder/resources/decode_unit.hh" -#include "cpu/inorder/resources/execution_unit.hh" -#include "cpu/inorder/resources/fetch_seq_unit.hh" -#include "cpu/inorder/resources/fetch_unit.hh" -#include "cpu/inorder/resources/graduation_unit.hh" -#include "cpu/inorder/resources/inst_buffer.hh" -#include "cpu/inorder/resources/mult_div_unit.hh" -// The TLBUnit is only needed with the 9-stage pipe and is -// triggering a gcc LTO bug -//#include "cpu/inorder/resources/tlb_unit.hh" -#include "cpu/inorder/resources/use_def.hh" - -#endif diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc deleted file mode 100644 index c2619f15e..000000000 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ /dev/null @@ -1,259 +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 "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/tlb_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/pipeline_traits.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -TLBUnit::TLBUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) -: Resource(res_name, res_id, res_width, res_latency, _cpu) -{ - // Hard-Code Selection For Now - if (res_name == "I-TLB") - _tlb = params->itb; - else if (res_name == "D-TLB") - _tlb = params->dtb; - else - fatal("Unrecognized TLB name passed by user"); - - for (int i=0; i < MaxThreads; i++) { - tlbBlocked[i] = false; - } -} - -TheISA::TLB* -TLBUnit::tlb() -{ - return _tlb; - -} - -void -TLBUnit::init() -{ - resourceEvent = new TLBUnitEvent[width]; - - for (int i = 0; i < width; i++) { - reqs[i] = new TLBUnitRequest(this); - } - - initSlots(); -} - -int -TLBUnit::getSlot(DynInstPtr inst) -{ - if (tlbBlocked[inst->threadNumber]) { - return -1; - } else { - return Resource::getSlot(inst); - } -} - -ResourceRequest* -TLBUnit::getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd) -{ - TLBUnitRequest *tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_num]); - tlb_req->setRequest(inst, stage_num, id, slot_num, cmd); - return ud_req; -} - -void -TLBUnit::execute(int slot_idx) -{ - // After this is working, change this to a reinterpret cast - // for performance considerations - TLBUnitRequest* tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_idx]); - assert(tlb_req != 0x0); - - DynInstPtr inst = tlb_req->inst; - ThreadID tid = inst->readTid(); - InstSeqNum seq_num = inst->seqNum; - int stage_num = tlb_req->getStageNum(); - - tlb_req->fault = NoFault; - - assert(cpu->thread[tid]->getTC() != 0x0); - assert(cpu->pipelineStage[stage_num] != 0x0); - - switch (tlb_req->cmd) - { - case FetchLookup: - { - tlb_req->fault = - _tlb->translateAtomic(tlb_req->memReq, - cpu->thread[tid]->getTC(), TheISA::TLB::Execute); - - if (tlb_req->fault != NoFault) { - DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " - "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(), - tlb_req->memReq->getVaddr(), seq_num); - - DPRINTF(InOrderTLB, "slot:%i sn:%i schedule event.\n", slot_idx, seq_num); - - cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid); - tlbBlocked[tid] = true; - scheduleEvent(slot_idx, 1); - - // @TODO: SHOULDNT BREAK EXECUTION at misspeculated PC Fault - // Let CPU handle the fault - cpu->trap(tlb_req->fault, tid); - } else { - DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " - "to phys. addr:%08p.\n", tid, seq_num, - tlb_req->memReq->getVaddr(), - tlb_req->memReq->getPaddr()); - tlb_req->done(); - } - } - break; - - case DataReadLookup: - case DataWriteLookup: - { - DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n", - tid, seq_num, tlb_req->memReq->getVaddr()); - - - TheISA::TLB::Mode tlb_mode = (tlb_req->cmd == DataReadLookup) ? - TheISA::TLB::Read : TheISA::TLB::Write; - - tlb_req->fault = - _tlb->translateAtomic(tlb_req->memReq, - cpu->thread[tid]->getTC(), tlb_mode); - - if (tlb_req->fault != NoFault) { - DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " - "addr:%08p for [sn:%i] %s.\n", tid, tlb_req->fault->name(), - tlb_req->memReq->getVaddr(), seq_num, inst->instName()); - - if (inst->isDataPrefetch()) { - DPRINTF(InOrderTLB, "Ignoring %s fault for data prefetch\n", - tlb_req->fault->name()); - - tlb_req->fault = NoFault; - - tlb_req->done(); - } else { - cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid); - tlbBlocked[tid] = true; - scheduleEvent(slot_idx, 1); - - // Let CPU handle the fault - cpu->trap(tlb_req->fault, tid, inst); - } - } else { - DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " - "to phys. addr:%08p.\n", tid, seq_num, - tlb_req->memReq->getVaddr(), - tlb_req->memReq->getPaddr()); - tlb_req->done(); - } - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -TLBUnitEvent::TLBUnitEvent() - : ResourceEvent() -{ } - -void -TLBUnitEvent::process() -{ - 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", - inst->seqNum); - - TLBUnit* tlb_res = dynamic_cast<TLBUnit*>(resource); - assert(tlb_res); - - tlb_res->tlbBlocked[tid] = false; - - 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) -{ - for (int i = 0; i < width; i++) { - ResReqPtr req_ptr = reqs[i]; - - if (req_ptr->valid && - req_ptr->getInst()->readTid() == tid && - req_ptr->getInst()->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(); - - tlbBlocked[tid] = false; - - int stall_stage = reqs[req_slot_num]->getStageNum(); - - cpu->pipelineStage[stall_stage]-> - unsetResStall(reqs[req_slot_num], tid); - - if (resourceEvent[req_slot_num].scheduled()) - unscheduleEvent(req_slot_num); - - freeSlot(req_slot_num); - } - } -} - - diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh deleted file mode 100644 index 916f67559..000000000 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ /dev/null @@ -1,152 +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_TLB_UNIT_HH__ -#define __CPU_INORDER_TLB_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "config/the_isa.hh" -#include "cpu/inorder/resources/inst_buffer.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" - -class TLBUnit : public Resource -{ - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - enum TLBCommand { - FetchLookup, - DataReadLookup, - DataWriteLookup - }; - - public: - TLBUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - virtual ~TLBUnit() {} - - void init(); - - int getSlot(DynInstPtr inst); - - virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd); - - virtual void execute(int slot_num); - - void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, - ThreadID tid); - - bool tlbBlocked[ThePipeline::MaxThreads]; - - TheISA::TLB* tlb(); - - protected: - /** List of instructions this resource is currently - * processing. - */ - std::list<DynInstPtr> instList; - - TheISA::TLB *_tlb; -}; - -class TLBUnitEvent : public ResourceEvent { - public: - /** Constructs a resource event. */ - TLBUnitEvent(); - virtual ~TLBUnitEvent() {} - - /** Processes a resource event. */ - virtual void process(); -}; - -class TLBUnitRequest : public ResourceRequest { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - 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; - unsigned flags; - - if (_cmd == TLBUnit::FetchLookup) { - aligned_addr = inst->getMemAddr(); - req_size = sizeof(TheISA::MachInst); - flags = 0; - inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, - req_size, flags, - res->cpu->instMasterId(), - inst->instAddr(), - res->cpu->readCpuId(), - inst->readTid()); - memReq = inst->fetchMemReq; - } else { - aligned_addr = inst->getMemAddr();; - req_size = 0; //inst->getMemAccSize(); - flags = 0; //inst->getMemFlags(); - - if (req_size == 0 && (inst->isDataPrefetch() || inst->isInstPrefetch())) { - req_size = 8; - } - - inst->dataMemReq = new Request(inst->readTid(), aligned_addr, - req_size, flags, - res->cpu->dataMasterId(), - inst->instAddr(), - res->cpu->readCpuId(), - inst->readTid()); - memReq = inst->dataMemReq; - } - - ResourceRequest::setRequest(inst, stage_num, res_idx, slot_num, _cmd); - } - -}; - - -#endif //__CPU_INORDER_TLB_UNIT_HH__ diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc deleted file mode 100644 index 5a871d0d4..000000000 --- a/src/cpu/inorder/resources/use_def.cc +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2013 Advanced Micro Devices, 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 "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/use_def.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "debug/InOrderStall.hh" -#include "debug/InOrderUseDef.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -UseDefUnit::UseDefUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ - for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; - nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; - serializeOnNextInst[tid] = false; - serializeAfterSeqNum[tid] = 0; - regDepMap[tid] = &cpu->archRegDepMap[tid]; - } - -} - -void -UseDefUnit::regStats() -{ - uniqueRegsPerSwitch - .name(name() + ".uniqueRegsPerSwitch") - .desc("Number of Unique Registers Needed Per Context Switch") - .prereq(uniqueRegsPerSwitch); - - intRegFileReads - .name(name() + ".intRegFileReads") - .desc("Number of Reads from Int. Register File"); - - intRegFileWrites - .name(name() + ".intRegFileWrites") - .desc("Number of Writes to Int. Register File"); - - intRegFileAccs - .name(name() + ".intRegFileAccesses") - .desc("Total Accesses (Read+Write) to the Int. Register File"); - intRegFileAccs = intRegFileReads + intRegFileWrites; - - floatRegFileReads - .name(name() + ".floatRegFileReads") - .desc("Number of Reads from FP Register File"); - - floatRegFileWrites - .name(name() + ".floatRegFileWrites") - .desc("Number of Writes to FP Register File"); - - floatRegFileAccs - .name(name() + ".floatRegFileAccesses") - .desc("Total Accesses (Read+Write) to the FP Register File"); - floatRegFileAccs = floatRegFileReads + floatRegFileWrites; - - //@todo: add miscreg reads/writes - // add forwarding by type??? - - regForwards - .name(name() + ".regForwards") - .desc("Number of Registers Read Through Forwarding Logic"); - - Resource::regStats(); -} - -void -UseDefUnit::init() -{ - // Set Up Resource Events to Appropriate Resource BandWidth - if (latency > Cycles(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) -{ - 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) -{ - for (int i = 0; i < width; i++) { - UseDefRequest* ud_req = - dynamic_cast<UseDefRequest*>(reqs[i]); - assert(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; - } - } - - return NULL; -} - -void -UseDefUnit::execute(int slot_idx) -{ - UseDefRequest* ud_req = dynamic_cast<UseDefRequest*>(reqs[slot_idx]); - DynInstPtr inst = ud_req->inst; - ThreadID tid = inst->readTid(); - InstSeqNum seq_num = inst->seqNum; - int ud_idx = ud_req->useDefIdx; - - if (serializeOnNextInst[tid] && - seq_num > serializeAfterSeqNum[tid]) { - inst->setSerializeBefore(); - serializeOnNextInst[tid] = false; - } - - if ((inst->isIprAccess() || inst->isSerializeBefore()) && - cpu->instList[tid].front() != inst) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] Serialize before instruction encountered." - " Blocking until pipeline is clear.\n", tid, seq_num); - ud_req->done(false); - return; - } else if (inst->isStoreConditional() || inst->isSerializeAfter()) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] Serialize after instruction encountered." - " Blocking until pipeline is clear.\n", tid, seq_num); - serializeOnNextInst[tid] = true; - serializeAfterSeqNum[tid] = seq_num; - } - - if (inst->fault != NoFault) { - DPRINTF(InOrderUseDef, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->pcState()); - ud_req->done(); - return; - } - - // If there is a non-speculative instruction - // in the pipeline then stall instructions here - // --- - if (*nonSpecInstActive[tid] && seq_num > *nonSpecSeqNum[tid]) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] cannot execute because" - "there is non-speculative instruction [sn:%i] has not " - "graduated.\n", tid, seq_num, *nonSpecSeqNum[tid]); - ud_req->done(false); - return; - } else if (inst->isNonSpeculative()) { - *nonSpecInstActive[tid] = true; - *nonSpecSeqNum[tid] = seq_num; - } - - switch (ud_req->cmd) - { - case ReadSrcReg: - { - RegClass reg_type; - RegIndex reg_idx = inst->_srcRegIdx[ud_idx]; - RegIndex flat_idx = cpu->flattenRegIdx(reg_idx, reg_type, tid); - inst->flattenSrcReg(ud_idx, flat_idx); - - if (flat_idx == TheISA::ZeroReg && reg_type == IntRegClass) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Ignoring Reading of ISA-ZeroReg " - "(Int. Reg %i).\n", tid, inst->seqNum, flat_idx); - ud_req->done(); - return; - } else { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Attempting to read source " - "register idx %i (reg #%i, flat#%i).\n", - tid, seq_num, ud_idx, reg_idx, flat_idx); - } - - if (regDepMap[tid]->canRead(reg_type, flat_idx, inst)) { - switch (reg_type) - { - case IntRegClass: - { - uniqueIntRegMap[flat_idx] = true; - - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Reading Int Reg %i" - " (%i) from Register File:0x%x.\n", - tid, seq_num, - reg_idx, flat_idx, - cpu->readIntReg(flat_idx,inst->readTid())); - inst->setIntSrc(ud_idx, - cpu->readIntReg(flat_idx, - inst->readTid())); - intRegFileReads++; - } - break; - - case FloatRegClass: - { - uniqueFloatRegMap[flat_idx] = true; - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Reading Float Reg %i" - " (%i) from Register File:%x (%08f).\n", - tid, seq_num, - reg_idx - FP_Reg_Base, flat_idx, - cpu->readFloatRegBits(flat_idx, - inst->readTid()), - cpu->readFloatReg(flat_idx, - inst->readTid())); - - inst->setFloatSrc(ud_idx, - cpu->readFloatReg(flat_idx, - inst->readTid())); - inst->setFloatRegBitsSrc(ud_idx, - cpu->readFloatRegBits(flat_idx, - inst->readTid())); - floatRegFileReads++; - } - break; - - case MiscRegClass: - { - uniqueMiscRegMap[flat_idx] = true; - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Reading Misc Reg %i " - " (%i) from Register File:0x%x.\n", - tid, seq_num, - reg_idx - Misc_Reg_Base, flat_idx, - cpu->readMiscReg(flat_idx, - inst->readTid())); - inst->setIntSrc(ud_idx, - cpu->readMiscReg(flat_idx, - inst->readTid())); - } - break; - - default: - panic("Invalid Register Type: %i", reg_type); - } - - ud_req->done(); - } else { - // Look for forwarding opportunities - DynInstPtr forward_inst = regDepMap[tid]->canForward(reg_type, - flat_idx, - inst); - - if (forward_inst) { - int dest_reg_idx = - forward_inst->getDestIdxNum(flat_idx); - - switch (reg_type) - { - case IntRegClass: - { - DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest." - " reg %i (%i), value 0x%x from " - "[sn:%i] to [sn:%i] source #%x.\n", - tid, reg_idx, flat_idx, - forward_inst->readIntResult(dest_reg_idx), - forward_inst->seqNum, - inst->seqNum, ud_idx); - inst->setIntSrc(ud_idx, - forward_inst-> - readIntResult(dest_reg_idx)); - } - break; - - case FloatRegClass: - { - DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest." - " reg %i (%i) value 0x%x from " - "[sn:%i] to [sn:%i] source #%i.\n", - tid, reg_idx - FP_Reg_Base, flat_idx, - forward_inst->readFloatResult(dest_reg_idx), - forward_inst->seqNum, inst->seqNum, ud_idx); - inst->setFloatSrc(ud_idx, - forward_inst-> - readFloatResult(dest_reg_idx)); - } - break; - - case MiscRegClass: - { - DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest." - " reg %i (%i) value 0x%x from " - "[sn:%i] to [sn:%i] source #%i.\n", - tid, reg_idx - Misc_Reg_Base, flat_idx, - forward_inst->readIntResult(dest_reg_idx), - forward_inst->seqNum, - inst->seqNum, ud_idx); - inst->setIntSrc(ud_idx, - forward_inst-> - readIntResult(dest_reg_idx)); - } - break; - - default: - panic("Invalid Register Type: %i", reg_type); - } - - regForwards++; - ud_req->done(); - } else { - DPRINTF(InOrderUseDef, "[tid:%i]: Source register idx: %i " - "is not ready to read.\n", - tid, reg_idx); - DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to read " - "register (idx=%i)\n", - tid, reg_idx); - ud_req->done(false); - } - } - } - break; - - case WriteDestReg: - { - RegClass reg_type; - RegIndex reg_idx = inst->_destRegIdx[ud_idx]; - RegIndex flat_idx = cpu->flattenRegIdx(reg_idx, reg_type, tid); - - if (flat_idx == TheISA::ZeroReg && reg_type == IntRegClass) { - DPRINTF(IntRegs, "[tid:%i]: Ignoring Writing of ISA-ZeroReg " - "(Int. Reg %i)\n", tid, flat_idx); - ud_req->done(); - return; - } - - if (regDepMap[tid]->canWrite(reg_type, flat_idx, inst)) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Flattening register idx %i " - "(%i) and Attempting to write to Register File.\n", - tid, seq_num, reg_idx, flat_idx); - - switch (reg_type) - { - case IntRegClass: - { - uniqueIntRegMap[flat_idx] = true; - - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Writing Int. Result " - "0x%x to register idx %i (%i).\n", - tid, seq_num, inst->readIntResult(ud_idx), - reg_idx, flat_idx); - - // Remove Dependencies - regDepMap[tid]->removeFront(reg_type, flat_idx, inst); - - cpu->setIntReg(flat_idx, - inst->readIntResult(ud_idx), - inst->readTid()); - intRegFileWrites++; - } - break; - - case FloatRegClass: - { - uniqueFloatRegMap[flat_idx] = true; - - // Remove Reg. Dependecny Block on this Register - regDepMap[tid]->removeFront(reg_type, flat_idx, inst); - - if (inst->resultType(ud_idx) == - InOrderDynInst::FloatBits) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Writing FP-Bits " - "Result %08f (bits:0x%x) to register " - "idx %i (%i).\n", - tid, seq_num, - inst->readFloatResult(ud_idx), - inst->readFloatBitsResult(ud_idx), - reg_idx - FP_Reg_Base, flat_idx); - - // Check for FloatRegBits Here - cpu->setFloatRegBits(flat_idx, - inst->readFloatBitsResult(ud_idx), - inst->readTid()); - } else if (inst->resultType(ud_idx) == - InOrderDynInst::Float) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Writing Float " - "Result %08f (bits:0x%x) to register " - "idx %i (%i).\n", - tid, seq_num, inst->readFloatResult(ud_idx), - inst->readIntResult(ud_idx), - reg_idx - FP_Reg_Base, flat_idx); - - cpu->setFloatReg(flat_idx, - inst->readFloatResult(ud_idx), - inst->readTid()); - } else if (inst->resultType(ud_idx) == - InOrderDynInst::Double) { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Writing Double " - "Result %08f (bits:0x%x) to register " - "idx %i (%i).\n", - tid, seq_num, - inst->readFloatResult(ud_idx), - inst->readIntResult(ud_idx), - reg_idx - FP_Reg_Base, flat_idx); - - cpu->setFloatReg(flat_idx, - inst->readFloatResult(ud_idx), - inst->readTid()); - } else { - panic("Result Type Not Set For [sn:%i] %s.\n", - inst->seqNum, inst->instName()); - } - - floatRegFileWrites++; - } - break; - - case MiscRegClass: - { - uniqueMiscRegMap[flat_idx] = true; - - DPRINTF(InOrderUseDef, "[tid:%i]: Writing Misc. 0x%x " - "to register idx %i.\n", - tid, inst->readIntResult(ud_idx), reg_idx - Misc_Reg_Base); - - // Remove Dependencies - regDepMap[tid]->removeFront(reg_type, flat_idx, inst); - - cpu->setMiscReg(flat_idx, - inst->readIntResult(ud_idx), - inst->readTid()); - } - break; - - default: - panic("Invalid Register Type: %i", reg_type); - } - - ud_req->done(); - } else { - DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Dest. register idx: %i is " - "not ready to write.\n", - tid, seq_num, reg_idx); - DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to write " - "register (idx=%i)\n", - tid, reg_idx); - ud_req->done(false); - } - } - break; - - case MarkDestRegs: - { - regDepMap[tid]->insert(inst); - ud_req->done(); - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } - -} - -void -UseDefUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) -{ - uniqueRegsPerSwitch = uniqueIntRegMap.size() + uniqueFloatRegMap.size() - + uniqueMiscRegMap.size(); - uniqueIntRegMap.clear(); - uniqueFloatRegMap.clear(); - uniqueMiscRegMap.clear(); -} diff --git a/src/cpu/inorder/resources/use_def.hh b/src/cpu/inorder/resources/use_def.hh deleted file mode 100644 index 9eb516345..000000000 --- a/src/cpu/inorder/resources/use_def.hh +++ /dev/null @@ -1,135 +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_USE_DEF_UNIT_HH__ -#define __CPU_INORDER_USE_DEF_UNIT_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/reg_dep_map.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/func_unit.hh" - -class UseDefUnit : public Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - typedef TheISA::RegIndex RegIndex; - - enum Command { - ReadSrcReg, - WriteDestReg, - MarkDestRegs - }; - - public: - UseDefUnit(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params); - - void init(); - - ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd); - - ResReqPtr findRequest(DynInstPtr inst); - - void execute(int slot_num); - - void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid); - - void regStats(); - - protected: - RegDepMap *regDepMap[ThePipeline::MaxThreads]; - - bool *nonSpecInstActive[ThePipeline::MaxThreads]; - InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; - - bool serializeOnNextInst[ThePipeline::MaxThreads]; - InstSeqNum serializeAfterSeqNum[ThePipeline::MaxThreads]; - - Stats::Average uniqueRegsPerSwitch; - std::map<RegIndex, bool> uniqueIntRegMap; - std::map<RegIndex, bool> uniqueFloatRegMap; - std::map<RegIndex, bool> uniqueMiscRegMap; - - public: - class UseDefRequest : public ResourceRequest { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - 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: - /** Int. Register File Reads */ - Stats::Scalar intRegFileReads; - - /** Int. Register File Writes */ - Stats::Scalar intRegFileWrites; - - /** Int. Register File Total Accesses (Read+Write) */ - Stats::Formula intRegFileAccs; - - /** Float Register File Reads */ - Stats::Scalar floatRegFileReads; - - /** Float Register File Writes */ - Stats::Scalar floatRegFileWrites; - - /** Float Register File Total Accesses (Read+Write) */ - Stats::Formula floatRegFileAccs; - - /** Source Register Forwarding */ - Stats::Scalar regForwards; -}; - -#endif //__CPU_INORDER_USE_DEF_UNIT_HH__ |