X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Finorder%2Fcpu.hh;h=1183f6fc9ab29876b2b80fd653a132c6978d5504;hb=7d0344704a9ecc566d82ad43ec44b4becbaf4d77;hp=75d77c81822fafe6430d63dd5493ea5e9687d4b2;hpb=100da6b3267b4e3d6834cd872502b8303d289d17;p=gem5.git diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 75d77c818..1183f6fc9 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -1,4 +1,17 @@ /* + * 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. * @@ -39,27 +52,30 @@ #include #include "arch/isa_traits.hh" +#include "arch/registers.hh" #include "arch/types.hh" #include "base/statistics.hh" -#include "base/timebuf.hh" #include "base/types.hh" -#include "config/full_system.hh" -#include "cpu/activity.hh" -#include "cpu/base.hh" -#include "cpu/simple_thread.hh" +#include "config/the_isa.hh" #include "cpu/inorder/inorder_dyn_inst.hh" -#include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/pipeline_stage.hh" -#include "cpu/inorder/thread_state.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; @@ -77,7 +93,9 @@ class InOrderCPU : public BaseCPU 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; @@ -87,17 +105,39 @@ class InOrderCPU : public BaseCPU typedef TimeBuffer 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; } @@ -115,8 +155,35 @@ class InOrderCPU : public BaseCPU /** 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 { @@ -132,19 +199,17 @@ class InOrderCPU : public BaseCPU void process(); /** Returns the description of the tick event. */ - const char *description(); + 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) + void scheduleTickEvent(Cycles delay) { - if (tickEvent.squashed()) - mainEventQueue.reschedule(&tickEvent, nextCycle(curTick + ticks(delay))); - else if (!tickEvent.scheduled()) - mainEventQueue.schedule(&tickEvent, nextCycle(curTick + ticks(delay))); + assert(!tickEvent.scheduled() || tickEvent.squashed()); + reschedule(&tickEvent, clockEdge(delay), true); } /** Unschedule tick event, regardless of its current state. */ @@ -163,21 +228,25 @@ class InOrderCPU : public BaseCPU // pool event. enum CPUEventType { ActivateThread, - DeallocateThread, + ActivateNextReadyThread, + DeactivateThread, + HaltThread, SuspendThread, - DisableThreads, - EnableThreads, - DisableVPEs, - EnableVPEs, Trap, - InstGraduated, - SquashAll, + 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 { @@ -187,32 +256,35 @@ class InOrderCPU : public BaseCPU public: CPUEventType cpuEventType; ThreadID tid; - unsigned vpe; + DynInstPtr inst; Fault fault; - + unsigned vpe; + short syscall_num; + public: /** Constructs a CPU event. */ CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault, - ThreadID _tid, unsigned _vpe); + ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri); /** Set Type of Event To Be Scheduled */ void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid, - unsigned _vpe) + DynInstPtr _inst) { fault = _fault; cpuEventType = e_type; tid = _tid; - vpe = _vpe; + inst = _inst; + vpe = 0; } - /** Processes a resource event. */ - virtual void process(); + /** Processes a CPU event. */ + void process(); - /** Returns the description of the resource event. */ - const char *description(); + /** Returns the description of the CPU event. */ + const char *description() const; /** Schedule Event */ - void scheduleEvent(int delay); + void scheduleEvent(Cycles delay); /** Unschedule This Event */ void unscheduleEvent(); @@ -220,41 +292,35 @@ class InOrderCPU : public BaseCPU /** Schedule a CPU Event */ void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid, - unsigned vpe, unsigned delay = 0); + 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 */ + /** 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; - - /** Identifies the resource id that identifies a fetch - * access unit. - */ - unsigned fetchPortIdx; - - /** Identifies the resource id that identifies a ITB */ - unsigned itbIdx; - - /** Identifies the resource id that identifies a data - * access unit. - */ - unsigned dataPortIdx; - - /** Identifies the resource id that identifies a DTB */ - unsigned dtbIdx; + ResourceRequest *dummyReq[ThePipeline::MaxThreads]; /** The Pipeline Stages for the CPU */ PipelineStage *pipelineStage[ThePipeline::NumStages]; /** Program Counters */ - TheISA::IntReg PC[ThePipeline::MaxThreads]; - TheISA::IntReg nextPC[ThePipeline::MaxThreads]; - TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; + TheISA::PCState pc[ThePipeline::MaxThreads]; + + /** Last Committed PC */ + TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads]; /** The Register File for the CPU */ union { @@ -262,9 +328,12 @@ class InOrderCPU : public BaseCPU 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 */ - TheISA::ISA isa[ThePipeline::MaxThreads]; + std::vector isa; /** Dependency Tracker for Integer & Floating Point Regs */ RegDepMap archRegDepMap[ThePipeline::MaxThreads]; @@ -278,6 +347,106 @@ class InOrderCPU : public BaseCPU 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 skedCache; + + typedef m5::hash_map::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. */ @@ -291,38 +460,88 @@ class InOrderCPU : public BaseCPU /** Initialize the CPU */ void init(); - /** Reset State in the CPU */ - void reset(); + /** HW return from error interrupt. */ + Fault hwrei(ThreadID tid); - /** Get a Memory Port */ - Port* getPort(const std::string &if_name, int idx = 0); + bool simPalCheck(int palFunc, ThreadID tid); - /** trap() - sets up a trap event on the cpuTraps to handle given fault. - * trapCPU() - Traps to handle given fault - */ - void trap(Fault fault, ThreadID tid, int delay = 0); - void trapCPU(Fault fault, 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"); } - /** Setup CPU to insert a thread's context */ - void insertThread(ThreadID tid); + /** Check if this address is a valid instruction address. */ + bool validInstAddr(Addr addr) { return true; } - /** Remove all of a thread's context from CPU */ - void removeThread(ThreadID tid); + /** 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, + Cycles delay = Cycles(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, + Cycles delay = Cycles(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, Cycles delay = Cycles(0)); /** Add Thread to Active Threads List. */ - void activateContext(ThreadID tid, int delay = 0); void activateThread(ThreadID tid); - /** Remove Thread from Active Threads List */ - void suspendContext(ThreadID tid, int delay = 0); + /** Activate Thread In Each Pipeline Stage */ + void activateThreadInPipeline(ThreadID tid); + + /** Schedule Thread Activation from Ready List */ + void activateNextReadyContext(Cycles delay = Cycles(0)); + + /** Add Thread From Ready List to Active Threads List. */ + void activateNextReadyThread(); + + /** Schedule a thread deactivation on the CPU */ + void deactivateContext(ThreadID tid, Cycles delay = Cycles(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); - /** Remove Thread from Active Threads List && - * Remove Thread Context from CPU. + /** 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 deallocateContext(ThreadID tid, int delay = 0); - void deallocateThread(ThreadID tid); - void deactivateThread(ThreadID tid); + 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); @@ -333,37 +552,6 @@ class InOrderCPU : public BaseCPU return 0; } - /** Remove Thread from Active Threads List && - * Remove Thread Context from CPU. - */ - void haltContext(ThreadID tid, int delay = 0); - - void removePipelineStalls(ThreadID tid); - - void squashThreadInPipeline(ThreadID tid); - - /// Notify the CPU to enable a virtual processor element. - virtual void enableVirtProcElement(unsigned vpe); - void enableVPEs(unsigned vpe); - - /// Notify the CPU to disable a virtual processor element. - virtual void disableVirtProcElement(ThreadID tid, unsigned vpe); - void disableVPEs(ThreadID tid, unsigned vpe); - - /// Notify the CPU that multithreading is enabled. - virtual void enableMultiThreading(unsigned vpe); - void enableThreads(unsigned vpe); - - /// Notify the CPU that multithreading is disabled. - virtual void disableMultiThreading(ThreadID tid, unsigned vpe); - void disableThreads(ThreadID tid, unsigned vpe); - - /** Activate a Thread When CPU Resources are Available. */ - void activateWhenReady(ThreadID tid); - - /** Add or Remove a Thread Context in the CPU. */ - void doContextSwitch(); - /** Update The Order In Which We Process Threads. */ void updateThreadPriority(); @@ -392,21 +580,31 @@ class InOrderCPU : public BaseCPU /** Get & Update Next Event Number */ InstSeqNum getNextEventNum() { +#ifdef DEBUG return cpuEventNum++; +#else + return 0; +#endif } /** Register file accessors */ - uint64_t readIntReg(int reg_idx, ThreadID tid); + uint64_t readIntReg(RegIndex reg_idx, ThreadID tid); + + FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid); + + FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid); - FloatReg readFloatReg(int reg_idx, ThreadID tid); + CCReg readCCReg(RegIndex reg_idx, ThreadID tid); - FloatRegBits readFloatRegBits(int reg_idx, ThreadID tid); + void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid); - void setIntReg(int reg_idx, uint64_t val, ThreadID tid); + void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid); - void setFloatReg(int reg_idx, FloatReg val, ThreadID tid); + void setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid); - void setFloatRegBits(int 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); @@ -438,50 +636,50 @@ class InOrderCPU : public BaseCPU ThreadID tid); /** Reads the commit PC of a specific thread. */ - uint64_t readPC(ThreadID tid); + TheISA::PCState + pcState(ThreadID tid) + { + return pc[tid]; + } /** Sets the commit PC of a specific thread. */ - void setPC(Addr new_PC, ThreadID tid); - - /** Reads the next PC of a specific thread. */ - uint64_t readNextPC(ThreadID tid); - - /** Sets the next PC of a specific thread. */ - void setNextPC(uint64_t val, ThreadID tid); - - /** Reads the next NPC of a specific thread. */ - uint64_t readNextNPC(ThreadID tid); + void + pcState(const TheISA::PCState &newPC, ThreadID tid) + { + pc[tid] = newPC; + } - /** Sets the next NPC of a specific thread. */ - void setNextNPC(uint64_t val, ThreadID tid); + 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); + 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); + void addToRemoveList(DynInstPtr inst); /** Remove an instruction from CPU */ - void removeInst(DynInstPtr &inst); + 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 &instIt, ThreadID tid); + inline void squashInstIt(const ListIt inst_it, ThreadID tid); /** Cleans up all instructions on the instruction remove list. */ void cleanUpRemovedInsts(); - /** Cleans up all instructions on the request remove list. */ - void cleanUpRemovedReqs(); - - /** Cleans up all instructions on the CPU event remove list. */ + /** Cleans up all events on the CPU event remove list. */ void cleanUpRemovedEvents(); /** Debug function to print all instructions on the list. */ @@ -490,28 +688,14 @@ class InOrderCPU : public BaseCPU /** Forwards an instruction read to the appropriate data * resource (indexes into Resource Pool thru "dataPortIdx") */ - template - Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags); + 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") */ - template - Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags, - uint64_t *write_res = NULL); - - /** Forwards an instruction prefetch to the appropriate data - * resource (indexes into Resource Pool thru "dataPortIdx") - */ - void prefetch(DynInstPtr inst); - - /** Forwards an instruction writeHint to the appropriate data - * resource (indexes into Resource Pool thru "dataPortIdx") - */ - void writeHint(DynInstPtr inst); - - /** Executes a syscall.*/ - void syscall(int64_t callnum, ThreadID tid); + 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. */ @@ -522,10 +706,7 @@ class InOrderCPU : public BaseCPU */ std::queue removeList; - /** List of all the resource requests that will be removed at the end of this - * cycle. - */ - std::queue reqRemoveList; + bool trapPending[ThePipeline::MaxThreads]; /** List of all the cpu event requests that will be removed at the end of * the current cycle. @@ -557,18 +738,19 @@ class InOrderCPU : public BaseCPU /** Active Threads List */ std::list activeThreads; - /** Current Threads List */ - std::list currentThreads; + /** Ready Threads List */ + std::list readyThreads; /** Suspended Threads List */ std::list suspendedThreads; - /** Thread Status Functions (Unused Currently) */ - bool isThreadInCPU(ThreadID tid); + /** Halted Threads List */ + std::list haltedThreads; + + /** Thread Status Functions */ bool isThreadActive(ThreadID tid); + bool isThreadReady(ThreadID tid); bool isThreadSuspended(ThreadID tid); - void addToCurrentThreads(ThreadID tid); - void removeFromCurrentThreads(ThreadID tid); private: /** The activity recorder; used to tell if the CPU has any @@ -578,11 +760,22 @@ class InOrderCPU : public BaseCPU ActivityRecorder activityRec; public: - void readFunctional(Addr addr, uint32_t &buffer); - /** 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(); } @@ -597,13 +790,17 @@ class InOrderCPU : public BaseCPU /** Wakes the CPU, rescheduling the CPU if it's not already active. */ void wakeCPU(); - /** Gets a free thread id. Use if thread ids change across system. */ - ThreadID getFreeTid(); + virtual void wakeup(); - // LL/SC debug functionality + /* LL/SC debug functionality unsigned stCondFails; - unsigned readStCondFailures() { return stCondFails; } - unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; } + + 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) @@ -612,7 +809,7 @@ class InOrderCPU : public BaseCPU } /** Count the Total Instructions Committed in the CPU. */ - virtual Counter totalInstructions() const + virtual Counter totalInsts() const { Counter total(0); @@ -622,42 +819,53 @@ class InOrderCPU : public BaseCPU 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; - /** Counter of how many stages have completed switching out. */ - int switchCount; + /** Number of resource requests active in CPU **/ + unsigned resReqCount; +#endif - /** Pointers to all of the threads in the CPU. */ - std::vector thread; + Addr lockAddr; - /** Pointer to the icache interface. */ - MemInterface *icacheInterface; + /** Temporary fix for the lock flag, works in the UP case. */ + bool lockFlag; - /** Pointer to the dcache interface. */ - MemInterface *dcacheInterface; + /** Counter of how many stages have completed draining */ + int drainCount; - /** Whether or not the CPU should defer its registration. */ - bool deferRegistration; + /** Pointers to all of the threads in the CPU. */ + std::vector thread; /** Per-Stage Instruction Tracing */ bool stageTracing; - /** Is there a context switch pending? */ - bool contextSwitch; - - /** Threads Scheduled to Enter CPU */ - std::list cpuWaitList; - /** The cycle that the CPU was last running, used for statistics. */ Tick lastRunningCycle; - /** Number of Virtual Processors the CPU can process */ - unsigned numVirtProcs; - + void updateContextSwitchStats(); + unsigned instsPerSwitch; + Stats::Average instsPerCtxtSwitch; + Stats::Scalar numCtxtSwitches; + /** Update Thread , used for statistic purposes*/ inline void tickThreadStats(); @@ -670,12 +878,32 @@ class InOrderCPU : public BaseCPU /** Stat for total number of times the CPU is descheduled. */ Stats::Scalar timesIdled; - /** Stat for total number of cycles the CPU spends descheduled. */ + /** 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;