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