+++ /dev/null
-# 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")
+++ /dev/null
-# 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"
+++ /dev/null
-# -*- 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')
-
+++ /dev/null
-# -*- 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)
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-};
-
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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++;
- }
- }
-
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
-
-};
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
-
-};
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
-
-};
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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");
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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
-
-
-
-
-
-
-
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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++;
- }
- }
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
- }
-}
-
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
- }
-}
-
-
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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]);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
-
-
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
- }
- }
-}
-
-
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__