Adding gem5 source to svn.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1819 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
934
simulators/gem5/src/cpu/inorder/cpu.hh
Normal file
934
simulators/gem5/src/cpu/inorder/cpu.hh
Normal file
@ -0,0 +1,934 @@
|
||||
/*
|
||||
* 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_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/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::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();
|
||||
|
||||
/** Return a reference to the data port. */
|
||||
virtual CpuPort &getDataPort() { return dataPort; }
|
||||
|
||||
/** Return a reference to the instruction port. */
|
||||
virtual CpuPort &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 CpuPort
|
||||
{
|
||||
|
||||
private:
|
||||
/** Pointer to cache unit */
|
||||
CacheUnit *cacheUnit;
|
||||
|
||||
public:
|
||||
/** Default constructor. */
|
||||
CachePort(CacheUnit *_cacheUnit);
|
||||
|
||||
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(int delay)
|
||||
{
|
||||
assert(!tickEvent.scheduled() || tickEvent.squashed());
|
||||
reschedule(&tickEvent, nextCycle(curTick() + ticks(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, Fault fault,
|
||||
ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri);
|
||||
|
||||
/** Set Type of Event To Be Scheduled */
|
||||
void setEvent(CPUEventType e_type, 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(int delay);
|
||||
|
||||
/** Unschedule This Event */
|
||||
void unscheduleEvent();
|
||||
};
|
||||
|
||||
/** Schedule a CPU Event */
|
||||
void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid,
|
||||
DynInstPtr inst, unsigned delay = 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];
|
||||
|
||||
/** ISA state */
|
||||
TheISA::ISA isa[ThePipeline::MaxThreads];
|
||||
|
||||
/** Dependency Tracker for Integer & Floating Point Regs */
|
||||
RegDepMap archRegDepMap[ThePipeline::MaxThreads];
|
||||
|
||||
/** Register Types Used in Dependency Tracking */
|
||||
enum RegType { IntType, FloatType, MiscType, NumRegTypes};
|
||||
|
||||
/** 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(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(Fault fault, ThreadID tid, DynInstPtr inst,
|
||||
int delay = 0);
|
||||
|
||||
/** Executes a syscall.*/
|
||||
void syscall(int64_t callnum, ThreadID tid);
|
||||
|
||||
/** Schedule a trap on the CPU */
|
||||
void trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
|
||||
|
||||
/** Perform trap to Handle Given Fault */
|
||||
void trap(Fault fault, ThreadID tid, DynInstPtr inst);
|
||||
|
||||
/** Schedule thread activation on the CPU */
|
||||
void activateContext(ThreadID tid, int delay = 0);
|
||||
|
||||
/** 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(int delay = 0);
|
||||
|
||||
/** Add Thread From Ready List to Active Threads List. */
|
||||
void activateNextReadyThread();
|
||||
|
||||
/** Schedule a thread deactivation on the CPU */
|
||||
void deactivateContext(ThreadID tid, int delay = 0);
|
||||
|
||||
/** 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, int delay = 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);
|
||||
|
||||
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);
|
||||
|
||||
RegType inline getRegType(RegIndex reg_idx)
|
||||
{
|
||||
if (reg_idx < TheISA::FP_Base_DepTag)
|
||||
return IntType;
|
||||
else if (reg_idx < TheISA::Ctrl_Base_DepTag)
|
||||
return FloatType;
|
||||
else
|
||||
return MiscType;
|
||||
}
|
||||
|
||||
RegIndex flattenRegIdx(RegIndex reg_idx, RegType ®_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;
|
||||
|
||||
/** Whether or not the CPU should defer its registration. */
|
||||
bool deferRegistration;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** 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__
|
||||
Reference in New Issue
Block a user