diff options
author | Andreas Hansson <andreas.hansson@arm.com> | 2015-04-20 12:46:35 -0400 |
---|---|---|
committer | Andreas Hansson <andreas.hansson@arm.com> | 2015-04-20 12:46:35 -0400 |
commit | cd76e34056afab83697beef1d1ced94ee671a20d (patch) | |
tree | 8adaa80ba72593bdf67103ad5cd0a072b95e8acb /src/cpu/inorder/resources | |
parent | 076ea249ae47b935bea424954174f33fdecb7fcc (diff) | |
download | gem5-cd76e34056afab83697beef1d1ced94ee671a20d.tar.xz |
cpu: Remove the InOrderCPU from the tree
This patch takes the final step in removing the InOrderCPU from the
tree. Rest in peace.
The MinorCPU is now used to model an in-order microarchitecture, and
long term the MinorCPU will eventually be renamed InOrderCPU.
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__ |