diff options
Diffstat (limited to 'src')
62 files changed, 0 insertions, 17803 deletions
diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py deleted file mode 100644 index dddcbbcec..000000000 --- a/src/cpu/inorder/InOrderCPU.py +++ /dev/null @@ -1,77 +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 - -from m5.params import * -from m5.proxy import * -from BaseCPU import BaseCPU -from BranchPredictor import * - -class ThreadModel(Enum): - vals = ['Single', 'SMT', 'SwitchOnCacheMiss'] - -class InOrderCPU(BaseCPU): - type = 'InOrderCPU' - cxx_header = "cpu/inorder/cpu.hh" - activity = Param.Unsigned(0, "Initial count") - - @classmethod - def memory_mode(cls): - return 'timing' - - @classmethod - def require_caches(cls): - return True - - @classmethod - def support_take_over(cls): - return True - - threadModel = Param.ThreadModel('SMT', "Multithreading model (SE-MODE only)") - - cachePorts = Param.Unsigned(2, "Cache Ports") - stageWidth = Param.Unsigned(4, "Stage width") - - fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)") - memBlockSize = Param.Unsigned(64, "Memory Block Size") - - stageTracing = Param.Bool(False, "Enable tracing of each stage in CPU") - - multLatency = Param.Cycles(1, "Latency for Multiply Operations") - multRepeatRate = Param.Cycles(1, "Repeat Rate for Multiply Operations") - div8Latency = Param.Cycles(1, "Latency for 8-bit Divide Operations") - div8RepeatRate = Param.Cycles(1, "Repeat Rate for 8-bit Divide Operations") - div16Latency = Param.Cycles(1, "Latency for 16-bit Divide Operations") - div16RepeatRate = Param.Cycles(1, "Repeat Rate for 16-bit Divide Operations") - div24Latency = Param.Cycles(1, "Latency for 24-bit Divide Operations") - div24RepeatRate = Param.Cycles(1, "Repeat Rate for 24-bit Divide Operations") - div32Latency = Param.Cycles(1, "Latency for 32-bit Divide Operations") - div32RepeatRate = Param.Cycles(1, "Repeat Rate for 32-bit Divide Operations") - - branchPred = Param.BranchPredictor(TournamentBP(numThreads = - Parent.numThreads), - "Branch Predictor") diff --git a/src/cpu/inorder/InOrderTrace.py b/src/cpu/inorder/InOrderTrace.py deleted file mode 100644 index fd4e00ed1..000000000 --- a/src/cpu/inorder/InOrderTrace.py +++ /dev/null @@ -1,36 +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 - -from m5.SimObject import SimObject -from m5.params import * -from InstTracer import InstTracer - -class InOrderTrace(InstTracer): - type = 'InOrderTrace' - cxx_class = 'Trace::InOrderTrace' - cxx_header = "cpu/inorder/inorder_trace.hh" diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript deleted file mode 100644 index c5406444c..000000000 --- a/src/cpu/inorder/SConscript +++ /dev/null @@ -1,89 +0,0 @@ -# -*- mode:python -*- - -# 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 - -Import('*') - -if 'InOrderCPU' in env['CPU_MODELS']: - SimObject('InOrderCPU.py') - SimObject('InOrderTrace.py') - - DebugFlag('ResReqCount') - DebugFlag('InOrderStage') - DebugFlag('InOrderStall') - DebugFlag('InOrderCPU') - DebugFlag('RegDepMap') - DebugFlag('InOrderDynInst') - DebugFlag('Resource') - DebugFlag('InOrderAGEN') - DebugFlag('InOrderFetchSeq') - DebugFlag('InOrderTLB') - DebugFlag('InOrderCachePort') - DebugFlag('InOrderBPred') - DebugFlag('InOrderDecode') - DebugFlag('InOrderExecute') - DebugFlag('InOrderInstBuffer') - DebugFlag('InOrderUseDef') - DebugFlag('InOrderMDU') - DebugFlag('InOrderGraduation') - DebugFlag('ThreadModel') - DebugFlag('RefCount') - DebugFlag('AddrDep') - DebugFlag('SkedCache') - - CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU', - 'InOrderMDU', 'InOrderAGEN', 'InOrderFetchSeq', 'InOrderTLB', 'InOrderBPred', - 'InOrderDecode', 'InOrderExecute', 'InOrderInstBuffer', 'InOrderUseDef', - 'InOrderGraduation', 'InOrderCachePort', 'RegDepMap', 'Resource', - 'InOrderStall','ThreadModel', 'AddrDep']) - - Source('inorder_dyn_inst.cc') - Source('inorder_cpu_builder.cc') - Source('inorder_trace.cc') - Source('pipeline_stage.cc') - Source('first_stage.cc') - Source('resource.cc') - Source('resources/agen_unit.cc') - Source('resources/execution_unit.cc') - Source('resources/branch_predictor.cc') - Source('resources/cache_unit.cc') - Source('resources/fetch_unit.cc') - Source('resources/use_def.cc') - Source('resources/decode_unit.cc') - Source('resources/inst_buffer.cc') - Source('resources/graduation_unit.cc') - Source('resources/fetch_seq_unit.cc') - Source('resources/mult_div_unit.cc') - Source('resource_pool.cc') - Source('resource_sked.cc') - Source('reg_dep_map.cc') - Source('thread_state.cc') - Source('thread_context.cc') - Source('cpu.cc') - diff --git a/src/cpu/inorder/SConsopts b/src/cpu/inorder/SConsopts deleted file mode 100644 index f6b8917c6..000000000 --- a/src/cpu/inorder/SConsopts +++ /dev/null @@ -1,33 +0,0 @@ -# -*- mode:python -*- - -# 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 - -Import('*') - -CpuModel('InOrderCPU', default=True) diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh deleted file mode 100644 index c2c97cd83..000000000 --- a/src/cpu/inorder/comm.hh +++ /dev/null @@ -1,85 +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_COMM_HH__ -#define __CPU_INORDER_COMM_HH__ - -#include <vector> - -#include "arch/isa_traits.hh" -#include "base/types.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inst_seq.hh" - -/** Struct that defines the information passed from in between stages */ -/** This information mainly goes forward through the pipeline. */ -struct InterStageStruct { - //@todo: probably should make this a list since the amount of - // instructions that get passed forward per cycle is - // really dependent on issue width, CPI, etc. - std::vector<ThePipeline::DynInstPtr> insts; - - // Add any information that needs to be passed forward to stages - // below ... -}; - -/** Struct that defines all backwards communication. */ -struct TimeStruct { - struct StageComm { - bool squash; - InstSeqNum doneSeqNum; - - bool uncached; - ThePipeline::DynInstPtr uncachedLoad; - - StageComm() - : squash(false), doneSeqNum(0), uncached(false), uncachedLoad(NULL) - { } - }; - - StageComm stageInfo[ThePipeline::NumStages][ThePipeline::MaxThreads]; - bool stageBlock[ThePipeline::NumStages][ThePipeline::MaxThreads]; - bool stageUnblock[ThePipeline::NumStages][ThePipeline::MaxThreads]; - - TimeStruct() - { - for (int i = 0; i < ThePipeline::NumStages; i++) { - for (int j = 0; j < ThePipeline::MaxThreads; j++) { - stageBlock[i][j] = false; - stageUnblock[i][j] = false; - } - } - } - -}; - -#endif //__CPU_INORDER_COMM_HH__ diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc deleted file mode 100644 index 86a44ab38..000000000 --- a/src/cpu/inorder/cpu.cc +++ /dev/null @@ -1,1922 +0,0 @@ -/* - * Copyright (c) 2012 ARM Limited - * Copyright (c) 2013 Advanced Micro Devices, Inc. - * 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 <algorithm> - -#include "arch/utility.hh" -#include "base/bigint.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/resources/cache_unit.hh" -#include "cpu/inorder/resources/resource_list.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource_pool.hh" -#include "cpu/inorder/thread_context.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/activity.hh" -#include "cpu/base.hh" -#include "cpu/exetrace.hh" -#include "cpu/quiesce_event.hh" -#include "cpu/reg_class.hh" -#include "cpu/simple_thread.hh" -#include "cpu/thread_context.hh" -#include "debug/Activity.hh" -#include "debug/Drain.hh" -#include "debug/InOrderCPU.hh" -#include "debug/InOrderCachePort.hh" -#include "debug/Interrupt.hh" -#include "debug/Quiesce.hh" -#include "debug/RefCount.hh" -#include "debug/SkedCache.hh" -#include "params/InOrderCPU.hh" -#include "sim/full_system.hh" -#include "sim/process.hh" -#include "sim/stat_control.hh" -#include "sim/system.hh" - -#if THE_ISA == ALPHA_ISA -#include "arch/alpha/osfpal.hh" -#endif - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit, - const std::string& name) : - MasterPort(_cacheUnit->name() + name, _cacheUnit->cpu), - cacheUnit(_cacheUnit) -{ } - -bool -InOrderCPU::CachePort::recvTimingResp(Packet *pkt) -{ - if (pkt->isError()) - DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", - pkt->getAddr()); - else - cacheUnit->processCacheCompletion(pkt); - - return true; -} - -void -InOrderCPU::CachePort::recvRetry() -{ - cacheUnit->recvRetry(); -} - -InOrderCPU::TickEvent::TickEvent(InOrderCPU *c) - : Event(CPU_Tick_Pri), cpu(c) -{ } - - -void -InOrderCPU::TickEvent::process() -{ - cpu->tick(); -} - - -const char * -InOrderCPU::TickEvent::description() const -{ - return "InOrderCPU tick event"; -} - -InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, - const Fault &fault, ThreadID _tid, - DynInstPtr inst, CPUEventPri event_pri) - : Event(event_pri), cpu(_cpu) -{ - setEvent(e_type, fault, _tid, inst); -} - - -std::string InOrderCPU::eventNames[NumCPUEvents] = -{ - "ActivateThread", - "ActivateNextReadyThread", - "DeactivateThread", - "HaltThread", - "SuspendThread", - "Trap", - "Syscall", - "SquashFromMemStall", - "UpdatePCs" -}; - -void -InOrderCPU::CPUEvent::process() -{ - switch (cpuEventType) - { - case ActivateThread: - cpu->activateThread(tid); - cpu->resPool->activateThread(tid); - break; - - case ActivateNextReadyThread: - cpu->activateNextReadyThread(); - break; - - case DeactivateThread: - cpu->deactivateThread(tid); - cpu->resPool->deactivateThread(tid); - break; - - case HaltThread: - cpu->haltThread(tid); - cpu->resPool->deactivateThread(tid); - break; - - case SuspendThread: - cpu->suspendThread(tid); - cpu->resPool->suspendThread(tid); - break; - - case SquashFromMemStall: - cpu->squashDueToMemStall(inst->squashingStage, inst->seqNum, tid); - cpu->resPool->squashDueToMemStall(inst, inst->squashingStage, - inst->seqNum, tid); - break; - - case Trap: - DPRINTF(InOrderCPU, "Trapping CPU\n"); - cpu->trap(fault, tid, inst); - cpu->resPool->trap(fault, tid, inst); - cpu->trapPending[tid] = false; - break; - - case Syscall: - cpu->syscall(inst->syscallNum, tid); - cpu->resPool->trap(fault, tid, inst); - break; - - default: - fatal("Unrecognized Event Type %s", eventNames[cpuEventType]); - } - - cpu->cpuEventRemoveList.push(this); -} - - - -const char * -InOrderCPU::CPUEvent::description() const -{ - return "InOrderCPU event"; -} - -void -InOrderCPU::CPUEvent::scheduleEvent(Cycles delay) -{ - assert(!scheduled() || squashed()); - cpu->reschedule(this, cpu->clockEdge(delay), true); -} - -void -InOrderCPU::CPUEvent::unscheduleEvent() -{ - if (scheduled()) - squash(); -} - -InOrderCPU::InOrderCPU(Params *params) - : BaseCPU(params), - cpu_id(params->cpu_id), - coreType("default"), - _status(Idle), - tickEvent(this), - stageWidth(params->stageWidth), - resPool(new ResourcePool(this, params)), - isa(numThreads, NULL), - timeBuffer(2 , 2), - dataPort(resPool->getDataUnit(), ".dcache_port"), - instPort(resPool->getInstUnit(), ".icache_port"), - removeInstsThisCycle(false), - activityRec(params->name, NumStages, 10, params->activity), - system(params->system), -#ifdef DEBUG - cpuEventNum(0), - resReqCount(0), -#endif // DEBUG - drainCount(0), - stageTracing(params->stageTracing), - lastRunningCycle(0), - instsPerSwitch(0) -{ - cpu_params = params; - - // Resize for Multithreading CPUs - thread.resize(numThreads); - - ThreadID active_threads = params->workload.size(); - if (FullSystem) { - active_threads = 1; - } else { - active_threads = params->workload.size(); - - if (active_threads > MaxThreads) { - panic("Workload Size too large. Increase the 'MaxThreads'" - "in your InOrder implementation or " - "edit your workload size."); - } - - - if (active_threads > 1) { - threadModel = (InOrderCPU::ThreadModel) params->threadModel; - - if (threadModel == SMT) { - DPRINTF(InOrderCPU, "Setting Thread Model to SMT.\n"); - } else if (threadModel == SwitchOnCacheMiss) { - DPRINTF(InOrderCPU, "Setting Thread Model to " - "Switch On Cache Miss\n"); - } - - } else { - threadModel = Single; - } - } - - for (ThreadID tid = 0; tid < numThreads; ++tid) { - isa[tid] = params->isa[tid]; - pc[tid].set(0); - lastCommittedPC[tid].set(0); - - if (FullSystem) { - // SMT is not supported in FS mode yet. - assert(numThreads == 1); - thread[tid] = new Thread(this, 0, NULL); - } else { - if (tid < (ThreadID)params->workload.size()) { - DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", - tid, params->workload[tid]->progName()); - thread[tid] = - new Thread(this, tid, params->workload[tid]); - } else { - //Allocate Empty thread so M5 can use later - //when scheduling threads to CPU - Process* dummy_proc = params->workload[0]; - thread[tid] = new Thread(this, tid, dummy_proc); - } - - // Eventually set this with parameters... - asid[tid] = tid; - } - - // Setup the TC that will serve as the interface to the threads/CPU. - InOrderThreadContext *tc = new InOrderThreadContext; - tc->cpu = this; - tc->thread = thread[tid]; - - // Setup quiesce event. - this->thread[tid]->quiesceEvent = new EndQuiesceEvent(tc); - - // Give the thread the TC. - thread[tid]->tc = tc; - thread[tid]->setFuncExeInst(0); - globalSeqNum[tid] = 1; - - // Add the TC to the CPU's list of TC's. - this->threadContexts.push_back(tc); - } - - // Initialize TimeBuffer Stage Queues - for (int stNum=0; stNum < NumStages - 1; stNum++) { - stageQueue[stNum] = new StageQueue(NumStages, NumStages); - stageQueue[stNum]->id(stNum); - } - - - // Set Up Pipeline Stages - for (int stNum=0; stNum < NumStages; stNum++) { - if (stNum == 0) - pipelineStage[stNum] = new FirstStage(params, stNum); - else - pipelineStage[stNum] = new PipelineStage(params, stNum); - - pipelineStage[stNum]->setCPU(this); - pipelineStage[stNum]->setActiveThreads(&activeThreads); - pipelineStage[stNum]->setTimeBuffer(&timeBuffer); - - // Take Care of 1st/Nth stages - if (stNum > 0) - pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]); - if (stNum < NumStages - 1) - pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum]); - } - - // Initialize thread specific variables - for (ThreadID tid = 0; tid < numThreads; tid++) { - archRegDepMap[tid].setCPU(this); - - nonSpecInstActive[tid] = false; - nonSpecSeqNum[tid] = 0; - - squashSeqNum[tid] = MaxAddr; - lastSquashCycle[tid] = 0; - - memset(intRegs[tid], 0, sizeof(intRegs[tid])); - memset(floatRegs.i[tid], 0, sizeof(floatRegs.i[tid])); -#ifdef ISA_HAS_CC_REGS - memset(ccRegs[tid], 0, sizeof(ccRegs[tid])); -#endif - isa[tid]->clear(); - - // Define dummy instructions and resource requests to be used. - dummyInst[tid] = new InOrderDynInst(this, - thread[tid], - 0, - tid, - asid[tid]); - - dummyReq[tid] = new ResourceRequest(resPool->getResource(0)); - - - if (FullSystem) { - // Use this dummy inst to force squashing behind every instruction - // in pipeline - dummyTrapInst[tid] = new InOrderDynInst(this, NULL, 0, 0, 0); - dummyTrapInst[tid]->seqNum = 0; - dummyTrapInst[tid]->squashSeqNum = 0; - dummyTrapInst[tid]->setTid(tid); - } - - trapPending[tid] = false; - - } - - // InOrderCPU always requires an interrupt controller. - if (!params->switched_out && !interrupts) { - fatal("InOrderCPU %s has no interrupt controller.\n" - "Ensure createInterruptController() is called.\n", name()); - } - - dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0); - dummyReqInst->setSquashed(); - dummyReqInst->resetInstCount(); - - dummyBufferInst = new InOrderDynInst(this, NULL, 0, 0, 0); - dummyBufferInst->setSquashed(); - dummyBufferInst->resetInstCount(); - - endOfSkedIt = skedCache.end(); - frontEndSked = createFrontEndSked(); - faultSked = createFaultSked(); - - lastRunningCycle = curCycle(); - - lockAddr = 0; - lockFlag = false; - - // Schedule First Tick Event, CPU will reschedule itself from here on out. - scheduleTickEvent(Cycles(0)); -} - -InOrderCPU::~InOrderCPU() -{ - delete resPool; - - SkedCacheIt sked_it = skedCache.begin(); - SkedCacheIt sked_end = skedCache.end(); - - while (sked_it != sked_end) { - delete (*sked_it).second; - sked_it++; - } - skedCache.clear(); -} - -m5::hash_map<InOrderCPU::SkedID, ThePipeline::RSkedPtr> InOrderCPU::skedCache; - -RSkedPtr -InOrderCPU::createFrontEndSked() -{ - RSkedPtr res_sked = new ResourceSked(); - int stage_num = 0; - StageScheduler F(res_sked, stage_num++); - StageScheduler D(res_sked, stage_num++); - - // FETCH - F.needs(FetchSeq, FetchSeqUnit::AssignNextPC); - F.needs(ICache, FetchUnit::InitiateFetch); - - // DECODE - D.needs(ICache, FetchUnit::CompleteFetch); - D.needs(Decode, DecodeUnit::DecodeInst); - D.needs(BPred, BranchPredictor::PredictBranch); - D.needs(FetchSeq, FetchSeqUnit::UpdateTargetPC); - - - DPRINTF(SkedCache, "Resource Sked created for instruction Front End\n"); - - return res_sked; -} - -RSkedPtr -InOrderCPU::createFaultSked() -{ - RSkedPtr res_sked = new ResourceSked(); - StageScheduler W(res_sked, NumStages - 1); - W.needs(Grad, GraduationUnit::CheckFault); - DPRINTF(SkedCache, "Resource Sked created for instruction Faults\n"); - return res_sked; -} - -RSkedPtr -InOrderCPU::createBackEndSked(DynInstPtr inst) -{ - RSkedPtr res_sked = lookupSked(inst); - if (res_sked != NULL) { - DPRINTF(SkedCache, "Found %s in sked cache.\n", - inst->instName()); - return res_sked; - } else { - res_sked = new ResourceSked(); - } - - int stage_num = ThePipeline::BackEndStartStage; - StageScheduler X(res_sked, stage_num++); - StageScheduler M(res_sked, stage_num++); - StageScheduler W(res_sked, stage_num++); - - if (!inst->staticInst) { - warn_once("Static Instruction Object Not Set. Can't Create" - " Back End Schedule"); - return NULL; - } - - // EXECUTE - X.needs(RegManager, UseDefUnit::MarkDestRegs); - for (int idx=0; idx < inst->numSrcRegs(); idx++) { - if (!idx || !inst->isStore()) { - X.needs(RegManager, UseDefUnit::ReadSrcReg, idx); - } - } - - //@todo: schedule non-spec insts to operate on this cycle - // as long as all previous insts are done - if ( inst->isNonSpeculative() ) { - // skip execution of non speculative insts until later - } else if ( inst->isMemRef() ) { - if ( inst->isLoad() ) { - X.needs(AGEN, AGENUnit::GenerateAddr); - } - } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { - X.needs(MDU, MultDivUnit::StartMultDiv); - } else { - X.needs(ExecUnit, ExecutionUnit::ExecuteInst); - } - - // MEMORY - if (!inst->isNonSpeculative()) { - if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { - M.needs(MDU, MultDivUnit::EndMultDiv); - } - - if ( inst->isLoad() ) { - M.needs(DCache, CacheUnit::InitiateReadData); - if (inst->splitInst) - M.needs(DCache, CacheUnit::InitSecondSplitRead); - } else if ( inst->isStore() ) { - for (int i = 1; i < inst->numSrcRegs(); i++ ) { - M.needs(RegManager, UseDefUnit::ReadSrcReg, i); - } - M.needs(AGEN, AGENUnit::GenerateAddr); - M.needs(DCache, CacheUnit::InitiateWriteData); - if (inst->splitInst) - M.needs(DCache, CacheUnit::InitSecondSplitWrite); - } - } - - // WRITEBACK - if (!inst->isNonSpeculative()) { - if ( inst->isLoad() ) { - W.needs(DCache, CacheUnit::CompleteReadData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::CompleteSecondSplitRead); - } else if ( inst->isStore() ) { - W.needs(DCache, CacheUnit::CompleteWriteData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::CompleteSecondSplitWrite); - } - } else { - // Finally, Execute Speculative Data - if (inst->isMemRef()) { - if (inst->isLoad()) { - W.needs(AGEN, AGENUnit::GenerateAddr); - W.needs(DCache, CacheUnit::InitiateReadData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::InitSecondSplitRead); - W.needs(DCache, CacheUnit::CompleteReadData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::CompleteSecondSplitRead); - } else if (inst->isStore()) { - if ( inst->numSrcRegs() >= 2 ) { - W.needs(RegManager, UseDefUnit::ReadSrcReg, 1); - } - W.needs(AGEN, AGENUnit::GenerateAddr); - W.needs(DCache, CacheUnit::InitiateWriteData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::InitSecondSplitWrite); - W.needs(DCache, CacheUnit::CompleteWriteData); - if (inst->splitInst) - W.needs(DCache, CacheUnit::CompleteSecondSplitWrite); - } - } else { - W.needs(ExecUnit, ExecutionUnit::ExecuteInst); - } - } - - W.needs(Grad, GraduationUnit::CheckFault); - - for (int idx=0; idx < inst->numDestRegs(); idx++) { - W.needs(RegManager, UseDefUnit::WriteDestReg, idx); - } - - if (inst->isControl()) - W.needs(BPred, BranchPredictor::UpdatePredictor); - - W.needs(Grad, GraduationUnit::GraduateInst); - - // Insert Back Schedule into our cache of - // resource schedules - addToSkedCache(inst, res_sked); - - DPRINTF(SkedCache, "Back End Sked Created for instruction: %s (%08p)\n", - inst->instName(), inst->getMachInst()); - res_sked->print(); - - return res_sked; -} - -void -InOrderCPU::regStats() -{ - /* Register the Resource Pool's stats here.*/ - resPool->regStats(); - - /* Register for each Pipeline Stage */ - for (int stage_num=0; stage_num < ThePipeline::NumStages; stage_num++) { - pipelineStage[stage_num]->regStats(); - } - - /* Register any of the InOrderCPU's stats here.*/ - instsPerCtxtSwitch - .name(name() + ".instsPerContextSwitch") - .desc("Instructions Committed Per Context Switch") - .prereq(instsPerCtxtSwitch); - - numCtxtSwitches - .name(name() + ".contextSwitches") - .desc("Number of context switches"); - - comLoads - .name(name() + ".comLoads") - .desc("Number of Load instructions committed"); - - comStores - .name(name() + ".comStores") - .desc("Number of Store instructions committed"); - - comBranches - .name(name() + ".comBranches") - .desc("Number of Branches instructions committed"); - - comNops - .name(name() + ".comNops") - .desc("Number of Nop instructions committed"); - - comNonSpec - .name(name() + ".comNonSpec") - .desc("Number of Non-Speculative instructions committed"); - - comInts - .name(name() + ".comInts") - .desc("Number of Integer instructions committed"); - - comFloats - .name(name() + ".comFloats") - .desc("Number of Floating Point instructions committed"); - - timesIdled - .name(name() + ".timesIdled") - .desc("Number of times that the entire CPU went into an idle state and" - " unscheduled itself") - .prereq(timesIdled); - - idleCycles - .name(name() + ".idleCycles") - .desc("Number of cycles cpu's stages were not processed"); - - runCycles - .name(name() + ".runCycles") - .desc("Number of cycles cpu stages are processed."); - - activity - .name(name() + ".activity") - .desc("Percentage of cycles cpu is active") - .precision(6); - activity = (runCycles / numCycles) * 100; - - threadCycles - .init(numThreads) - .name(name() + ".threadCycles") - .desc("Total Number of Cycles A Thread Was Active in CPU (Per-Thread)"); - - smtCycles - .name(name() + ".smtCycles") - .desc("Total number of cycles that the CPU was in SMT-mode"); - - committedInsts - .init(numThreads) - .name(name() + ".committedInsts") - .desc("Number of Instructions committed (Per-Thread)"); - - committedOps - .init(numThreads) - .name(name() + ".committedOps") - .desc("Number of Ops committed (Per-Thread)"); - - smtCommittedInsts - .init(numThreads) - .name(name() + ".smtCommittedInsts") - .desc("Number of SMT Instructions committed (Per-Thread)"); - - totalCommittedInsts - .name(name() + ".committedInsts_total") - .desc("Number of Instructions committed (Total)"); - - cpi - .name(name() + ".cpi") - .desc("CPI: Cycles Per Instruction (Per-Thread)") - .precision(6); - cpi = numCycles / committedInsts; - - smtCpi - .name(name() + ".smt_cpi") - .desc("CPI: Total SMT-CPI") - .precision(6); - smtCpi = smtCycles / smtCommittedInsts; - - totalCpi - .name(name() + ".cpi_total") - .desc("CPI: Total CPI of All Threads") - .precision(6); - totalCpi = numCycles / totalCommittedInsts; - - ipc - .name(name() + ".ipc") - .desc("IPC: Instructions Per Cycle (Per-Thread)") - .precision(6); - ipc = committedInsts / numCycles; - - smtIpc - .name(name() + ".smt_ipc") - .desc("IPC: Total SMT-IPC") - .precision(6); - smtIpc = smtCommittedInsts / smtCycles; - - totalIpc - .name(name() + ".ipc_total") - .desc("IPC: Total IPC of All Threads") - .precision(6); - totalIpc = totalCommittedInsts / numCycles; - - BaseCPU::regStats(); -} - - -void -InOrderCPU::tick() -{ - DPRINTF(InOrderCPU, "\n\nInOrderCPU: Ticking main, InOrderCPU.\n"); - - ++numCycles; - - checkForInterrupts(); - - bool pipes_idle = true; - //Tick each of the stages - for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { - pipelineStage[stNum]->tick(); - - pipes_idle = pipes_idle && pipelineStage[stNum]->idle; - } - - if (pipes_idle) - idleCycles++; - else - runCycles++; - - // Now advance the time buffers one tick - timeBuffer.advance(); - for (int sqNum=0; sqNum < NumStages - 1; sqNum++) { - stageQueue[sqNum]->advance(); - } - activityRec.advance(); - - // Any squashed events, or insts then remove them now - cleanUpRemovedEvents(); - cleanUpRemovedInsts(); - - // Re-schedule CPU for this cycle - if (!tickEvent.scheduled()) { - if (_status == SwitchedOut) { - // increment stat - lastRunningCycle = curCycle(); - } else if (!activityRec.active()) { - DPRINTF(InOrderCPU, "sleeping CPU.\n"); - lastRunningCycle = curCycle(); - timesIdled++; - } else { - //Tick next_tick = curTick() + cycles(1); - //tickEvent.schedule(next_tick); - schedule(&tickEvent, clockEdge(Cycles(1))); - DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", - clockEdge(Cycles(1))); - } - } - - tickThreadStats(); - updateThreadPriority(); -} - - -void -InOrderCPU::init() -{ - BaseCPU::init(); - - for (ThreadID tid = 0; tid < numThreads; ++tid) { - // Set noSquashFromTC so that the CPU doesn't squash when initially - // setting up registers. - thread[tid]->noSquashFromTC = true; - // Initialise the ThreadContext's memory proxies - thread[tid]->initMemProxies(thread[tid]->getTC()); - } - - if (FullSystem && !params()->switched_out) { - for (ThreadID tid = 0; tid < numThreads; tid++) { - ThreadContext *src_tc = threadContexts[tid]; - TheISA::initCPU(src_tc, src_tc->contextId()); - } - } - - // Clear noSquashFromTC. - for (ThreadID tid = 0; tid < numThreads; ++tid) - thread[tid]->noSquashFromTC = false; - - // Call Initializiation Routine for Resource Pool - resPool->init(); -} - -void -InOrderCPU::verifyMemoryMode() const -{ - if (!system->isTimingMode()) { - fatal("The in-order CPU requires the memory system to be in " - "'timing' mode.\n"); - } -} - -Fault -InOrderCPU::hwrei(ThreadID tid) -{ -#if THE_ISA == ALPHA_ISA - // Need to clear the lock flag upon returning from an interrupt. - setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); - - thread[tid]->kernelStats->hwrei(); - // FIXME: XXX check for interrupts? XXX -#endif - - return NoFault; -} - - -bool -InOrderCPU::simPalCheck(int palFunc, ThreadID tid) -{ -#if THE_ISA == ALPHA_ISA - if (this->thread[tid]->kernelStats) - this->thread[tid]->kernelStats->callpal(palFunc, - this->threadContexts[tid]); - - switch (palFunc) { - case PAL::halt: - halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (this->system->breakpoint()) - return false; - break; - } -#endif - return true; -} - -void -InOrderCPU::checkForInterrupts() -{ - for (int i = 0; i < threadContexts.size(); i++) { - ThreadContext *tc = threadContexts[i]; - - if (interrupts->checkInterrupts(tc)) { - Fault interrupt = interrupts->getInterrupt(tc); - - if (interrupt != NoFault) { - DPRINTF(Interrupt, "Processing Intterupt for [tid:%i].\n", - tc->threadId()); - - ThreadID tid = tc->threadId(); - interrupts->updateIntrInfo(tc); - - // Squash from Last Stage in Pipeline - unsigned last_stage = NumStages - 1; - dummyTrapInst[tid]->squashingStage = last_stage; - pipelineStage[last_stage]->setupSquash(dummyTrapInst[tid], - tid); - - // By default, setupSquash will always squash from stage + 1 - pipelineStage[BackEndStartStage - 1]->setupSquash(dummyTrapInst[tid], - tid); - - // Schedule Squash Through-out Resource Pool - resPool->scheduleEvent( - (InOrderCPU::CPUEventType)ResourcePool::SquashAll, - dummyTrapInst[tid], Cycles(0)); - - // Finally, Setup Trap to happen at end of cycle - trapContext(interrupt, tid, dummyTrapInst[tid]); - } - } - } -} - -Fault -InOrderCPU::getInterrupts() -{ - // Check if there are any outstanding interrupts - return interrupts->getInterrupt(threadContexts[0]); -} - -void -InOrderCPU::processInterrupts(const Fault &interrupt) -{ - // Check for interrupts here. For now can copy the code that - // exists within isa_fullsys_traits.hh. Also assume that thread 0 - // is the one that handles the interrupts. - // @todo: Possibly consolidate the interrupt checking code. - // @todo: Allow other threads to handle interrupts. - - assert(interrupt != NoFault); - interrupts->updateIntrInfo(threadContexts[0]); - - DPRINTF(InOrderCPU, "Interrupt %s being handled\n", interrupt->name()); - - // Note: Context ID ok here? Impl. of FS mode needs to revisit this - trap(interrupt, threadContexts[0]->contextId(), dummyBufferInst); -} - -void -InOrderCPU::trapContext(const Fault &fault, ThreadID tid, DynInstPtr inst, - Cycles delay) -{ - scheduleCpuEvent(Trap, fault, tid, inst, delay); - trapPending[tid] = true; -} - -void -InOrderCPU::trap(const Fault &fault, ThreadID tid, DynInstPtr inst) -{ - fault->invoke(tcBase(tid), inst->staticInst); - removePipelineStalls(tid); -} - -void -InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, - Cycles delay) -{ - scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay); -} - - -void -InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num, - ThreadID tid) -{ - DPRINTF(InOrderCPU, "Squashing Pipeline Stages Due to Memory Stall...\n"); - - // Squash all instructions in each stage including - // instruction that caused the squash (seq_num - 1) - // NOTE: The stage bandwidth needs to be cleared so thats why - // the stalling instruction is squashed as well. The stalled - // instruction is previously placed in another intermediate buffer - // while it's stall is being handled. - InstSeqNum squash_seq_num = seq_num - 1; - - for (int stNum=stage_num; stNum >= 0 ; stNum--) { - pipelineStage[stNum]->squashDueToMemStall(squash_seq_num, tid); - } -} - -void -InOrderCPU::scheduleCpuEvent(CPUEventType c_event, const Fault &fault, - ThreadID tid, DynInstPtr inst, - Cycles delay, CPUEventPri event_pri) -{ - CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, inst, - event_pri); - - Tick sked_tick = clockEdge(delay); - DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n", - eventNames[c_event], curTick() + delay, tid); - schedule(cpu_event, sked_tick); - - // Broadcast event to the Resource Pool - // Need to reset tid just in case this is a dummy instruction - inst->setTid(tid); - // @todo: Is this really right? Should the delay not be passed on? - resPool->scheduleEvent(c_event, inst, Cycles(0), 0, tid); -} - -bool -InOrderCPU::isThreadActive(ThreadID tid) -{ - list<ThreadID>::iterator isActive = - std::find(activeThreads.begin(), activeThreads.end(), tid); - - return (isActive != activeThreads.end()); -} - -bool -InOrderCPU::isThreadReady(ThreadID tid) -{ - list<ThreadID>::iterator isReady = - std::find(readyThreads.begin(), readyThreads.end(), tid); - - return (isReady != readyThreads.end()); -} - -bool -InOrderCPU::isThreadSuspended(ThreadID tid) -{ - list<ThreadID>::iterator isSuspended = - std::find(suspendedThreads.begin(), suspendedThreads.end(), tid); - - return (isSuspended != suspendedThreads.end()); -} - -void -InOrderCPU::activateNextReadyThread() -{ - if (readyThreads.size() >= 1) { - ThreadID ready_tid = readyThreads.front(); - - // Activate in Pipeline - activateThread(ready_tid); - - // Activate in Resource Pool - resPool->activateThread(ready_tid); - - list<ThreadID>::iterator ready_it = - std::find(readyThreads.begin(), readyThreads.end(), ready_tid); - readyThreads.erase(ready_it); - } else { - DPRINTF(InOrderCPU, - "Attempting to activate new thread, but No Ready Threads to" - "activate.\n"); - DPRINTF(InOrderCPU, - "Unable to switch to next active thread.\n"); - } -} - -void -InOrderCPU::activateThread(ThreadID tid) -{ - if (isThreadSuspended(tid)) { - DPRINTF(InOrderCPU, - "Removing [tid:%i] from suspended threads list.\n", tid); - - list<ThreadID>::iterator susp_it = - std::find(suspendedThreads.begin(), suspendedThreads.end(), - tid); - suspendedThreads.erase(susp_it); - } - - if (threadModel == SwitchOnCacheMiss && - numActiveThreads() == 1) { - DPRINTF(InOrderCPU, - "Ignoring activation of [tid:%i], since [tid:%i] is " - "already running.\n", tid, activeThreadId()); - - DPRINTF(InOrderCPU,"Placing [tid:%i] on ready threads list\n", - tid); - - readyThreads.push_back(tid); - - } else if (!isThreadActive(tid)) { - DPRINTF(InOrderCPU, - "Adding [tid:%i] to active threads list.\n", tid); - activeThreads.push_back(tid); - - activateThreadInPipeline(tid); - - thread[tid]->lastActivate = curTick(); - - tcBase(tid)->setStatus(ThreadContext::Active); - - wakeCPU(); - - numCtxtSwitches++; - } -} - -void -InOrderCPU::activateThreadInPipeline(ThreadID tid) -{ - for (int stNum=0; stNum < NumStages; stNum++) { - pipelineStage[stNum]->activateThread(tid); - } -} - -void -InOrderCPU::deactivateContext(ThreadID tid) -{ - DPRINTF(InOrderCPU,"[tid:%i]: Deactivating ...\n", tid); - - scheduleCpuEvent(DeactivateThread, NoFault, tid, dummyInst[tid]); - - // Be sure to signal that there's some activity so the CPU doesn't - // deschedule itself. - activityRec.activity(); - - _status = Running; -} - -void -InOrderCPU::deactivateThread(ThreadID tid) -{ - DPRINTF(InOrderCPU, "[tid:%i]: Calling deactivate thread.\n", tid); - - if (isThreadActive(tid)) { - DPRINTF(InOrderCPU,"[tid:%i]: Removing from active threads list\n", - tid); - list<ThreadID>::iterator thread_it = - std::find(activeThreads.begin(), activeThreads.end(), tid); - - removePipelineStalls(*thread_it); - - activeThreads.erase(thread_it); - - // Ideally, this should be triggered from the - // suspendContext/Thread functions - tcBase(tid)->setStatus(ThreadContext::Suspended); - } - - assert(!isThreadActive(tid)); -} - -void -InOrderCPU::removePipelineStalls(ThreadID tid) -{ - DPRINTF(InOrderCPU,"[tid:%i]: Removing all pipeline stalls\n", - tid); - - for (int stNum = 0; stNum < NumStages ; stNum++) { - pipelineStage[stNum]->removeStalls(tid); - } - -} - -void -InOrderCPU::updateThreadPriority() -{ - if (activeThreads.size() > 1) - { - //DEFAULT TO ROUND ROBIN SCHEME - //e.g. Move highest priority to end of thread list - list<ThreadID>::iterator list_begin = activeThreads.begin(); - - unsigned high_thread = *list_begin; - - activeThreads.erase(list_begin); - - activeThreads.push_back(high_thread); - } -} - -inline void -InOrderCPU::tickThreadStats() -{ - /** Keep track of cycles that each thread is active */ - list<ThreadID>::iterator thread_it = activeThreads.begin(); - while (thread_it != activeThreads.end()) { - threadCycles[*thread_it]++; - thread_it++; - } - - // Keep track of cycles where SMT is active - if (activeThreads.size() > 1) { - smtCycles++; - } -} - -void -InOrderCPU::activateContext(ThreadID tid) -{ - DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid); - - - scheduleCpuEvent(ActivateThread, NoFault, tid, dummyInst[tid]); - - // Be sure to signal that there's some activity so the CPU doesn't - // deschedule itself. - activityRec.activity(); - - _status = Running; -} - -void -InOrderCPU::activateNextReadyContext() -{ - DPRINTF(InOrderCPU,"Activating next ready thread\n"); - - scheduleCpuEvent(ActivateNextReadyThread, NoFault, 0/*tid*/, dummyInst[0], - Cycles(0), ActivateNextReadyThread_Pri); - - // Be sure to signal that there's some activity so the CPU doesn't - // deschedule itself. - activityRec.activity(); - - _status = Running; -} - -void -InOrderCPU::haltContext(ThreadID tid) -{ - DPRINTF(InOrderCPU, "[tid:%i]: Calling Halt Context...\n", tid); - - scheduleCpuEvent(HaltThread, NoFault, tid, dummyInst[tid]); - - activityRec.activity(); -} - -void -InOrderCPU::haltThread(ThreadID tid) -{ - DPRINTF(InOrderCPU, "[tid:%i]: Placing on Halted Threads List...\n", tid); - deactivateThread(tid); - squashThreadInPipeline(tid); - haltedThreads.push_back(tid); - - tcBase(tid)->setStatus(ThreadContext::Halted); - - if (threadModel == SwitchOnCacheMiss) { - activateNextReadyContext(); - } -} - -void -InOrderCPU::suspendContext(ThreadID tid) -{ - scheduleCpuEvent(SuspendThread, NoFault, tid, dummyInst[tid]); -} - -void -InOrderCPU::suspendThread(ThreadID tid) -{ - DPRINTF(InOrderCPU, "[tid:%i]: Placing on Suspended Threads List...\n", - tid); - deactivateThread(tid); - suspendedThreads.push_back(tid); - thread[tid]->lastSuspend = curTick(); - - tcBase(tid)->setStatus(ThreadContext::Suspended); -} - -void -InOrderCPU::squashThreadInPipeline(ThreadID tid) -{ - //Squash all instructions in each stage - for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { - pipelineStage[stNum]->squash(0 /*seq_num*/, tid); - } -} - -PipelineStage* -InOrderCPU::getPipeStage(int stage_num) -{ - return pipelineStage[stage_num]; -} - - -RegIndex -InOrderCPU::flattenRegIdx(RegIndex reg_idx, RegClass ®_type, ThreadID tid) -{ - RegIndex rel_idx; - - reg_type = regIdxToClass(reg_idx, &rel_idx); - - switch (reg_type) { - case IntRegClass: - return isa[tid]->flattenIntIndex(rel_idx); - - case FloatRegClass: - return isa[tid]->flattenFloatIndex(rel_idx); - - case MiscRegClass: - return rel_idx; - - default: - panic("register %d out of range\n", reg_idx); - } -} - -uint64_t -InOrderCPU::readIntReg(RegIndex reg_idx, ThreadID tid) -{ - DPRINTF(IntRegs, "[tid:%i]: Reading Int. Reg %i as %x\n", - tid, reg_idx, intRegs[tid][reg_idx]); - - return intRegs[tid][reg_idx]; -} - -FloatReg -InOrderCPU::readFloatReg(RegIndex reg_idx, ThreadID tid) -{ - DPRINTF(FloatRegs, "[tid:%i]: Reading Float Reg %i as %x, %08f\n", - tid, reg_idx, floatRegs.i[tid][reg_idx], floatRegs.f[tid][reg_idx]); - - return floatRegs.f[tid][reg_idx]; -} - -FloatRegBits -InOrderCPU::readFloatRegBits(RegIndex reg_idx, ThreadID tid) -{ - DPRINTF(FloatRegs, "[tid:%i]: Reading Float Reg %i as %x, %08f\n", - tid, reg_idx, floatRegs.i[tid][reg_idx], floatRegs.f[tid][reg_idx]); - - return floatRegs.i[tid][reg_idx]; -} - -CCReg -InOrderCPU::readCCReg(RegIndex reg_idx, ThreadID tid) -{ -#ifdef ISA_HAS_CC_REGS - DPRINTF(CCRegs, "[tid:%i]: Reading CC. Reg %i as %x\n", - tid, reg_idx, ccRegs[tid][reg_idx]); - - return ccRegs[tid][reg_idx]; -#else - panic("readCCReg: ISA does not have CC regs\n"); -#endif -} - -void -InOrderCPU::setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid) -{ - if (reg_idx == TheISA::ZeroReg) { - DPRINTF(IntRegs, "[tid:%i]: Ignoring Setting of ISA-ZeroReg " - "(Int. Reg %i) to %x\n", tid, reg_idx, val); - return; - } else { - DPRINTF(IntRegs, "[tid:%i]: Setting Int. Reg %i to %x\n", - tid, reg_idx, val); - - intRegs[tid][reg_idx] = val; - } -} - - -void -InOrderCPU::setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid) -{ - floatRegs.f[tid][reg_idx] = val; - DPRINTF(FloatRegs, "[tid:%i]: Setting Float. Reg %i bits to " - "%x, %08f\n", - tid, reg_idx, - floatRegs.i[tid][reg_idx], - floatRegs.f[tid][reg_idx]); -} - - -void -InOrderCPU::setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid) -{ - floatRegs.i[tid][reg_idx] = val; - DPRINTF(FloatRegs, "[tid:%i]: Setting Float. Reg %i bits to " - "%x, %08f\n", - tid, reg_idx, - floatRegs.i[tid][reg_idx], - floatRegs.f[tid][reg_idx]); -} - -void -InOrderCPU::setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid) -{ -#ifdef ISA_HAS_CC_REGS - DPRINTF(CCRegs, "[tid:%i]: Setting CC. Reg %i to %x\n", - tid, reg_idx, val); - ccRegs[tid][reg_idx] = val; -#else - panic("readCCReg: ISA does not have CC regs\n"); -#endif -} - -uint64_t -InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid) -{ - // If Default value is set, then retrieve target thread - if (tid == InvalidThreadID) { - tid = TheISA::getTargetThread(tcBase(tid)); - } - - RegIndex rel_idx; - - switch (regIdxToClass(reg_idx, &rel_idx)) { - case IntRegClass: - // Integer Register File - return readIntReg(rel_idx, tid); - - case FloatRegClass: - // Float Register File - return readFloatRegBits(rel_idx, tid); - - case MiscRegClass: - return readMiscReg(rel_idx, tid); // Misc. Register File - - default: - panic("register %d out of range\n", reg_idx); - } -} - -void -InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, - ThreadID tid) -{ - // If Default value is set, then retrieve target thread - if (tid == InvalidThreadID) { - tid = TheISA::getTargetThread(tcBase(tid)); - } - - RegIndex rel_idx; - - switch (regIdxToClass(reg_idx, &rel_idx)) { - case IntRegClass: - setIntReg(rel_idx, val, tid); - break; - - case FloatRegClass: - setFloatRegBits(rel_idx, val, tid); - break; - - case CCRegClass: - setCCReg(rel_idx, val, tid); - break; - - case MiscRegClass: - setMiscReg(rel_idx, val, tid); // Misc. Register File - break; - } -} - -MiscReg -InOrderCPU::readMiscRegNoEffect(int misc_reg, ThreadID tid) -{ - return isa[tid]->readMiscRegNoEffect(misc_reg); -} - -MiscReg -InOrderCPU::readMiscReg(int misc_reg, ThreadID tid) -{ - return isa[tid]->readMiscReg(misc_reg, tcBase(tid)); -} - -void -InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid) -{ - isa[tid]->setMiscRegNoEffect(misc_reg, val); -} - -void -InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid) -{ - isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); -} - - -InOrderCPU::ListIt -InOrderCPU::addInst(DynInstPtr inst) -{ - ThreadID tid = inst->readTid(); - - instList[tid].push_back(inst); - - return --(instList[tid].end()); -} - -InOrderCPU::ListIt -InOrderCPU::findInst(InstSeqNum seq_num, ThreadID tid) -{ - ListIt it = instList[tid].begin(); - ListIt end = instList[tid].end(); - - while (it != end) { - if ((*it)->seqNum == seq_num) - return it; - else if ((*it)->seqNum > seq_num) - break; - - it++; - } - - return instList[tid].end(); -} - -void -InOrderCPU::updateContextSwitchStats() -{ - // Set Average Stat Here, then reset to 0 - instsPerCtxtSwitch = instsPerSwitch; - instsPerSwitch = 0; -} - - -void -InOrderCPU::drainResume() -{ - setDrainState(Drainable::Running); - if (switchedOut()) - return; - - DPRINTF(Drain, "Resuming...\n"); - verifyMemoryMode(); - - assert(!tickEvent.scheduled()); - - // Activate threads and also signal the resource pool to activate - // the thread on all resources. - _status = Idle; - for (ThreadID i = 0; i < thread.size(); i++) { - if (thread[i]->status() == ThreadContext::Active) { - DPRINTF(Drain, "Activating thread: %i\n", i); - activateThread(i); - resPool->activateThread(i); - _status = Running; - } - } -} - -void -InOrderCPU::switchOut() -{ - DPRINTF(InOrderCPU, "Switching out\n"); - BaseCPU::switchOut(); - - activityRec.reset(); - - _status = SwitchedOut; -} - -void -InOrderCPU::takeOverFrom(BaseCPU *oldCPU) -{ - BaseCPU::takeOverFrom(oldCPU); - - // Call takeOverFrom() on each pipeline stage - for (int stNum=0; stNum < NumStages; stNum++) { - pipelineStage[stNum]->takeOverFrom(); - } - - assert(!tickEvent.scheduled()); - - // Copy over the current instruction sequence numbers if we are - // taking over from another InOrderCPU. - InOrderCPU *oldIOCPU = dynamic_cast<InOrderCPU*>(oldCPU); - if (oldIOCPU) { - for (ThreadID tid = 0; tid < numThreads; tid++) - globalSeqNum[tid] = oldIOCPU->globalSeqNum[tid]; - } - - lastRunningCycle = curCycle(); - _status = Idle; -} - - -void -InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) -{ - // Set the nextPC to be fetched if this is the last instruction - // committed - // ======== - // This contributes to the precise state of the CPU - // which can be used when restoring a thread to the CPU after after any - // type of context switching activity (fork, exception, etc.) - TheISA::PCState comm_pc = inst->pcState(); - lastCommittedPC[tid] = comm_pc; - TheISA::advancePC(comm_pc, inst->staticInst); - pcState(comm_pc, tid); - - //@todo: may be unnecessary with new-ISA-specific branch handling code - if (inst->isControl()) { - thread[tid]->lastGradIsBranch = true; - thread[tid]->lastBranchPC = inst->pcState(); - TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst); - } else { - thread[tid]->lastGradIsBranch = false; - } - - - // Finalize Trace Data For Instruction - if (inst->traceData) { - //inst->traceData->setCycle(curTick()); - inst->traceData->setFetchSeq(inst->seqNum); - //inst->traceData->setCPSeq(cpu->tcBase(tid)->numInst); - inst->traceData->dump(); - delete inst->traceData; - inst->traceData = NULL; - } - - // Increment active thread's instruction count - instsPerSwitch++; - - // Increment thread-state's instruction count - thread[tid]->numInst++; - thread[tid]->numOp++; - - // Increment thread-state's instruction stats - thread[tid]->numInsts++; - thread[tid]->numOps++; - - // Count committed insts per thread stats - if (!inst->isMicroop() || inst->isLastMicroop()) { - committedInsts[tid]++; - - // Count total insts committed stat - totalCommittedInsts++; - } - - committedOps[tid]++; - - // Count SMT-committed insts per thread stat - if (numActiveThreads() > 1) { - if (!inst->isMicroop() || inst->isLastMicroop()) - smtCommittedInsts[tid]++; - } - - // Instruction-Mix Stats - if (inst->isLoad()) { - comLoads++; - } else if (inst->isStore()) { - comStores++; - } else if (inst->isControl()) { - comBranches++; - } else if (inst->isNop()) { - comNops++; - } else if (inst->isNonSpeculative()) { - comNonSpec++; - } else if (inst->isInteger()) { - comInts++; - } else if (inst->isFloating()) { - comFloats++; - } - - // Check for instruction-count-based events. - comInstEventQueue[tid]->serviceEvents(thread[tid]->numOp); - - // Finally, remove instruction from CPU - removeInst(inst); -} - -// currently unused function, but substitute repetitive code w/this function -// call -void -InOrderCPU::addToRemoveList(DynInstPtr inst) -{ - removeInstsThisCycle = true; - if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " - "[sn:%lli] to remove list\n", - inst->threadNumber, inst->pcState(), inst->seqNum); - inst->setRemoveList(); - removeList.push(inst->getInstListIt()); - } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " - "[sn:%lli], already remove list\n", - inst->threadNumber, inst->pcState(), inst->seqNum); - } - -} - -void -InOrderCPU::removeInst(DynInstPtr inst) -{ - DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s " - "[sn:%lli]\n", - inst->threadNumber, inst->pcState(), inst->seqNum); - - removeInstsThisCycle = true; - - // Remove the instruction. - if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " - "[sn:%lli] to remove list\n", - inst->threadNumber, inst->pcState(), inst->seqNum); - inst->setRemoveList(); - removeList.push(inst->getInstListIt()); - } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " - "[sn:%lli], already on remove list\n", - inst->threadNumber, inst->pcState(), inst->seqNum); - } - -} - -void -InOrderCPU::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) -{ - //assert(!instList[tid].empty()); - - removeInstsThisCycle = true; - - ListIt inst_iter = instList[tid].end(); - - inst_iter--; - - DPRINTF(InOrderCPU, "Squashing instructions from CPU instruction " - "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", - tid, seq_num, (*inst_iter)->seqNum); - - while ((*inst_iter)->seqNum > seq_num) { - - bool break_loop = (inst_iter == instList[tid].begin()); - - squashInstIt(inst_iter, tid); - - inst_iter--; - - if (break_loop) - break; - } -} - - -inline void -InOrderCPU::squashInstIt(const ListIt inst_it, ThreadID tid) -{ - DynInstPtr inst = (*inst_it); - if (inst->threadNumber == tid) { - DPRINTF(InOrderCPU, "Squashing instruction, " - "[tid:%i] [sn:%lli] PC %s\n", - inst->threadNumber, - inst->seqNum, - inst->pcState()); - - inst->setSquashed(); - archRegDepMap[tid].remove(inst); - - if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " - "[sn:%lli] to remove list\n", - inst->threadNumber, inst->pcState(), - inst->seqNum); - inst->setRemoveList(); - removeList.push(inst_it); - } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]" - " PC %s [sn:%lli], already on remove list\n", - inst->threadNumber, inst->pcState(), - inst->seqNum); - } - - } - -} - - -void -InOrderCPU::cleanUpRemovedInsts() -{ - while (!removeList.empty()) { - DPRINTF(InOrderCPU, "Removing instruction, " - "[tid:%i] [sn:%lli] PC %s\n", - (*removeList.front())->threadNumber, - (*removeList.front())->seqNum, - (*removeList.front())->pcState()); - - DynInstPtr inst = *removeList.front(); - ThreadID tid = inst->threadNumber; - - // Remove From Register Dependency Map, If Necessary - // archRegDepMap[tid].remove(inst); - - // Clear if Non-Speculative - if (inst->staticInst && - inst->seqNum == nonSpecSeqNum[tid] && - nonSpecInstActive[tid]) { - nonSpecInstActive[tid] = false; - } - - inst->onInstList = false; - - instList[tid].erase(removeList.front()); - - removeList.pop(); - } - - removeInstsThisCycle = false; -} - -void -InOrderCPU::cleanUpRemovedEvents() -{ - while (!cpuEventRemoveList.empty()) { - Event *cpu_event = cpuEventRemoveList.front(); - cpuEventRemoveList.pop(); - delete cpu_event; - } -} - - -void -InOrderCPU::dumpInsts() -{ - int num = 0; - - ListIt inst_list_it = instList[0].begin(); - - cprintf("Dumping Instruction List\n"); - - while (inst_list_it != instList[0].end()) { - cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" - "Squashed:%i\n\n", - num, (*inst_list_it)->pcState(), - (*inst_list_it)->threadNumber, - (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - inst_list_it++; - ++num; - } -} - -void -InOrderCPU::wakeCPU() -{ - if (/*activityRec.active() || */tickEvent.scheduled()) { - DPRINTF(Activity, "CPU already running.\n"); - return; - } - - DPRINTF(Activity, "Waking up CPU\n"); - - Tick extra_cycles = curCycle() - lastRunningCycle; - if (extra_cycles != 0) - --extra_cycles; - - idleCycles += extra_cycles; - for (int stage_num = 0; stage_num < NumStages; stage_num++) { - pipelineStage[stage_num]->idleCycles += extra_cycles; - } - - numCycles += extra_cycles; - - schedule(&tickEvent, clockEdge()); -} - -// Lots of copied full system code...place into BaseCPU class? -void -InOrderCPU::wakeup() -{ - if (thread[0]->status() != ThreadContext::Suspended) - return; - - wakeCPU(); - - DPRINTF(Quiesce, "Suspended Processor woken\n"); - threadContexts[0]->activate(); -} - -void -InOrderCPU::syscallContext(const Fault &fault, ThreadID tid, DynInstPtr inst, - Cycles delay) -{ - // Syscall must be non-speculative, so squash from last stage - unsigned squash_stage = NumStages - 1; - inst->setSquashInfo(squash_stage); - - // Squash In Pipeline Stage - pipelineStage[squash_stage]->setupSquash(inst, tid); - - // Schedule Squash Through-out Resource Pool - resPool->scheduleEvent( - (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, - Cycles(0)); - scheduleCpuEvent(Syscall, fault, tid, inst, delay, Syscall_Pri); -} - -void -InOrderCPU::syscall(int64_t callnum, ThreadID tid) -{ - DPRINTF(InOrderCPU, "[tid:%i] Executing syscall().\n\n", tid); - - DPRINTF(Activity,"Activity: syscall() called.\n"); - - // Temporarily increase this by one to account for the syscall - // instruction. - ++(this->thread[tid]->funcExeInst); - - // Execute the actual syscall. - this->thread[tid]->syscall(callnum); - - // Decrease funcExeInst by one as the normal commit will handle - // incrementing it. - --(this->thread[tid]->funcExeInst); - - // Clear Non-Speculative Block Variable - nonSpecInstActive[tid] = false; -} - -TheISA::TLB* -InOrderCPU::getITBPtr() -{ - CacheUnit *itb_res = resPool->getInstUnit(); - return itb_res->tlb(); -} - - -TheISA::TLB* -InOrderCPU::getDTBPtr() -{ - return resPool->getDataUnit()->tlb(); -} - -TheISA::Decoder * -InOrderCPU::getDecoderPtr(unsigned tid) -{ - return resPool->getInstUnit()->decoder[tid]; -} - -Fault -InOrderCPU::read(DynInstPtr inst, Addr addr, - uint8_t *data, unsigned size, unsigned flags) -{ - return resPool->getDataUnit()->read(inst, addr, data, size, flags); -} - -Fault -InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *write_res) -{ - return resPool->getDataUnit()->write(inst, data, size, addr, flags, - write_res); -} diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh deleted file mode 100644 index b82aba779..000000000 --- a/src/cpu/inorder/cpu.hh +++ /dev/null @@ -1,942 +0,0 @@ -/* - * Copyright (c) 2012-2013 ARM Limited - * Copyright (c) 2013 Advanced Micro Devices, Inc. - * 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 - * - */ - -#ifndef __CPU_INORDER_CPU_HH__ -#define __CPU_INORDER_CPU_HH__ - -#include <iostream> -#include <list> -#include <queue> -#include <set> -#include <vector> - -#include "arch/isa_traits.hh" -#include "arch/registers.hh" -#include "arch/types.hh" -#include "base/statistics.hh" -#include "base/types.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_stage.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/reg_dep_map.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/o3/dep_graph.hh" -#include "cpu/o3/rename_map.hh" -#include "cpu/activity.hh" -#include "cpu/base.hh" -#include "cpu/reg_class.hh" -#include "cpu/simple_thread.hh" -#include "cpu/timebuf.hh" -#include "mem/packet.hh" -#include "mem/port.hh" -#include "mem/request.hh" -#include "sim/eventq.hh" -#include "sim/process.hh" - -class CacheUnit; -class ThreadContext; -class MemInterface; -class MemObject; -class Process; -class ResourcePool; - -class InOrderCPU : public BaseCPU -{ - - protected: - typedef ThePipeline::Params Params; - typedef InOrderThreadState Thread; - - //ISA TypeDefs - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - typedef TheISA::CCReg CCReg; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::RegIndex RegIndex; - - //DynInstPtr TypeDefs - typedef ThePipeline::DynInstPtr DynInstPtr; - typedef std::list<DynInstPtr>::iterator ListIt; - - //TimeBuffer TypeDefs - typedef TimeBuffer<InterStageStruct> StageQueue; - - friend class Resource; - - public: - /** Constructs a CPU with the given parameters. */ - InOrderCPU(Params *params); - /* Destructor */ - ~InOrderCPU(); - - void verifyMemoryMode() const; - - /** Return a reference to the data port. */ - virtual MasterPort &getDataPort() { return dataPort; } - - /** Return a reference to the instruction port. */ - virtual MasterPort &getInstPort() { return instPort; } - - /** CPU ID */ - int cpu_id; - - // SE Mode ASIDs - ThreadID asid[ThePipeline::MaxThreads]; - - /** Type of core that this is */ - std::string coreType; - - // Only need for SE MODE - enum ThreadModel { - Single, - SMT, - SwitchOnCacheMiss - }; - - ThreadModel threadModel; - - int readCpuId() { return cpu_id; } - - void setCpuId(int val) { cpu_id = val; } - - Params *cpu_params; - - public: - enum Status { - Running, - Idle, - Halted, - Blocked, - SwitchedOut - }; - - /** Overall CPU status. */ - Status _status; - private: - - /** - * CachePort class for the in-order CPU, interacting with a - * specific CacheUnit in the pipeline. - */ - class CachePort : public MasterPort - { - - private: - /** Pointer to cache unit */ - CacheUnit *cacheUnit; - - public: - /** Default constructor. */ - CachePort(CacheUnit *_cacheUnit, const std::string& name); - - protected: - - /** Timing version of receive */ - bool recvTimingResp(PacketPtr pkt); - - /** Handles doing a retry of a failed timing request. */ - void recvRetry(); - - /** Ignoring snoops for now. */ - void recvTimingSnoopReq(PacketPtr pkt) { } - }; - - /** Define TickEvent for the CPU */ - class TickEvent : public Event - { - private: - /** Pointer to the CPU. */ - InOrderCPU *cpu; - - public: - /** Constructs a tick event. */ - TickEvent(InOrderCPU *c); - - /** Processes a tick event, calling tick() on the CPU. */ - void process(); - - /** Returns the description of the tick event. */ - const char *description() const; - }; - - /** The tick event used for scheduling CPU ticks. */ - TickEvent tickEvent; - - /** Schedule tick event, regardless of its current state. */ - void scheduleTickEvent(Cycles delay) - { - assert(!tickEvent.scheduled() || tickEvent.squashed()); - reschedule(&tickEvent, clockEdge(delay), true); - } - - /** Unschedule tick event, regardless of its current state. */ - void unscheduleTickEvent() - { - if (tickEvent.scheduled()) - tickEvent.squash(); - } - - public: - // List of Events That can be scheduled from - // within the CPU. - // NOTE(1): The Resource Pool also uses this event list - // to schedule events broadcast to all resources interfaces - // NOTE(2): CPU Events usually need to schedule a corresponding resource - // pool event. - enum CPUEventType { - ActivateThread, - ActivateNextReadyThread, - DeactivateThread, - HaltThread, - SuspendThread, - Trap, - Syscall, - SquashFromMemStall, - UpdatePCs, - NumCPUEvents - }; - - static std::string eventNames[NumCPUEvents]; - - enum CPUEventPri { - InOrderCPU_Pri = Event::CPU_Tick_Pri, - Syscall_Pri = Event::CPU_Tick_Pri + 9, - ActivateNextReadyThread_Pri = Event::CPU_Tick_Pri + 10 - }; - - /** Define CPU Event */ - class CPUEvent : public Event - { - protected: - InOrderCPU *cpu; - - public: - CPUEventType cpuEventType; - ThreadID tid; - DynInstPtr inst; - Fault fault; - unsigned vpe; - short syscall_num; - - public: - /** Constructs a CPU event. */ - CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, const Fault &fault, - ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri); - - /** Set Type of Event To Be Scheduled */ - void setEvent(CPUEventType e_type, const Fault &_fault, ThreadID _tid, - DynInstPtr _inst) - { - fault = _fault; - cpuEventType = e_type; - tid = _tid; - inst = _inst; - vpe = 0; - } - - /** Processes a CPU event. */ - void process(); - - /** Returns the description of the CPU event. */ - const char *description() const; - - /** Schedule Event */ - void scheduleEvent(Cycles delay); - - /** Unschedule This Event */ - void unscheduleEvent(); - }; - - /** Schedule a CPU Event */ - void scheduleCpuEvent(CPUEventType cpu_event, const Fault &fault, - ThreadID tid, - DynInstPtr inst, Cycles delay = Cycles(0), - CPUEventPri event_pri = InOrderCPU_Pri); - - public: - - /** Width (processing bandwidth) of each stage */ - int stageWidth; - - /** Interface between the CPU and CPU resources. */ - ResourcePool *resPool; - - /** Instruction used to signify that there is no *real* instruction in - buffer slot */ - DynInstPtr dummyInst[ThePipeline::MaxThreads]; - DynInstPtr dummyBufferInst; - DynInstPtr dummyReqInst; - DynInstPtr dummyTrapInst[ThePipeline::MaxThreads]; - - /** Used by resources to signify a denied access to a resource. */ - ResourceRequest *dummyReq[ThePipeline::MaxThreads]; - - /** The Pipeline Stages for the CPU */ - PipelineStage *pipelineStage[ThePipeline::NumStages]; - - /** Program Counters */ - TheISA::PCState pc[ThePipeline::MaxThreads]; - - /** Last Committed PC */ - TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads]; - - /** The Register File for the CPU */ - union { - FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs]; - FloatRegBits i[ThePipeline::MaxThreads][TheISA::NumFloatRegs]; - } floatRegs; - TheISA::IntReg intRegs[ThePipeline::MaxThreads][TheISA::NumIntRegs]; -#ifdef ISA_HAS_CC_REGS - TheISA::CCReg ccRegs[ThePipeline::MaxThreads][TheISA::NumCCRegs]; -#endif - - /** ISA state */ - std::vector<TheISA::ISA *> isa; - - /** Dependency Tracker for Integer & Floating Point Regs */ - RegDepMap archRegDepMap[ThePipeline::MaxThreads]; - - /** Global communication structure */ - TimeBuffer<TimeStruct> timeBuffer; - - /** Communication structure that sits in between pipeline stages */ - StageQueue *stageQueue[ThePipeline::NumStages-1]; - - TheISA::TLB *getITBPtr(); - TheISA::TLB *getDTBPtr(); - - TheISA::Decoder *getDecoderPtr(unsigned tid); - - /** Accessor Type for the SkedCache */ - typedef uint32_t SkedID; - - /** Cache of Instruction Schedule using the instruction's name as a key */ - static m5::hash_map<SkedID, ThePipeline::RSkedPtr> skedCache; - - typedef m5::hash_map<SkedID, ThePipeline::RSkedPtr>::iterator SkedCacheIt; - - /** Initialized to last iterator in map, signifying a invalid entry - on map searches - */ - SkedCacheIt endOfSkedIt; - - ThePipeline::RSkedPtr frontEndSked; - ThePipeline::RSkedPtr faultSked; - - /** Add a new instruction schedule to the schedule cache */ - void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked) - { - SkedID sked_id = genSkedID(inst); - assert(skedCache.find(sked_id) == skedCache.end()); - skedCache[sked_id] = inst_sked; - } - - - /** Find a instruction schedule */ - ThePipeline::RSkedPtr lookupSked(DynInstPtr inst) - { - SkedID sked_id = genSkedID(inst); - SkedCacheIt lookup_it = skedCache.find(sked_id); - - if (lookup_it != endOfSkedIt) { - return (*lookup_it).second; - } else { - return NULL; - } - } - - static const uint8_t INST_OPCLASS = 26; - static const uint8_t INST_LOAD = 25; - static const uint8_t INST_STORE = 24; - static const uint8_t INST_CONTROL = 23; - static const uint8_t INST_NONSPEC = 22; - static const uint8_t INST_DEST_REGS = 18; - static const uint8_t INST_SRC_REGS = 14; - static const uint8_t INST_SPLIT_DATA = 13; - - inline SkedID genSkedID(DynInstPtr inst) - { - SkedID id = 0; - id = (inst->opClass() << INST_OPCLASS) | - (inst->isLoad() << INST_LOAD) | - (inst->isStore() << INST_STORE) | - (inst->isControl() << INST_CONTROL) | - (inst->isNonSpeculative() << INST_NONSPEC) | - (inst->numDestRegs() << INST_DEST_REGS) | - (inst->numSrcRegs() << INST_SRC_REGS) | - (inst->splitInst << INST_SPLIT_DATA); - return id; - } - - ThePipeline::RSkedPtr createFrontEndSked(); - ThePipeline::RSkedPtr createFaultSked(); - ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst); - - class StageScheduler { - private: - ThePipeline::RSkedPtr rsked; - int stageNum; - int nextTaskPriority; - - public: - StageScheduler(ThePipeline::RSkedPtr _rsked, int stage_num) - : rsked(_rsked), stageNum(stage_num), - nextTaskPriority(0) - { } - - void needs(int unit, int request) { - rsked->push(new ScheduleEntry( - stageNum, nextTaskPriority++, unit, request - )); - } - - void needs(int unit, int request, int param) { - rsked->push(new ScheduleEntry( - stageNum, nextTaskPriority++, unit, request, param - )); - } - }; - - private: - - /** Data port. Note that it has to appear after the resPool. */ - CachePort dataPort; - - /** Instruction port. Note that it has to appear after the resPool. */ - CachePort instPort; - - public: - - /** Registers statistics. */ - void regStats(); - - /** Ticks CPU, calling tick() on each stage, and checking the overall - * activity to see if the CPU should deschedule itself. - */ - void tick(); - - /** Initialize the CPU */ - void init(); - - /** HW return from error interrupt. */ - Fault hwrei(ThreadID tid); - - bool simPalCheck(int palFunc, ThreadID tid); - - void checkForInterrupts(); - - /** Returns the Fault for any valid interrupt. */ - Fault getInterrupts(); - - /** Processes any an interrupt fault. */ - void processInterrupts(const Fault &interrupt); - - /** Halts the CPU. */ - void halt() { panic("Halt not implemented!\n"); } - - /** Check if this address is a valid instruction address. */ - bool validInstAddr(Addr addr) { return true; } - - /** Check if this address is a valid data address. */ - bool validDataAddr(Addr addr) { return true; } - - /** Schedule a syscall on the CPU */ - void syscallContext(const Fault &fault, ThreadID tid, DynInstPtr inst, - Cycles delay = Cycles(0)); - - /** Executes a syscall.*/ - void syscall(int64_t callnum, ThreadID tid); - - /** Schedule a trap on the CPU */ - void trapContext(const Fault &fault, ThreadID tid, DynInstPtr inst, - Cycles delay = Cycles(0)); - - /** Perform trap to Handle Given Fault */ - void trap(const Fault &fault, ThreadID tid, DynInstPtr inst); - - /** Schedule thread activation on the CPU */ - void activateContext(ThreadID tid); - - /** Add Thread to Active Threads List. */ - void activateThread(ThreadID tid); - - /** Activate Thread In Each Pipeline Stage */ - void activateThreadInPipeline(ThreadID tid); - - /** Schedule Thread Activation from Ready List */ - void activateNextReadyContext(); - - /** Add Thread From Ready List to Active Threads List. */ - void activateNextReadyThread(); - - /** Schedule a thread deactivation on the CPU */ - void deactivateContext(ThreadID tid); - - /** Remove from Active Thread List */ - void deactivateThread(ThreadID tid); - - /** Schedule a thread suspension on the CPU */ - void suspendContext(ThreadID tid); - - /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */ - void suspendThread(ThreadID tid); - - /** Schedule a thread halt on the CPU */ - void haltContext(ThreadID tid); - - /** Halt Thread, Remove from Active Thread List, Place Thread on Halted - * Threads List - */ - void haltThread(ThreadID tid); - - /** squashFromMemStall() - sets up a squash event - * squashDueToMemStall() - squashes pipeline - * @note: maybe squashContext/squashThread would be better? - */ - void squashFromMemStall(DynInstPtr inst, ThreadID tid, - Cycles delay = Cycles(0)); - void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid); - - void removePipelineStalls(ThreadID tid); - void squashThreadInPipeline(ThreadID tid); - void squashBehindMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid); - - PipelineStage* getPipeStage(int stage_num); - - int - contextId() - { - hack_once("return a bogus context id"); - return 0; - } - - /** Update The Order In Which We Process Threads. */ - void updateThreadPriority(); - - /** Switches a Pipeline Stage to Active. (Unused currently) */ - void switchToActive(int stage_idx) - { /*pipelineStage[stage_idx]->switchToActive();*/ } - - /** Get the current instruction sequence number, and increment it. */ - InstSeqNum getAndIncrementInstSeq(ThreadID tid) - { return globalSeqNum[tid]++; } - - /** Get the current instruction sequence number, and increment it. */ - InstSeqNum nextInstSeqNum(ThreadID tid) - { return globalSeqNum[tid]; } - - /** Increment Instruction Sequence Number */ - void incrInstSeqNum(ThreadID tid) - { globalSeqNum[tid]++; } - - /** Set Instruction Sequence Number */ - void setInstSeqNum(ThreadID tid, InstSeqNum seq_num) - { - globalSeqNum[tid] = seq_num; - } - - /** Get & Update Next Event Number */ - InstSeqNum getNextEventNum() - { -#ifdef DEBUG - return cpuEventNum++; -#else - return 0; -#endif - } - - /** Register file accessors */ - uint64_t readIntReg(RegIndex reg_idx, ThreadID tid); - - FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid); - - FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid); - - CCReg readCCReg(RegIndex reg_idx, ThreadID tid); - - void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid); - - void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid); - - void setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid); - - void setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid); - - RegIndex flattenRegIdx(RegIndex reg_idx, RegClass ®_type, ThreadID tid); - - /** Reads a miscellaneous register. */ - MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid = 0); - - /** Reads a misc. register, including any side effects the read - * might have as defined by the architecture. - */ - MiscReg readMiscReg(int misc_reg, ThreadID tid = 0); - - /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val, - ThreadID tid = 0); - - /** Sets a misc. register, including any side effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid = 0); - - /** Reads a int/fp/misc reg. from another thread depending on ISA-defined - * target thread - */ - uint64_t readRegOtherThread(unsigned misc_reg, - ThreadID tid = InvalidThreadID); - - /** Sets a int/fp/misc reg. from another thread depending on an ISA-defined - * target thread - */ - void setRegOtherThread(unsigned misc_reg, const MiscReg &val, - ThreadID tid); - - /** Reads the commit PC of a specific thread. */ - TheISA::PCState - pcState(ThreadID tid) - { - return pc[tid]; - } - - /** Sets the commit PC of a specific thread. */ - void - pcState(const TheISA::PCState &newPC, ThreadID tid) - { - pc[tid] = newPC; - } - - Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } - Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } - MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); } - - /** Function to add instruction onto the head of the list of the - * instructions. Used when new instructions are fetched. - */ - ListIt addInst(DynInstPtr inst); - - /** Find instruction on instruction list */ - ListIt findInst(InstSeqNum seq_num, ThreadID tid); - - /** Function to tell the CPU that an instruction has completed. */ - void instDone(DynInstPtr inst, ThreadID tid); - - /** Add Instructions to the CPU Remove List*/ - void addToRemoveList(DynInstPtr inst); - - /** Remove an instruction from CPU */ - void removeInst(DynInstPtr inst); - - /** Remove all instructions younger than the given sequence number. */ - void removeInstsUntil(const InstSeqNum &seq_num,ThreadID tid); - - /** Removes the instruction pointed to by the iterator. */ - inline void squashInstIt(const ListIt inst_it, ThreadID tid); - - /** Cleans up all instructions on the instruction remove list. */ - void cleanUpRemovedInsts(); - - /** Cleans up all events on the CPU event remove list. */ - void cleanUpRemovedEvents(); - - /** Debug function to print all instructions on the list. */ - void dumpInsts(); - - /** Forwards an instruction read to the appropriate data - * resource (indexes into Resource Pool thru "dataPortIdx") - */ - Fault read(DynInstPtr inst, Addr addr, - uint8_t *data, unsigned size, unsigned flags); - - /** Forwards an instruction write. to the appropriate data - * resource (indexes into Resource Pool thru "dataPortIdx") - */ - Fault write(DynInstPtr inst, uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *write_res = NULL); - - public: - /** Per-Thread List of all the instructions in flight. */ - std::list<DynInstPtr> instList[ThePipeline::MaxThreads]; - - /** List of all the instructions that will be removed at the end of this - * cycle. - */ - std::queue<ListIt> removeList; - - bool trapPending[ThePipeline::MaxThreads]; - - /** List of all the cpu event requests that will be removed at the end of - * the current cycle. - */ - std::queue<Event*> cpuEventRemoveList; - - /** Records if instructions need to be removed this cycle due to - * being retired or squashed. - */ - bool removeInstsThisCycle; - - /** True if there is non-speculative Inst Active In Pipeline. Lets any - * execution unit know, NOT to execute while the instruction is active. - */ - bool nonSpecInstActive[ThePipeline::MaxThreads]; - - /** Instruction Seq. Num of current non-speculative instruction. */ - InstSeqNum nonSpecSeqNum[ThePipeline::MaxThreads]; - - /** Instruction Seq. Num of last instruction squashed in pipeline */ - InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; - - /** Last Cycle that the CPU squashed instruction end. */ - Tick lastSquashCycle[ThePipeline::MaxThreads]; - - std::list<ThreadID> fetchPriorityList; - - protected: - /** Active Threads List */ - std::list<ThreadID> activeThreads; - - /** Ready Threads List */ - std::list<ThreadID> readyThreads; - - /** Suspended Threads List */ - std::list<ThreadID> suspendedThreads; - - /** Halted Threads List */ - std::list<ThreadID> haltedThreads; - - /** Thread Status Functions */ - bool isThreadActive(ThreadID tid); - bool isThreadReady(ThreadID tid); - bool isThreadSuspended(ThreadID tid); - - private: - /** The activity recorder; used to tell if the CPU has any - * activity remaining or if it can go to idle and deschedule - * itself. - */ - ActivityRecorder activityRec; - - public: - /** Number of Active Threads in the CPU */ - ThreadID numActiveThreads() { return activeThreads.size(); } - - /** Thread id of active thread - * Only used for SwitchOnCacheMiss model. - * Assumes only 1 thread active - */ - ThreadID activeThreadId() - { - if (numActiveThreads() > 0) - return activeThreads.front(); - else - return InvalidThreadID; - } - - - /** Records that there was time buffer activity this cycle. */ - void activityThisCycle() { activityRec.activity(); } - - /** Changes a stage's status to active within the activity recorder. */ - void activateStage(const int idx) - { activityRec.activateStage(idx); } - - /** Changes a stage's status to inactive within the activity recorder. */ - void deactivateStage(const int idx) - { activityRec.deactivateStage(idx); } - - /** Wakes the CPU, rescheduling the CPU if it's not already active. */ - void wakeCPU(); - - virtual void wakeup(); - - /* LL/SC debug functionality - unsigned stCondFails; - - unsigned readStCondFailures() - { return stCondFails; } - - unsigned setStCondFailures(unsigned st_fails) - { return stCondFails = st_fails; } - */ - - /** Returns a pointer to a thread context. */ - ThreadContext *tcBase(ThreadID tid = 0) - { - return thread[tid]->getTC(); - } - - /** Count the Total Instructions Committed in the CPU. */ - virtual Counter totalInsts() const - { - Counter total(0); - - for (ThreadID tid = 0; tid < (ThreadID)thread.size(); tid++) - total += thread[tid]->numInst; - - return total; - } - - /** Count the Total Ops Committed in the CPU. */ - virtual Counter totalOps() const - { - Counter total(0); - - for (ThreadID tid = 0; tid < (ThreadID)thread.size(); tid++) - total += thread[tid]->numOp; - - return total; - } - - /** Pointer to the system. */ - System *system; - - /** The global sequence number counter. */ - InstSeqNum globalSeqNum[ThePipeline::MaxThreads]; - -#ifdef DEBUG - /** The global event number counter. */ - InstSeqNum cpuEventNum; - - /** Number of resource requests active in CPU **/ - unsigned resReqCount; -#endif - - Addr lockAddr; - - /** Temporary fix for the lock flag, works in the UP case. */ - bool lockFlag; - - /** Counter of how many stages have completed draining */ - int drainCount; - - /** Pointers to all of the threads in the CPU. */ - std::vector<Thread *> thread; - - /** Per-Stage Instruction Tracing */ - bool stageTracing; - - /** The cycle that the CPU was last running, used for statistics. */ - Tick lastRunningCycle; - - void updateContextSwitchStats(); - unsigned instsPerSwitch; - Stats::Average instsPerCtxtSwitch; - Stats::Scalar numCtxtSwitches; - - /** Resumes execution after a drain. */ - void drainResume(); - - /** Switches out this CPU. */ - virtual void switchOut(); - - /** Takes over from another CPU. */ - virtual void takeOverFrom(BaseCPU *oldCPU); - - /** Update Thread , used for statistic purposes*/ - inline void tickThreadStats(); - - /** Per-Thread Tick */ - Stats::Vector threadCycles; - - /** Tick for SMT */ - Stats::Scalar smtCycles; - - /** Stat for total number of times the CPU is descheduled. */ - Stats::Scalar timesIdled; - - /** Stat for total number of cycles the CPU spends descheduled or no - * stages active. - */ - Stats::Scalar idleCycles; - - /** Stat for total number of cycles the CPU is active. */ - Stats::Scalar runCycles; - - /** Percentage of cycles a stage was active */ - Stats::Formula activity; - - /** Instruction Mix Stats */ - Stats::Scalar comLoads; - Stats::Scalar comStores; - Stats::Scalar comBranches; - Stats::Scalar comNops; - Stats::Scalar comNonSpec; - Stats::Scalar comInts; - Stats::Scalar comFloats; - - /** Stat for the number of committed instructions per thread. */ - Stats::Vector committedInsts; - - /** Stat for the number of committed ops per thread. */ - Stats::Vector committedOps; - - /** Stat for the number of committed instructions per thread. */ - Stats::Vector smtCommittedInsts; - - /** Stat for the total number of committed instructions. */ - Stats::Scalar totalCommittedInsts; - - /** Stat for the CPI per thread. */ - Stats::Formula cpi; - - /** Stat for the SMT-CPI per thread. */ - Stats::Formula smtCpi; - - /** Stat for the total CPI. */ - Stats::Formula totalCpi; - - /** Stat for the IPC per thread. */ - Stats::Formula ipc; - - /** Stat for the total IPC. */ - Stats::Formula smtIpc; - - /** Stat for the total IPC. */ - Stats::Formula totalIpc; -}; - -#endif // __CPU_O3_CPU_HH__ diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc deleted file mode 100644 index f59e89410..000000000 --- a/src/cpu/inorder/first_stage.cc +++ /dev/null @@ -1,289 +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 "base/str.hh" -#include "cpu/inorder/resources/resource_list.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/first_stage.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/InOrderStage.hh" -#include "params/InOrderTrace.hh" - -using namespace std; -using namespace ThePipeline; - -FirstStage::FirstStage(Params *params, unsigned stage_num) - : PipelineStage(params, stage_num), numFetchingThreads(1), - fetchPolicy(FirstStage::RoundRobin) -{ - for(ThreadID tid = 0; tid < this->numThreads; tid++) { - stageStatus[tid] = Running; - } -} - -void -FirstStage::setCPU(InOrderCPU *cpu_ptr) -{ - cpu = cpu_ptr; - - fetchPriorityList = &cpu->fetchPriorityList; - - DPRINTF(InOrderStage, "Set CPU pointer.\n"); -} - - -void -FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid) -{ - // Set status to squashing. - //stageStatus[tid] = Squashing; - - // Clear the instruction list and skid buffer in case they have any - // insts in them. - DPRINTF(InOrderStage, "Removing instructions from stage instruction " - "list.\n"); - while (!skidBuffer[tid].empty()) { - if (skidBuffer[tid].front()->seqNum <= squash_seq_num) { - DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because " - "it's <= squashing seqNum %i.\n", - tid, - skidBuffer[tid].front()->seqNum, - squash_seq_num); - - DPRINTF(InOrderStage, "[tid:%i]: Cannot remove incoming " - "instructions before delay slot [sn:%i]. %i insts" - "left.\n", tid, squash_seq_num, - skidBuffer[tid].size()); - break; - } - DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - "PC %s.\n", tid, skidBuffer[tid].front()->seqNum, - skidBuffer[tid].front()->pc); - skidBuffer[tid].pop_front(); - } - - // Now that squash has propagated to the first stage, - // Alert CPU to remove instructions from the CPU instruction list. - // @todo: Move this to the CPU object. - cpu->removeInstsUntil(squash_seq_num, tid); -} - -void -FirstStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid) -{ - // Need to preserve the stalling instruction in first-stage - // since the squash() from first stage also removes - // the instruction from the CPU (removeInstsUntil). If that - // functionality gets changed then you can move this offset. - // (stalling instruction = seq_num + 1) - squash(seq_num+1, tid); -} - - -void -FirstStage::processStage(bool &status_change) -{ - list<ThreadID>::iterator threads = activeThreads->begin(); - - //Check stall and squash signals. - while (threads != activeThreads->end()) { - ThreadID tid = *threads++; - status_change = checkSignalsAndUpdate(tid) || status_change; - } - - while (instsProcessed < stageWidth) { - ThreadID tid = getFetchingThread(fetchPolicy); - - if (tid >= 0) { - DPRINTF(InOrderStage, "Processing [tid:%i]\n",tid); - processThread(status_change, tid); - DPRINTF(InOrderStage, "Done Processing [tid:%i]\n",tid); - } else { - DPRINTF(InOrderStage, "No more threads to fetch from.\n"); - break; - } - } - - if (instsProcessed > 0) { - ++runCycles; - idle = false; - } else { - ++idleCycles; - idle = true; - } - -} - -//@TODO: Note in documentation, that when you make a pipeline stage change, -//then make sure you change the first stage too -void -FirstStage::processInsts(ThreadID tid) -{ - bool all_reqs_completed = true; - - for (int insts_fetched = instsProcessed; - insts_fetched < stageWidth; - insts_fetched++) { - - DynInstPtr inst; - bool new_inst = false; - - if (!skidBuffer[tid].empty()) { - inst = skidBuffer[tid].front(); - } else { - // Get new instruction. - new_inst = true; - - inst = new InOrderDynInst(cpu, - cpu->thread[tid], - cpu->nextInstSeqNum(tid), - tid, - tid); - -#if TRACING_ON - inst->traceData = - tracer->getInstRecord(ThePipeline::NumStages, - cpu->stageTracing, - cpu->thread[tid]->getTC()); - -#else - inst->traceData = NULL; -#endif // TRACING_ON - - // Add instruction to the CPU's list of instructions. - inst->setInstListIt(cpu->addInst(inst)); - - // Create Front-End Resource Schedule For Instruction - inst->setFrontSked(cpu->frontEndSked); - } - - int reqs_processed = 0; - all_reqs_completed = processInstSchedule(inst, reqs_processed); - - // If the instruction isnt squashed & we've completed one request - // Then we can officially count this instruction toward the stage's - // bandwidth count - if (reqs_processed > 0) - instsProcessed++; - - if (!all_reqs_completed || !sendInstToNextStage(inst)) { - if (new_inst) { - DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Did not finish all " - "requests for this stage. Keep in stage inst. " - "list.\n", tid, inst->seqNum); - skidBuffer[tid].push_back(inst); - } - block(tid); - break; - } else if (!skidBuffer[tid].empty()){ - DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Finished all " - "requests for this stage.\n", tid, inst->seqNum); - skidBuffer[tid].pop_front(); - } - - } - - // Record that stage has written to the time buffer for activity - // tracking. - if (instsProcessed) { - wroteToTimeBuffer = true; - } -} - -ThreadID -FirstStage::getFetchingThread(FetchPriority &fetch_priority) -{ - ThreadID num_active_threads = cpu->numActiveThreads(); - - if (num_active_threads > 1) { - switch (fetch_priority) { - case SingleThread: - return cpu->activeThreadId(); - - case RoundRobin: - return roundRobin(); - - default: - return InvalidThreadID; - } - } else if (num_active_threads == 1) { - ThreadID tid = *activeThreads->begin(); - - if (stageStatus[tid] == Running || - stageStatus[tid] == Idle || - stageStatus[tid] == Unblocking) { - return tid; - } else { - return InvalidThreadID; - } - } else { - return InvalidThreadID; - } -} - -ThreadID -FirstStage::roundRobin() -{ - list<ThreadID>::iterator pri_iter = fetchPriorityList->begin(); - list<ThreadID>::iterator end = fetchPriorityList->end(); - - ThreadID high_pri; - - while (pri_iter != end) { - high_pri = *pri_iter; - - assert(high_pri <= numThreads); - - if (stageStatus[high_pri] == Running || - stageStatus[high_pri] == Idle || - stageStatus[high_pri] == Unblocking){ - - fetchPriorityList->erase(pri_iter); - fetchPriorityList->push_back(high_pri); - - return high_pri; - } - - pri_iter++; - } - - return InvalidThreadID; -} - -void -FirstStage::takeOverFrom() -{ - PipelineStage::takeOverFrom(); - - for(ThreadID tid = 0; tid < this->numThreads; tid++) { - stageStatus[tid] = Running; - } -} diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh deleted file mode 100644 index ae8b12102..000000000 --- a/src/cpu/inorder/first_stage.hh +++ /dev/null @@ -1,96 +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_FIRST_STAGE_HH__ -#define __CPU_INORDER_FIRST_STAGE_HH__ - -#include <queue> -#include <vector> - -#include "base/statistics.hh" -#include "cpu/inorder/comm.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_stage.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/timebuf.hh" - -class InOrderCPU; - -class FirstStage : public PipelineStage { - public: - FirstStage(ThePipeline::Params *params, unsigned stage_num); - - /** Set Pointer to CPU */ - void setCPU(InOrderCPU *cpu_ptr); - - /** Evaluate Stage Info. & Execute Stage */ - void processStage(bool &status_change); - - /** Process All Instructions Available */ - void processInsts(ThreadID tid); - - /** Squash Instructions Above a Seq. Num */ - void squash(InstSeqNum squash_seq_num, ThreadID tid); - - void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid); - - /** There are no insts. coming from previous stages, so there is - * no need to sort insts here - */ - void sortInsts() {} - - /** The number of fetching threads in the CPU */ - int numFetchingThreads; - - //@TODO: Add fetch priority information to a resource class... - /** Fetching Policy, Add new policies here.*/ - enum FetchPriority { - SingleThread, - RoundRobin - }; - - /** Fetch policy. */ - FetchPriority fetchPolicy; - - /** List that has the threads organized by priority. */ - std::list<ThreadID> *fetchPriorityList; - - /** Return the next fetching thread */ - ThreadID getFetchingThread(FetchPriority &fetch_priority); - - /** Return next thread given Round Robin Policy for Thread Fetching */ - ThreadID roundRobin(); - - /** Takes over from another CPU's thread. */ - void takeOverFrom(); -}; - -#endif // __CPU_INORDER_FIRST_STAGE_HH__ diff --git a/src/cpu/inorder/inorder_cpu_builder.cc b/src/cpu/inorder/inorder_cpu_builder.cc deleted file mode 100644 index 569652bd2..000000000 --- a/src/cpu/inorder/inorder_cpu_builder.cc +++ /dev/null @@ -1,61 +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 <string> - -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/base.hh" -#include "cpu/inst_seq.hh" -#include "cpu/static_inst.hh" -#include "params/InOrderCPU.hh" -#include "sim/full_system.hh" - -InOrderCPU * -InOrderCPUParams::create() -{ - ThreadID actual_num_threads; - if (FullSystem) { - // Full-system only supports a single thread for the moment. - actual_num_threads = 1; - } else { - actual_num_threads = - (numThreads >= workload.size()) ? numThreads : workload.size(); - - if (workload.size() == 0) { - fatal("Must specify at least one workload!"); - } - } - - numThreads = actual_num_threads; - return new InOrderCPU(this); -} diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc deleted file mode 100644 index c64cf9da4..000000000 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ /dev/null @@ -1,626 +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 <iostream> -#include <set> -#include <sstream> -#include <string> - -#include "base/bigint.hh" -#include "base/cp_annotate.hh" -#include "base/cprintf.hh" -#include "base/trace.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/exetrace.hh" -#include "cpu/reg_class.hh" -#include "debug/InOrderDynInst.hh" -#include "mem/request.hh" -#include "sim/full_system.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -InOrderDynInst::InOrderDynInst(InOrderCPU *cpu, - InOrderThreadState *state, - InstSeqNum seq_num, - ThreadID tid, - unsigned _asid) - : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid), - virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu), - thread(state), fault(NoFault), memData(NULL), loadData(0), - storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0), - readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0), - memTime(0), splitMemData(NULL), splitMemReq(NULL), totalSize(0), - split2ndSize(0), split2ndAddr(0), split2ndAccess(false), - split2ndDataPtr(NULL), split2ndFlags(0), splitInst(false), - splitFinishCnt(0), split2ndStoreDataPtr(NULL), splitInstSked(false), - inFrontEnd(true), frontSked(NULL), backSked(NULL), - squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false), - fetchMemReq(NULL), dataMemReq(NULL), instEffAddr(0), eaCalcDone(false), - lqIdx(0), sqIdx(0), onInstList(false) -{ - for(int i = 0; i < MaxInstSrcRegs; i++) { - _readySrcRegIdx[i] = false; - _srcRegIdx[i] = 0; - } - - for(int j = 0; j < MaxInstDestRegs; j++) { - _destRegIdx[j] = 0; - _prevDestRegIdx[j] = 0; - } - - ++instcount; - DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created." - " (active insts: %i)\n", threadNumber, seqNum, instcount); - -} - -int InOrderDynInst::instcount = 0; - -int -InOrderDynInst::cpuId() const -{ - return cpu->cpuId(); -} - -void -InOrderDynInst::setStaticInst(StaticInstPtr si) -{ - staticInst = si; - - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } -} - -void -InOrderDynInst::initVars() -{ - inFrontEnd = true; - - fetchMemReq = NULL; - dataMemReq = NULL; - splitMemData = NULL; - split2ndAddr = 0; - split2ndAccess = false; - splitInst = false; - splitInstSked = false; - splitFinishCnt = 0; - - effAddr = 0; - physEffAddr = 0; - - readyRegs = 0; - - nextStage = 0; - - status.reset(); - - memAddrReady = false; - eaCalcDone = false; - - predictTaken = false; - procDelaySlotOnMispred = false; - - lqIdx = -1; - sqIdx = -1; - - // Also make this a parameter, or perhaps get it from xc or cpu. - asid = 0; - - virtProcNumber = 0; - - // Initialize the fault to be NoFault. - fault = NoFault; - - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - if (this->staticInst) { - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } - } - - // Update Instruction Count for this instruction - if (instcount > 100) { - fatal("Number of Active Instructions in CPU is too high. " - "(Not Dereferencing Ptrs. Correctly?)\n"); - } -} - -void -InOrderDynInst::resetInstCount() -{ - instcount = 0; -} - - -InOrderDynInst::~InOrderDynInst() -{ - if (traceData) - delete traceData; - - if (splitMemData) - delete [] splitMemData; - - fault = NoFault; - - --instcount; - - DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed" - " (active insts: %i)\n", threadNumber, seqNum, instcount); -} - -void -InOrderDynInst::setStaticInst(StaticInstPtr &static_inst) -{ - this->staticInst = static_inst; - - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - if (this->staticInst) { - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - _destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - _srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } - } -} - -Fault -InOrderDynInst::execute() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool no_squash_from_TC = this->thread->noSquashFromTC; - this->thread->noSquashFromTC = true; - - this->fault = this->staticInst->execute(this, this->traceData); - - this->thread->noSquashFromTC = no_squash_from_TC; - - return this->fault; -} - -Fault -InOrderDynInst::calcEA() -{ - this->fault = this->staticInst->eaComp(this, this->traceData); - return this->fault; -} - -Fault -InOrderDynInst::initiateAcc() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool no_squash_from_TC = this->thread->noSquashFromTC; - this->thread->noSquashFromTC = true; - - this->fault = this->staticInst->initiateAcc(this, this->traceData); - - this->thread->noSquashFromTC = no_squash_from_TC; - - return this->fault; -} - - -Fault -InOrderDynInst::completeAcc(Packet *pkt) -{ - this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); - - return this->fault; -} - -Fault -InOrderDynInst::memAccess() -{ - return initiateAcc(); -} - - -Fault -InOrderDynInst::hwrei() -{ -#if THE_ISA == ALPHA_ISA - // Can only do a hwrei when in pal mode. - if (!(this->instAddr() & 0x3)) - return std::make_shared<AlphaISA::UnimplementedOpcodeFault>(); - - // Set the next PC based on the value of the EXC_ADDR IPR. - AlphaISA::PCState pc = this->pcState(); - pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - this->threadNumber)); - this->pcState(pc); - if (CPA::available()) { - ThreadContext *tc = this->cpu->tcBase(this->threadNumber); - CPA::cpa()->swAutoBegin(tc, this->nextInstAddr()); - } - - // Tell CPU to clear any state it needs to if a hwrei is taken. - this->cpu->hwrei(this->threadNumber); -#endif - return NoFault; -} - - -void -InOrderDynInst::trap(const Fault &fault) -{ - this->cpu->trap(fault, this->threadNumber, this); -} - - -bool -InOrderDynInst::simPalCheck(int palFunc) -{ -#if THE_ISA != ALPHA_ISA - panic("simPalCheck called, but PAL only exists in Alpha!\n"); -#endif - return this->cpu->simPalCheck(palFunc, this->threadNumber); -} - -void -InOrderDynInst::syscall(int64_t callnum) -{ - if (FullSystem) - panic("Syscall emulation isn't available in FS mode.\n"); - - syscallNum = callnum; - cpu->syscallContext(NoFault, this->threadNumber, this); -} - -void -InOrderDynInst::setSquashInfo(unsigned stage_num) -{ - squashingStage = stage_num; - - // If it's a fault, then we need to squash - // the faulting instruction too. Squash - // functions squash above a seqNum, so we - // decrement here for that case - if (fault != NoFault) { - squashSeqNum = seqNum - 1; - return; - } else - squashSeqNum = seqNum; - -#if ISA_HAS_DELAY_SLOT - if (staticInst && isControl()) { - TheISA::PCState nextPC = pc; - TheISA::advancePC(nextPC, staticInst); - - // Check to see if we should squash after the - // branch or after a branch delay slot. - if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst)) - squashSeqNum = seqNum + 1; - else - squashSeqNum = seqNum; - } -#endif -} - -void -InOrderDynInst::releaseReq(ResourceRequest* req) -{ - std::list<ResourceRequest*>::iterator list_it = reqList.begin(); - std::list<ResourceRequest*>::iterator list_end = reqList.end(); - - while(list_it != list_end) { - if((*list_it)->getResIdx() == req->getResIdx() && - (*list_it)->getSlot() == req->getSlot()) { - DPRINTF(InOrderDynInst, "[tid:%u]: [sn:%i] Done with request " - "to %s.\n", threadNumber, seqNum, req->res->name()); - reqList.erase(list_it); - return; - } - list_it++; - } - - panic("Releasing Res. Request That Isnt There!\n"); -} - -/** Records an integer source register being set to a value. */ -void -InOrderDynInst::setIntSrc(int idx, uint64_t val) -{ - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] Int being set " - "to %#x.\n", threadNumber, seqNum, idx, val); - instSrc[idx].intVal = val; -} - -/** Records an fp register being set to a value. */ -void -InOrderDynInst::setFloatSrc(int idx, FloatReg val) -{ - instSrc[idx].fpVal.f = val; - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FP being set " - "to %x, %08f...%08f\n", threadNumber, seqNum, idx, - instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val); -} - -/** Records an fp register being set to an integer value. */ -void -InOrderDynInst::setFloatRegBitsSrc(int idx, FloatRegBits val) -{ - instSrc[idx].fpVal.i = val; - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being set " - "to %x, %08f...%x\n", threadNumber, seqNum, idx, - instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val); -} - -/** Reads a integer register. */ -IntReg -InOrderDynInst::readIntRegOperand(const StaticInst *si, int idx, ThreadID tid) -{ - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n", - threadNumber, seqNum, idx, instSrc[idx].intVal); - return instSrc[idx].intVal; -} - -/** Reads a FP register. */ -FloatReg -InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx) -{ - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPVal being read " - "as %x, %08f.\n", threadNumber, seqNum, idx, - instSrc[idx].fpVal.i, instSrc[idx].fpVal.f); - return instSrc[idx].fpVal.f; -} - - -/** Reads a FP register as a integer. */ -FloatRegBits -InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx) -{ - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being read " - "as %x, %08f.\n", threadNumber, seqNum, idx, - instSrc[idx].fpVal.i, instSrc[idx].fpVal.f); - return instSrc[idx].fpVal.i; -} - -/** Reads a miscellaneous register. */ -MiscReg -InOrderDynInst::readMiscReg(int misc_reg) -{ - return this->cpu->readMiscReg(misc_reg, threadNumber); -} - - -/** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ -MiscReg -InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx) -{ - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i" - " read as %#x.\n", threadNumber, seqNum, idx, - instSrc[idx].intVal); - return instSrc[idx].intVal; -} - - -/** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ -void -InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx, - const MiscReg &val) -{ - instResult[idx].type = Integer; - instResult[idx].res.intVal = val; - instResult[idx].tick = curTick(); - - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i " - "being set to %#x.\n", threadNumber, seqNum, idx, val); -} - -MiscReg -InOrderDynInst::readRegOtherThread(int reg_idx, ThreadID tid) -{ - if (tid == -1) { - tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); - } - - RegIndex rel_idx; - - switch (regIdxToClass(reg_idx, &rel_idx)) { - case IntRegClass: - return this->cpu->readIntReg(rel_idx, tid); - - case FloatRegClass: - return this->cpu->readFloatRegBits(rel_idx, tid); - - case MiscRegClass: - return this->cpu->readMiscReg(rel_idx, tid); // Misc. Register File - - default: - panic("register %d out of range\n", reg_idx); - - } -} - -/** Sets a Integer register. */ -void -InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val) -{ - instResult[idx].type = Integer; - instResult[idx].res.intVal = val; - instResult[idx].tick = curTick(); - - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i " - "being set to %#x (result-tick:%i).\n", - threadNumber, seqNum, idx, val, instResult[idx].tick); -} - -/** Sets a FP register. */ -void -InOrderDynInst::setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) -{ - instResult[idx].type = Float; - instResult[idx].res.fpVal.f = val; - instResult[idx].tick = curTick(); - - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. %i " - "being set to %#x, %08f (result-tick:%i).\n", - threadNumber, seqNum, idx, val, val, instResult[idx].tick); -} - -/** Sets a FP register as a integer. */ -void -InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val) -{ - instResult[idx].type = FloatBits; - instResult[idx].res.fpVal.i = val; - instResult[idx].tick = curTick(); - - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i " - "being set to %#x (result-tick:%i).\n", - threadNumber, seqNum, idx, val, instResult[idx].tick); -} - -/** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ -/* Alter this if/when wanting to *speculate* on Miscellaneous registers */ -void -InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val) -{ - this->cpu->setMiscReg(misc_reg, val, threadNumber); -} - -void -InOrderDynInst::setRegOtherThread(int reg_idx, MiscReg val, ThreadID tid) -{ - if (tid == InvalidThreadID) { - tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); - } - - RegIndex rel_idx; - - switch (regIdxToClass(reg_idx, &rel_idx)) { - case IntRegClass: - this->cpu->setIntReg(rel_idx, val, tid); - break; - - case FloatRegClass: - this->cpu->setFloatRegBits(rel_idx, val, tid); - break; - - case CCRegClass: - this->cpu->setCCReg(rel_idx, val, tid); - break; - - case MiscRegClass: - this->cpu->setMiscReg(rel_idx, val, tid); // Misc. Register File - break; - } -} - -Fault -InOrderDynInst::readMem(Addr addr, uint8_t *data, - unsigned size, unsigned flags) -{ - return cpu->read(this, addr, data, size, flags); -} - -Fault -InOrderDynInst::writeMem(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res) -{ - return cpu->write(this, data, size, addr, flags, res); -} - - -void -InOrderDynInst::dump() -{ - cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); - cout << staticInst->disassemble(pc.instAddr()); - cprintf("'\n"); -} - -void -InOrderDynInst::dump(std::string &outstring) -{ - std::ostringstream s; - s << "T" << threadNumber << " : " << pc << " " - << staticInst->disassemble(pc.instAddr()); - - outstring = s.str(); -} - -void -InOrderDynInst::armMonitor(Addr address) { - cpu->armMonitor(address); -} - -bool -InOrderDynInst::mwait(PacketPtr pkt) { - return cpu->mwait(pkt); -} - -void -InOrderDynInst::mwaitAtomic(ThreadContext *tc) -{ - return cpu->mwaitAtomic(tc, cpu->getDTBPtr()); -} - -AddressMonitor * -InOrderDynInst::getAddrMonitor() -{ - return cpu->getCpuAddrMonitor(); -} diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh deleted file mode 100644 index ebb7bf912..000000000 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * 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: Kevin Lim - * Korey Sewell - */ - -#ifndef __CPU_INORDER_DYN_INST_HH__ -#define __CPU_INORDER_DYN_INST_HH__ - -#include <bitset> -#include <list> -#include <string> - -#include "arch/isa_traits.hh" -#include "arch/mt.hh" -#include "arch/types.hh" -#include "arch/utility.hh" -#include "base/trace.hh" -#include "base/types.hh" -#include "config/the_isa.hh" -#include "cpu/exec_context.hh" -#include "cpu/inorder/inorder_trace.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/inorder/resource_sked.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/exetrace.hh" -#include "cpu/inst_seq.hh" -#include "cpu/op_class.hh" -#include "cpu/static_inst.hh" -#include "cpu/thread_context.hh" -#include "debug/InOrderDynInst.hh" -#include "mem/packet.hh" -#include "sim/system.hh" - -#if THE_ISA == ALPHA_ISA -#include "arch/alpha/ev5.hh" -#endif - -/** - * @file - * Defines a dynamic instruction context for a inorder CPU model. - */ - -// Forward declaration. -class ResourceRequest; -class Packet; - -class InOrderDynInst : public ExecContext, public RefCounted -{ - public: - // Binary machine instruction type. - typedef TheISA::MachInst MachInst; - // Extended machine instruction type - typedef TheISA::ExtMachInst ExtMachInst; - // Logical register index type. - typedef TheISA::RegIndex RegIndex; - // Integer register type. - typedef TheISA::IntReg IntReg; - // Floating point register type. - typedef TheISA::FloatReg FloatReg; - // Floating point register type. - typedef TheISA::FloatRegBits FloatRegBits; - // Condition code register type. - typedef TheISA::CCReg CCReg; - // Floating point register type. - typedef TheISA::MiscReg MiscReg; - - typedef short int PhysRegIndex; - - /** The refcounted DynInst pointer to be used. In most cases this is - * what should be used, and not DynInst*. - */ - typedef RefCountingPtr<InOrderDynInst> DynInstPtr; - - // The list of instructions iterator type. - typedef std::list<DynInstPtr>::iterator ListIt; - - enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs /// Max dest regs - }; - - public: - /** BaseDynInst constructor given a binary instruction. - * @param seq_num The sequence number of the instruction. - * @param cpu Pointer to the instruction's CPU. - * NOTE: Must set Binary Instrution through Member Function - */ - InOrderDynInst(InOrderCPU *cpu, InOrderThreadState *state, - InstSeqNum seq_num, ThreadID tid, unsigned asid = 0); - - /** InOrderDynInst destructor. */ - ~InOrderDynInst(); - - public: - /** The sequence number of the instruction. */ - InstSeqNum seqNum; - - /** If this instruction is squashing, the number should we squash behind. */ - InstSeqNum squashSeqNum; - - enum Status { - RegDepMapEntry, /// Instruction is entered onto the RegDepMap - IqEntry, /// Instruction is in the IQ - RobEntry, /// Instruction is in the ROB - LsqEntry, /// Instruction is in the LSQ - Completed, /// Instruction has completed - ResultReady, /// Instruction has its result - CanIssue, /// Instruction can issue and execute - Issued, /// Instruction has issued - Executed, /// Instruction has executed - CanCommit, /// Instruction can commit - AtCommit, /// Instruction has reached commit - Committed, /// Instruction has committed - Squashed, /// Instruction is squashed - SquashedInIQ, /// Instruction is squashed in the IQ - SquashedInLSQ, /// Instruction is squashed in the LSQ - SquashedInROB, /// Instruction is squashed in the ROB - RecoverInst, /// Is a recover instruction - BlockingInst, /// Is a blocking instruction - ThreadsyncWait, /// Is a thread synchronization instruction - SerializeBefore, /// Needs to serialize on - /// instructions ahead of it - SerializeAfter, /// Needs to serialize instructions behind it - SerializeHandled, /// Serialization has been handled - RemoveList, /// Is Instruction on Remove List? - NumStatus - }; - - /** The status of this BaseDynInst. Several bits can be set. */ - std::bitset<NumStatus> status; - - /** The thread this instruction is from. */ - short threadNumber; - - /** data address space ID, for loads & stores. */ - short asid; - - /** The virtual processor number */ - short virtProcNumber; - - /** The StaticInst used by this BaseDynInst. */ - StaticInstPtr staticInst; - - /** InstRecord that tracks this instructions. */ - Trace::InOrderTraceRecord *traceData; - - /** Pointer to the Impl's CPU object. */ - InOrderCPU *cpu; - - /** Pointer to the thread state. */ - InOrderThreadState *thread; - - /** The kind of fault this instruction has generated. */ - Fault fault; - - /** The memory request. */ - Request *req; - - /** Pointer to the data for the memory access. */ - uint8_t *memData; - - /** Data used for a store for operation. */ - uint64_t loadData; - - /** Data used for a store for operation. */ - uint64_t storeData; - - /** List of active resource requests for this instruction */ - std::list<ResourceRequest*> reqList; - - /** The effective virtual address (lds & stores only). */ - Addr effAddr; - - /** The effective physical address. */ - Addr physEffAddr; - - /** The memory request flags (from translation). */ - unsigned memReqFlags; - - /** How many source registers are ready. */ - unsigned readyRegs; - - enum ResultType { - None, - Integer, - Float, - FloatBits, - Double - }; - - /** An instruction src/dest has to be one of these types */ - struct InstValue { - IntReg intVal; - union { - FloatReg f; - FloatRegBits i; - } fpVal; - - InstValue() - { - intVal = 0; - fpVal.i = 0; - } - }; - - /** Result of an instruction execution */ - struct InstResult { - ResultType type; - InstValue res; - Tick tick; - - InstResult() - : type(None), tick(0) - { } - }; - - /** The source of the instruction; assumes for now that there's only one - * destination register. - */ - InstValue instSrc[MaxInstSrcRegs]; - - /** The result of the instruction; assumes for now that there's only one - * destination register. - */ - InstResult instResult[MaxInstDestRegs]; - - /** PC of this instruction. */ - TheISA::PCState pc; - - /** Predicted next PC. */ - TheISA::PCState predPC; - - /** Address to get/write data from/to */ - /* Fetching address when inst. starts, Data address for load/store after fetch*/ - Addr memAddr; - - /** Whether or not the source register is ready. - * @todo: Not sure this should be here vs the derived class. - */ - bool _readySrcRegIdx[MaxInstSrcRegs]; - - /** Flattened register index of the destination registers of this - * instruction. - */ - TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs]; - - /** Flattened register index of the source registers of this - * instruction. - */ - TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs]; - - /** Physical register index of the destination registers of this - * instruction. - */ - PhysRegIndex _destRegIdx[MaxInstDestRegs]; - - /** Physical register index of the source registers of this - * instruction. - */ - PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; - - /** Physical register index of the previous producers of the - * architected destinations. - */ - PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; - - int nextStage; - - private: - /** Function to initialize variables in the constructors. */ - void initVars(); - - public: - Tick memTime; - - PacketDataPtr splitMemData; - RequestPtr splitMemReq; - int totalSize; - int split2ndSize; - Addr split2ndAddr; - bool split2ndAccess; - uint8_t split2ndData; - PacketDataPtr split2ndDataPtr; - unsigned split2ndFlags; - bool splitInst; - int splitFinishCnt; - uint64_t *split2ndStoreDataPtr; - bool splitInstSked; - - //////////////////////////////////////////////////////////// - // - // BASE INSTRUCTION INFORMATION. - // - //////////////////////////////////////////////////////////// - std::string instName() - { return (staticInst) ? staticInst->getName() : "undecoded-inst"; } - - void setStaticInst(StaticInstPtr si); - - ExtMachInst getMachInst() { return staticInst->machInst; } - - /** Sets the StaticInst. */ - void setStaticInst(StaticInstPtr &static_inst); - - /** Sets the sequence number. */ - void setSeqNum(InstSeqNum seq_num) { seqNum = seq_num; } - - /** Sets the ASID. */ - void setASID(short addr_space_id) { asid = addr_space_id; } - - /** Reads the thread id. */ - short readTid() { return threadNumber; } - - /** Sets the thread id. */ - void setTid(ThreadID tid) { threadNumber = tid; } - - void setVpn(int id) { virtProcNumber = id; } - - int readVpn() { return virtProcNumber; } - - /** Sets the pointer to the thread state. */ - void setThreadState(InOrderThreadState *state) { thread = state; } - - /** Returns the thread context. */ - ThreadContext *tcBase() { return thread->getTC(); } - - /** Returns the fault type. */ - Fault getFault() { return fault; } - - /** Read this CPU's ID. */ - int cpuId() const; - - /** Read this context's system-wide ID **/ - int contextId() const { return thread->contextId(); } - - //////////////////////////////////////////////////////////// - // - // INSTRUCTION TYPES - Forward checks to StaticInst object. - // - //////////////////////////////////////////////////////////// - bool isNop() const { return staticInst->isNop(); } - bool isMemRef() const { return staticInst->isMemRef(); } - bool isLoad() const { return staticInst->isLoad(); } - bool isStore() const { return staticInst->isStore(); } - bool isStoreConditional() const - { return staticInst->isStoreConditional(); } - bool isInstPrefetch() const { return staticInst->isInstPrefetch(); } - bool isDataPrefetch() const { return staticInst->isDataPrefetch(); } - bool isInteger() const { return staticInst->isInteger(); } - bool isFloating() const { return staticInst->isFloating(); } - bool isControl() const { return staticInst->isControl(); } - bool isCall() const { return staticInst->isCall(); } - bool isReturn() const { return staticInst->isReturn(); } - bool isDirectCtrl() const { return staticInst->isDirectCtrl(); } - bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); } - bool isCondCtrl() const { return staticInst->isCondCtrl(); } - bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } - bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); } - - bool isThreadSync() const { return staticInst->isThreadSync(); } - bool isSerializing() const { return staticInst->isSerializing(); } - bool isSerializeBefore() const - { return staticInst->isSerializeBefore() || status[SerializeBefore]; } - bool isSerializeAfter() const - { return staticInst->isSerializeAfter() || status[SerializeAfter]; } - bool isMemBarrier() const { return staticInst->isMemBarrier(); } - bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } - bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } - bool isQuiesce() const { return staticInst->isQuiesce(); } - bool isIprAccess() const { return staticInst->isIprAccess(); } - bool isUnverifiable() const { return staticInst->isUnverifiable(); } - bool isSyscall() const - { return staticInst->isSyscall(); } - bool isMicroop() const { return staticInst->isMicroop(); } - bool isLastMicroop() const { return staticInst->isLastMicroop(); } - - - ///////////////////////////////////////////// - // - // RESOURCE SCHEDULING - // - ///////////////////////////////////////////// - typedef ThePipeline::RSkedPtr RSkedPtr; - bool inFrontEnd; - - RSkedPtr frontSked; - RSkedIt frontSked_end; - - RSkedPtr backSked; - RSkedIt backSked_end; - - RSkedIt curSkedEntry; - - void setFrontSked(RSkedPtr front_sked) - { - frontSked = front_sked; - frontSked_end.init(frontSked); - frontSked_end = frontSked->end(); - //DPRINTF(InOrderDynInst, "Set FrontSked End to : %x \n" , - // frontSked_end.getIt()/*, frontSked->end()*/); - //assert(frontSked_end == frontSked->end()); - - // This initializes instruction to be able - // to walk the resource schedule - curSkedEntry.init(frontSked); - curSkedEntry = frontSked->begin(); - } - - void setBackSked(RSkedPtr back_sked) - { - backSked = back_sked; - backSked_end.init(backSked); - backSked_end = backSked->end(); - } - - void setNextStage(int stage_num) { nextStage = stage_num; } - int getNextStage() { return nextStage; } - - /** Print Resource Schedule */ - void printSked() - { - if (frontSked != NULL) { - frontSked->print(); - } - - if (backSked != NULL) { - backSked->print(); - } - } - - /** Return Next Resource Stage To Be Used */ - int nextResStage() - { - assert((inFrontEnd && curSkedEntry != frontSked_end) || - (!inFrontEnd && curSkedEntry != backSked_end)); - - return curSkedEntry->stageNum; - } - - - /** Return Next Resource To Be Used */ - int nextResource() - { - assert((inFrontEnd && curSkedEntry != frontSked_end) || - (!inFrontEnd && curSkedEntry != backSked_end)); - - return curSkedEntry->resNum; - } - - /** Finish using a schedule entry, increment to next entry */ - bool finishSkedEntry() - { - curSkedEntry++; - - if (inFrontEnd && curSkedEntry == frontSked_end) { - DPRINTF(InOrderDynInst, "[sn:%i] Switching to " - "back end schedule.\n", seqNum); - assert(backSked != NULL); - curSkedEntry.init(backSked); - curSkedEntry = backSked->begin(); - inFrontEnd = false; - } else if (!inFrontEnd && curSkedEntry == backSked_end) { - return true; - } - - DPRINTF(InOrderDynInst, "[sn:%i] Next Stage: %i " - "Next Resource: %i.\n", seqNum, curSkedEntry->stageNum, - curSkedEntry->resNum); - - return false; - } - - /** Release a Resource Request (Currently Unused) */ - void releaseReq(ResourceRequest* req); - - //////////////////////////////////////////// - // - // INSTRUCTION EXECUTION - // - //////////////////////////////////////////// - /** Returns the opclass of this instruction. */ - OpClass opClass() const { return staticInst->opClass(); } - - /** Executes the instruction.*/ - Fault execute(); - - unsigned curResSlot; - - unsigned getCurResSlot() { return curResSlot; } - - void setCurResSlot(unsigned slot_num) { curResSlot = slot_num; } - - /** Calls a syscall. */ - /** Calls hardware return from error interrupt. */ - Fault hwrei(); - /** Traps to handle specified fault. */ - void trap(const Fault &fault); - bool simPalCheck(int palFunc); - short syscallNum; - - /** Emulates a syscall. */ - void syscall(int64_t callnum); - - //////////////////////////////////////////////////////////// - // - // PROGRAM COUNTERS - PC/NPC/NPC - // - //////////////////////////////////////////////////////////// - /** Read the PC of this instruction. */ - TheISA::PCState pcState() const { return pc; } - - /** Sets the PC of this instruction. */ - void pcState(const TheISA::PCState &_pc) { pc = _pc; } - - const Addr instAddr() { return pc.instAddr(); } - const Addr nextInstAddr() { return pc.nextInstAddr(); } - const MicroPC microPC() { return pc.microPC(); } - - //////////////////////////////////////////////////////////// - // - // BRANCH PREDICTION - // - //////////////////////////////////////////////////////////// - /** Set the predicted target of this current instruction. */ - void setPredTarg(const TheISA::PCState &predictedPC) - { predPC = predictedPC; } - - /** Returns the predicted target of the branch. */ - TheISA::PCState readPredTarg() { return predPC; } - - /** Returns the predicted PC immediately after the branch. */ - Addr predInstAddr() { return predPC.instAddr(); } - - /** Returns the predicted PC two instructions after the branch */ - Addr predNextInstAddr() { return predPC.nextInstAddr(); } - - /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predPC.microPC(); } - - /** Returns whether the instruction was predicted taken or not. */ - bool predTaken() { return predictTaken; } - - /** Returns whether the instruction mispredicted. */ - bool - mispredicted() - { - TheISA::PCState nextPC = pc; - TheISA::advancePC(nextPC, staticInst); - return !(nextPC == predPC); - } - - /** Returns the branch target address. */ - TheISA::PCState branchTarget() const - { return staticInst->branchTarget(pc); } - - /** Checks whether or not this instruction has had its branch target - * calculated yet. For now it is not utilized and is hacked to be - * always false. - * @todo: Actually use this instruction. - */ - bool doneTargCalc() { return false; } - - void setBranchPred(bool prediction) { predictTaken = prediction; } - - int squashingStage; - - bool predictTaken; - - bool procDelaySlotOnMispred; - - void setSquashInfo(unsigned stage_num); - - //////////////////////////////////////////// - // - // MEMORY ACCESS - // - //////////////////////////////////////////// - - Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); - - Fault writeMem(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res); - - /** Initiates a memory access - Calculate Eff. Addr & Initiate Memory - * Access Only valid for memory operations. - */ - Fault initiateAcc(); - - /** Completes a memory access - Only valid for memory operations. */ - Fault completeAcc(Packet *pkt); - - /** Calculates Eff. Addr. part of a memory instruction. */ - Fault calcEA(); - - /** Read Effective Address from instruction & do memory access */ - Fault memAccess(); - - RequestPtr fetchMemReq; - RequestPtr dataMemReq; - - bool memAddrReady; - - bool validMemAddr() - { return memAddrReady; } - - void setMemAddr(Addr addr) - { memAddr = addr; memAddrReady = true;} - - void unsetMemAddr() - { memAddrReady = false;} - - Addr getMemAddr() - { return memAddr; } - - /** Sets the effective address. */ - void setEA(Addr ea) { instEffAddr = ea; eaCalcDone = true; } - - /** Returns the effective address. */ - Addr getEA() const { return instEffAddr; } - - /** Returns whether or not the eff. addr. calculation has been completed.*/ - bool doneEACalc() { return eaCalcDone; } - - /** Returns whether or not the eff. addr. source registers are ready. - * Assume that src registers 1..n-1 are the ones that the - * EA calc depends on. (i.e. src reg 0 is the source of the data to be - * stored) - */ - bool eaSrcsReady() - { - for (int i = 1; i < numSrcRegs(); ++i) { - if (!_readySrcRegIdx[i]) - return false; - } - - return true; - } - - ////////////////////////////////////////////////// - // - // SOURCE-DESTINATION REGISTER INDEXING - // - ////////////////////////////////////////////////// - /** Returns the number of source registers. */ - int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } - - /** Returns the number of destination registers. */ - int8_t numDestRegs() const { return staticInst->numDestRegs(); } - - // the following are used to track physical register usage - // for machines with separate int & FP reg files - int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); } - int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); } - - /** Returns the logical register index of the i'th destination register. */ - RegIndex destRegIdx(int i) const { return staticInst->destRegIdx(i); } - - /** Returns the logical register index of the i'th source register. */ - RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); } - - ////////////////////////////////////////////////// - // - // RENAME/PHYSICAL REGISTER FILE SUPPORT - // - ////////////////////////////////////////////////// - /** Returns the physical register index of the i'th destination - * register. - */ - PhysRegIndex renamedDestRegIdx(int idx) const - { - return _destRegIdx[idx]; - } - - /** Returns the physical register index of the i'th source register. */ - PhysRegIndex renamedSrcRegIdx(int idx) const - { - return _srcRegIdx[idx]; - } - - /** Flattens a source architectural register index into a logical index. - */ - void flattenSrcReg(int idx, TheISA::RegIndex flattened_src) - { - _flatSrcRegIdx[idx] = flattened_src; - } - - /** Flattens a destination architectural register index into a logical - * index. - */ - void flattenDestReg(int idx, TheISA::RegIndex flattened_dest) - { - _flatDestRegIdx[idx] = flattened_dest; - } - - /** Returns the flattened register index of the i'th destination - * register. - */ - TheISA::RegIndex flattenedDestRegIdx(int idx) const - { - return _flatDestRegIdx[idx]; - } - - /** Returns the flattened register index of the i'th source register */ - TheISA::RegIndex flattenedSrcRegIdx(int idx) const - { - return _flatSrcRegIdx[idx]; - } - - /** Returns the physical register index of the previous physical register - * that remapped to the same logical register index. - */ - PhysRegIndex prevDestRegIdx(int idx) const - { - return _prevDestRegIdx[idx]; - } - - /** Returns if a source register is ready. */ - bool isReadySrcRegIdx(int idx) const - { - return this->_readySrcRegIdx[idx]; - } - - /** Records that one of the source registers is ready. */ - void markSrcRegReady() - { - if (++readyRegs == numSrcRegs()) { - status.set(CanIssue); - } - } - - /** Marks a specific register as ready. */ - void markSrcRegReady(RegIndex src_idx) - { - _readySrcRegIdx[src_idx] = true; - - markSrcRegReady(); - } - - /** Renames a destination register to a physical register. Also records - * the previous physical register that the logical register mapped to. - */ - void renameDestReg(int idx, - PhysRegIndex renamed_dest, - PhysRegIndex previous_rename) - { - _destRegIdx[idx] = renamed_dest; - _prevDestRegIdx[idx] = previous_rename; - } - - /** Renames a source logical register to the physical register which - * has/will produce that logical register's result. - * @todo: add in whether or not the source register is ready. - */ - void renameSrcReg(int idx, PhysRegIndex renamed_src) - { - _srcRegIdx[idx] = renamed_src; - } - - - PhysRegIndex readDestRegIdx(int idx) - { - return _destRegIdx[idx]; - } - - void setDestRegIdx(int idx, PhysRegIndex dest_idx) - { - _destRegIdx[idx] = dest_idx; - } - - int getDestIdxNum(PhysRegIndex dest_idx) - { - for (int i=0; i < staticInst->numDestRegs(); i++) { - if (_flatDestRegIdx[i] == dest_idx) - return i; - } - - return -1; - } - - PhysRegIndex readSrcRegIdx(int idx) - { - return _srcRegIdx[idx]; - } - - void setSrcRegIdx(int idx, PhysRegIndex src_idx) - { - _srcRegIdx[idx] = src_idx; - } - - int getSrcIdxNum(PhysRegIndex src_idx) - { - for (int i=0; i < staticInst->numSrcRegs(); i++) { - if (_srcRegIdx[i] == src_idx) - return i; - } - - return -1; - } - - //////////////////////////////////////////////////// - // - // SOURCE-DESTINATION REGISTER VALUES - // - //////////////////////////////////////////////////// - - /** Functions that sets an integer or floating point - * source register to a value. */ - void setIntSrc(int idx, uint64_t val); - void setFloatSrc(int idx, FloatReg val); - void setFloatRegBitsSrc(int idx, TheISA::FloatRegBits val); - - TheISA::IntReg* getIntSrcPtr(int idx) { return &instSrc[idx].intVal; } - uint64_t readIntSrc(int idx) { return instSrc[idx].intVal; } - - /** These Instructions read a integer/float/misc. source register - * value in the instruction. The instruction's execute function will - * call these and it is the interface that is used by the ISA descr. - * language (which is why the name isnt readIntSrc(...)) Note: That - * the source reg. value is set using the setSrcReg() function. - */ - IntReg readIntRegOperand(const StaticInst *si, int idx, ThreadID tid); - IntReg readIntRegOperand(const StaticInst *si, int idx) { - return readIntRegOperand(si, idx, 0); - } - FloatReg readFloatRegOperand(const StaticInst *si, int idx); - TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx); - MiscReg readMiscReg(int misc_reg); - MiscReg readMiscRegNoEffect(int misc_reg); - MiscReg readMiscRegOperand(const StaticInst *si, int idx); - MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx); - - /** Returns the result value instruction. */ - ResultType resultType(int idx) - { - return instResult[idx].type; - } - - IntReg readIntResult(int idx) - { - return instResult[idx].res.intVal; - } - - FloatReg readFloatResult(int idx) - { - return instResult[idx].res.fpVal.f; - } - - FloatRegBits readFloatBitsResult(int idx) - { - return instResult[idx].res.fpVal.i; - } - - CCReg readCCResult(int idx) - { - return instResult[idx].res.intVal; - } - - Tick readResultTime(int idx) { return instResult[idx].tick; } - - IntReg* getIntResultPtr(int idx) { return &instResult[idx].res.intVal; } - - /** This is the interface that an instruction will use to write - * it's destination register. - */ - void setIntRegOperand(const StaticInst *si, int idx, IntReg val); - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val); - void setFloatRegOperandBits(const StaticInst *si, int idx, - TheISA::FloatRegBits val); - void setMiscReg(int misc_reg, const MiscReg &val); - void setMiscRegNoEffect(int misc_reg, const MiscReg &val); - void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val); - void setMiscRegOperandNoEffect(const StaticInst *si, int idx, - const MiscReg &val); - - MiscReg readRegOtherThread(int idx, ThreadID tid); - void setRegOtherThread(int idx, MiscReg val, ThreadID tid); - - /** Returns the number of consecutive store conditional failures. */ - unsigned int readStCondFailures() const - { return thread->storeCondFailures; } - - /** Sets the number of consecutive store conditional failures. */ - void setStCondFailures(unsigned int sc_failures) - { thread->storeCondFailures = sc_failures; } - - ////////////////////////////////////////////////////////////// - // - // INSTRUCTION STATUS FLAGS (READ/SET) - // - ////////////////////////////////////////////////////////////// - /** Sets this instruction as entered on the CPU Reg Dep Map */ - void setRegDepEntry() { status.set(RegDepMapEntry); } - - /** Unsets this instruction as entered on the CPU Reg Dep Map */ - void clearRegDepEntry() { status.reset(RegDepMapEntry); } - - /** Returns whether or not the entry is on the CPU Reg Dep Map */ - bool isRegDepEntry() const { return status[RegDepMapEntry]; } - - /** Sets this instruction as entered on the CPU Reg Dep Map */ - void setRemoveList() { status.set(RemoveList); } - - /** Returns whether or not the entry is on the CPU Reg Dep Map */ - bool isRemoveList() const { return status[RemoveList]; } - - /** Sets this instruction as completed. */ - void setCompleted() { status.set(Completed); } - - /** Returns whether or not this instruction is completed. */ - bool isCompleted() const { return status[Completed]; } - - /** Marks the result as ready. */ - void setResultReady() { status.set(ResultReady); } - - /** Returns whether or not the result is ready. */ - bool isResultReady() const { return status[ResultReady]; } - - /** Sets this instruction as ready to issue. */ - void setCanIssue() { status.set(CanIssue); } - - /** Returns whether or not this instruction is ready to issue. */ - bool readyToIssue() const { return status[CanIssue]; } - - /** Sets this instruction as issued from the IQ. */ - void setIssued() { status.set(Issued); } - - /** Returns whether or not this instruction has issued. */ - bool isIssued() const { return status[Issued]; } - - /** Sets this instruction as executed. */ - void setExecuted() { status.set(Executed); } - - /** Returns whether or not this instruction has executed. */ - bool isExecuted() const { return status[Executed]; } - - /** Sets this instruction as ready to commit. */ - void setCanCommit() { status.set(CanCommit); } - - /** Clears this instruction as being ready to commit. */ - void clearCanCommit() { status.reset(CanCommit); } - - /** Returns whether or not this instruction is ready to commit. */ - bool readyToCommit() const { return status[CanCommit]; } - - void setAtCommit() { status.set(AtCommit); } - - bool isAtCommit() { return status[AtCommit]; } - - /** Sets this instruction as committed. */ - void setCommitted() { status.set(Committed); } - - /** Returns whether or not this instruction is committed. */ - bool isCommitted() const { return status[Committed]; } - - /** Sets this instruction as squashed. */ - void setSquashed() { status.set(Squashed); } - - /** Returns whether or not this instruction is squashed. */ - bool isSquashed() const { return status[Squashed]; } - - /** Temporarily sets this instruction as a serialize before instruction. */ - void setSerializeBefore() { status.set(SerializeBefore); } - - /** Clears the serializeBefore part of this instruction. */ - void clearSerializeBefore() { status.reset(SerializeBefore); } - - /** Checks if this serializeBefore is only temporarily set. */ - bool isTempSerializeBefore() { return status[SerializeBefore]; } - - /** Temporarily sets this instruction as a serialize after instruction. */ - void setSerializeAfter() { status.set(SerializeAfter); } - - /** Clears the serializeAfter part of this instruction.*/ - void clearSerializeAfter() { status.reset(SerializeAfter); } - - /** Checks if this serializeAfter is only temporarily set. */ - bool isTempSerializeAfter() { return status[SerializeAfter]; } - - /** Sets the serialization part of this instruction as handled. */ - void setSerializeHandled() { status.set(SerializeHandled); } - - /** Checks if the serialization part of this instruction has been - * handled. This does not apply to the temporary serializing - * state; it only applies to this instruction's own permanent - * serializing state. - */ - bool isSerializeHandled() { return status[SerializeHandled]; } - - private: - /** Instruction effective address. - * @todo: Consider if this is necessary or not. - */ - Addr instEffAddr; - - /** Whether or not the effective address calculation is completed. - * @todo: Consider if this is necessary or not. - */ - bool eaCalcDone; - - public: - /** Load queue index. */ - int16_t lqIdx; - - /** Store queue index. */ - int16_t sqIdx; - - /** Iterator pointing to this BaseDynInst in the list of all insts. */ - ListIt instListIt; - - bool onInstList; - - /** Returns iterator to this instruction in the list of all insts. */ - ListIt getInstListIt() { return instListIt; } - - /** Sets iterator for this instruction in the list of all insts. */ - void setInstListIt(ListIt _instListIt) { onInstList = true; instListIt = _instListIt; } - - /** Count of total number of dynamic instructions. */ - static int instcount; - - void resetInstCount(); - - /** Dumps out contents of this BaseDynInst. */ - void dump(); - - /** Dumps out contents of this BaseDynInst into given string. */ - void dump(std::string &outstring); - - //inline int curCount() { return curCount(); } - - - CCReg readCCRegOperand(const StaticInst *si, int idx) { - panic("readCCRegOperand unimplemented"); - } - - void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { - panic("setCCRegOperand unimplemented"); - } - - void setPredicate(bool val) { - panic("setPredicate unimplemented"); - } - - bool readPredicate() { - panic("readPredicate unimplemented"); - } - - void demapPage(Addr vaddr, uint64_t asn) { - panic("demapPage unimplemented"); - } - - public: - // monitor/mwait funtions - void armMonitor(Addr address); - bool mwait(PacketPtr pkt); - void mwaitAtomic(ThreadContext *tc); - AddressMonitor *getAddrMonitor(); -}; - - -#endif // __CPU_BASE_DYN_INST_HH__ diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc deleted file mode 100644 index 8edb5b1cc..000000000 --- a/src/cpu/inorder/inorder_trace.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2001-2005 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 <iomanip> - -#include "config/the_isa.hh" -#include "cpu/inorder/inorder_trace.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/exetrace.hh" -#include "cpu/static_inst.hh" -#include "cpu/thread_context.hh" -#include "debug/ExecEnable.hh" -#include "params/InOrderTrace.hh" - -using namespace std; -using namespace TheISA; - -namespace Trace { - -inline void -Trace::InOrderTraceRecord::dumpTicks(std::ostream &outs) -{ - if (!stageTrace) { - ccprintf(outs, "%7d: ", when); - } else { - ccprintf(outs, ""); - for (int i=0; i < stageCycle.size(); i++) { - if (i < stageCycle.size() - 1) - outs << dec << stageCycle[i] << "-"; - else - outs << dec << stageCycle[i] << ":"; - } - } -} - -InOrderTraceRecord * -InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing, - ThreadContext *tc) -{ - if (!Debug::ExecEnable) - return NULL; - - if (!Trace::enabled) - return NULL; - - return new InOrderTraceRecord(num_stages, stage_tracing, tc, 0); -} - -InOrderTraceRecord * -InOrderTrace::getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, TheISA::PCState _pc, - const StaticInstPtr macroStaticInst) -{ - return new InOrderTraceRecord(ThePipeline::NumStages, true, tc, _pc); -} - -} // namespace Trace - -//////////////////////////////////////////////////////////////////////// -// -// ExeTracer Simulation Object -// -Trace::InOrderTrace * -InOrderTraceParams::create() -{ - return new Trace::InOrderTrace(this); -}; - diff --git a/src/cpu/inorder/inorder_trace.hh b/src/cpu/inorder/inorder_trace.hh deleted file mode 100644 index bb90f305e..000000000 --- a/src/cpu/inorder/inorder_trace.hh +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * Copyright (c) 2001-2005 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_INORDER_TRACE_HH__ -#define __CPU_INORDER_INORDER_TRACE_HH__ - -#include "base/trace.hh" -#include "base/types.hh" -#include "cpu/exetrace.hh" -#include "cpu/static_inst.hh" -#include "params/InOrderTrace.hh" -#include "sim/insttracer.hh" - -class ThreadContext; - -namespace Trace { - -class InOrderTraceRecord : public ExeTracerRecord -{ - public: - InOrderTraceRecord(unsigned num_stages, bool _stage_tracing, - ThreadContext *_thread, TheISA::PCState _pc) - : ExeTracerRecord(0, _thread, NULL, _pc) - { - stageTrace = _stage_tracing; - stageCycle.resize(num_stages); - } - - // Trace stage-by-stage execution of instructions. - bool stageTrace; - std::vector<Tick> stageCycle; - - void dumpTicks(std::ostream &outs); - - void - setStageCycle(int num_stage, Tick cur_cycle) - { - if (stageTrace) { - stageCycle[num_stage] = cur_cycle; - } else { - when = cur_cycle; - } - } - - void - setStaticInst(const StaticInstPtr &_staticInst) - { - staticInst = _staticInst; - } - - void setPC(TheISA::PCState _pc) { pc = _pc; } -}; - -class InOrderTrace : public InstTracer -{ - public: - InOrderTrace(const InOrderTraceParams *p) : InstTracer(p) - {} - - InOrderTraceRecord * - getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc); - - InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, TheISA::PCState pc, - const StaticInstPtr macroStaticInst = NULL); -}; - -} // namespace Trace - -#endif // __CPU_INORDER_INORDER_TRACE_HH__ diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc deleted file mode 100644 index 5e94c665f..000000000 --- a/src/cpu/inorder/pipeline_stage.cc +++ /dev/null @@ -1,1125 +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 "base/str.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/pipeline_stage.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/Activity.hh" -#include "debug/InOrderStage.hh" -#include "debug/InOrderStall.hh" -#include "debug/Resource.hh" -#include "debug/ThreadModel.hh" - -using namespace std; -using namespace ThePipeline; - -PipelineStage::PipelineStage(Params *params, unsigned stage_num) - : stageNum(stage_num), stageWidth(params->stageWidth), - numThreads(ThePipeline::MaxThreads), _status(Inactive), - stageBufferMax(params->stageWidth), - prevStageValid(false), nextStageValid(false), idle(false) -{ - init(params); -} - -PipelineStage::~PipelineStage() -{ - for(ThreadID tid = 0; tid < numThreads; tid++) { - skidBuffer[tid].clear(); - stalls[tid].resources.clear(); - } -} - -void -PipelineStage::init(Params *params) -{ - for(ThreadID tid = 0; tid < numThreads; tid++) { - stageStatus[tid] = Idle; - - for (int stNum = 0; stNum < NumStages; stNum++) { - stalls[tid].stage[stNum] = false; - } - stalls[tid].resources.clear(); - - if (stageNum < BackEndStartStage) - lastStallingStage[tid] = BackEndStartStage - 1; - else - lastStallingStage[tid] = NumStages - 1; - } - - if ((InOrderCPU::ThreadModel) params->threadModel == - InOrderCPU::SwitchOnCacheMiss) { - switchedOutBuffer.resize(ThePipeline::MaxThreads); - switchedOutValid.resize(ThePipeline::MaxThreads); - } -} - - -std::string -PipelineStage::name() const -{ - return cpu->name() + ".stage" + to_string(stageNum); -} - - -void -PipelineStage::regStats() -{ - idleCycles - .name(name() + ".idleCycles") - .desc("Number of cycles 0 instructions are processed."); - - runCycles - .name(name() + ".runCycles") - .desc("Number of cycles 1+ instructions are processed."); - - utilization - .name(name() + ".utilization") - .desc("Percentage of cycles stage was utilized (processing insts).") - .precision(6); - utilization = (runCycles / cpu->numCycles) * 100; - -} - - -void -PipelineStage::setCPU(InOrderCPU *cpu_ptr) -{ - cpu = cpu_ptr; - - DPRINTF(InOrderStage, "Set CPU pointer.\n"); - - tracer = dynamic_cast<Trace::InOrderTrace *>(cpu->getTracer()); -} - - -void -PipelineStage::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) -{ - DPRINTF(InOrderStage, "Setting time buffer pointer.\n"); - timeBuffer = tb_ptr; - - // Setup wire to write information back to fetch. - // @todo: should this be writing to the next stage => -1 and reading from is (0)??? - toPrevStages = timeBuffer->getWire(0); - - // Create wires to get information from proper places in time buffer. - fromNextStages = timeBuffer->getWire(-1); -} - - -void -PipelineStage::setPrevStageQueue(TimeBuffer<InterStageStruct> *prev_stage_ptr) -{ - DPRINTF(InOrderStage, "Setting previous stage queue pointer.\n"); - prevStageQueue = prev_stage_ptr; - - // Setup wire to read information from fetch queue. - prevStage = prevStageQueue->getWire(-1); - - prevStageValid = true; -} - - - -void -PipelineStage::setNextStageQueue(TimeBuffer<InterStageStruct> *next_stage_ptr) -{ - DPRINTF(InOrderStage, "Setting next stage pointer.\n"); - nextStageQueue = next_stage_ptr; - - // Setup wire to write information to proper place in stage queue. - nextStage = nextStageQueue->getWire(0); - nextStageValid = true; -} - - - -void -PipelineStage::setActiveThreads(list<ThreadID> *at_ptr) -{ - DPRINTF(InOrderStage, "Setting active threads list pointer.\n"); - activeThreads = at_ptr; -} - -/*inline void -PipelineStage::switchToActive() -{ - if (_status == Inactive) { - DPRINTF(Activity, "Activating stage.\n"); - - cpu->activateStage(stageNum); - - _status = Active; - } -}*/ - -void -PipelineStage::switchOut() -{ - // Stage can immediately switch out. - panic("Switching Out of Stages Unimplemented"); -} - - -void -PipelineStage::takeOverFrom() -{ - _status = Inactive; - - // Be sure to reset state and clear out any old instructions. - for (ThreadID tid = 0; tid < numThreads; ++tid) { - stageStatus[tid] = Idle; - - for (int stNum = 0; stNum < NumStages; stNum++) { - stalls[tid].stage[stNum] = false; - } - - stalls[tid].resources.clear(); - - skidBuffer[tid].clear(); - } - wroteToTimeBuffer = false; -} - - - -bool -PipelineStage::checkStall(ThreadID tid) const -{ - bool ret_val = false; - - // Only check pipeline stall from stage directly following this stage - if (nextStageValid && stalls[tid].stage[stageNum + 1]) { - DPRINTF(InOrderStage,"[tid:%i]: Stall fom Stage %i detected.\n", - tid, stageNum + 1); - ret_val = true; - } - - if (!stalls[tid].resources.empty()) { -#if TRACING_ON - string stall_src; - - for (int i=0; i < stalls[tid].resources.size(); i++) { - stall_src += stalls[tid].resources[i]->res->name() + ":"; - } - - DPRINTF(InOrderStage,"[tid:%i]: Stall fom resources (%s) detected.\n", - tid, stall_src); -#endif - ret_val = true; - } - - return ret_val; -} - - -void -PipelineStage::removeStalls(ThreadID tid) -{ - for (int st_num = 0; st_num < NumStages; st_num++) { - if (stalls[tid].stage[st_num]) { - DPRINTF(InOrderStage, "Removing stall from stage %i.\n", - st_num); - stalls[tid].stage[st_num] = false; - } - - if (toPrevStages->stageBlock[st_num][tid]) { - DPRINTF(InOrderStage, "Removing pending block from stage %i.\n", - st_num); - toPrevStages->stageBlock[st_num][tid] = false; - } - - if (fromNextStages->stageBlock[st_num][tid]) { - DPRINTF(InOrderStage, "Removing pending block from stage %i.\n", - st_num); - fromNextStages->stageBlock[st_num][tid] = false; - } - } - stalls[tid].resources.clear(); -} - -inline bool -PipelineStage::prevStageInstsValid() -{ - return prevStage->insts.size() > 0; -} - -bool -PipelineStage::isBlocked(ThreadID tid) -{ - return stageStatus[tid] == Blocked; -} - -bool -PipelineStage::block(ThreadID tid) -{ - DPRINTF(InOrderStage, "[tid:%d]: Blocking, sending block signal back to " - "previous stages.\n", tid); - - // If the stage status is blocked or unblocking then stage has not yet - // signalled fetch to unblock. In that case, there is no need to tell - // fetch to block. - if (stageStatus[tid] != Blocked) { - if (stageStatus[tid] != Unblocking) { - wroteToTimeBuffer = true; - } - - stageStatus[tid] = Blocked; - - if (prevStageValid) { - DPRINTF(InOrderStage, "[tid:%d]: Stage %i setting block signal.\n", - tid, stageNum); - toPrevStages->stageBlock[stageNum][tid] = true; - } - - return true; - } - - - return false; -} - -void -PipelineStage::blockDueToBuffer(ThreadID tid) -{ - DPRINTF(InOrderStage, "[tid:%d]: Blocking instructions from passing to " - "next stage.\n", tid); - - if (stageStatus[tid] != Blocked) { - if (stageStatus[tid] != Unblocking) { - wroteToTimeBuffer = true; - } - - // Set the status to Blocked. - stageStatus[tid] = Blocked; - } -} - -bool -PipelineStage::unblock(ThreadID tid) -{ - // @todo: Shouldnt this be if any available slots are open??? - // Stage is done unblocking only if the skid buffer is empty. - if (skidBuffer[tid].empty()) { - DPRINTF(InOrderStage, "[tid:%u]: Done unblocking.\n", tid); - - if (prevStageValid) - toPrevStages->stageUnblock[stageNum][tid] = true; - - wroteToTimeBuffer = true; - - stageStatus[tid] = Running; - - return true; - } - - DPRINTF(InOrderStage, "[tid:%u]: Currently unblocking.\n", tid); - return false; -} - -void -PipelineStage::setupSquash(DynInstPtr inst, ThreadID tid) -{ - if (cpu->lastSquashCycle[tid] == curTick() && - cpu->squashSeqNum[tid] < inst->seqNum){ - DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to " - "another stage's squash signal for after [sn:%i].\n", - inst->seqNum, cpu->squashSeqNum[tid]); - } else { - InstSeqNum squash_seq_num = inst->squashSeqNum; - unsigned squash_stage = (nextStageValid) ? stageNum + 1 - : stageNum; - - toPrevStages->stageInfo[squash_stage][tid].squash = true; - toPrevStages->stageInfo[squash_stage][tid].doneSeqNum = - squash_seq_num; - - DPRINTF(InOrderStage, "[tid:%i]: Setting up squashing after " - "[sn:%i], due to [sn:%i] %s. Squash-Start-Stage:%i\n", - tid, squash_seq_num, inst->seqNum, inst->instName(), - squash_stage); - - // Save squash num for later stage use - cpu->lastSquashCycle[tid] = curTick(); - cpu->squashSeqNum[tid] = squash_seq_num; - } -} - -void -PipelineStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid) -{ - squash(seq_num, tid); -} - -void -PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid) -{ - DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from " - "incoming stage queue.\n", tid); - - int insts_from_prev_stage = prevStage->insts.size(); - for (int i=0; i < insts_from_prev_stage; i++) { - if (prevStage->insts[i]->threadNumber == tid && - prevStage->insts[i]->seqNum > squash_seq_num) { - DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, " - "[sn:%i] PC %s.\n", - tid, - prevStage->insts[i]->seqNum, - prevStage->insts[i]->pcState()); - prevStage->insts[i]->setSquashed(); - - prevStage->insts[i] = cpu->dummyBufferInst; - } - } -} - -void -PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid) -{ - // Set status to squashing. - stageStatus[tid] = Squashing; - - squashPrevStageInsts(squash_seq_num, tid); - - DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from incoming stage" - " skidbuffer.\n", tid); - //@TODO: Walk Through List Using iterator and remove - // all instructions over the value - std::list<DynInstPtr>::iterator cur_it = skidBuffer[tid].begin(); - std::list<DynInstPtr>::iterator end_it = skidBuffer[tid].end(); - - while (cur_it != end_it) { - if ((*cur_it)->seqNum <= squash_seq_num) { - DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer " - "instructions (starting w/[sn:%i]) before " - "[sn:%i]. %i insts left.\n", tid, - (*cur_it)->seqNum, squash_seq_num, - skidBuffer[tid].size()); - cur_it++; - } else { - DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - " PC %s.\n", tid, (*cur_it)->seqNum, (*cur_it)->pc); - (*cur_it)->setSquashed(); - cur_it = skidBuffer[tid].erase(cur_it); - } - - } - -} - -int -PipelineStage::stageBufferAvail() -{ - unsigned total = 0; - - for (int i=0; i < ThePipeline::MaxThreads; i++) { - total += skidBuffer[i].size(); - } - - int avail = stageBufferMax - total; - assert(avail >= 0); - - return avail; -} - -bool -PipelineStage::canSendInstToStage(unsigned stage_num) -{ - bool buffer_avail = false; - - if (cpu->pipelineStage[stage_num]->prevStageValid) { - buffer_avail = cpu->pipelineStage[stage_num]->stageBufferAvail() - - cpu->pipelineStage[stage_num-1]->nextStage->insts.size() >= 1; - } - - if (!buffer_avail && nextStageQueueValid(stage_num)) { - DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n", - stageNum + 1); - } - - return buffer_avail; -} - -int -PipelineStage::skidSize() -{ - int total = 0; - - for (int i=0; i < ThePipeline::MaxThreads; i++) { - total += skidBuffer[i].size(); - } - - return total; -} - -bool -PipelineStage::skidsEmpty() -{ - list<ThreadID>::iterator threads = activeThreads->begin(); - - while (threads != activeThreads->end()) { - if (!skidBuffer[*threads++].empty()) - return false; - } - - return true; -} - - - -void -PipelineStage::updateStatus() -{ - bool any_unblocking = false; - - list<ThreadID>::iterator threads = activeThreads->begin(); - - while (threads != activeThreads->end()) { - ThreadID tid = *threads++; - - if (stageStatus[tid] == Unblocking) { - any_unblocking = true; - break; - } - } - - // Stage will have activity if it's unblocking. - if (any_unblocking) { - if (_status == Inactive) { - _status = Active; - - DPRINTF(Activity, "Activating stage.\n"); - - cpu->activateStage(stageNum); - } - } else { - // If it's not unblocking, then stage will not have any internal - // activity. Switch it to inactive. - if (_status == Active) { - _status = Inactive; - DPRINTF(Activity, "Deactivating stage.\n"); - - cpu->deactivateStage(stageNum); - } - } -} - -void -PipelineStage::activateThread(ThreadID tid) -{ - if (cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) { - if (!switchedOutValid[tid]) { - DPRINTF(InOrderStage, "[tid:%i] No instruction available in " - "switch out buffer.\n", tid); - } else { - DynInstPtr inst = switchedOutBuffer[tid]; - - DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%s into" - " stage skidBuffer %i\n", tid, inst->seqNum, - inst->pcState(), inst->threadNumber); - - // Make instruction available for pipeline processing - skidBuffer[tid].push_back(inst); - - // Update PC so that we start fetching after this instruction to - // prevent "double"-execution of instructions - cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType) - ResourcePool::UpdateAfterContextSwitch, - inst, Cycles(0), 0, tid); - - // Clear switchout buffer - switchedOutBuffer[tid] = NULL; - switchedOutValid[tid] = false; - - // Update any CPU stats based off context switches - cpu->updateContextSwitchStats(); - } - } - -} - - -void -PipelineStage::sortInsts() -{ - if (prevStageValid) { - assert(prevStage->insts.size() <= stageWidth); - - int insts_from_prev_stage = prevStage->insts.size(); - int insts_from_cur_stage = skidSize(); - DPRINTF(InOrderStage, "%i insts available from stage buffer %i. Stage " - "currently has %i insts from last cycle.\n", - insts_from_prev_stage, prevStageQueue->id(), - insts_from_cur_stage); - - int inserted_insts = 0; - - for (int i = 0; i < insts_from_prev_stage; i++) { - if (prevStage->insts[i]->isSquashed()) { - DPRINTF(InOrderStage, "[tid:%i]: Ignoring squashed [sn:%i], " - "not inserting into stage buffer.\n", - prevStage->insts[i]->readTid(), - prevStage->insts[i]->seqNum); - continue; - } - - ThreadID tid = prevStage->insts[i]->threadNumber; - - if (inserted_insts + insts_from_cur_stage == stageWidth) { - DPRINTF(InOrderStage, "Stage %i has accepted all insts " - "possible for this tick. Placing [sn:%i] in stage %i skidBuffer\n", - stageNum, prevStage->insts[i]->seqNum, stageNum - 1); - cpu->pipelineStage[stageNum - 1]-> - skidBuffer[tid].push_front(prevStage->insts[i]); - - int prev_stage = stageNum - 1; - if (cpu->pipelineStage[prev_stage]->stageStatus[tid] == Running || - cpu->pipelineStage[prev_stage]->stageStatus[tid] == Idle) { - cpu->pipelineStage[prev_stage]->stageStatus[tid] = Unblocking; - } - } else { - DPRINTF(InOrderStage, "[tid:%i]: Inserting [sn:%i] into stage " - "buffer.\n", prevStage->insts[i]->readTid(), - prevStage->insts[i]->seqNum); - - skidBuffer[tid].push_back(prevStage->insts[i]); - } - - prevStage->insts[i] = cpu->dummyBufferInst; - - inserted_insts++; - } - } -} - - - -void -PipelineStage::readStallSignals(ThreadID tid) -{ - for (int stage_idx = stageNum+1; stage_idx <= lastStallingStage[tid]; - stage_idx++) { - - DPRINTF(InOrderStage, "[tid:%i] Reading stall signals from Stage " - "%i. Block:%i Unblock:%i.\n", - tid, - stage_idx, - fromNextStages->stageBlock[stage_idx][tid], - fromNextStages->stageUnblock[stage_idx][tid]); - - // Check for Stage Blocking Signal - if (fromNextStages->stageBlock[stage_idx][tid]) { - DPRINTF(InOrderStage, "[tid:%i] Stall from stage %i set.\n", tid, - stage_idx); - stalls[tid].stage[stage_idx] = true; - } - - // Check for Stage Unblocking Signal - if (fromNextStages->stageUnblock[stage_idx][tid]) { - DPRINTF(InOrderStage, "[tid:%i] Stall from stage %i unset.\n", tid, - stage_idx); - stalls[tid].stage[stage_idx] = false; - } - } -} - - - -bool -PipelineStage::checkSignalsAndUpdate(ThreadID tid) -{ - // Check if there's a squash signal, squash if there is. - // Check stall signals, block if necessary. - // If status was blocked - // Check if stall conditions have passed - // if so then go to unblocking - // If status was Squashing - // check if squashing is not high. Switch to running this cycle. - - // Update the per thread stall statuses. - readStallSignals(tid); - - // Check for squash from later pipeline stages - for (int stage_idx=stageNum; stage_idx < NumStages; stage_idx++) { - if (fromNextStages->stageInfo[stage_idx][tid].squash) { - DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to " - "squash from stage %u.\n", tid, stage_idx); - InstSeqNum squash_seq_num = fromNextStages-> - stageInfo[stage_idx][tid].doneSeqNum; - squash(squash_seq_num, tid); - break; //return true; - } - } - - if (checkStall(tid)) { - return block(tid); - } - - if (stageStatus[tid] == Blocked) { - DPRINTF(InOrderStage, "[tid:%u]: Done blocking, switching to " - "unblocking.\n", tid); - - stageStatus[tid] = Unblocking; - - unblock(tid); - - return true; - } - - if (stageStatus[tid] == Squashing) { - if (!skidBuffer[tid].empty()) { - DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to " - "unblocking.\n", tid); - - stageStatus[tid] = Unblocking; - } else { - // Switch status to running if stage isn't being told to block or - // squash this cycle. - DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to " - "running.\n", tid); - - stageStatus[tid] = Running; - } - - return true; - } - - // If we've reached this point, we have not gotten any signals that - // cause stage to change its status. Stage remains the same as before.*/ - return false; -} - - - -void -PipelineStage::tick() -{ - idle = false; - - wroteToTimeBuffer = false; - - bool status_change = false; - - sortInsts(); - - instsProcessed = 0; - - processStage(status_change); - - if (status_change) { - updateStatus(); - } - - if (wroteToTimeBuffer) { - DPRINTF(Activity, "Activity this cycle.\n"); - cpu->activityThisCycle(); - } - - DPRINTF(InOrderStage, "\n\n"); -} - -void -PipelineStage::setResStall(ResReqPtr res_req, ThreadID tid) -{ - DPRINTF(InOrderStage, "Inserting stall from %s.\n", res_req->res->name()); - stalls[tid].resources.push_back(res_req); -} - -void -PipelineStage::unsetResStall(ResReqPtr res_req, ThreadID tid) -{ - // Search through stalls to find stalling request and then - // remove it - vector<ResReqPtr>::iterator req_it = stalls[tid].resources.begin(); - vector<ResReqPtr>::iterator req_end = stalls[tid].resources.end(); - - while (req_it != req_end) { - if( (*req_it)->res == res_req->res && // Same Resource - (*req_it)->inst == res_req->inst && // Same Instruction - (*req_it)->getSlot() == res_req->getSlot()) { - DPRINTF(InOrderStage, "[tid:%u]: Clearing stall by %s.\n", - tid, res_req->res->name()); - stalls[tid].resources.erase(req_it); - break; - } - - req_it++; - } - - if (stalls[tid].resources.size() == 0) { - DPRINTF(InOrderStage, "[tid:%u]: There are no remaining resource" - "stalls.\n", tid); - } -} - -// @TODO: Update How we handled threads in CPU. Maybe threads shouldnt be -// handled one at a time, but instead first come first serve by instruction? -// Questions are how should a pipeline stage handle thread-specific stalls & -// pipeline squashes -void -PipelineStage::processStage(bool &status_change) -{ - list<ThreadID>::iterator threads = activeThreads->begin(); - - //Check stall and squash signals. - while (threads != activeThreads->end()) { - ThreadID tid = *threads++; - - DPRINTF(InOrderStage,"Processing [tid:%i]\n",tid); - status_change = checkSignalsAndUpdate(tid) || status_change; - - processThread(status_change, tid); - } - - if (nextStageValid) { - DPRINTF(InOrderStage, "%i insts now available for stage %i.\n", - nextStage->insts.size(), stageNum + 1); - } - - if (instsProcessed > 0) { - ++runCycles; - idle = false; - } else { - ++idleCycles; - idle = true; - } - - DPRINTF(InOrderStage, "%i left in stage %i incoming buffer.\n", skidSize(), - stageNum); - - DPRINTF(InOrderStage, "%i available in stage %i incoming buffer.\n", - stageBufferAvail(), stageNum); -} - -void -PipelineStage::processThread(bool &status_change, ThreadID tid) -{ - // If status is Running or idle, - // call processInsts() - // If status is Unblocking, - // buffer any instructions coming from fetch - // continue trying to empty skid buffer - // check if stall conditions have passed - - // Stage should try to process as many instructions as its bandwidth - // will allow, as long as it is not currently blocked. - if (stageStatus[tid] == Running || - stageStatus[tid] == Idle) { - DPRINTF(InOrderStage, "[tid:%u]: Not blocked, so attempting to run " - "stage.\n",tid); - - processInsts(tid); - } else if (stageStatus[tid] == Unblocking) { - // Make sure that the skid buffer has something in it if the - // status is unblocking. - assert(!skidsEmpty()); - - // If the status was unblocking, then instructions from the skid - // buffer were used. Remove those instructions and handle - // the rest of unblocking. - processInsts(tid); - - status_change = unblock(tid) || status_change; - } -} - - -void -PipelineStage::processInsts(ThreadID tid) -{ - // Instructions can come either from the skid buffer or the list of - // instructions coming from fetch, depending on stage's status. - int insts_available = skidBuffer[tid].size(); - - std::list<DynInstPtr> &insts_to_stage = skidBuffer[tid]; - - if (insts_available == 0) { - DPRINTF(InOrderStage, "[tid:%u]: Nothing to do, breaking out" - " early.\n",tid); - return; - } - - DynInstPtr inst; - bool last_req_completed = true; - - while (insts_available > 0 && - instsProcessed < stageWidth && - last_req_completed) { - assert(!insts_to_stage.empty()); - - inst = insts_to_stage.front(); - - DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] " - "%s with PC %s\n", tid, inst->seqNum, - inst->instName(), - inst->pcState()); - - if (inst->isSquashed()) { - DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %s is " - "squashed, skipping.\n", - tid, inst->seqNum, inst->pcState()); - - insts_to_stage.pop_front(); - - --insts_available; - - continue; - } - - int reqs_processed = 0; - last_req_completed = processInstSchedule(inst, reqs_processed); - - // If the instruction isnt squashed & we've completed one request - // Then we can officially count this instruction toward the stage's - // bandwidth count - if (reqs_processed > 0) - instsProcessed++; - - // Don't let instruction pass to next stage if it hasnt completed - // all of it's requests for this stage. - if (!last_req_completed) - continue; - - // Send to Next Stage or Break Loop - if (nextStageValid && !sendInstToNextStage(inst)) { - DPRINTF(InOrderStage, "[tid:%i] [sn:%i] unable to proceed to stage" - " %i.\n", tid, inst->seqNum,inst->nextStage); - break; - } - - insts_to_stage.pop_front(); - - --insts_available; - } - - // If we didn't process all instructions, then we will need to block - // and put all those instructions into the skid buffer. - if (!insts_to_stage.empty()) { - blockDueToBuffer(tid); - } - - // Record that stage has written to the time buffer for activity - // tracking. - if (instsProcessed) { - wroteToTimeBuffer = true; - } -} - -bool -PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) -{ - bool last_req_completed = true; - ThreadID tid = inst->readTid(); - - if (inst->nextResStage() == stageNum) { - int res_stage_num = inst->nextResStage(); - - while (res_stage_num == stageNum) { - int res_num = inst->nextResource(); - - - DPRINTF(InOrderStage, "[tid:%i]: [sn:%i]: sending request to %s." - "\n", tid, inst->seqNum, cpu->resPool->name(res_num)); - - ResReqPtr req = cpu->resPool->request(res_num, inst); - assert(req->valid); - - bool req_completed = req->isCompleted(); - bool done_in_pipeline = false; - if (req_completed) { - DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s " - "completed.\n", tid, inst->seqNum, - cpu->resPool->name(res_num)); - - reqs_processed++; - - req->stagePasses++; - - done_in_pipeline = inst->finishSkedEntry(); - if (done_in_pipeline) { - DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] finished " - "in pipeline.\n", tid, inst->seqNum); - } - } else { - DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed." - "\n", tid, inst->seqNum, cpu->resPool->name(res_num)); - - last_req_completed = false; - - if (req->isMemStall() && - cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) { - // Save Stalling Instruction - DPRINTF(ThreadModel, "[tid:%i] [sn:%i] Detected cache " - "miss.\n", tid, inst->seqNum); - - DPRINTF(InOrderStage, "Inserting [tid:%i][sn:%i] into " - "switch out buffer.\n", tid, inst->seqNum); - - switchedOutBuffer[tid] = inst; - switchedOutValid[tid] = true; - - // Remove Thread From Pipeline & Resource Pool - inst->squashingStage = stageNum; - inst->squashSeqNum = inst->seqNum; - cpu->squashFromMemStall(inst, tid); - - // Switch On Cache Miss - //===================== - // Suspend Thread at end of cycle - DPRINTF(ThreadModel, "Suspending [tid:%i] due to cache " - "miss.\n", tid); - cpu->suspendContext(tid); - - // Activate Next Ready Thread at end of cycle - DPRINTF(ThreadModel, "Attempting to activate next ready " - "thread due to cache miss.\n"); - cpu->activateNextReadyContext(); - } - } - - // If this request is no longer needs to take up bandwidth in the - // resource, go ahead and free that bandwidth up - if (req->doneInResource) { - req->freeSlot(); - } - - // No longer need to process this instruction if the last - // request it had wasn't completed or if there is nothing - // else for it to do in the pipeline - if (done_in_pipeline || !req_completed) { - break; - } - - res_stage_num = inst->nextResStage(); - } - } else { - DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %s " - " needed no resources in stage %i.\n", - tid, inst->seqNum, inst->pcState(), stageNum); - } - - return last_req_completed; -} - -bool -PipelineStage::nextStageQueueValid(int stage_num) -{ - return cpu->pipelineStage[stage_num]->nextStageValid; -} - - -bool -PipelineStage::sendInstToNextStage(DynInstPtr inst) -{ - // Update Next Stage Variable in Instruction - // NOTE: Some Resources will update this nextStage var. to - // for bypassing, so can't always assume nextStage=stageNum+1 - if (inst->nextStage == stageNum) - inst->nextStage++; - - bool success = false; - ThreadID tid = inst->readTid(); - int next_stage = inst->nextStage; - int prev_stage = next_stage - 1; - - assert(next_stage >= 1); - assert(prev_stage >= 0); - - DPRINTF(InOrderStage, "[tid:%u]: Attempting to send instructions to " - "stage %u.\n", tid, stageNum+1); - - if (!canSendInstToStage(inst->nextStage)) { - DPRINTF(InOrderStage, "[tid:%u]: Could not send instruction to " - "stage %u.\n", tid, stageNum+1); - return false; - } - - - if (nextStageQueueValid(inst->nextStage - 1)) { - if (inst->seqNum > cpu->squashSeqNum[tid] && - curTick() == cpu->lastSquashCycle[tid]) { - DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, skipping " - "insertion into stage %i queue.\n", tid, inst->seqNum, - inst->nextStage); - } else { - if (nextStageValid) { - DPRINTF(InOrderStage, "[tid:%u] %i slots available in next " - "stage buffer.\n", tid, - cpu->pipelineStage[next_stage]->stageBufferAvail()); - } - - DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: being placed into " - "index %i of stage buffer %i queue.\n", - tid, inst->seqNum, - cpu->pipelineStage[prev_stage]->nextStage->insts.size(), - cpu->pipelineStage[prev_stage]->nextStageQueue->id()); - - // Place instructions in inter-stage communication struct for next - // pipeline stage to read next cycle - cpu->pipelineStage[prev_stage]->nextStage->insts.push_back(inst); - - success = true; - - // Take note of trace data for this inst & stage - if (inst->traceData) { - //@todo: exec traces are broke. fix them - inst->traceData->setStageCycle(stageNum, curTick()); - } - - } - } - - return success; -} - -void -PipelineStage::dumpInsts() -{ - cprintf("Insts in Stage %i skidbuffers\n",stageNum); - - for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - std::list<DynInstPtr>::iterator cur_it = skidBuffer[tid].begin(); - std::list<DynInstPtr>::iterator end_it = skidBuffer[tid].end(); - - while (cur_it != end_it) { - DynInstPtr inst = (*cur_it); - - cprintf("Inst. PC:%s\n[tid:%i]\n[sn:%i]\n\n", - inst->pcState(), inst->threadNumber, inst->seqNum); - - cur_it++; - } - } - -} diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh deleted file mode 100644 index 478561a8e..000000000 --- a/src/cpu/inorder/pipeline_stage.hh +++ /dev/null @@ -1,349 +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_PIPELINE_STAGE_HH__ -#define __CPU_INORDER_PIPELINE_STAGE_HH__ - -#include <queue> -#include <vector> - -#include "base/statistics.hh" -#include "cpu/inorder/comm.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/timebuf.hh" -#include "params/InOrderCPU.hh" - -class InOrderCPU; - -class PipelineStage -{ - protected: - typedef ThePipeline::Params Params; - typedef ThePipeline::DynInstPtr DynInstPtr; - - public: - /** Overall stage status. Used to determine if the CPU can - * deschedule itself due to a lack of activity. - */ - enum StageStatus { - Active, - Inactive - }; - - /** Individual thread status. */ - enum ThreadStatus { - Running, - Idle, - StartSquash, - Squashing, - Blocked, - Unblocking, - MemWaitResponse, - MemWaitRetry, - MemAccessComplete - }; - - protected: - /** The Number of This Pipeline Stage */ - unsigned stageNum; - - /** The width of stage, in instructions. */ - unsigned stageWidth; - - /** Number of Threads*/ - ThreadID numThreads; - - /** Stage status. */ - StageStatus _status; - - /** Per-thread status. */ - ThreadStatus stageStatus[ThePipeline::MaxThreads]; - - public: - PipelineStage(Params *params, unsigned stage_num); - - virtual ~PipelineStage(); - - /** PipelineStage initialization. */ - void init(Params *params); - - /** Returns the name of stage. */ - std::string name() const; - - /** Registers statistics. */ - void regStats(); - - /** Sets CPU pointer. */ - void setCPU(InOrderCPU *cpu_ptr); - - /** Sets the main backwards communication time buffer pointer. */ - void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); - - /** Sets pointer to time buffer coming from fetch. */ - void setPrevStageQueue(TimeBuffer<InterStageStruct> *prev_stage_ptr); - - /** Sets pointer to time buffer used to communicate to the next stage. */ - void setNextStageQueue(TimeBuffer<InterStageStruct> *next_stage_ptr); - - /** Sets pointer to list of active threads. */ - void setActiveThreads(std::list<ThreadID> *at_ptr); - - bool nextStageQueueValid(int stage_num); - - bool isBlocked(ThreadID tid); - - /** Changes the status of this stage to active, and indicates this - * to the CPU. - */ - //inline void switchToActive(); - - /** Changes the status of this stage to inactive, and indicates - * this to the CPU. - */ - //inline void switchToInactive(); - - /** Switches out the stage stage. */ - void switchOut(); - - /** Takes over from another CPU's thread. */ - virtual void takeOverFrom(); - - /** Ticks stage, processing all input signals and executing as many - * instructions as possible. - */ - void tick(); - - /** Set a resource stall in the pipeline-stage */ - void setResStall(ResReqPtr res_req, ThreadID tid); - - /** Unset a resource stall in the pipeline-stage */ - void unsetResStall(ResReqPtr res_req, ThreadID tid); - - /** Remove all stall signals for a particular thread; */ - void removeStalls(ThreadID tid); - - /** Is there room in the stage buffer? */ - int stageBufferAvail(); - - protected: - /** Evaluate Stage Conditions and then process stage */ - virtual void processStage(bool &status_change); - - /** Determines what to do based on stage's current status. - * @param status_change stage() sets this variable if there was a status - * change (ie switching from from blocking to unblocking). - * @param tid Thread id to stage instructions from. - */ - void processThread(bool &status_change, ThreadID tid); - - /** Processes instructions from fetch and passes them on to rename. - * Decoding of instructions actually happens when they are created in - * fetch, so this function mostly checks if PC-relative branches are - * correct. - */ - virtual void processInsts(ThreadID tid); - - /** Process all resources on an instruction's resource schedule */ - bool processInstSchedule(DynInstPtr inst, int &reqs_processed); - - /** Is there room in the next stage buffer for this instruction? */ - bool canSendInstToStage(unsigned stage_num); - - /** Send an instruction to the next stage buffer */ - bool sendInstToNextStage(DynInstPtr inst); - - /** Total size of all skid buffers */ - int skidSize(); - - /** Returns if all of the skid buffers are empty. */ - bool skidsEmpty(); - - /** Updates overall stage status based on all of the threads' statuses. */ - void updateStatus(); - - /** Separates instructions from fetch into individual lists of instructions - * sorted by thread. - */ - void sortInsts(); - - /** Reads all stall signals from the backwards communication timebuffer. */ - void readStallSignals(ThreadID tid); - - /** Checks all input signals and updates stage's status appropriately. */ - bool checkSignalsAndUpdate(ThreadID tid); - - /** Checks all stall signals, and returns if any are true. */ - bool checkStall(ThreadID tid) const; - - /** Returns if there any instructions from the previous stage - * on this cycle. - */ - inline bool prevStageInstsValid(); - - /** Switches stage to blocking, and signals back that stage has - * become blocked. - * @return Returns true if there is a status change. - */ - bool block(ThreadID tid); - - void blockDueToBuffer(ThreadID tid); - - /** Switches stage to unblocking if the skid buffer is empty, and - * signals back that stage has unblocked. - * @return Returns true if there is a status change. - */ - bool unblock(ThreadID tid); - - - public: - void activateThread(ThreadID tid); - - /** Setup Squashing Information to be passed back thru the pipeline */ - void setupSquash(DynInstPtr inst, ThreadID tid); - - virtual void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid); - - /** Perform squash of instructions above seq_num */ - virtual void squash(InstSeqNum squash_num, ThreadID tid); - - /** Squash instructions from stage buffer */ - void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid); - - void dumpInsts(); - - protected: - /** CPU interface. */ - InOrderCPU *cpu; - - Trace::InOrderTrace *tracer; - - /** List of active thread ids */ - std::list<ThreadID> *activeThreads; - - /** Buffer of instructions switched out to mem-stall. - * Only used when using SwitchOnCacheMiss threading model - * Used as 1-to-1 mapping between ThreadID and Entry. - */ - std::vector<DynInstPtr> switchedOutBuffer; - std::vector<bool> switchedOutValid; - - /** Instructions that we've processed this tick - * NOTE: "Processed" means completed at least 1 instruction request - */ - unsigned instsProcessed; - - /** Skid buffer between previous stage and this one. */ - std::list<DynInstPtr> skidBuffer[ThePipeline::MaxThreads]; - - /** Instruction used to signify that there is no *real* instruction in - * buffer slot */ - DynInstPtr dummyBufferInst; - - /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */ - Addr bdelayDoneSeqNum[ThePipeline::MaxThreads]; - - /** Tells when their is a pending delay slot inst. to send - * to rename. If there is, then wait squash after the next - * instruction (used for MIPS). - */ - bool squashAfterDelaySlot[ThePipeline::MaxThreads]; - - /** Instruction used for squashing branch (used for MIPS) */ - DynInstPtr squashInst[ThePipeline::MaxThreads]; - - /** Maximum size of the inter-stage buffer connecting the previous stage to - * this stage (which we call a skid buffer) */ - unsigned stageBufferMax; - - /** Variable that tracks if stage has written to the time buffer this - * cycle. Used to tell CPU if there is activity this cycle. - */ - bool wroteToTimeBuffer; - - /** Index of instructions being sent to the next stage. */ - unsigned toNextStageIndex; - - /** The last stage that this particular stage should look for stalls */ - int lastStallingStage[ThePipeline::MaxThreads]; - - /** Time buffer interface. */ - TimeBuffer<TimeStruct> *timeBuffer; - - public: - /** Wire to get rename's output from backwards time buffer. */ - TimeBuffer<TimeStruct>::wire fromNextStages; - - /** Wire to get iew's information from backwards time buffer. */ - TimeBuffer<TimeStruct>::wire toPrevStages; - - /** Instruction queue linking previous stage */ - TimeBuffer<InterStageStruct> *prevStageQueue; - - /** Wire to get the previous stage's. */ - TimeBuffer<InterStageStruct>::wire prevStage; - - /** Instruction queue linking next stage */ - TimeBuffer<InterStageStruct> *nextStageQueue; - - /** Wire to write to the next stage */ - TimeBuffer<InterStageStruct>::wire nextStage; - - /** Is Previous Stage Valid? */ - bool prevStageValid; - - /** Is Next Stage Valid? */ - bool nextStageValid; - - bool idle; - - /** Source of possible stalls. */ - struct Stalls { - bool stage[ThePipeline::NumStages]; - std::vector<ResReqPtr> resources; - }; - - /** Tracks stage/resource stalls */ - Stalls stalls[ThePipeline::MaxThreads]; - - /** Number of cycles 0 instruction(s) are processed. */ - Stats::Scalar idleCycles; - - /** Number of cycles 1+ instructions are processed. */ - Stats::Scalar runCycles; - - /** Percentage of cycles 1+ instructions are processed. */ - Stats::Formula utilization; - - -}; - -#endif diff --git a/src/cpu/inorder/pipeline_traits.5stage.cc b/src/cpu/inorder/pipeline_traits.5stage.cc deleted file mode 100644 index f15a3cb11..000000000 --- a/src/cpu/inorder/pipeline_traits.5stage.cc +++ /dev/null @@ -1,166 +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/resource_list.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" - -using namespace std; - -namespace ThePipeline { - -//@TODO: create my own Instruction Schedule Class -//that operates as a Priority QUEUE -int getNextPriority(DynInstPtr &inst, int stage_num) -{ - int cur_pri = 20; - - /* - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_it = inst->resSched.begin(); - - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_end = inst->resSched.end(); - - while (sked_it != sked_end) { - - if (sked_it.top()->stageNum == stage_num) { - cur_pri = sked_it.top()->priority; - } - - sked_it++; - } - */ - - return cur_pri; -} - -void createFrontEndSchedule(DynInstPtr &inst) -{ - int stNum = 0; - int stPri = 0; - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // IF - Stage 0 - // --------------------------------------- - inst_sched->push(new ScheduleEntry(stNum, stPri++, FetchSeq, FetchSeqUnit::AssignNextPC)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, ITLB, TLBUnit::FetchLookup)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, ICache, CacheUnit::InitiateFetch)); - - // - // DE - Stage 1 - // --------------------------------------- - stNum++; stPri = 0; - inst_sched->push(new ScheduleEntry(stNum, stPri++, ICache, CacheUnit::CompleteFetch)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, Decode, DecodeUnit::DecodeInst)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, BPred, BranchPredictor::PredictBranch)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, FetchSeq, FetchSeqUnit::UpdateTargetPC)); - -} - -bool createBackEndSchedule(DynInstPtr &inst) -{ - if (!inst->staticInst) { - return false; - } - - int stNum = BackEndStartStage; - int stPri = 0; - - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // EX - Stage 2 - // --------------------------------------- - for (int idx=0; idx < inst->numSrcRegs(); idx++) { - if (!idx || !inst->isStore()) - inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::ReadSrcReg, idx)); - } - - if ( inst->isNonSpeculative() ) { - // skip execution of non speculative insts until later - } else if (inst->isMemRef()) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, AGEN, AGENUnit::GenerateAddr)); - if ( inst->isLoad() ) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, DTLB, TLBUnit::DataLookup)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::InitiateReadData)); - } - } else { - inst_sched->push(new ScheduleEntry(stNum, stPri++, ExecUnit, ExecutionUnit::ExecuteInst)); - } - - // - // MEM - Stage 3 - // --------------------------------------- - stPri = 0; stNum++; - if ( inst->isStore() ) { // for store, need src reg at this point - inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::ReadSrcReg, 1)); - } - if ( inst->isLoad() ) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::CompleteReadData)); - } else if ( inst->isStore() ) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, DTLB, TLBUnit::DataLookup)); - inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::InitiateWriteData)); - } - - // - // WB - Stage 4 - // --------------------------------------- - stPri = 0; stNum++; - if (inst->isNonSpeculative()) { - if (inst->isMemRef()) - fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); - - if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); - } else { - inst_sched->push(new ScheduleEntry(stNum, stPri++, ExecUnit, ExecutionUnit::ExecuteInst)); - } - } - - if ( inst->isStore() ) - inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::CompleteWriteData)); - - // Write Back to Register File - for (int idx=0; idx < inst->numDestRegs(); idx++) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::WriteDestReg, idx)); - } - - // Graduate Instructions - inst_sched->push(new ScheduleEntry(stNum, stPri++, Grad, GraduationUnit::GraduateInst)); - - return true; -} - -}; diff --git a/src/cpu/inorder/pipeline_traits.5stage.hh b/src/cpu/inorder/pipeline_traits.5stage.hh deleted file mode 100644 index 5f1587587..000000000 --- a/src/cpu/inorder/pipeline_traits.5stage.hh +++ /dev/null @@ -1,145 +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_PIPELINE_IMPL_HH__ -#define __CPU_INORDER_PIPELINE_IMPL_HH__ - -#include <list> -#include <queue> -#include <vector> - -#include "arch/isa_traits.hh" - -class InOrderDynInst; - -/* This Namespace contains constants, typedefs, functions and - * objects specific to the Pipeline Implementation. - */ -namespace ThePipeline { - // Pipeline Constants - const unsigned NumStages = 5; - const unsigned MaxThreads = 3; - const unsigned StageWidth = 1; - const unsigned BackEndStartStage = 2; - - // Enumerated List of Resources The Pipeline Uses - enum ResourceList { - FetchSeq = 0, - ITLB, - ICache, - Decode, - BPred, - FetchBuff, - RegManager, - AGEN, - ExecUnit, - DTLB, - DCache, - Grad, - FetchBuff2 - }; - - // Expand this as necessary for your inter stage buffer sizes - static const unsigned interStageBuffSize[] = { - StageWidth, /* Stage 0 - 1 */ - StageWidth, /* Stage 1 - 2 */ - StageWidth, /* Stage 2 - 3 */ - StageWidth, /* Stage 3 - 4 */ - StageWidth, /* Stage 4 - 5 */ - StageWidth, /* Stage 5 - 6 */ - StageWidth, /* Stage 6 - 7 */ - StageWidth, /* Stage 7 - 8 */ - StageWidth /* Stage 8 - 9 */ - }; - - typedef InOrderCPUParams Params; - typedef RefCountingPtr<InOrderDynInst> DynInstPtr; - - ////////////////////////// - // RESOURCE SCHEDULING - ////////////////////////// - struct ScheduleEntry { - ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, - int _idx = 0) : - stageNum(stage_num), resNum(res_num), cmd(_cmd), - idx(_idx), priority(_priority) - { } - virtual ~ScheduleEntry(){} - - // Stage number to perform this service. - int stageNum; - - // Resource ID to access - int resNum; - - // See specific resource for meaning - unsigned cmd; - - // See specific resource for meaning - unsigned idx; - - // Some Resources May Need Priority? - int priority; - }; - - struct entryCompare { - bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const - { - // Prioritize first by stage number that the resource is needed - if (lhs->stageNum > rhs->stageNum) { - return true; - } else if (lhs->stageNum == rhs->stageNum) { - /*if (lhs->resNum > rhs->resNum) { - return true; - } else { - return false; - }*/ - - if (lhs->priority > rhs->priority) { - return true; - } else { - return false; - } - } else { - return false; - } - } - }; - - - typedef std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare> ResSchedule; - - void createFrontEndSchedule(DynInstPtr &inst); - bool createBackEndSchedule(DynInstPtr &inst); - int getNextPriority(DynInstPtr &inst, int stage_num); -}; -#endif diff --git a/src/cpu/inorder/pipeline_traits.9stage.cc b/src/cpu/inorder/pipeline_traits.9stage.cc deleted file mode 100644 index e8ff3acd4..000000000 --- a/src/cpu/inorder/pipeline_traits.9stage.cc +++ /dev/null @@ -1,242 +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/resource_list.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" - -using namespace std; - -namespace ThePipeline { - - -//@TODO: create my own Instruction Schedule Class -//that operates as a Priority QUEUE -int getNextPriority(DynInstPtr &inst, int stage_num) -{ - int cur_pri = 20; - - /* - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_it = inst->resSched.begin(); - - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_end = inst->resSched.end(); - - while (sked_it != sked_end) { - - if (sked_it.top()->stageNum == stage_num) { - cur_pri = sked_it.top()->priority; - } - - sked_it++; - } - */ - - return cur_pri; -} - -void createFrontEndSchedule(DynInstPtr &inst) -{ - int stNum = 0; - int stPri = 0; - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // Stage 0 - // --------------------------------------- - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::AssignNextPC)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, ITLB, TLBUnit::FetchLookup)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::InitiateFetch)); - stPri++; - - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; - - // - // Stage 1 - // --------------------------------------- - inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::CompleteFetch)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, Decode, DecodeUnit::DecodeInst)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, BPred, BranchPredictor::PredictBranch)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::UpdateTargetPC)); - stPri++; - - if (inst->readTid() == 0) - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchBuff, InstBuffer::ScheduleOrBypass)); - else //if (inst->readTid() == 1) - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchBuff2, InstBuffer::ScheduleOrBypass)); - stPri++; - - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; - - // - // Stage 2 - // --------------------------------------- - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; -} - -bool createBackEndSchedule(DynInstPtr &inst) -{ - if (!inst->staticInst) { - return false; - } - - std::string name = inst->staticInst->getName(); - - int stNum = BackEndStartStage; - int stPri = 0; - - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // Stage 3 - // --------------------------------------- - // Set When Source Registers Should be read - Stage 4 - for (int idx=0; idx < inst->numSrcRegs(); idx++) { - inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::ReadSrcReg, idx)); - } - stPri++; - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 4 - // --------------------------------------- - if (inst->isMemRef()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, AGEN, AGENUnit::GenerateAddr)); - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 5 - // --------------------------------------- - // Execution Unit - if (!inst->isNonSpeculative() && !inst->isMemRef()) { - if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { - inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); - } else { - inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); - } - } - stPri++; - - // DCache Initiate Access - if (inst->isMemRef()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DTLB, TLBUnit::DataLookup)); - stPri++; - - if (inst->isLoad()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateReadData)); - } else if (inst->isStore()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateWriteData)); - } - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 6 - // --------------------------------------- - // DCache Complete Access - if (inst->isMemRef()) { - if (inst->isLoad()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteReadData)); - } else if (inst->isStore()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteWriteData)); - } - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 7 - // --------------------------------------- - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 8 - // --------------------------------------- - // NonSpeculative Execution - if (inst->isNonSpeculative() ) { - if (inst->isMemRef()) - fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); - - inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); - stPri++; - } - - // Write Back to Register File - for (int idx=0; idx < inst->numDestRegs(); idx++) { - inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::WriteDestReg, idx)); - stPri++; - } - - // Graduate Instructions - inst_sched->push(new ScheduleEntry(stNum, stPri, Grad, GraduationUnit::GraduateInst)); - stPri++; - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - return true; -} - -}; diff --git a/src/cpu/inorder/pipeline_traits.9stage.hh b/src/cpu/inorder/pipeline_traits.9stage.hh deleted file mode 100644 index dce99f630..000000000 --- a/src/cpu/inorder/pipeline_traits.9stage.hh +++ /dev/null @@ -1,153 +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_PIPELINE_IMPL_HH__ -#define __CPU_INORDER_PIPELINE_IMPL_HH__ - -#include <list> -#include <map> -#include <queue> -#include <vector> - -#include "arch/isa_traits.hh" - -class InOrderDynInst; - -/* This Namespace contains constants, typedefs, functions and - * objects specific to the Pipeline Implementation. - */ -namespace ThePipeline { - // Pipeline Constants - const unsigned NumStages = 9; - const unsigned MaxThreads = 3; - const unsigned StageWidth = 2; - const unsigned BackEndStartStage = 3; - - // Use this to over-ride default stage widths - static std::map<unsigned, unsigned> stageBufferSizes; - - //static unsigned interStageBuffSize[NumStages]; - - static const unsigned interStageBuffSize[NumStages] = { - StageWidth, /* Stage 0 - 1 */ - StageWidth, /* Stage 1 - 2 */ - 4, /* Stage 2 - 3 */ - StageWidth, /* Stage 3 - 4 */ - StageWidth, /* Stage 4 - 5 */ - StageWidth, /* Stage 5 - 6 */ - StageWidth, /* Stage 6 - 7 */ - StageWidth, /* Stage 7 - 8 */ - StageWidth /* Stage 8 - 9 */ - }; - - - // Enumerated List of Resources The Pipeline Uses - enum ResourceList { - FetchSeq = 0, - ITLB, - ICache, - Decode, - BPred, - FetchBuff, - RegManager, - AGEN, - ExecUnit, - DTLB, - DCache, - Grad, - FetchBuff2 - }; - - typedef InOrderCPUParams Params; - typedef RefCountingPtr<InOrderDynInst> DynInstPtr; - -//void initPipelineTraits(); - - ////////////////////////// - // RESOURCE SCHEDULING - ////////////////////////// - struct ScheduleEntry { - ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, - int _idx = 0) : - stageNum(stage_num), resNum(res_num), cmd(_cmd), - idx(_idx), priority(_priority) - { } - virtual ~ScheduleEntry(){} - - // Stage number to perform this service. - int stageNum; - - // Resource ID to access - int resNum; - - // See specific resource for meaning - unsigned cmd; - - // See specific resource for meaning - unsigned idx; - - // Some Resources May Need Priority? - int priority; - }; - - struct entryCompare { - bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const - { - // Prioritize first by stage number that the resource is needed - if (lhs->stageNum > rhs->stageNum) { - return true; - } else if (lhs->stageNum == rhs->stageNum) { - /*if (lhs->resNum > rhs->resNum) { - return true; - } else { - return false; - }*/ - - if (lhs->priority > rhs->priority) { - return true; - } else { - return false; - } - } else { - return false; - } - } - }; - - - typedef std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare> ResSchedule; - - void createFrontEndSchedule(DynInstPtr &inst); - bool createBackEndSchedule(DynInstPtr &inst); - int getNextPriority(DynInstPtr &inst, int stage_num); -}; -#endif diff --git a/src/cpu/inorder/pipeline_traits.9stage.smt2.cc b/src/cpu/inorder/pipeline_traits.9stage.smt2.cc deleted file mode 100644 index 68c1d0eab..000000000 --- a/src/cpu/inorder/pipeline_traits.9stage.smt2.cc +++ /dev/null @@ -1,240 +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/resource_list.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" - -using namespace std; - -namespace ThePipeline { - - -//@TODO: create my own Instruction Schedule Class -//that operates as a Priority QUEUE -int getNextPriority(DynInstPtr &inst, int stage_num) -{ - int cur_pri = 20; - - /* - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_it = inst->resSched.begin(); - - std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare>::iterator sked_end = inst->resSched.end(); - - while (sked_it != sked_end) { - - if (sked_it.top()->stageNum == stage_num) { - cur_pri = sked_it.top()->priority; - } - - sked_it++; - } - */ - - return cur_pri; -} - -void createFrontEndSchedule(DynInstPtr &inst) -{ - int stNum = 0; - int stPri = 0; - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // Stage 0 - // --------------------------------------- - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::AssignNextPC)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, ITLB, TLBUnit::FetchLookup)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::InitiateFetch)); - stPri++; - - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; - - // - // Stage 1 - // --------------------------------------- - inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::CompleteFetch)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, Decode, DecodeUnit::DecodeInst)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, BPred, BranchPredictor::PredictBranch)); - stPri++; - - inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::UpdateTargetPC)); - stPri++; - - int fetch_buff_num = FetchBuff + inst->readTid(); - - inst_sched->push(new ScheduleEntry(stNum, stPri, fetch_buff_num, InstBuffer::ScheduleOrBypass)); - - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; - - // - // Stage 2 - // --------------------------------------- - // Reset Priority / Update Next Stage Number - stNum++; - stPri = 0; -} - -bool createBackEndSchedule(DynInstPtr &inst) -{ - if (!inst->staticInst) { - return false; - } - - std::string name = inst->staticInst->getName(); - - int stNum = BackEndStartStage; - int stPri = 0; - - // Get Pointer to Instuction's Schedule - ResSchedule *inst_sched = &inst->resSched; - - // - // Stage 3 - // --------------------------------------- - // Set When Source Registers Should be read - Stage 4 - for (int idx=0; idx < inst->numSrcRegs(); idx++) { - inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::ReadSrcReg, idx)); - } - stPri++; - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 4 - // --------------------------------------- - if (inst->isMemRef()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, AGEN, AGENUnit::GenerateAddr)); - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 5 - // --------------------------------------- - // Execution Unit - if (!inst->isNonSpeculative() && !inst->isMemRef()) { - //if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { - //inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); - //} else { - inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); - //} - } - stPri++; - - // DCache Initiate Access - if (inst->isMemRef()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DTLB, TLBUnit::DataLookup)); - stPri++; - - if (inst->isLoad()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateReadData)); - } else if (inst->isStore()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateWriteData)); - } - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 6 - // --------------------------------------- - // DCache Complete Access - if (inst->isMemRef()) { - if (inst->isLoad()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteReadData)); - } else if (inst->isStore()) { - inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteWriteData)); - } - } - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 7 - // --------------------------------------- - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - // - // Stage 8 - // --------------------------------------- - // NonSpeculative Execution - if (inst->isNonSpeculative() ) { - if (inst->isMemRef()) - fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); - - inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); - stPri++; - } - - // Write Back to Register File - for (int idx=0; idx < inst->numDestRegs(); idx++) { - inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::WriteDestReg, idx)); - stPri++; - } - - // Graduate Instructions - inst_sched->push(new ScheduleEntry(stNum, stPri, Grad, GraduationUnit::GraduateInst)); - stPri++; - - // Reset Priority / Update Next Stage Number - stPri = 0; - stNum++; - - return true; -} - -}; diff --git a/src/cpu/inorder/pipeline_traits.9stage.smt2.hh b/src/cpu/inorder/pipeline_traits.9stage.smt2.hh deleted file mode 100644 index 97759b549..000000000 --- a/src/cpu/inorder/pipeline_traits.9stage.smt2.hh +++ /dev/null @@ -1,153 +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_PIPELINE_IMPL_HH__ -#define __CPU_INORDER_PIPELINE_IMPL_HH__ - -#include <list> -#include <map> -#include <queue> -#include <vector> - -#include "arch/isa_traits.hh" - -class InOrderDynInst; - -/* This Namespace contains constants, typedefs, functions and - * objects specific to the Pipeline Implementation. - */ -namespace ThePipeline { - // Pipeline Constants - const unsigned NumStages = 9; - const unsigned MaxThreads = 2; - const unsigned StageWidth = 1; - const unsigned BackEndStartStage = 3; - - // Use this to over-ride default stage widths - static std::map<unsigned, unsigned> stageBufferSizes; - - //static unsigned interStageBuffSize[NumStages]; - - static const unsigned interStageBuffSize[NumStages] = { - StageWidth, /* Stage 0 - 1 */ - StageWidth, /* Stage 1 - 2 */ - MaxThreads * 4, /* Stage 2 - 3 */ - StageWidth, /* Stage 3 - 4 */ - MaxThreads * 4, /* Stage 4 - 5 */ - StageWidth, /* Stage 5 - 6 */ - StageWidth, /* Stage 6 - 7 */ - StageWidth, /* Stage 7 - 8 */ - MaxThreads /* Stage 8 - 9 */ - }; - - - // Enumerated List of Resources The Pipeline Uses - enum ResourceList { - FetchSeq = 0, - ITLB, - ICache, - Decode, - BPred, - RegManager, - AGEN, - ExecUnit, - DTLB, - DCache, - Grad, - FetchBuff, - FetchBuff2 - }; - - typedef InOrderCPUParams Params; - typedef RefCountingPtr<InOrderDynInst> DynInstPtr; - -//void initPipelineTraits(); - - ////////////////////////// - // RESOURCE SCHEDULING - ////////////////////////// - struct ScheduleEntry { - ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, - int _idx = 0) : - stageNum(stage_num), resNum(res_num), cmd(_cmd), - idx(_idx), priority(_priority) - { } - virtual ~ScheduleEntry(){} - - // Stage number to perform this service. - int stageNum; - - // Resource ID to access - int resNum; - - // See specific resource for meaning - unsigned cmd; - - // See specific resource for meaning - unsigned idx; - - // Some Resources May Need Priority? - int priority; - }; - - struct entryCompare { - bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const - { - // Prioritize first by stage number that the resource is needed - if (lhs->stageNum > rhs->stageNum) { - return true; - } else if (lhs->stageNum == rhs->stageNum) { - /*if (lhs->resNum > rhs->resNum) { - return true; - } else { - return false; - }*/ - - if (lhs->priority > rhs->priority) { - return true; - } else { - return false; - } - } else { - return false; - } - } - }; - - - typedef std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>, - entryCompare> ResSchedule; - - void createFrontEndSchedule(DynInstPtr &inst); - bool createBackEndSchedule(DynInstPtr &inst); - int getNextPriority(DynInstPtr &inst, int stage_num); -}; -#endif diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh deleted file mode 100644 index 5df61368f..000000000 --- a/src/cpu/inorder/pipeline_traits.hh +++ /dev/null @@ -1,85 +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_PIPELINE_IMPL_HH__ -#define __CPU_INORDER_PIPELINE_IMPL_HH__ - -#include <list> -#include <queue> -#include <vector> - -#include "arch/isa_traits.hh" -#include "cpu/base.hh" -#include "params/InOrderCPU.hh" - -class InOrderDynInst; -class ScheduleEntry; -class ResourceSked; - -/* This Namespace contains constants, typedefs, functions and - * objects specific to the Pipeline Implementation. - */ -namespace ThePipeline { - // Pipeline Constants - const unsigned NumStages = 5; - const ThreadID MaxThreads = 1; - const unsigned BackEndStartStage = 2; - - // List of Resources The Pipeline Uses - enum ResourceId { - FetchSeq = 0, - ICache, - Decode, - BPred, - FetchBuff, - RegManager, - AGEN, - ExecUnit, - MDU, - DCache, - Grad, - FetchBuff2 - }; - - typedef InOrderCPUParams Params; - typedef RefCountingPtr<InOrderDynInst> DynInstPtr; - - ////////////////////////// - // RESOURCE SCHEDULING - ////////////////////////// - typedef ResourceSked ResSchedule; - typedef ResourceSked* RSkedPtr; -} - - - - -#endif diff --git a/src/cpu/inorder/reg_dep_map.cc b/src/cpu/inorder/reg_dep_map.cc deleted file mode 100644 index a64d2fb66..000000000 --- a/src/cpu/inorder/reg_dep_map.cc +++ /dev/null @@ -1,304 +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 "arch/isa_traits.hh" -#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/reg_dep_map.hh" -#include "debug/RegDepMap.hh" - -using namespace std; -using namespace TheISA; -using namespace ThePipeline; - -RegDepMap::RegDepMap(int size) -{ - regMap.resize(NumRegClasses); - regMap[IntRegClass].resize(NumIntRegs); - regMap[FloatRegClass].resize(NumFloatRegs); - regMap[MiscRegClass].resize(NumMiscRegs); -} - -RegDepMap::~RegDepMap() -{ - clear(); -} - -string -RegDepMap::name() -{ - return cpu->name() + ".RegDepMap"; -} - -void -RegDepMap::setCPU(InOrderCPU *_cpu) -{ - cpu = _cpu; - -} - -void -RegDepMap::clear() -{ - for (int i = 0; i < regMap.size(); i++) { - for (int j = 0; j < regMap[j].size(); j++) - regMap[i][j].clear(); - regMap[i].clear(); - } - regMap.clear(); -} - -void -RegDepMap::insert(DynInstPtr inst) -{ - int dest_regs = inst->numDestRegs(); - - DPRINTF(RegDepMap, "Setting Output Dependencies for [sn:%i] " - ", %s (dest. regs = %i).\n", - inst->seqNum, - inst->instName(), - dest_regs); - - for (int i = 0; i < dest_regs; i++) { - RegClass reg_type; - TheISA::RegIndex raw_idx = inst->destRegIdx(i); - TheISA::RegIndex flat_idx = cpu->flattenRegIdx(raw_idx, - reg_type, - inst->threadNumber); - - DPRINTF(RegDepMap, "[sn:%i] #%i flattened %i to %i.\n", - inst->seqNum, i, raw_idx, flat_idx); - - inst->flattenDestReg(i, flat_idx); - - if (flat_idx == TheISA::ZeroReg && reg_type == IntRegClass) { - DPRINTF(RegDepMap, "[sn:%i]: Ignoring Insert-Dependency tracking for " - "ISA-ZeroReg (Int. Reg %i).\n", inst->seqNum, - flat_idx); - continue; - } - - insert(reg_type, flat_idx, inst); - } -} - - -void -RegDepMap::insert(uint8_t reg_type, RegIndex idx, DynInstPtr inst) -{ - DPRINTF(RegDepMap, "Inserting [sn:%i] onto %s dep. list for " - "reg. idx %i.\n", inst->seqNum, RegClassStrings[reg_type], - idx); - - regMap[reg_type][idx].push_back(inst); - - inst->setRegDepEntry(); -} - -void -RegDepMap::remove(DynInstPtr inst) -{ - if (inst->isRegDepEntry()) { - int dest_regs = inst->numDestRegs(); - - DPRINTF(RegDepMap, "Removing [sn:%i]'s entries from reg. dep. map. for " - ", %s (dest. regs = %i).\n", - inst->seqNum, - inst->instName(), - dest_regs); - - - for (int i = 0; i < dest_regs; i++) { - RegIndex flat_idx = inst->flattenedDestRegIdx(i); - RegClass reg_type = regIdxToClass(inst->destRegIdx(i)); - - // Merge Dyn Inst & CPU Result Types - if (flat_idx == TheISA::ZeroReg && - reg_type == IntRegClass) { - DPRINTF(RegDepMap, "[sn:%i]: Ignoring Remove-Dependency tracking for " - "ISA-ZeroReg (Int. Reg %i).\n", inst->seqNum, - flat_idx); - continue; - } - - - remove(reg_type, flat_idx, inst); - } - - inst->clearRegDepEntry(); - } -} - -void -RegDepMap::remove(uint8_t reg_type, RegIndex idx, DynInstPtr inst) -{ - std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin(); - std::list<DynInstPtr>::iterator list_end = regMap[reg_type][idx].end(); - - - while (list_it != list_end) { - if((*list_it) == inst) { - DPRINTF(RegDepMap, "Removing [sn:%i] from %s dep. list for " - "reg. idx %i.\n", inst->seqNum, RegClassStrings[reg_type], - idx); - regMap[reg_type][idx].erase(list_it); - return; - } - list_it++; - } - panic("[sn:%i] Did not find entry for %i, type:%i\n", inst->seqNum, idx, reg_type); -} - -void -RegDepMap::removeFront(uint8_t reg_type, RegIndex idx, DynInstPtr inst) -{ - std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin(); - - DPRINTF(RegDepMap, "[tid:%u]: Removing dependency entry on reg. idx " - "%i for [sn:%i].\n", inst->readTid(), idx, inst->seqNum); - - assert(list_it != regMap[reg_type][idx].end()); - - assert(inst == (*list_it)); - - regMap[reg_type][idx].erase(list_it); -} - -bool -RegDepMap::canRead(uint8_t reg_type, RegIndex idx, DynInstPtr inst) -{ - if (regMap[reg_type][idx].size() == 0) - return true; - - std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin(); - - if (inst->seqNum <= (*list_it)->seqNum) { - return true; - } else { - DPRINTF(RegDepMap, "[sn:%i] Can't read from RegFile, [sn:%i] has " - "not written it's value back yet.\n", - inst->seqNum, (*list_it)->seqNum); - return false; - } -} - -ThePipeline::DynInstPtr -RegDepMap::canForward(uint8_t reg_type, unsigned reg_idx, DynInstPtr inst) -{ - std::list<DynInstPtr>::iterator list_it = regMap[reg_type][reg_idx].begin(); - std::list<DynInstPtr>::iterator list_end = regMap[reg_type][reg_idx].end(); - - DynInstPtr forward_inst = NULL; - - // Look for instruction immediately in front of requestor to supply - // data - while (list_it != list_end && - (*list_it)->seqNum < inst->seqNum) { - forward_inst = (*list_it); - list_it++; - } - - if (forward_inst) { - int dest_reg_idx = forward_inst->getDestIdxNum(reg_idx); - assert(dest_reg_idx != -1); - - DPRINTF(RegDepMap, "[sn:%i] Found potential forwarding value for reg %i " - " w/ [sn:%i] dest. reg. #%i\n", - inst->seqNum, reg_idx, forward_inst->seqNum, dest_reg_idx); - - if (forward_inst->isExecuted() && - forward_inst->readResultTime(dest_reg_idx) < curTick()) { - return forward_inst; - } else { - if (!forward_inst->isExecuted()) { - DPRINTF(RegDepMap, "[sn:%i] Can't get value through " - "forwarding, [sn:%i] %s has not been executed yet.\n", - inst->seqNum, forward_inst->seqNum, forward_inst->instName()); - } else if (forward_inst->readResultTime(dest_reg_idx) >= curTick()) { - DPRINTF(RegDepMap, "[sn:%i] Can't get value through " - "forwarding, [sn:%i] executed on tick:%i.\n", - inst->seqNum, forward_inst->seqNum, - forward_inst->readResultTime(dest_reg_idx)); - } - - return NULL; - } - } else { - DPRINTF(RegDepMap, "[sn:%i] No instruction found to forward from.\n", - inst->seqNum); - return NULL; - } -} - -bool -RegDepMap::canWrite(uint8_t reg_type, RegIndex idx, DynInstPtr inst) -{ - if (regMap[reg_type][idx].size() == 0) - return true; - - std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin(); - - if (inst->seqNum <= (*list_it)->seqNum) { - return true; - } else { - DPRINTF(RegDepMap, "[sn:%i] Can't write from RegFile: [sn:%i] " - "has not written it's value back yet.\n", inst->seqNum, - (*list_it)->seqNum); - } - - return false; -} - -void -RegDepMap::dump() -{ - for (int reg_type = 0; reg_type < NumRegClasses; reg_type++) { - for (int idx=0; idx < regMap.size(); idx++) { - if (regMap[idx].size() > 0) { - cprintf("Reg #%i (size:%i): ", idx, regMap[reg_type][idx].size()); - - std::list<DynInstPtr>::iterator list_it = - regMap[reg_type][idx].begin(); - std::list<DynInstPtr>::iterator list_end = - regMap[reg_type][idx].end(); - - while (list_it != list_end) { - cprintf("[sn:%i] ", (*list_it)->seqNum); - list_it++; - } - cprintf("\n"); - } - } - } -} diff --git a/src/cpu/inorder/reg_dep_map.hh b/src/cpu/inorder/reg_dep_map.hh deleted file mode 100644 index b7219cdac..000000000 --- a/src/cpu/inorder/reg_dep_map.hh +++ /dev/null @@ -1,115 +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 - * - */ - -#ifndef CPU_INORDER_REG_DEP_MAP_HH -#define CPU_INORDER_REG_DEP_MAP_HH - -#include <list> -#include <vector> -#include <string> - -#include "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/pipeline_traits.hh" - -class RegDepMap -{ - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - typedef TheISA::RegIndex RegIndex; - - RegDepMap(int size = TheISA::TotalNumRegs); - ~RegDepMap(); - - std::string name(); - - void setCPU(InOrderCPU *_cpu); - - /** Clear the Entire Map */ - void clear(); - - /** Insert all of a instruction's destination registers into map*/ - void insert(DynInstPtr inst); - - /** Remove all of a instruction's destination registers into map*/ - void remove(DynInstPtr inst); - - /** Remove Front instruction from a destination register */ - void removeFront(uint8_t reg_type, RegIndex idx, DynInstPtr inst); - - /** Is the current instruction able to read from this - * destination register? - */ - bool canRead(uint8_t reg_type, RegIndex idx, DynInstPtr inst); - - /** Is the current instruction able to get a forwarded value from - * another instruction for this destination register? - */ - DynInstPtr canForward(uint8_t reg_type, unsigned reg_idx, - DynInstPtr inst); - - /** find an instruction to forward/bypass a value from */ - DynInstPtr findBypassInst(RegIndex idx); - - /** Is the current instruction able to write to this - * destination register? - */ - bool canWrite(uint8_t reg_type, RegIndex idx, DynInstPtr inst); - - /** Size of Dependency of Map */ - int depSize(RegIndex idx); - - void dump(); - - private: - /** Insert an instruction into a specific destination register index - * onto map. - */ - void insert(uint8_t reg_type, RegIndex idx, DynInstPtr inst); - - /** Remove a specific instruction and dest. register index from map */ - void remove(uint8_t reg_type, RegIndex idx, DynInstPtr inst); - - typedef std::vector<std::list<DynInstPtr> > DepMap; - std::vector<DepMap> regMap; - - InOrderCPU *cpu; -}; - -#endif - - - - - - - diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc deleted file mode 100644 index c732b8519..000000000 --- a/src/cpu/inorder/resource.cc +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Korey Sewell - * - */ - -#include <list> -#include <vector> - -#include "base/str.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/resource.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/ExecFaulting.hh" -#include "debug/RefCount.hh" -#include "debug/ResReqCount.hh" -#include "debug/Resource.hh" - -using namespace std; - -Resource::Resource(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu) - : resName(res_name), id(res_id), - width(res_width), latency(res_latency), cpu(_cpu), - resourceEvent(NULL) -{ - reqs.resize(width); - - // Use to deny a instruction a resource. - deniedReq = new ResourceRequest(this); - deniedReq->valid = true; -} - -Resource::~Resource() -{ - if (resourceEvent) { - delete [] resourceEvent; - } - - delete deniedReq; - - for (int i = 0; i < width; i++) { - delete reqs[i]; - } -} - - -void -Resource::init() -{ - // If the resource has a zero-cycle (no latency) - // function, then no reason to have events - // that will process them for the right tick - if (latency > Cycles(0)) - resourceEvent = new ResourceEvent[width]; - - - for (int i = 0; i < width; i++) - reqs[i] = new ResourceRequest(this); - - - initSlots(); -} - -void -Resource::initSlots() -{ - // Add available slot numbers for resource - for (int slot_idx = 0; slot_idx < width; slot_idx++) { - availSlots.push_back(slot_idx); - - if (resourceEvent) { - resourceEvent[slot_idx].init(this, slot_idx); - } - } -} - -std::string -Resource::name() -{ - return cpu->name() + "." + resName; -} - -int -Resource::slotsAvail() -{ - return availSlots.size(); -} - -int -Resource::slotsInUse() -{ - return width - availSlots.size(); -} - -void -Resource::freeSlot(int slot_idx) -{ - DPRINTF(Resource, "Deallocating [slot:%i].\n", - slot_idx); - - // Put slot number on this resource's free list - availSlots.push_back(slot_idx); - - // Invalidate Request & Reset it's flags - reqs[slot_idx]->clearRequest(); -} - -int -Resource::findSlot(DynInstPtr inst) -{ - int slot_num = -1; - - for (int i = 0; i < width; i++) { - if (reqs[i]->valid && - reqs[i]->getInst()->seqNum == inst->seqNum) { - slot_num = reqs[i]->getSlot(); - } - } - return slot_num; -} - -int -Resource::getSlot(DynInstPtr inst) -{ - int slot_num = -1; - - if (slotsAvail() != 0) { - slot_num = availSlots[0]; - - vector<int>::iterator vect_it = availSlots.begin(); - - assert(slot_num == *vect_it); - - availSlots.erase(vect_it); - } - - return slot_num; -} - -ResReqPtr -Resource::request(DynInstPtr inst) -{ - // See if the resource is already serving this instruction. - // If so, use that request; - bool try_request = false; - int slot_num = -1; - int stage_num; - ResReqPtr inst_req = findRequest(inst); - - if (inst_req) { - // If some preprocessing has to be done on instruction - // that has already requested once, then handle it here. - // update the 'try_request' variable if we should - // re-execute the request. - requestAgain(inst, try_request); - - slot_num = inst_req->getSlot(); - stage_num = inst_req->getStageNum(); - } else { - // Get new slot # for instruction - slot_num = getSlot(inst); - - if (slot_num != -1) { - DPRINTF(Resource, "Allocating [slot:%i] for [tid:%i]: [sn:%i]\n", - slot_num, inst->readTid(), inst->seqNum); - - // Get Stage # from Schedule Entry - stage_num = inst->curSkedEntry->stageNum; - unsigned cmd = inst->curSkedEntry->cmd; - - // Generate Resource Request - inst_req = getRequest(inst, stage_num, id, slot_num, cmd); - - if (inst->staticInst) { - DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this " - "resource.\n", - inst->readTid(), inst->seqNum); - } else { - DPRINTF(Resource, "[tid:%i]: instruction requesting this " - "resource.\n", - inst->readTid()); - } - - try_request = true; - } else { - DPRINTF(Resource, "No slot available for [tid:%i]: [sn:%i]\n", - inst->readTid(), inst->seqNum); - } - - } - - if (try_request) { - // Schedule execution of resource - scheduleExecution(slot_num); - } else { - inst_req = deniedReq; - rejectRequest(inst); - } - - return inst_req; -} - -void -Resource::requestAgain(DynInstPtr inst, bool &do_request) -{ - do_request = true; - - if (inst->staticInst) { - DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this resource " - "again.\n", - inst->readTid(), inst->seqNum); - } else { - DPRINTF(Resource, "[tid:%i]: requesting this resource again.\n", - inst->readTid()); - } -} - -ResReqPtr -Resource::getRequest(DynInstPtr inst, int stage_num, int res_idx, - int slot_num, unsigned cmd) -{ - reqs[slot_num]->setRequest(inst, stage_num, id, slot_num, cmd); - return reqs[slot_num]; -} - -ResReqPtr -Resource::findRequest(DynInstPtr inst) -{ - for (int i = 0; i < width; i++) { - if (reqs[i]->valid && - reqs[i]->getInst() == inst) { - return reqs[i]; - } - } - - return NULL; -} - -void -Resource::rejectRequest(DynInstPtr inst) -{ - DPRINTF(RefCount, "[tid:%i]: Unable to grant request for [sn:%i].\n", - inst->readTid(), inst->seqNum); -} - -void -Resource::execute(int slot_idx) -{ - //@todo: have each resource print out command their executing - DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n", - reqs[slot_idx]->getTid(), name()); - reqs[slot_idx]->setCompleted(true); - reqs[slot_idx]->done(); -} - -void -Resource::deactivateThread(ThreadID tid) -{ - // In the most basic case, deactivation means squashing everything - // from a particular thread - DynInstPtr dummy_inst = new InOrderDynInst(cpu, NULL, 0, tid, tid); - squash(dummy_inst, 0, 0, tid); -} - -void -Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid) -{ - // Squash In Pipeline Stage - cpu->pipelineStage[stage_num]->setupSquash(inst, tid); - - // Schedule Squash Through-out Resource Pool - cpu->resPool->scheduleEvent( - (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, - Cycles(0)); -} - -void -Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, - ThreadID tid) -{ - //@todo: check squash seq num before squashing. can save time going - // through this function. - for (int i = 0; i < width; i++) { - ResReqPtr req_ptr = reqs[i]; - DynInstPtr inst = req_ptr->getInst(); - - if (req_ptr->valid && - inst->readTid() == tid && - inst->seqNum > squash_seq_num) { - - DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n", - req_ptr->getInst()->readTid(), - req_ptr->getInst()->seqNum); - - req_ptr->setSquashed(); - - int req_slot_num = req_ptr->getSlot(); - - if (latency > Cycles(0)) { - if (resourceEvent[req_slot_num].scheduled()) - unscheduleEvent(req_slot_num); - } - - freeSlot(req_slot_num); - } - } -} - -void -Resource::squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, - ThreadID tid) -{ - squash(inst, stage_num, squash_seq_num, tid); -} - -void -Resource::squashThenTrap(int stage_num, DynInstPtr inst) -{ - ThreadID tid = inst->readTid(); - - inst->setSquashInfo(stage_num); - setupSquash(inst, stage_num, tid); - - if (inst->traceData) { - if (inst->staticInst && - inst->fault != NoFault && DTRACE(ExecFaulting)) { - inst->traceData->setStageCycle(stage_num, curTick()); - inst->traceData->setFetchSeq(inst->seqNum); - inst->traceData->dump(); - } - - delete inst->traceData; - inst->traceData = NULL; - } - - cpu->trapContext(inst->fault, tid, inst); -} - -void -Resource::scheduleExecution(int slot_num) -{ - if (latency > Cycles(0)) { - scheduleEvent(slot_num, latency); - } else { - execute(slot_num); - } -} - -void -Resource::scheduleEvent(int slot_idx, Cycles delay) -{ - DPRINTF(Resource, "[tid:%i]: Scheduling event for [sn:%i] on tick %i.\n", - reqs[slot_idx]->inst->readTid(), - reqs[slot_idx]->inst->seqNum, - cpu->clockEdge(delay)); - resourceEvent[slot_idx].scheduleEvent(delay); -} - -bool -Resource::scheduleEvent(DynInstPtr inst, Cycles delay) -{ - int slot_idx = findSlot(inst); - - if(slot_idx != -1) - resourceEvent[slot_idx].scheduleEvent(delay); - - return slot_idx; -} - -void -Resource::unscheduleEvent(int slot_idx) -{ - resourceEvent[slot_idx].unscheduleEvent(); -} - -bool -Resource::unscheduleEvent(DynInstPtr inst) -{ - int slot_idx = findSlot(inst); - - if(slot_idx != -1) - resourceEvent[slot_idx].unscheduleEvent(); - - return slot_idx; -} - -int ResourceRequest::resReqID = 0; - -int ResourceRequest::maxReqCount = 0; - -ResourceRequest::ResourceRequest(Resource *_res) - : res(_res), inst(NULL), stagePasses(0), valid(false), doneInResource(false), - completed(false), squashed(false), processing(false), - memStall(false) -{ -} - -ResourceRequest::~ResourceRequest() -{ -#ifdef DEBUG - res->cpu->resReqCount--; - DPRINTF(ResReqCount, "Res. Req %i deleted. resReqCount=%i.\n", reqID, - res->cpu->resReqCount); -#endif - inst = NULL; -} - -std::string -ResourceRequest::name() -{ - return csprintf("%s[slot:%i]:", res->name(), slotNum); -} - -void -ResourceRequest::setRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, unsigned _cmd) -{ - valid = true; - inst = _inst; - stageNum = stage_num; - resIdx = res_idx; - slotNum = slot_num; - cmd = _cmd; -} - -void -ResourceRequest::clearRequest() -{ - valid = false; - inst = NULL; - stagePasses = 0; - completed = false; - doneInResource = false; - squashed = false; - memStall = false; -} - -void -ResourceRequest::freeSlot() -{ - assert(res); - - // Free Slot So Another Instruction Can Use This Resource - res->freeSlot(slotNum); -} - -void -ResourceRequest::done(bool completed) -{ - DPRINTF(Resource, "done with request from " - "[sn:%i] [tid:%i].\n", - inst->seqNum, inst->readTid()); - - setCompleted(completed); - - doneInResource = true; -} - -ResourceEvent::ResourceEvent() - : Event((Event::Priority)Resource_Event_Pri) -{ } - -ResourceEvent::ResourceEvent(Resource *res, int slot_idx) - : Event((Event::Priority)Resource_Event_Pri), resource(res), - slotIdx(slot_idx) -{ } - -void -ResourceEvent::init(Resource *res, int slot_idx) -{ - resource = res; - slotIdx = slot_idx; -} - -void -ResourceEvent::process() -{ - resource->execute(slotIdx); -} - -const char * -ResourceEvent::description() const -{ - string desc = resource->name() + "-event:slot[" + to_string(slotIdx) - + "]"; - - return desc.c_str(); -} - -void -ResourceEvent::scheduleEvent(Cycles delay) -{ - assert(!scheduled() || squashed()); - resource->cpu->reschedule(this, - resource->cpu->clockEdge(delay), true); -} diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh deleted file mode 100644 index eaecc2824..000000000 --- a/src/cpu/inorder/resource.hh +++ /dev/null @@ -1,411 +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_HH__ -#define __CPU_INORDER_RESOURCE_HH__ - -#include <list> -#include <string> -#include <vector> - -#include "base/types.hh" -#include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inst_seq.hh" -#include "sim/eventq.hh" -#include "sim/sim_object.hh" - -class Event; -class InOrderCPU; -class ResourceEvent; -class ResourceRequest; - -typedef ResourceRequest ResReq; -typedef ResourceRequest* ResReqPtr; - -class CacheRequest; -typedef CacheRequest* CacheReqPtr; - -class Resource { - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - friend class ResourceEvent; - friend class ResourceRequest; - - public: - Resource(std::string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu); - virtual ~Resource(); - - - /** Return name of this resource */ - virtual std::string name(); - - /** Return ID for this resource */ - int getId() { return id; } - - /** Any extra initiliazation stuff can be set up using this function that - * should get called before the simulation starts (tick 0) - */ - virtual void init(); - virtual void initSlots(); - - /** Register Stats for this resource */ - virtual void regStats() { } - - /** Resources that care about thread activation override this. */ - virtual void activateThread(ThreadID tid) { } - - /** Deactivate Thread. Default action is to squash all instructions - * from deactivated thread. - */ - virtual void deactivateThread(ThreadID tid); - - /** Resources that care about thread activation override this. */ - virtual void suspendThread(ThreadID tid) { } - - /** Will be called the cycle before a context switch. Any bookkeeping - * that needs to be kept for that, can be done here - */ - virtual void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) { } - - /** Resources that care when an instruction has been graduated - * can override this - */ - virtual void instGraduated(InstSeqNum seq_num, ThreadID tid) { } - - /** Post-processsing for Trap Generated from this instruction */ - virtual void trap(const Fault &fault, ThreadID tid, DynInstPtr inst) { } - - /** Request usage of this resource. Returns a ResourceRequest object - * with all the necessary resource information - */ - virtual ResourceRequest* request(DynInstPtr inst); - - /** Get the next available slot in this resource. Instruction is passed - * so that resources can check the instruction before allocating a slot - * if necessary. - */ - virtual int getSlot(DynInstPtr inst); - - /** Find the slot that this instruction is using in a resource */ - virtual int findSlot(DynInstPtr inst); - - /** Free a resource slot */ - virtual void freeSlot(int slot_idx); - - /** Request usage of a resource for this instruction. If this instruction - * already has made this request to this resource, and that request is - * uncompleted this function will just return that request - */ - virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, - unsigned cmd); - - /** Schedule Execution of This Resource For A Given Slot*/ - void scheduleExecution(int slot_idx); - - /** 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. - */ - virtual void execute(int slot_idx); - - /** Fetch on behalf of an instruction. Will check to see - * if instruction is actually in resource before - * trying to fetch. Needs to be defined for derived units. - */ - virtual Fault doFetchAccess(DynInstPtr inst) - { panic("doFetchAccess undefined for %s", name()); return NoFault; } - - /** Read/Write on behalf of an instruction. Will check to see - * if instruction is actually in resource before - * trying to do access.Needs to be defined for derived units. - */ - virtual void doCacheAccess(DynInstPtr inst, uint64_t *write_result = NULL, - CacheReqPtr split_req = NULL) - { panic("doCacheAccess undefined for %s", name()); } - - /** Setup Squash to be sent out to pipeline and resource pool */ - void setupSquash(DynInstPtr inst, int stage_num, ThreadID tid); - - /** Squash All Requests After This Seq Num */ - virtual void squash(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - - /** Squash Requests Due to a Memory Stall (By Default, same as "squash" */ - virtual void squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum squash_seq_num, ThreadID tid); - - /** Handle Squash & Trap that occured from an instruction in a resource */ - void squashThenTrap(int stage_num, DynInstPtr inst); - - /** The number of instructions available that this resource can - * can still process - */ - int slotsAvail(); - - /** The number of instructions using this resource */ - int slotsInUse(); - - /** Schedule resource event, regardless of its current state. */ - void scheduleEvent(int slot_idx, Cycles delay); - - /** Find instruction in list, Schedule resource event, regardless of its - * current state. */ - bool scheduleEvent(DynInstPtr inst, Cycles delay); - - /** Unschedule resource event, regardless of its current state. */ - void unscheduleEvent(int slot_idx); - - /** Unschedule resource event, regardless of its current state. */ - bool unscheduleEvent(DynInstPtr inst); - - /** Find the request that corresponds to this instruction */ - virtual ResReqPtr findRequest(DynInstPtr inst); - - /** */ - void rejectRequest(DynInstPtr inst); - - /** Request a Resource again. Some resources have to special process this - * in subsequent accesses. - */ - virtual void requestAgain(DynInstPtr inst, bool &try_request); - - /** Return Latency of Resource */ - /* Can be overridden for complex cases */ - virtual Cycles getLatency(int slot_num) { return latency; } - - protected: - /** The name of this resource */ - std::string resName; - - /** ID of the resource. The Resource Pool uses this # to identify this - * resource. - */ - int id; - - /** The number of instructions the resource can simultaneously - * process. - */ - int width; - - /** Constant latency for this resource. - * Note: Dynamic latency resources set this to 0 and - * manage the latency themselves - */ - const Cycles latency; - - public: - /** List of all Requests the Resource is Servicing. Each request - represents part of the resource's bandwidth - */ - std::vector<ResReqPtr> reqs; - - /** A list of all the available execution slots for this resource. - * This correlates with the actual resource event idx. - */ - std::vector<int> availSlots; - - /** The CPU(s) that this resource interacts with */ - InOrderCPU *cpu; - - protected: - /** The resource event used for scheduling resource slots on the - * event queue - */ - ResourceEvent *resourceEvent; - - /** Default denied resource request pointer*/ - ResReqPtr deniedReq; -}; - -class ResourceEvent : public Event -{ - public: - /** Pointer to the Resource this is an event for */ - Resource *resource; - - - /// Resource events that come before other associated CPU events - /// (for InOrderCPU model). - /// check src/sim/eventq.hh for more event priorities. - enum InOrderPriority { - Resource_Event_Pri = 45 - }; - - /** The Resource Slot that this event is servicing */ - int slotIdx; - - /** Constructs a resource event. */ - ResourceEvent(); - ResourceEvent(Resource *res, int slot_idx); - virtual ~ResourceEvent() { } - - /** Initialize data for this resource event. */ - virtual void init(Resource *res, int slot_idx); - - /** Processes a resource event. */ - virtual void process(); - - /** Returns the description of the resource event. */ - const char *description() const; - - /** Set slot idx for event */ - void setSlot(int slot) { slotIdx = slot; } - - /** Schedule resource event, regardless of its current state. */ - void scheduleEvent(Cycles delay); - - /** Unschedule resource event, regardless of its current state. */ - void unscheduleEvent() - { - if (scheduled()) - squash(); - } - -}; - -class ResourceRequest -{ - public: - typedef ThePipeline::DynInstPtr DynInstPtr; - - static int resReqID; - - static int maxReqCount; - - friend class Resource; - - public: - ResourceRequest(Resource *_res); - - virtual ~ResourceRequest(); - - std::string name(); - - int reqID; - - void setRequest(DynInstPtr _inst, int stage_num, - int res_idx, int slot_num, unsigned _cmd); - - virtual void clearRequest(); - - /** Acknowledge that this is a request is done and remove - * from resource. - */ - void done(bool completed = true); - - void freeSlot(); - - ///////////////////////////////////////////// - // - // GET RESOURCE REQUEST IDENTIFICATION / INFO - // - ///////////////////////////////////////////// - /** Get Resource Index */ - int getResIdx() { return resIdx; } - - /** Get Slot Number */ - int getSlot() { return slotNum; } - bool hasSlot() { return slotNum >= 0; } - - /** Get Stage Number */ - int getStageNum() { return stageNum; } - - /** Set/Get Thread Ids */ - void setTid(ThreadID _tid) { tid = _tid; } - ThreadID getTid() { return tid; } - - /** Instruction this request is for */ - DynInstPtr getInst() { return inst; } - - /** Data from this request. Overridden by Resource-Specific Request - * Objects - */ - virtual PacketDataPtr getData() { return NULL; } - - /** Pointer to Resource that is being used */ - Resource *res; - - /** Instruction being used */ - DynInstPtr inst; - - /** Not guaranteed to be set, used for debugging */ - InstSeqNum seqNum; - - /** Command For This Resource */ - unsigned cmd; - - short stagePasses; - - bool valid; - - bool doneInResource; - - //////////////////////////////////////// - // - // GET RESOURCE REQUEST STATUS FROM VARIABLES - // - //////////////////////////////////////// - /** Get/Set Completed variables */ - bool isCompleted() { return completed; } - void setCompleted(bool cond = true) { completed = cond; } - - /** Get/Set Squashed variables */ - bool isSquashed() { return squashed; } - void setSquashed() { squashed = true; } - - /** Get/Set IsProcessing variables */ - bool isProcessing() { return processing; } - void setProcessing(bool cond = true) { processing = cond; } - - /** Get/Set IsWaiting variables */ - bool isMemStall() { return memStall; } - void setMemStall(bool stall = true) { memStall = stall; } - - protected: - /** Resource Identification */ - ThreadID tid; - int stageNum; - int resIdx; - int slotNum; - - /** Resource Request Status */ - bool completed; - bool squashed; - bool processing; - - bool memStall; -}; - -#endif //__CPU_INORDER_RESOURCE_HH__ diff --git a/src/cpu/inorder/resource_pool.9stage.cc b/src/cpu/inorder/resource_pool.9stage.cc deleted file mode 100644 index d231aafba..000000000 --- a/src/cpu/inorder/resource_pool.9stage.cc +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2012 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 "cpu/inorder/resources/resource_list.hh" -#include "cpu/inorder/resource_pool.hh" - -using namespace std; -using namespace ThePipeline; - -ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params) - : cpu(_cpu), instUnit(NULL), dataUnit(NULL) -{ - //@todo: use this function to instantiate the resources in resource pool. This will help in the - //auto-generation of this pipeline model. - //ThePipeline::addResources(resources, memObjects); - - // Declare Resource Objects - // name - id - bandwidth - latency - CPU - Parameters - // -------------------------------------------------- - resources.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq, - StageWidth * 2, 0, _cpu, params)); - - resources.push_back(new TLBUnit("itlb", ITLB, StageWidth, 0, _cpu, params)); - - - // Keep track of the instruction fetch unit so we can easily - // provide a pointer to it in the CPU. - instUnit = new FetchUnit("icache_port", ICache, - StageWidth * MaxThreads, 0, _cpu, - params); - resources.push_back(instUnit); - - resources.push_back(new DecodeUnit("decode_unit", Decode, StageWidth, 0, - _cpu, params)); - - resources.push_back(new BranchPredictor("branch_predictor", BPred, - StageWidth, 0, _cpu, params)); - - for (int i = 0; i < params->numberOfThreads; i++) { - char fbuff_name[20]; - sprintf(fbuff_name, "fetch_buffer_t%i", i); - resources.push_back(new InstBuffer(fbuff_name, FetchBuff + i, 4, 0, - _cpu, params)); - } - - resources.push_back(new UseDefUnit("regfile_manager", RegManager, - StageWidth * MaxThreads, 0, _cpu, params)); - - resources.push_back(new AGENUnit("agen_unit", AGEN, StageWidth, 0, _cpu, - params)); - - resources.push_back(new ExecutionUnit("execution_unit", ExecUnit, - StageWidth, 0, _cpu, params)); - - resources.push_back(new MultDivUnit("mult_div_unit", MDU, 5, 0, _cpu, - params)); - - resources.push_back(new TLBUnit("dtlb", DTLB, StageWidth, 0, _cpu, params)); - - // Keep track of the data load/store unit so we can easily provide - // a pointer to it in the CPU. - dataUnit = new CacheUnit("dcache_port", DCache, - StageWidth * MaxThreads, 0, _cpu, - params); - resources.push_back(dataUnit); - - resources.push_back(new GraduationUnit("graduation_unit", Grad, - StageWidth * MaxThreads, 0, _cpu, params)); -} - -void -ResourcePool::init() -{ - for (int i=0; i < resources.size(); i++) { - resources[i]->init(); - } -} - -string -ResourcePool::name() -{ - return cpu->name() + ".ResourcePool"; -} - - -void -ResourcePool::regStats() -{ - DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n"); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->regStats(); - } -} - -ResReqPtr -ResourcePool::request(int res_idx, DynInstPtr inst) -{ - //Make Sure This is a valid resource ID - assert(res_idx >= 0 && res_idx < resources.size()); - - return resources[res_idx]->request(inst); -} - -void -ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, - ThreadID tid) -{ - resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid); -} - -int -ResourcePool::slotsAvail(int res_idx) -{ - return resources[res_idx]->slotsAvail(); -} - -int -ResourcePool::slotsInUse(int res_idx) -{ - return resources[res_idx]->slotsInUse(); -} - -void -ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, - int delay, int res_idx, ThreadID tid) -{ - assert(delay >= 0); - - ResPoolEvent *res_pool_event = new ResPoolEvent(this); - - switch (e_type) - { - case InOrderCPU::ActivateThread: - { - DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n", - curTick() + delay); - res_pool_event->setEvent(e_type, - inst, - inst->squashingStage, - inst->squashSeqNum, - inst->readTid()); - res_pool_event->schedule(curTick() + cpu->cycles(delay)); - - } - break; - - case InOrderCPU::SuspendThread: - case InOrderCPU::DeallocateThread: - { - DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n", - curTick() + delay); - - res_pool_event->setEvent(e_type, - inst, - inst->squashingStage, - inst->squashSeqNum, - tid); - - res_pool_event->schedule(curTick() + cpu->cycles(delay)); - - } - break; - - case ResourcePool::InstGraduated: - { - DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n", - curTick() + delay); - - res_pool_event->setEvent(e_type, - inst, - inst->squashingStage, - inst->seqNum, - inst->readTid()); - res_pool_event->schedule(curTick() + cpu->cycles(delay)); - - } - break; - - case ResourcePool::SquashAll: - { - DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n", - curTick() + delay); - res_pool_event->setEvent(e_type, - inst, - inst->squashingStage, - inst->squashSeqNum, - inst->readTid()); - res_pool_event->schedule(curTick() + cpu->cycles(delay)); - - } - break; - - default: - DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type); - ; // If Resource Pool doesnt recognize event, we ignore it. - } -} - -void -ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst) -{ - resources[res_idx]->unscheduleEvent(inst); -} - -void -ResourcePool::squashAll(DynInstPtr inst, int stage_num, - InstSeqNum done_seq_num, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n", - stage_num, tid, done_seq_num); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->squash(inst, stage_num, done_seq_num, tid); - } -} - -void -ResourcePool::activateAll(ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n", - tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->activateThread(tid); - } -} - -void -ResourcePool::deactivateAll(ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n", - tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->deactivateThread(tid); - } -} - -void -ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n", - tid, seq_num); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->instGraduated(seq_num, tid); - } -} - -ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool) - : Event(&mainEventQueue, CPU_Tick_Pri), - resPool(_resPool) -{ eventType = (InOrderCPU::CPUEventType) Default; } - -void -ResourcePool::ResPoolEvent::process() -{ - switch (eventType) - { - case InOrderCPU::ActivateThread: - resPool->activateAll(tid); - break; - - case InOrderCPU::SuspendThread: - case InOrderCPU::DeallocateThread: - resPool->deactivateAll(tid); - break; - - case ResourcePool::InstGraduated: - resPool->instGraduated(seqNum, tid); - break; - - case ResourcePool::SquashAll: - resPool->squashAll(inst, stageNum, seqNum, tid); - break; - - default: - fatal("Unrecognized Event Type"); - } - - resPool->cpu->cpuEventRemoveList.push(this); -} - - -const char * -ResourcePool::ResPoolEvent::description() -{ - return "Resource Pool event"; -} - -/** Schedule resource event, regardless of its current state. */ -void -ResourcePool::ResPoolEvent::scheduleEvent(int delay) -{ - if (squashed()) - reschedule(curTick() + resPool->cpu->cycles(delay)); - else if (!scheduled()) - schedule(curTick() + resPool->cpu->cycles(delay)); -} - -/** Unschedule resource event, regardless of its current state. */ -void -ResourcePool::ResPoolEvent::unscheduleEvent() -{ - if (scheduled()) - squash(); -} diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc deleted file mode 100644 index e0f23235e..000000000 --- a/src/cpu/inorder/resource_pool.cc +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (c) 2012 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 "cpu/inorder/resources/resource_list.hh" -#include "cpu/inorder/resource_pool.hh" -#include "debug/Resource.hh" - -using namespace std; -using namespace ThePipeline; - -ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) - : cpu(_cpu), instUnit(NULL), dataUnit(NULL) -{ - //@todo: use this function to instantiate the resources in resource pool. - //This will help in the auto-generation of this pipeline model. - //ThePipeline::addResources(resources, memObjects); - - int stage_width = cpu->stageWidth; - - // Declare Resource Objects - // name - id - bandwidth - latency - CPU - Parameters - // -------------------------------------------------- - resources.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq, - stage_width * 2, Cycles(0), - _cpu, params)); - - // Keep track of the instruction fetch unit so we can easily - // provide a pointer to it in the CPU. - instUnit = new FetchUnit("icache_port", ICache, - stage_width * 2 + MaxThreads, Cycles(0), _cpu, - params); - resources.push_back(instUnit); - - resources.push_back(new DecodeUnit("decode_unit", Decode, - stage_width, Cycles(0), _cpu, - params)); - - resources.push_back(new BranchPredictor("branch_predictor", BPred, - stage_width, Cycles(0), - _cpu, params)); - - resources.push_back(new InstBuffer("fetch_buffer_t0", FetchBuff, 4, - Cycles(0), _cpu, params)); - - resources.push_back(new UseDefUnit("regfile_manager", RegManager, - stage_width * 3, Cycles(0), _cpu, - params)); - - resources.push_back(new AGENUnit("agen_unit", AGEN, - stage_width, Cycles(0), _cpu, - params)); - - resources.push_back(new ExecutionUnit("execution_unit", ExecUnit, - stage_width, Cycles(0), _cpu, - params)); - - resources.push_back(new MultDivUnit("mult_div_unit", MDU, - stage_width * 2, Cycles(0), - _cpu, params)); - - // Keep track of the data load/store unit so we can easily provide - // a pointer to it in the CPU. - dataUnit = new CacheUnit("dcache_port", DCache, - stage_width * 2 + MaxThreads, Cycles(0), _cpu, - params); - resources.push_back(dataUnit); - - gradObjects.push_back(BPred); - resources.push_back(new GraduationUnit("graduation_unit", Grad, - stage_width, Cycles(0), _cpu, - params)); - - resources.push_back(new InstBuffer("fetch_buffer_t1", FetchBuff2, 4, - Cycles(0), _cpu, params)); - -} - -ResourcePool::~ResourcePool() -{ - cout << "Deleting resources ..." << endl; - - for (int i=0; i < resources.size(); i++) { - DPRINTF(Resource, "Deleting resource: %s.\n", resources[i]->name()); - - delete resources[i]; - } -} - - -void -ResourcePool::init() -{ - for (int i=0; i < resources.size(); i++) { - DPRINTF(Resource, "Initializing resource: %s.\n", - resources[i]->name()); - - resources[i]->init(); - } -} - -string -ResourcePool::name() -{ - return cpu->name() + ".ResourcePool"; -} - -void -ResourcePool::print() -{ - for (int i=0; i < resources.size(); i++) { - DPRINTF(InOrderDynInst, "Res:%i %s\n", - i, resources[i]->name()); - } - -} - - -void -ResourcePool::regStats() -{ - DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n"); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->regStats(); - } -} - -unsigned -ResourcePool::getResIdx(const ThePipeline::ResourceId &res_id) -{ - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - if (resources[idx]->getId() == res_id) - return idx; - } - - // todo: change return value to int and return a -1 here - // maybe even have enumerated type - // panic for now... - panic("Can't find resource idx for: %i\n", res_id); - - return 0; -} - -ResReqPtr -ResourcePool::request(int res_idx, DynInstPtr inst) -{ - //Make Sure This is a valid resource ID - assert(res_idx >= 0 && res_idx < resources.size()); - - return resources[res_idx]->request(inst); -} - -void -ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, - ThreadID tid) -{ - resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, - tid); -} - -void -ResourcePool::trap(const Fault &fault, ThreadID tid, DynInstPtr inst) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Trap to all " - "resources.\n", tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) - resources[idx]->trap(fault, tid, inst); -} - -int -ResourcePool::slotsAvail(int res_idx) -{ - return resources[res_idx]->slotsAvail(); -} - -int -ResourcePool::slotsInUse(int res_idx) -{ - return resources[res_idx]->slotsInUse(); -} - -//@todo: split this function and call this version schedulePoolEvent -// and use this scheduleEvent for scheduling a specific event on -// a resource -//@todo: For arguments that arent being used in a ResPoolEvent, a dummyParam -// or some typedef can be used to signify what's important info -// to the event construction -void -ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, - Cycles delay, int res_idx, ThreadID tid) -{ - assert(delay >= 0); - - Tick when = cpu->clockEdge(delay); - - switch ((int)e_type) - { - case ResourcePool::InstGraduated: - { - DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool " - "Event for tick %i.\n", curTick() + delay); - ResPoolEventPri grad_pri = ResGrad_Pri; - ResPoolEvent *res_pool_event = - new ResPoolEvent(this, - e_type, - inst, - inst->squashingStage, - inst->seqNum, - inst->readTid(), - grad_pri); - cpu->schedule(res_pool_event, when); - } - break; - - case ResourcePool::SquashAll: - { - DPRINTF(Resource, "Scheduling Squash Resource Pool Event for " - "tick %i.\n", curTick() + delay); - ResPoolEventPri squash_pri = ResSquash_Pri; - ResPoolEvent *res_pool_event = - new ResPoolEvent(this, - e_type, - inst, - inst->squashingStage, - inst->squashSeqNum, - inst->readTid(), - squash_pri); - cpu->schedule(res_pool_event, when); - } - break; - - case ResourcePool::UpdateAfterContextSwitch: - { - DPRINTF(Resource, "Scheduling UpdatePC Resource Pool Event " - "for tick %i.\n", - curTick() + delay); - ResPoolEvent *res_pool_event = new ResPoolEvent(this, - e_type, - inst, - inst->squashingStage, - inst->seqNum, - inst->readTid()); - cpu->schedule(res_pool_event, when); - } - break; - - default: - DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", - InOrderCPU::eventNames[e_type]); - } -} - -void -ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst) -{ - resources[res_idx]->unscheduleEvent(inst); -} - -void -ResourcePool::squashAll(DynInstPtr inst, int stage_num, - InstSeqNum done_seq_num, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Squash All Event " - " starting w/stage %i for all instructions above [sn:%i].\n", - tid, stage_num, done_seq_num); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->squash(inst, stage_num, done_seq_num, tid); - } -} - -void -ResourcePool::squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum done_seq_num, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting SquashDueToMemStall Event" - " starting w/stage %i for all instructions above [sn:%i].\n", - tid, stage_num, done_seq_num); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->squashDueToMemStall(inst, stage_num, done_seq_num, - tid); - } -} - -void -ResourcePool::activateThread(ThreadID tid) -{ - bool do_activate = cpu->threadModel != InOrderCPU::SwitchOnCacheMiss || - cpu->numActiveThreads() < 1 || - cpu->activeThreadId() == tid; - - - if (do_activate) { - DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all " - "resources.\n", tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->activateThread(tid); - } - } else { - DPRINTF(Resource, "[tid:%i] Ignoring Thread Activation to all " - "resources.\n", tid); - } -} - -void -ResourcePool::deactivateThread(ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all " - "resources.\n", tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->deactivateThread(tid); - } -} - -void -ResourcePool::suspendThread(ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Thread Suspension to all " - "resources.\n", tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->suspendThread(tid); - } -} - -void -ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to " - "appropriate resources.\n", tid, seq_num); - - int num_resources = gradObjects.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[gradObjects[idx]]->instGraduated(seq_num, tid); - } -} - -void -ResourcePool::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) -{ - DPRINTF(Resource, "[tid:%i] Broadcasting Update PC to all resources.\n", - tid); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - resources[idx]->updateAfterContextSwitch(inst, tid); - } -} - -ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool, - InOrderCPU::CPUEventType e_type, - DynInstPtr _inst, - int stage_num, - InstSeqNum seq_num, - ThreadID _tid, - ResPoolEventPri res_pri) - : Event(res_pri), resPool(_resPool), - eventType(e_type), inst(_inst), seqNum(seq_num), - stageNum(stage_num), tid(_tid) -{ } - - -void -ResourcePool::ResPoolEvent::process() -{ - switch ((int)eventType) - { - - case ResourcePool::InstGraduated: - resPool->instGraduated(seqNum, tid); - break; - - case ResourcePool::SquashAll: - resPool->squashAll(inst, stageNum, seqNum, tid); - break; - - case ResourcePool::UpdateAfterContextSwitch: - resPool->updateAfterContextSwitch(inst, tid); - break; - - default: - fatal("Unrecognized Event Type"); - } - - resPool->cpu->cpuEventRemoveList.push(this); -} - - -const char * -ResourcePool::ResPoolEvent::description() const -{ - return "Resource Pool event"; -} - -/** Schedule resource event, regardless of its current state. */ -void -ResourcePool::ResPoolEvent::scheduleEvent(Cycles delay) -{ - InOrderCPU *cpu = resPool->cpu; - assert(!scheduled() || squashed()); - cpu->reschedule(this, cpu->clockEdge(delay), true); -} - -/** Unschedule resource event, regardless of its current state. */ -void -ResourcePool::ResPoolEvent::unscheduleEvent() -{ - if (scheduled()) - squash(); -} diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh deleted file mode 100644 index 9e3198e1e..000000000 --- a/src/cpu/inorder/resource_pool.hh +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2012 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 - * - */ - -#ifndef __CPU_INORDER_RESOURCE_POOL_HH__ -#define __CPU_INORDER_RESOURCE_POOL_HH__ - -#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" -#include "cpu/inst_seq.hh" -#include "params/InOrderCPU.hh" -#include "sim/eventq.hh" -#include "sim/sim_object.hh" - -class CacheUnit; -class Event; -class FetchUnit; -class ResourceEvent; - -class ResourcePool { - public: - typedef InOrderDynInst::DynInstPtr DynInstPtr; - - public: - // List of Resource Pool Events that extends - // the list started by the CPU - // NOTE(1): Resource Pool also uses event list - // CPUEventType defined in inorder/cpu.hh - enum ResPoolEventType { - InstGraduated = InOrderCPU::NumCPUEvents, - SquashAll, - UpdateAfterContextSwitch, - Default - }; - - enum ResPoolEventPri { - ResPool_Pri = InOrderCPU::InOrderCPU_Pri - 5, - ResGrad_Pri, - ResSquash_Pri - }; - - class ResPoolEvent : public Event - { - protected: - /** Resource Pool */ - ResourcePool *resPool; - - public: - InOrderCPU::CPUEventType eventType; - - DynInstPtr inst; - - InstSeqNum seqNum; - - int stageNum; - - ThreadID tid; - - public: - /** Constructs a resource event. */ - ResPoolEvent(ResourcePool *_resPool, - InOrderCPU::CPUEventType e_type, - DynInstPtr _inst, - int stage_num, - InstSeqNum seq_num, - ThreadID _tid, - ResPoolEventPri res_pri = ResPool_Pri); - - /** Set Type of Event To Be Scheduled */ - void setEvent(InOrderCPU::CPUEventType e_type, - DynInstPtr _inst, - int stage_num, - InstSeqNum seq_num, - ThreadID _tid) - { - eventType = e_type; - inst = _inst; - seqNum = seq_num; - stageNum = stage_num; - tid = _tid; - } - - /** Processes a resource event. */ - void process(); - - /** Returns the description of the resource event. */ - const char *description() const; - - /** Schedule Event */ - void scheduleEvent(Cycles delay); - - /** Unschedule This Event */ - void unscheduleEvent(); - }; - - public: - ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params); - virtual ~ResourcePool(); - - std::string name(); - - std::string name(int res_idx) { return resources[res_idx]->name(); } - - void init(); - - void print(); - - /** Register Statistics in All Resources */ - void regStats(); - - /** Returns a specific resource. */ - unsigned getResIdx(const ThePipeline::ResourceId &res_id); - - /** Returns a pointer to a resource */ - Resource* getResource(int res_idx) { return resources[res_idx]; } - - /** Request usage of this resource. Returns -1 if not granted and - * a positive request tag if granted. - */ - ResReqPtr request(int res_idx, DynInstPtr inst); - - /** Squash The Resource */ - void squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, - ThreadID tid); - - /** Squash All Resources in Pool after Done Seq. Num */ - void squashAll(DynInstPtr inst, int stage_num, - InstSeqNum done_seq_num, ThreadID tid); - - /** Squash Resources in Pool after a memory stall - * NOTE: Only use during Switch-On-Miss Thread model - */ - void squashDueToMemStall(DynInstPtr inst, int stage_num, - InstSeqNum done_seq_num, ThreadID tid); - - /** Activate Thread in all resources */ - void activateThread(ThreadID tid); - - /** De-Activate Thread in all resources */ - void deactivateThread(ThreadID tid); - - /** Suspend Thread in all resources */ - void suspendThread(ThreadID tid); - - /** Broadcast Context Switch Update to all resources */ - void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid); - - /** Broadcast graduation to all resources */ - void instGraduated(InstSeqNum seq_num, ThreadID tid); - - /** Broadcast trap to all resources */ - void trap(const Fault &fault, ThreadID tid, DynInstPtr inst); - - /** The number of instructions available that a resource can - * can still process. - */ - int slotsAvail(int res_idx); - - /** The number of instructions using a resource */ - int slotsInUse(int res_idx); - - /** Schedule resource event, regardless of its current state. */ - void scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst = NULL, - Cycles delay = Cycles(0), int res_idx = 0, - ThreadID tid = 0); - - /** UnSchedule resource event, regardless of its current state. */ - void unscheduleEvent(int res_idx, DynInstPtr inst); - - /** Tasks to perform when simulation starts */ - virtual void startup() { } - - /** The CPU(s) that this resource interacts with */ - InOrderCPU *cpu; - - DynInstPtr dummyInst[ThePipeline::MaxThreads]; - - /** - * Get a pointer to the (always present) instruction fetch unit. - * - * @return the instruction unit - */ - FetchUnit *getInstUnit() const { return instUnit; } - - /** - * Get a pointer to the (always present) data load/store unit. - * - * @return the data cache unit - */ - CacheUnit *getDataUnit() const { return dataUnit; } - - private: - - /** The instruction fetch unit. */ - FetchUnit *instUnit; - - /** The data load/store unit. */ - CacheUnit *dataUnit; - - std::vector<Resource *> resources; - - /** Resources that need to be updated on an inst. graduation */ - std::vector<int> gradObjects; -}; - -#endif //__CPU_INORDER_RESOURCE_HH__ diff --git a/src/cpu/inorder/resource_sked.cc b/src/cpu/inorder/resource_sked.cc deleted file mode 100644 index e52ed8ff0..000000000 --- a/src/cpu/inorder/resource_sked.cc +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2010 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 <cstdio> -#include <list> -#include <vector> - -#include "cpu/inorder/pipeline_traits.hh" -#include "cpu/inorder/resource_sked.hh" -#include "debug/SkedCache.hh" - -using namespace std; -using namespace ThePipeline; - -ResourceSked::ResourceSked() -{ - stages.resize(NumStages); -} - -void -ResourceSked::init() -{ - assert(!stages[0].empty()); - - curSkedEntry = stages[0].begin(); -} - -int -ResourceSked::size() -{ - int total = 0; - for (int i = 0; i < stages.size(); i++) { - total += stages[i].size(); - } - - return total; -} - -bool -ResourceSked::empty() -{ - return size() == 0; -} - - -ResourceSked::SkedIt -ResourceSked::begin() -{ - int num_stages = stages.size(); - for (int i = 0; i < num_stages; i++) { - if (stages[i].size() > 0) - return stages[i].begin(); - } - - return stages[num_stages - 1].end(); -} - -ResourceSked::SkedIt -ResourceSked::end() -{ - int num_stages = stages.size(); - return stages[num_stages - 1].end(); -} - -ResourceSked::SkedIt -ResourceSked::end(int stage_num) -{ - return stages[stage_num].end(); -} - -ResourceSked::SkedIt -ResourceSked::find(int stage_num, int cmd) -{ - SkedIt stage_it = stages[stage_num].begin(); - SkedIt stage_end = stages[stage_num].end(); - - while (stage_it != stage_end) { - if ((*stage_it)->cmd == cmd) - return stage_it; - stage_it++; - } - - return stages[stage_num].end(); -} - -ScheduleEntry* -ResourceSked::top() -{ - assert(size() > 0); - - return *curSkedEntry; -} - -void -ResourceSked::pop() -{ - int stage_num = (*curSkedEntry)->stageNum; - - stages[stage_num].erase(curSkedEntry); - - if (!stages[stage_num].empty()) { - curSkedEntry = stages[stage_num].begin(); - } else { - int next_stage = stage_num + 1; - - while (next_stage < NumStages) { - if (stages[next_stage].empty()) { - next_stage++; - } else { - curSkedEntry = stages[next_stage].begin(); - break; - } - } - } -} - -void -ResourceSked::push(ScheduleEntry* sked_entry) -{ - int stage_num = sked_entry->stageNum; - assert(stage_num < NumStages); - - SkedIt pri_iter = findIterByPriority(sked_entry, stage_num); - - stages[stage_num].insert(pri_iter, sked_entry); -} - -void -ResourceSked::pushBefore(ScheduleEntry* sked_entry, int sked_cmd, - int sked_cmd_idx) -{ - - int stage_num = sked_entry->stageNum; - assert(stage_num < NumStages); - - SkedIt pri_iter = findIterByCommand(sked_entry, stage_num, - sked_cmd, sked_cmd_idx); - - assert(pri_iter != stages[stage_num].end() && - "Could not find command to insert in front of."); - - stages[stage_num].insert(pri_iter, sked_entry); -} - -ResourceSked::SkedIt -ResourceSked::findIterByPriority(ScheduleEntry* sked_entry, int stage_num) -{ - if (stages[stage_num].empty()) { - return stages[stage_num].end(); - } - - int priority = sked_entry->priority; - - SkedIt sked_it = stages[stage_num].begin(); - SkedIt sked_end = stages[stage_num].end(); - - while (sked_it != sked_end) { - if ((*sked_it)->priority > priority) - break; - - sked_it++; - } - - return sked_it; -} - -ResourceSked::SkedIt -ResourceSked::findIterByCommand(ScheduleEntry* sked_entry, int stage_num, - int sked_cmd, int sked_cmd_idx) -{ - if (stages[stage_num].empty()) { - return stages[stage_num].end(); - } - - SkedIt sked_it = stages[stage_num].begin(); - SkedIt sked_end = stages[stage_num].end(); - - while (sked_it != sked_end) { - if ((*sked_it)->cmd == sked_cmd && - (sked_cmd_idx != -1) ? (*sked_it)->idx == sked_cmd_idx : true) - break; - - sked_it++; - } - - return sked_it; -} - -void -ResourceSked::print() -{ - for (int i = 0; i < stages.size(); i++) { - //ccprintf(cerr, "Stage %i\n====\n", i); - SkedIt sked_it = stages[i].begin(); - SkedIt sked_end = stages[i].end(); - while (sked_it != sked_end) { - DPRINTF(SkedCache, "\t stage:%i res:%i cmd:%i idx:%i\n", - (*sked_it)->stageNum, - (*sked_it)->resNum, - (*sked_it)->cmd, - (*sked_it)->idx); - sked_it++; - } - } -} diff --git a/src/cpu/inorder/resource_sked.hh b/src/cpu/inorder/resource_sked.hh deleted file mode 100644 index c44c2d3fa..000000000 --- a/src/cpu/inorder/resource_sked.hh +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2010-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_RESOURCE_SKED_HH__ -#define __CPU_INORDER_RESOURCE_SKED_HH__ - -#include <cstdlib> -#include <list> -#include <vector> - -/** ScheduleEntry class represents a single function that an instruction - wants to do at any pipeline stage. For example, if an instruction - needs to be decoded and do a branch prediction all in one stage - then each of those tasks would need it's own ScheduleEntry. - - Each schedule entry corresponds to some resource that the instruction - wants to interact with. - - The file pipeline_traits.cc shows how a typical instruction schedule is - made up of these schedule entries. -*/ -class ScheduleEntry { - public: - ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, - int _idx = 0) : - stageNum(stage_num), resNum(res_num), cmd(_cmd), - idx(_idx), priority(_priority) - { } - - /** Stage number to perform this service. */ - int stageNum; - - /** Resource ID to access */ - int resNum; - - /** See specific resource for meaning */ - unsigned cmd; - - /** See specific resource for meaning */ - unsigned idx; - - /** Some Resources May Need Priority */ - int priority; -}; - -/** The ResourceSked maintains the complete schedule - for an instruction. That schedule includes what - resources an instruction wants to acquire at each - pipeline stage and is represented by a collection - of ScheduleEntry objects (described above) that - must be executed in-order. - - In every pipeline stage, the InOrder model will - process all entries on the resource schedule for - that stage and then send the instruction to the next - stage if and only if the instruction successfully - completed each ScheduleEntry. -*/ -class ResourceSked { - public: - typedef std::list<ScheduleEntry*>::iterator SkedIt; - typedef std::vector<std::list<ScheduleEntry*> > StageList; - - ResourceSked(); - - /** Initializee the current entry pointer to - pipeline stage 0 and the 1st schedule entry - */ - void init(); - - /** Goes through the remaining stages on the schedule - and sums all the remaining entries left to be - processed - */ - int size(); - - /** Is the schedule empty? */ - bool empty(); - - /** Beginning Entry of this schedule */ - SkedIt begin(); - - /** Ending Entry of this schedule */ - SkedIt end(); - - /** Ending Entry of a specified stage */ - SkedIt end(int stage_num); - - /** Find a schedule entry based on stage and command */ - SkedIt find(int stage_num, int cmd); - - /** What is the next task for this instruction schedule? */ - ScheduleEntry* top(); - - /** Top() Task is completed, remove it from schedule */ - void pop(); - - /** Add To Schedule based on stage num and priority of - Schedule Entry - */ - void push(ScheduleEntry* sked_entry); - - /** Add Schedule Entry to be in front of another Entry */ - void pushBefore(ScheduleEntry* sked_entry, int sked_cmd, int sked_cmd_idx); - - /** Print what's left on the instruction schedule */ - void print(); - - StageList *getStages() - { - return &stages; - } - - private: - /** Current Schedule Entry Pointer */ - SkedIt curSkedEntry; - - /** The Stage-by-Stage Resource Schedule: - Resized to Number of Stages in the constructor - */ - StageList stages; - - /** Find a place to insert the instruction using the - schedule entries priority - */ - SkedIt findIterByPriority(ScheduleEntry *sked_entry, int stage_num); - - /** Find a place to insert the instruction using a particular command - to look for. - */ - SkedIt findIterByCommand(ScheduleEntry *sked_entry, int stage_num, - int sked_cmd, int sked_cmd_idx = -1); -}; - -/** Wrapper class around the SkedIt iterator in the Resource Sked so that - we can use ++ operator to automatically go to the next available - resource schedule entry but otherwise maintain same functionality - as a normal iterator. -*/ -class RSkedIt -{ - public: - RSkedIt() - : curStage(0), numStages(0) - { } - - - /** init() must be called before the use of any other member - in the RSkedIt class. - */ - void init(ResourceSked* rsked) - { - stages = rsked->getStages(); - numStages = stages->size(); - } - - /* Update the encapsulated "myIt" iterator, but only - update curStage/curStage_end if the iterator is valid. - The iterator could be invalid in the case where - someone is saving the end of a list (i.e. std::list->end()) - */ - RSkedIt operator=(ResourceSked::SkedIt const &rhs) - { - myIt = rhs; - if (myIt != (*stages)[numStages-1].end()) { - curStage = (*myIt)->stageNum; - curStage_end = (*stages)[curStage].end(); - } - return *this; - } - - /** Increment to the next entry in current stage. - If no more entries then find the next stage that has - resource schedule to complete. - If no more stages, then return the end() iterator from - the last stage to indicate we are done. - */ - RSkedIt &operator++(int unused) - { - if (++myIt == curStage_end) { - curStage++; - while (curStage < numStages) { - if ((*stages)[curStage].empty()) { - curStage++; - } else { - myIt = (*stages)[curStage].begin(); - curStage_end = (*stages)[curStage].end(); - return *this; - } - } - - myIt = (*stages)[numStages - 1].end(); - } - - return *this; - } - - /** The "pointer" operator can be used on a RSkedIt and it - will use the encapsulated iterator - */ - ScheduleEntry* operator->() - { - return *myIt; - } - - /** Dereferencing a RSKedIt will access the encapsulated - iterator - */ - ScheduleEntry* operator*() - { - return *myIt; - } - - /** Equality for RSkedIt only compares the "myIt" iterators, - as the other members are just ancillary - */ - bool operator==(RSkedIt const &rhs) - { - return this->myIt == rhs.myIt; - } - - /** Inequality for RSkedIt only compares the "myIt" iterators, - as the other members are just ancillary - */ - bool operator!=(RSkedIt const &rhs) - { - return this->myIt != rhs.myIt; - } - - /* The == and != operator overloads should be sufficient - here if need otherwise direct access to the schedule - iterator, then this can be used */ - ResourceSked::SkedIt getIt() - { - return myIt; - } - - private: - /** Schedule Iterator that this class is encapsulating */ - ResourceSked::SkedIt myIt; - - /** Ptr to resource schedule that the 'myIt' iterator - belongs to - */ - ResourceSked::StageList *stages; - - /** The last iterator in the current stage. */ - ResourceSked::SkedIt curStage_end; - - /** Current Stage that "myIt" refers to. */ - int curStage; - - /** Number of stages in the "*stages" object. */ - int numStages; -}; - -#endif //__CPU_INORDER_RESOURCE_SKED_HH__ 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__ diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc deleted file mode 100644 index 1fc66d827..000000000 --- a/src/cpu/inorder/thread_context.cc +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2012 ARM Limited - * Copyright (c) 2013 Advanced Micro Devices, Inc. - * 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 "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inorder/thread_context.hh" -#include "cpu/exetrace.hh" -#include "debug/InOrderCPU.hh" -#include "sim/full_system.hh" - -using namespace TheISA; - -FSTranslatingPortProxy& -InOrderThreadContext::getVirtProxy() -{ - return thread->getVirtProxy(); -} - -void -InOrderThreadContext::dumpFuncProfile() -{ - thread->dumpFuncProfile(); -} - - -Tick -InOrderThreadContext::readLastActivate() -{ - return thread->lastActivate; -} - - -Tick -InOrderThreadContext::readLastSuspend() -{ - return thread->lastSuspend; -} - - -void -InOrderThreadContext::profileClear() -{ - thread->profileClear(); -} - - -void -InOrderThreadContext::profileSample() -{ - thread->profileSample(); -} - -void -InOrderThreadContext::takeOverFrom(ThreadContext *old_context) -{ - ::takeOverFrom(*this, *old_context); - - thread->funcExeInst = old_context->readFuncExeInst(); - - thread->noSquashFromTC = false; - thread->trapPending = false; -} - -void -InOrderThreadContext::activate() -{ - DPRINTF(InOrderCPU, "Calling activate on Thread Context %d\n", - getThreadNum()); - - if (thread->status() == ThreadContext::Active) - return; - - thread->setStatus(ThreadContext::Active); - - cpu->activateContext(thread->threadId()); -} - - -void -InOrderThreadContext::suspend() -{ - DPRINTF(InOrderCPU, "Calling suspend on Thread Context %d\n", - getThreadNum()); - - if (thread->status() == ThreadContext::Suspended) - return; - - thread->setStatus(ThreadContext::Suspended); - cpu->suspendContext(thread->threadId()); -} - -void -InOrderThreadContext::halt() -{ - DPRINTF(InOrderCPU, "Calling halt on Thread Context %d\n", - getThreadNum()); - - if (thread->status() == ThreadContext::Halted) - return; - - thread->setStatus(ThreadContext::Halted); - cpu->haltContext(thread->threadId()); -} - - -void -InOrderThreadContext::regStats(const std::string &name) -{ - if (FullSystem) { - thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system); - thread->kernelStats->regStats(name + ".kern"); - } -} - -void -InOrderThreadContext::copyArchRegs(ThreadContext *src_tc) -{ - TheISA::copyRegs(src_tc, this); -} - - -void -InOrderThreadContext::clearArchRegs() -{ - cpu->isa[thread->threadId()]->clear(); -} - - -uint64_t -InOrderThreadContext::readIntReg(int reg_idx) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenIntIndex(reg_idx); - return cpu->readIntReg(reg_idx, tid); -} - -FloatReg -InOrderThreadContext::readFloatReg(int reg_idx) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenFloatIndex(reg_idx); - return cpu->readFloatReg(reg_idx, tid); -} - -FloatRegBits -InOrderThreadContext::readFloatRegBits(int reg_idx) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenFloatIndex(reg_idx); - return cpu->readFloatRegBits(reg_idx, tid); -} - -CCReg -InOrderThreadContext::readCCReg(int reg_idx) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenCCIndex(reg_idx); - return cpu->readCCReg(reg_idx, tid); -} - -uint64_t -InOrderThreadContext::readRegOtherThread(int reg_idx, ThreadID tid) -{ - return cpu->readRegOtherThread(reg_idx, tid); -} - -void -InOrderThreadContext::setIntReg(int reg_idx, uint64_t val) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenIntIndex(reg_idx); - cpu->setIntReg(reg_idx, val, tid); -} - -void -InOrderThreadContext::setFloatReg(int reg_idx, FloatReg val) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenFloatIndex(reg_idx); - cpu->setFloatReg(reg_idx, val, tid); -} - -void -InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenFloatIndex(reg_idx); - cpu->setFloatRegBits(reg_idx, val, tid); -} - -void -InOrderThreadContext::setCCReg(int reg_idx, CCReg val) -{ - ThreadID tid = thread->threadId(); - reg_idx = cpu->isa[tid]->flattenCCIndex(reg_idx); - cpu->setCCReg(reg_idx, val, tid); -} - -void -InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val, - ThreadID tid) -{ - cpu->setRegOtherThread(misc_reg, val, tid); -} - -void -InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) -{ - cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId()); -} - -void -InOrderThreadContext::setMiscReg(int misc_reg, const MiscReg &val) -{ - cpu->setMiscReg(misc_reg, val, thread->threadId()); -} - - -uint64_t -InOrderThreadContext::readIntRegFlat(int idx) -{ - const ThreadID tid = thread->threadId(); - return cpu->readIntReg(idx, tid); -} - -void -InOrderThreadContext::setIntRegFlat(int idx, uint64_t val) -{ - const ThreadID tid = thread->threadId(); - cpu->setIntReg(idx, val, tid); -} - -FloatReg -InOrderThreadContext::readFloatRegFlat(int idx) -{ - const ThreadID tid = thread->threadId(); - return cpu->readFloatReg(idx, tid); -} - -void -InOrderThreadContext::setFloatRegFlat(int idx, FloatReg val) -{ - const ThreadID tid = thread->threadId(); - cpu->setFloatReg(idx, val, tid); -} - -FloatRegBits -InOrderThreadContext::readFloatRegBitsFlat(int idx) -{ - const ThreadID tid = thread->threadId(); - return cpu->readFloatRegBits(idx, tid); -} - -void -InOrderThreadContext::setFloatRegBitsFlat(int idx, FloatRegBits val) -{ - const ThreadID tid = thread->threadId(); - cpu->setFloatRegBits(idx, val, tid); -} - -CCReg -InOrderThreadContext::readCCRegFlat(int idx) -{ - const ThreadID tid = thread->threadId(); - return cpu->readCCReg(idx, tid); -} - -void -InOrderThreadContext::setCCRegFlat(int idx, CCReg val) -{ - const ThreadID tid = thread->threadId(); - cpu->setCCReg(idx, val, tid); -} diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh deleted file mode 100644 index 022beaaee..000000000 --- a/src/cpu/inorder/thread_context.hh +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2012 ARM Limited - * Copyright (c) 2013 Advanced Micro Devices, Inc. - * 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 - * - */ - -#ifndef __CPU_INORDER_THREAD_CONTEXT_HH__ -#define __CPU_INORDER_THREAD_CONTEXT_HH__ - -#include "config/the_isa.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/exetrace.hh" -#include "cpu/thread_context.hh" -#include "arch/kernel_stats.hh" - -class EndQuiesceEvent; -class CheckerCPU; -namespace Kernel { - class Statistics; -}; - -/** - * Derived ThreadContext class for use with the InOrderCPU. It - * provides the interface for any external objects to access a - * single thread's state and some general CPU state. Any time - * external objects try to update state through this interface, - * the CPU will create an event to squash all in-flight - * instructions in order to ensure state is maintained correctly. - * It must be defined specifically for the InOrderCPU because - * not all architectural state is located within the O3ThreadState - * (such as the commit PC, and registers), and specific actions - * must be taken when using this interface (such as squashing all - * in-flight instructions when doing a write to this interface). - */ -class InOrderThreadContext : public ThreadContext -{ - public: - InOrderThreadContext() { } - - /** Pointer to the CPU. */ - InOrderCPU *cpu; - - /** Pointer to the thread state that this TC corrseponds to. */ - InOrderThreadState *thread; - - /** Returns a pointer to the ITB. */ - /** @TODO: PERF: Should we bind this to a pointer in constructor? */ - TheISA::TLB *getITBPtr() { return cpu->getITBPtr(); } - - /** Returns a pointer to the DTB. */ - /** @TODO: PERF: Should we bind this to a pointer in constructor? */ - TheISA::TLB *getDTBPtr() { return cpu->getDTBPtr(); } - - /** Currently InOrder model does not support CheckerCPU, this is - * merely here for supporting compilation of gem5 with the Checker - * as a runtime option - */ - CheckerCPU *getCheckerCpuPtr() { return NULL; } - - TheISA::Decoder * - getDecoderPtr() - { - return cpu->getDecoderPtr(thread->contextId()); - } - - System *getSystemPtr() { return cpu->system; } - - /** Returns a pointer to this CPU. */ - BaseCPU *getCpuPtr() { return cpu; } - - /** Returns a pointer to this CPU. */ - std::string getCpuName() { return cpu->name(); } - - /** Reads this CPU's ID. */ - int cpuId() const { return cpu->cpuId(); } - - /** Reads this CPU's Socket ID. */ - uint32_t socketId() const { return cpu->socketId(); } - - int contextId() const { return thread->contextId(); } - - void setContextId(int id) { thread->setContextId(id); } - - /** Returns this thread's ID number. */ - int threadId() const { return thread->threadId(); } - void setThreadId(int id) { return thread->setThreadId(id); } - - uint64_t readMicroPC() - { return 0; } - - void setMicroPC(uint64_t val) { }; - - uint64_t readNextMicroPC() - { return 0; } - - void setNextMicroPC(uint64_t val) { }; - - /** Returns a pointer to this thread's kernel statistics. */ - TheISA::Kernel::Statistics *getKernelStats() - { return thread->kernelStats; } - - PortProxy &getPhysProxy() { return thread->getPhysProxy(); } - - FSTranslatingPortProxy &getVirtProxy(); - - void initMemProxies(ThreadContext *tc) - { thread->initMemProxies(tc); } - - /** Dumps the function profiling information. - * @todo: Implement. - */ - void dumpFuncProfile(); - - /** Reads the last tick that this thread was activated on. */ - Tick readLastActivate(); - /** Reads the last tick that this thread was suspended on. */ - Tick readLastSuspend(); - - /** Clears the function profiling information. */ - void profileClear(); - - /** Samples the function profiling information. */ - void profileSample(); - - /** Returns pointer to the quiesce event. */ - EndQuiesceEvent *getQuiesceEvent() - { - return this->thread->quiesceEvent; - } - - SETranslatingPortProxy &getMemProxy() { return thread->getMemProxy(); } - - /** Returns a pointer to this thread's process. */ - Process *getProcessPtr() { return thread->getProcessPtr(); } - - /** Returns this thread's status. */ - Status status() const { return thread->status(); } - - /** Sets this thread's status. */ - void setStatus(Status new_status) - { thread->setStatus(new_status); } - - /** Set the status to Active. */ - void activate(); - - /** Set the status to Suspended. */ - void suspend(); - - /** Set the status to Halted. */ - void halt(); - - /** Takes over execution of a thread from another CPU. */ - void takeOverFrom(ThreadContext *old_context); - - /** Registers statistics associated with this TC. */ - void regStats(const std::string &name); - - /** Returns this thread's ID number. */ - int getThreadNum() { return thread->threadId(); } - - /** Copies the architectural registers from another TC into this TC. */ - void copyArchRegs(ThreadContext *src_tc); - - /** Resets all architectural registers to 0. */ - void clearArchRegs(); - - /** Reads an integer register. */ - uint64_t readIntReg(int reg_idx); - - FloatReg readFloatReg(int reg_idx); - - FloatRegBits readFloatRegBits(int reg_idx); - - CCReg readCCReg(int reg_idx); - - uint64_t readRegOtherThread(int misc_reg, ThreadID tid); - - /** Sets an integer register to a value. */ - void setIntReg(int reg_idx, uint64_t val); - - void setFloatReg(int reg_idx, FloatReg val); - - void setFloatRegBits(int reg_idx, FloatRegBits val); - - void setCCReg(int reg_idx, CCReg val); - - void setRegOtherThread(int misc_reg, - const MiscReg &val, - ThreadID tid); - - /** Reads this thread's PC. */ - TheISA::PCState pcState() - { return cpu->pcState(thread->threadId()); } - - /** Sets this thread's PC. */ - void pcState(const TheISA::PCState &val) - { cpu->pcState(val, thread->threadId()); } - - /** Needs to be implemented for future CheckerCPU support. - * See O3CPU for examples on how to integrate Checker. - */ - void pcStateNoRecord(const TheISA::PCState &val) - {} - - Addr instAddr() - { return cpu->instAddr(thread->threadId()); } - - Addr nextInstAddr() - { return cpu->nextInstAddr(thread->threadId()); } - - MicroPC microPC() - { return cpu->microPC(thread->threadId()); } - - /** Reads a miscellaneous register. */ - MiscReg readMiscRegNoEffect(int misc_reg) - { return cpu->readMiscRegNoEffect(misc_reg, thread->threadId()); } - - /** Reads a misc. register, including any side-effects the - * read might have as defined by the architecture. */ - MiscReg readMiscReg(int misc_reg) - { return cpu->readMiscReg(misc_reg, thread->threadId()); } - - /** Sets a misc. register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val); - - /** Sets a misc. register, including any side-effects the - * write might have as defined by the architecture. */ - void setMiscReg(int misc_reg, const MiscReg &val); - - int flattenIntIndex(int reg) - { return cpu->isa[thread->threadId()]->flattenIntIndex(reg); } - - int flattenFloatIndex(int reg) - { return cpu->isa[thread->threadId()]->flattenFloatIndex(reg); } - - int flattenCCIndex(int reg) - { return cpu->isa[thread->threadId()]->flattenCCIndex(reg); } - - int flattenMiscIndex(int reg) - { return cpu->isa[thread->threadId()]->flattenMiscIndex(reg); } - - void activateContext() - { cpu->activateContext(thread->threadId()); } - - /** Returns the number of consecutive store conditional failures. */ - // @todo: Figure out where these store cond failures should go. - unsigned readStCondFailures() - { return thread->storeCondFailures; } - - /** Sets the number of consecutive store conditional failures. */ - void setStCondFailures(unsigned sc_failures) - { thread->storeCondFailures = sc_failures; } - - /** Executes a syscall in SE mode. */ - void syscall(int64_t callnum) - { return cpu->syscall(callnum, thread->threadId()); } - - /** Reads the funcExeInst counter. */ - Counter readFuncExeInst() { return thread->funcExeInst; } - - void changeRegFileContext(unsigned param, - unsigned val) - { panic("Not supported!"); } - - uint64_t readIntRegFlat(int idx); - void setIntRegFlat(int idx, uint64_t val); - - FloatReg readFloatRegFlat(int idx); - void setFloatRegFlat(int idx, FloatReg val); - - FloatRegBits readFloatRegBitsFlat(int idx); - void setFloatRegBitsFlat(int idx, FloatRegBits val); - - CCReg readCCRegFlat(int idx); - void setCCRegFlat(int idx, CCReg val); -}; - -#endif diff --git a/src/cpu/inorder/thread_state.cc b/src/cpu/inorder/thread_state.cc deleted file mode 100644 index 040e29283..000000000 --- a/src/cpu/inorder/thread_state.cc +++ /dev/null @@ -1,44 +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 "arch/isa_traits.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/thread_state.hh" -#include "cpu/exetrace.hh" - -using namespace TheISA; - -void -InOrderThreadState::dumpFuncProfile() -{ - std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); - profile->dump(tc, *os); -} diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh deleted file mode 100644 index 4472bf1dd..000000000 --- a/src/cpu/inorder/thread_state.hh +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2006 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: Kevin Lim - */ - -#ifndef __CPU_INORDER_THREAD_STATE_HH__ -#define __CPU_INORDER_THREAD_STATE_HH__ - -#include "arch/isa_traits.hh" -#include "base/callback.hh" -#include "base/output.hh" -#include "cpu/thread_context.hh" -#include "cpu/thread_state.hh" -#include "sim/sim_exit.hh" - -class EndQuiesceEvent; -class Event; -class FunctionalMemory; -class FunctionProfile; -class InOrderCPU; -class Process; -class ProfileNode; - -/** - * Class that has various thread state, such as the status, the - * current instruction being processed, whether or not the thread has - * a trap pending or is being externally updated, the ThreadContext - * pointer, etc. It also handles anything related to a specific - * thread's process, such as syscalls and checking valid addresses. - */ -class InOrderThreadState : public ThreadState { - typedef ThreadContext::Status Status; - - private: - /** Pointer to the CPU. */ - InOrderCPU *cpu; - - public: - /* This variable controls if writes to a thread context should cause a all - * dynamic/speculative state to be thrown away. Nominally this is the - * desired behavior because the external thread context write has updated - * some state that could be used by an inflight instruction, however there - * are some cases like in a fault/trap handler where this behavior would - * lead to successive restarts and forward progress couldn't be made. This - * variable controls if the squashing will occur. - */ - bool noSquashFromTC; - - /** Whether or not the thread is currently waiting on a trap, and - * thus able to be externally updated without squashing. - */ - bool trapPending; - - InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num, - Process *_process) - : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num, - _process), - cpu(_cpu), noSquashFromTC(false), trapPending(false), - lastGradIsBranch(false) - { } - - /** Handles the syscall. */ - void syscall(int64_t callnum) { process->syscall(callnum, tc); } - - void dumpFuncProfile(); - - /** Pointer to the ThreadContext of this thread. */ - ThreadContext *tc; - - /** Returns a pointer to the TC of this thread. */ - ThreadContext *getTC() { return tc; } - - /** Is last instruction graduated a branch? */ - bool lastGradIsBranch; - TheISA::PCState lastBranchPC; -}; - -#endif // __CPU_INORDER_THREAD_STATE_HH__ |