X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Finorder%2Fcpu.hh;h=d8fe5c0573d44f0a8db00362bae2c14db47411cd;hb=b00949d88bb3185dfa2e27799de7f90e5a449be8;hp=154ab690c7f0aabb4f15b01970bcb45639a564ab;hpb=6713dbfe080df4dd04b0f29b5f2fbd6e221ffebf;p=gem5.git diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 154ab690c..d8fe5c057 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -1,4 +1,16 @@ /* + * 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. * @@ -39,29 +51,29 @@ #include #include "arch/isa_traits.hh" -#include "arch/types.hh" #include "arch/registers.hh" +#include "arch/types.hh" #include "base/statistics.hh" -#include "cpu/timebuf.hh" #include "base/types.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" -#include "cpu/activity.hh" -#include "cpu/base.hh" -#include "cpu/simple_thread.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/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; @@ -80,6 +92,7 @@ class InOrderCPU : public BaseCPU typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::MiscReg MiscReg; + typedef TheISA::RegIndex RegIndex; //DynInstPtr TypeDefs typedef ThePipeline::DynInstPtr DynInstPtr; @@ -96,6 +109,12 @@ class InOrderCPU : public BaseCPU /* 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; @@ -132,6 +151,31 @@ 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 CpuPort + { + + private: + /** Pointer to cache unit */ + CacheUnit *cacheUnit; + + public: + /** Default constructor. */ + CachePort(CacheUnit *_cacheUnit); + + protected: + + /** Timing version of receive */ + bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of a failed timing request. */ + void recvRetry(); + }; + /** Define TickEvent for the CPU */ class TickEvent : public Event { @@ -147,7 +191,7 @@ 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. */ @@ -181,7 +225,7 @@ class InOrderCPU : public BaseCPU HaltThread, SuspendThread, Trap, - InstGraduated, + Syscall, SquashFromMemStall, UpdatePCs, NumCPUEvents @@ -189,6 +233,12 @@ class InOrderCPU : public BaseCPU 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 { @@ -201,11 +251,12 @@ class InOrderCPU : public BaseCPU 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, unsigned event_pri_offset); + ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri); /** Set Type of Event To Be Scheduled */ void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid, @@ -222,7 +273,7 @@ class InOrderCPU : public BaseCPU void process(); /** Returns the description of the CPU event. */ - const char *description(); + const char *description() const; /** Schedule Event */ void scheduleEvent(int delay); @@ -234,9 +285,13 @@ class InOrderCPU : public BaseCPU /** Schedule a CPU Event */ void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid, DynInstPtr inst, unsigned delay = 0, - unsigned event_pri_offset = 0); + CPUEventPri event_pri = InOrderCPU_Pri); public: + + /** Width (processing bandwidth) of each stage */ + int stageWidth; + /** Interface between the CPU and CPU resources. */ ResourcePool *resPool; @@ -245,35 +300,20 @@ class InOrderCPU : public BaseCPU 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]; - /** 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; - /** The Pipeline Stages for the CPU */ PipelineStage *pipelineStage[ThePipeline::NumStages]; - /** Width (processing bandwidth) of each stage */ - int stageWidth; - /** 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]; @@ -287,6 +327,9 @@ class InOrderCPU : public BaseCPU /** 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 timeBuffer; @@ -296,23 +339,29 @@ class InOrderCPU : public BaseCPU TheISA::TLB *getITBPtr(); TheISA::TLB *getDTBPtr(); + Decoder *getDecoderPtr(); + /** Accessor Type for the SkedCache */ typedef uint32_t SkedID; /** Cache of Instruction Schedule using the instruction's name as a key */ - static std::map skedCache; + static m5::hash_map skedCache; - typedef std::map::iterator SkedCacheIt; + 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; } @@ -337,6 +386,7 @@ class InOrderCPU : public BaseCPU 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) { @@ -347,10 +397,47 @@ class InOrderCPU : public BaseCPU (inst->isControl() << INST_CONTROL) | (inst->isNonSpeculative() << INST_NONSPEC) | (inst->numDestRegs() << INST_DEST_REGS) | - (inst->numSrcRegs() << INST_SRC_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: @@ -365,18 +452,13 @@ class InOrderCPU : public BaseCPU /** Initialize the CPU */ void init(); - /** Reset State in the CPU */ - void reset(); - - /** Get a Memory Port */ - Port* getPort(const std::string &if_name, int idx = 0); - -#if FULL_SYSTEM /** 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(); @@ -386,44 +468,58 @@ class InOrderCPU : public BaseCPU /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } - /** Update the Virt and Phys ports of all ThreadContexts to - * reflect change in memory connections. */ - void updateMemPorts(); - /** 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; } -#endif - /** 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, DynInstPtr inst, int delay = 0); - void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst); + /** Schedule a syscall on the CPU */ + void syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, + int delay = 0); - /** Add Thread to Active Threads List. */ + /** 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); - /** Add Thread to Active Threads List. */ + /** Schedule Thread Activation from Ready List */ void activateNextReadyContext(int delay = 0); + + /** Add Thread From Ready List to Active Threads List. */ void activateNextReadyThread(); - /** Remove from Active Thread List */ + /** 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 suspendContext(ThreadID tid, int delay = 0); 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 haltContext(ThreadID tid, int delay = 0); void haltThread(ThreadID tid); /** squashFromMemStall() - sets up a squash event @@ -482,17 +578,29 @@ class InOrderCPU : public BaseCPU } /** Register file accessors */ - uint64_t readIntReg(int reg_idx, ThreadID tid); + uint64_t readIntReg(RegIndex reg_idx, ThreadID tid); - FloatReg readFloatReg(int reg_idx, ThreadID tid); + FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid); - FloatRegBits readFloatRegBits(int reg_idx, ThreadID tid); + FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid); - void setIntReg(int reg_idx, uint64_t val, ThreadID tid); + void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid); - void setFloatReg(int reg_idx, FloatReg val, ThreadID tid); + void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid); - void setFloatRegBits(int reg_idx, FloatRegBits 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); @@ -544,30 +652,30 @@ class InOrderCPU : public BaseCPU /** 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. */ @@ -585,9 +693,6 @@ class InOrderCPU : public BaseCPU Fault write(DynInstPtr inst, uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *write_res = NULL); - /** Executes a syscall.*/ - void syscall(int64_t callnum, ThreadID tid); - public: /** Per-Thread List of all the instructions in flight. */ std::list instList[ThePipeline::MaxThreads]; @@ -597,10 +702,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. @@ -684,11 +786,9 @@ class InOrderCPU : public BaseCPU /** Wakes the CPU, rescheduling the CPU if it's not already active. */ void wakeCPU(); -#if FULL_SYSTEM virtual void wakeup(); -#endif - // LL/SC debug functionality + /* LL/SC debug functionality unsigned stCondFails; unsigned readStCondFailures() @@ -696,6 +796,7 @@ class InOrderCPU : public BaseCPU unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; } + */ /** Returns a pointer to a thread context. */ ThreadContext *tcBase(ThreadID tid = 0) @@ -704,7 +805,7 @@ class InOrderCPU : public BaseCPU } /** Count the Total Instructions Committed in the CPU. */ - virtual Counter totalInstructions() const + virtual Counter totalInsts() const { Counter total(0); @@ -714,14 +815,20 @@ class InOrderCPU : public BaseCPU return total; } -#if FULL_SYSTEM + /** 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; - /** Pointer to physical memory. */ - PhysicalMemory *physmem; -#endif - /** The global sequence number counter. */ InstSeqNum globalSeqNum[ThePipeline::MaxThreads]; @@ -733,17 +840,16 @@ class InOrderCPU : public BaseCPU unsigned resReqCount; #endif - /** Counter of how many stages have completed switching out. */ - int switchCount; + Addr lockAddr; - /** Pointers to all of the threads in the CPU. */ - std::vector thread; + /** Temporary fix for the lock flag, works in the UP case. */ + bool lockFlag; - /** Pointer to the icache interface. */ - MemInterface *icacheInterface; + /** Counter of how many stages have completed draining */ + int drainCount; - /** Pointer to the dcache interface. */ - MemInterface *dcacheInterface; + /** Pointers to all of the threads in the CPU. */ + std::vector thread; /** Whether or not the CPU should defer its registration. */ bool deferRegistration; @@ -794,6 +900,9 @@ class InOrderCPU : public BaseCPU /** 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;