diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index c59d93238..4f439b8df 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -42,10 +42,190 @@ class StaticInstPtr; namespace AlphaISA { + using namespace LittleEndianGuest; - typedef uint32_t MachInst; - typedef uint64_t ExtMachInst; - typedef uint8_t RegIndex; + // These enumerate all the registers for dependence tracking. + enum DependenceTags { + // 0..31 are the integer regs 0..31 + // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = 40, + Ctrl_Base_DepTag = 72, + Fpcr_DepTag = 72, // floating point control register + Uniq_DepTag = 73, + Lock_Flag_DepTag = 74, + Lock_Addr_DepTag = 75, + IPR_Base_DepTag = 76 + }; + + StaticInstPtr decodeInst(ExtMachInst); + + // Alpha Does NOT have a delay slot + #define ISA_HAS_DELAY_SLOT 0 + + const Addr PageShift = 13; + const Addr PageBytes = ULL(1) << PageShift; + const Addr PageMask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; + +#if FULL_SYSTEM + + //////////////////////////////////////////////////////////////////////// + // + // Translation stuff + // + + const Addr PteShift = 3; + const Addr NPtePageShift = PageShift - PteShift; + const Addr NPtePage = ULL(1) << NPtePageShift; + const Addr PteMask = NPtePage - 1; + + // User Virtual + const Addr USegBase = ULL(0x0); + const Addr USegEnd = ULL(0x000003ffffffffff); + + // Kernel Direct Mapped + const Addr K0SegBase = ULL(0xfffffc0000000000); + const Addr K0SegEnd = ULL(0xfffffdffffffffff); + + // Kernel Virtual + const Addr K1SegBase = ULL(0xfffffe0000000000); + const Addr K1SegEnd = ULL(0xffffffffffffffff); + + // For loading... XXX This maybe could be USegEnd?? --ali + const Addr LoadAddrMask = ULL(0xffffffffff); + + //////////////////////////////////////////////////////////////////////// + // + // Interrupt levels + // + enum InterruptLevels + { + INTLEVEL_SOFTWARE_MIN = 4, + INTLEVEL_SOFTWARE_MAX = 19, + + INTLEVEL_EXTERNAL_MIN = 20, + INTLEVEL_EXTERNAL_MAX = 34, + + INTLEVEL_IRQ0 = 20, + INTLEVEL_IRQ1 = 21, + INTINDEX_ETHERNET = 0, + INTINDEX_SCSI = 1, + INTLEVEL_IRQ2 = 22, + INTLEVEL_IRQ3 = 23, + + INTLEVEL_SERIAL = 33, + + NumInterruptLevels = INTLEVEL_EXTERNAL_MAX + }; + + + // EV5 modes + enum mode_type + { + mode_kernel = 0, // kernel + mode_executive = 1, // executive (unused by unix) + mode_supervisor = 2, // supervisor (unused by unix) + mode_user = 3, // user mode + mode_number // number of modes + }; + +#endif + +#if FULL_SYSTEM + //////////////////////////////////////////////////////////////////////// + // + // Internal Processor Reigsters + // + enum md_ipr_names + { + IPR_ISR = 0x100, // interrupt summary register + IPR_ITB_TAG = 0x101, // ITLB tag register + IPR_ITB_PTE = 0x102, // ITLB page table entry register + IPR_ITB_ASN = 0x103, // ITLB address space register + IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register + IPR_ITB_IA = 0x105, // ITLB invalidate all register + IPR_ITB_IAP = 0x106, // ITLB invalidate all process register + IPR_ITB_IS = 0x107, // ITLB invalidate select register + IPR_SIRR = 0x108, // software interrupt request register + IPR_ASTRR = 0x109, // asynchronous system trap request register + IPR_ASTER = 0x10a, // asynchronous system trap enable register + IPR_EXC_ADDR = 0x10b, // exception address register + IPR_EXC_SUM = 0x10c, // exception summary register + IPR_EXC_MASK = 0x10d, // exception mask register + IPR_PAL_BASE = 0x10e, // PAL base address register + IPR_ICM = 0x10f, // instruction current mode + IPR_IPLR = 0x110, // interrupt priority level register + IPR_INTID = 0x111, // interrupt ID register + IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register + IPR_IVPTBR = 0x113, // virtual page table base register + IPR_HWINT_CLR = 0x115, // H/W interrupt clear register + IPR_SL_XMIT = 0x116, // serial line transmit register + IPR_SL_RCV = 0x117, // serial line receive register + IPR_ICSR = 0x118, // instruction control and status register + IPR_IC_FLUSH = 0x119, // instruction cache flush control + IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register + IPR_PMCTR = 0x11c, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + IPR_PALtemp0 = 0x140, // local scratch + IPR_PALtemp1 = 0x141, // local scratch + IPR_PALtemp2 = 0x142, // entUna + IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + IPR_PALtemp4 = 0x144, // memory management temp + IPR_PALtemp5 = 0x145, // memory management temp + IPR_PALtemp6 = 0x146, // memory management temp + IPR_PALtemp7 = 0x147, // entIF + IPR_PALtemp8 = 0x148, // intmask + IPR_PALtemp9 = 0x149, // entSys + IPR_PALtemp10 = 0x14a, // ?? + IPR_PALtemp11 = 0x14b, // entInt + IPR_PALtemp12 = 0x14c, // entArith + IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + IPR_PALtemp17 = 0x151, // sysval + IPR_PALtemp18 = 0x152, // usp + IPR_PALtemp19 = 0x153, // ksp + IPR_PALtemp20 = 0x154, // PTBR + IPR_PALtemp21 = 0x155, // entMM + IPR_PALtemp22 = 0x156, // kgp + IPR_PALtemp23 = 0x157, // PCBB + + IPR_DTB_ASN = 0x200, // DTLB address space number register + IPR_DTB_CM = 0x201, // DTLB current mode register + IPR_DTB_TAG = 0x202, // DTLB tag register + IPR_DTB_PTE = 0x203, // DTLB page table entry register + IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register + + IPR_MM_STAT = 0x205, // data MMU fault status register + IPR_VA = 0x206, // fault virtual address register + IPR_VA_FORM = 0x207, // formatted virtual address register + IPR_MVPTBR = 0x208, // MTU virtual page table base register + IPR_DTB_IAP = 0x209, // DTLB invalidate all process register + IPR_DTB_IA = 0x20a, // DTLB invalidate all register + IPR_DTB_IS = 0x20b, // DTLB invalidate single register + IPR_ALT_MODE = 0x20c, // alternate mode register + IPR_CC = 0x20d, // cycle counter register + IPR_CC_CTL = 0x20e, // cycle counter control register + IPR_MCSR = 0x20f, // MTU control register + + IPR_DC_FLUSH = 0x210, + IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register + IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register + IPR_DC_TEST_TAG = 0x214, // Dcache test tag register + IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register + IPR_DC_MODE = 0x216, // Dcache mode register + IPR_MAF_MODE = 0x217, // miss address file mode register + + NumInternalProcRegs // number of IPR registers + }; +#else + const int NumInternalProcRegs = 0; +#endif + + // Constants Related to the number of registers const int NumIntArchRegs = 32; const int NumPALShadowRegs = 8; @@ -53,6 +233,15 @@ namespace AlphaISA // @todo: Figure out what this number really should be. const int NumMiscArchRegs = 32; + const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; + const int NumFloatRegs = NumFloatArchRegs; + const int NumMiscRegs = NumMiscArchRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + + NumMiscRegs + NumInternalProcRegs; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + // Static instruction parameters const int MaxInstSrcRegs = 3; const int MaxInstDestRegs = 2; @@ -76,270 +265,23 @@ namespace AlphaISA const int SyscallPseudoReturnReg = ArgumentReg4; const int SyscallSuccessReg = 19; - - const int LogVMPageSize = 13; // 8K bytes const int VMPageSize = (1 << LogVMPageSize); const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned + const int MachineBytes = 8; const int WordBytes = 4; const int HalfwordBytes = 2; const int ByteBytes = 1; - - const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; - const int NumFloatRegs = NumFloatArchRegs; - const int NumMiscRegs = NumMiscArchRegs; - - // These enumerate all the registers for dependence tracking. - enum DependenceTags { - // 0..31 are the integer regs 0..31 - // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) - FP_Base_DepTag = 40, - Ctrl_Base_DepTag = 72, - Fpcr_DepTag = 72, // floating point control register - Uniq_DepTag = 73, - Lock_Flag_DepTag = 74, - Lock_Addr_DepTag = 75, - IPR_Base_DepTag = 76 - }; - - typedef uint64_t IntReg; - typedef IntReg IntRegFile[NumIntRegs]; - - // floating point register file entry type - typedef union { - uint64_t q; - double d; - } FloatReg; - - typedef union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view - - void clear() - { bzero(d, sizeof(d)); } - } FloatRegFile; - -extern const Addr PageShift; -extern const Addr PageBytes; -extern const Addr PageMask; -extern const Addr PageOffset; - -// redirected register map, really only used for the full system case. -extern const int reg_redir[NumIntRegs]; - -#if FULL_SYSTEM - - typedef uint64_t InternalProcReg; - -#include "arch/alpha/isa_fullsys_traits.hh" - -#else - const int NumInternalProcRegs = 0; -#endif - - // control register file contents - typedef uint64_t MiscReg; - class MiscRegFile { - protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - - public: - MiscReg readReg(int misc_reg); - - //These functions should be removed once the simplescalar cpu model - //has been replaced. - int getInstAsid(); - int getDataAsid(); - - MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc); - - Fault setReg(int misc_reg, const MiscReg &val); - - Fault setRegWithEffect(int misc_reg, const MiscReg &val, - ExecContext *xc); - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); - - void clear() - { - fpcr = uniq = 0; - lock_flag = 0; - lock_addr = 0; - } - -#if FULL_SYSTEM - protected: - InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs - - private: - MiscReg readIpr(int idx, Fault &fault, ExecContext *xc); - - Fault setIpr(int idx, uint64_t val, ExecContext *xc); - - void copyIprs(ExecContext *xc); -#endif - friend class RegFile; - }; - - const int TotalNumRegs = NumIntRegs + NumFloatRegs + - NumMiscRegs + NumInternalProcRegs; - - const int TotalDataRegs = NumIntRegs + NumFloatRegs; - - typedef union { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; - - struct RegFile { - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegs; // control register file - Addr pc; // program counter - Addr npc; // next-cycle program counter - Addr nnpc; - -#if FULL_SYSTEM - int intrflag; // interrupt flag - inline int instAsid() - { return EV5::ITB_ASN_ASN(miscRegs.ipr[IPR_ITB_ASN]); } - inline int dataAsid() - { return EV5::DTB_ASN_ASN(miscRegs.ipr[IPR_DTB_ASN]); } -#endif // FULL_SYSTEM - - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - - void clear() - { - bzero(intRegFile, sizeof(intRegFile)); - floatRegFile.clear(); - miscRegs.clear(); - } - }; - - static inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc); - - StaticInstPtr decodeInst(ExtMachInst); - - // Alpha Does NOT have a delay slot - #define ISA_HAS_DELAY_SLOT 0 - // return a no-op instruction... used for instruction fetch faults - extern const ExtMachInst NoopMachInst; + // Alpha UNOP (ldq_u r31,0(r0)) + const ExtMachInst NoopMachInst = 0x2ffe0000; - enum annotes { - ANNOTE_NONE = 0, - // An impossible number for instruction annotations - ITOUCH_ANNOTE = 0xffffffff, - }; + // redirected register map, really only used for the full system case. + extern const int reg_redir[NumIntRegs]; - static inline bool isCallerSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); - } - - static inline bool isCalleeSaveIntegerRegister(unsigned int reg) { - panic("register classification not implemented"); - return (reg >= 9 && reg <= 15); - } - - static inline bool isCallerSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } - - static inline bool isCalleeSaveFloatRegister(unsigned int reg) { - panic("register classification not implemented"); - return false; - } - - static inline Addr alignAddress(const Addr &addr, - unsigned int nbytes) { - return (addr & ~(nbytes - 1)); - } - - // Instruction address compression hooks - static inline Addr realPCToFetchPC(const Addr &addr) { - return addr; - } - - static inline Addr fetchPCToRealPC(const Addr &addr) { - return addr; - } - - // the size of "fetched" instructions (not necessarily the size - // of real instructions for PISA) - static inline size_t fetchInstSize() { - return sizeof(MachInst); - } - - static inline MachInst makeRegisterCopy(int dest, int src) { - panic("makeRegisterCopy not implemented"); - return 0; - } - - // Machine operations - - void saveMachineReg(AnyReg &savereg, const RegFile ®_file, - int regnum); - - void restoreMachineReg(RegFile ®s, const AnyReg ®, - int regnum); - -#if 0 - static void serializeSpecialRegs(const Serializable::Proxy &proxy, - const RegFile ®s); - - static void unserializeSpecialRegs(const IniFile *db, - const std::string &category, - ConfigNode *node, - RegFile ®s); -#endif - - /** - * Function to insure ISA semantics about 0 registers. - * @param xc The execution context. - */ - template - void zeroRegisters(XC *xc); - - const Addr MaxAddr = (Addr)-1; - -#if !FULL_SYSTEM - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) - { - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - regs->intRegFile[SyscallSuccessReg] = 0; - regs->intRegFile[ReturnValueReg] = return_value.value(); - } else { - // got an error, return details - regs->intRegFile[SyscallSuccessReg] = (IntReg) -1; - regs->intRegFile[ReturnValueReg] = -return_value.value(); - } - } -#endif - - void copyRegs(ExecContext *src, ExecContext *dest); - - void copyMiscRegs(ExecContext *src, ExecContext *dest); - -#if FULL_SYSTEM - void copyIprs(ExecContext *src, ExecContext *dest); -#endif }; #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/src/cpu/base.cc b/src/cpu/base.cc index f00dad7d6..513dd7c55 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -60,6 +60,15 @@ vector BaseCPU::cpuList; // been initialized int maxThreadsPerCPU = 1; +CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival, + BaseCPU *_cpu) + : Event(q, Event::Stat_Event_Pri), interval(ival), + lastNumInst(0), cpu(_cpu) +{ + if (interval) + schedule(curTick + interval); +} + void CPUProgressEvent::process() { @@ -156,12 +165,6 @@ BaseCPU::BaseCPU(Params *p) p->max_loads_all_threads, *counter); } - if (p->stats_reset_inst != 0) { - Stats::SetupEvent(Stats::Reset, p->stats_reset_inst, 0, comInstEventQueue[0]); - cprintf("Stats reset event scheduled for %lli insts\n", - p->stats_reset_inst); - } - #if FULL_SYSTEM memset(interrupts, 0, sizeof(interrupts)); intstatus = 0; diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 2a3fd9b56..e02527371 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -54,9 +54,7 @@ class CPUProgressEvent : public Event BaseCPU *cpu; public: - CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu) - : Event(q, Event::Stat_Event_Pri), interval(ival), lastNumInst(0), cpu(_cpu) - { schedule(curTick + interval); } + CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu); void process(); @@ -138,7 +136,6 @@ class BaseCPU : public MemObject Counter max_insts_all_threads; Counter max_loads_any_thread; Counter max_loads_all_threads; - Counter stats_reset_inst; Tick clock; bool functionTrace; Tick functionTraceStart; diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 926bfcbb2..c68810954 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -409,7 +409,7 @@ class BaseDynInst : public FastAlloc, public RefCounted void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { if (width == 32) - instResult.fp = val; + instResult.dbl = (double)val; else if (width == 64) instResult.dbl = val; else diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 737b4b5d4..00b01171f 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -258,7 +258,7 @@ class CheckerCPU : public BaseCPU thread->setFloatReg(reg_idx, val, width); switch(width) { case 32: - result.fp = val; + result.dbl = (double)val; break; case 64: result.dbl = val; diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 3bb81c4b9..8aec79754 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -403,19 +403,20 @@ Checker::validateState() warn("%lli: Instruction PC %#x results didn't match up, copying all " "registers from main CPU", curTick, unverifiedInst->readPC()); // Heavy-weight copying of all registers - cpuXC->copyArchRegs(unverifiedInst->xcBase()); + thread->copyArchRegs(unverifiedInst->tcBase()); // Also advance the PC. Hopefully no PC-based events happened. #if THE_ISA != MIPS_ISA // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); - cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); + thread->setPC(thread->readNextPC()); + thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); #else // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); - cpuXC->setNextPC(cpuXC->readNextNPC()); - cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); + thread->setPC(thread->readNextPC()); + thread->setNextPC(thread->readNextNPC()); + thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); #endif updateThisCycle = false; + } } template diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc index fbf1f342c..ff123a6f7 100644 --- a/src/cpu/o3/alpha/cpu_builder.cc +++ b/src/cpu/o3/alpha/cpu_builder.cc @@ -69,7 +69,6 @@ Param max_insts_any_thread; Param max_insts_all_threads; Param max_loads_any_thread; Param max_loads_all_threads; -Param stats_reset_inst; Param progress_interval; Param cachePorts; @@ -188,9 +187,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU) "Terminate when all threads have reached this load" "count", 0), - INIT_PARAM_DFLT(stats_reset_inst, - "blah", - 0), INIT_PARAM_DFLT(progress_interval, "Progress interval", 0), INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200), @@ -326,7 +322,6 @@ CREATE_SIM_OBJECT(DerivO3CPU) params->max_insts_all_threads = max_insts_all_threads; params->max_loads_any_thread = max_loads_any_thread; params->max_loads_all_threads = max_loads_all_threads; - params->stats_reset_inst = stats_reset_inst; params->progress_interval = progress_interval; // diff --git a/src/cpu/o3/checker_builder.cc b/src/cpu/o3/checker_builder.cc index ad83ec57a..02c817499 100644 --- a/src/cpu/o3/checker_builder.cc +++ b/src/cpu/o3/checker_builder.cc @@ -64,7 +64,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker) Param max_insts_all_threads; Param max_loads_any_thread; Param max_loads_all_threads; - Param stats_reset_inst; Param progress_interval; #if FULL_SYSTEM @@ -97,8 +96,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker) "terminate when any thread reaches this load count"), INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), - INIT_PARAM(stats_reset_inst, - "blah"), INIT_PARAM_DFLT(progress_interval, "CPU Progress Interval", 0), #if FULL_SYSTEM @@ -133,7 +130,6 @@ CREATE_SIM_OBJECT(O3Checker) params->max_insts_all_threads = 0; params->max_loads_any_thread = 0; params->max_loads_all_threads = 0; - params->stats_reset_inst = 0; params->exitOnError = exitOnError; params->updateOnError = updateOnError; params->warnOnlyOnLoadError = warnOnlyOnLoadError; @@ -148,7 +144,6 @@ CREATE_SIM_OBJECT(O3Checker) temp = max_insts_all_threads; temp = max_loads_any_thread; temp = max_loads_all_threads; - temp = stats_reset_inst; Tick temp2 = progress_interval; params->progress_interval = 0; temp2++; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 6ae01ae67..c80e4d8c1 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -1095,7 +1095,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) // (cpu->readMiscReg(AlphaISA::IPR_DTB_CM, tid) & 0x18) != 0; // thread[tid]->profilePC = usermode ? 1 : head_inst->readPC(); thread[tid]->profilePC = head_inst->readPC(); - ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getXCProxy(), + ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(), head_inst->staticInst); if (node) diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 4279df6f7..7386dfadd 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -795,7 +795,6 @@ unsigned int FullO3CPU::drain(Event *drain_event) { DPRINTF(O3CPU, "Switching out\n"); - BaseCPU::switchOut(_sampler); drainCount = 0; fetch.drain(); decode.drain(); @@ -852,6 +851,8 @@ FullO3CPU::signalDrained() changeState(SimObject::Drained); + BaseCPU::switchOut(); + if (drainEvent) { drainEvent->process(); drainEvent = NULL; @@ -878,6 +879,8 @@ FullO3CPU::switchOut() if (checker) checker->switchOut(); #endif + if (tickEvent.scheduled()) + tickEvent.squash(); } template @@ -934,45 +937,6 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) tickEvent.schedule(curTick); } -template -void -FullO3CPU::serialize(std::ostream &os) -{ - BaseCPU::serialize(os); - nameOut(os, csprintf("%s.tickEvent", name())); - tickEvent.serialize(os); - - // Use SimpleThread's ability to checkpoint to make it easier to - // write out the registers. Also make this static so it doesn't - // get instantiated multiple times (causes a panic in statistics). - static CPUExecContext temp; - - for (int i = 0; i < thread.size(); i++) { - nameOut(os, csprintf("%s.xc.%i", name(), i)); - temp.copyXC(thread[i]->getXCProxy()); - temp.serialize(os); - } -} - -template -void -FullO3CPU::unserialize(Checkpoint *cp, const std::string §ion) -{ - BaseCPU::unserialize(cp, section); - tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); - - // Use SimpleThread's ability to checkpoint to make it easier to - // read in the registers. Also make this static so it doesn't - // get instantiated multiple times (causes a panic in statistics). - static CPUExecContext temp; - - for (int i = 0; i < thread.size(); i++) { - temp.copyXC(thread[i]->getXCProxy()); - temp.unserialize(cp, csprintf("%s.xc.%i", section, i)); - thread[i]->getXCProxy()->copyArchRegs(temp.getProxy()); - } -} - template uint64_t FullO3CPU::readIntReg(int reg_idx) diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index c82f6dd21..b2baae296 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -904,22 +904,6 @@ DefaultIEW::emptyRenameInsts(unsigned tid) } } -template -void -DefaultIEW::emptyRenameInsts(unsigned tid) -{ - while (!insts[tid].empty()) { - if (insts[tid].front()->isLoad() || - insts[tid].front()->isStore() ) { - toRename->iewInfo[tid].dispatchedToLSQ++; - } - - toRename->iewInfo[tid].dispatched++; - - insts[tid].pop(); - } -} - template void DefaultIEW::wakeCPU() diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index a1ac5adb8..2bbab71f0 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -165,16 +165,6 @@ LSQ::regStats() } } -template -void -LSQ::regStats() -{ - //Initialize LSQs - for (int tid=0; tid < numThreads; tid++) { - thread[tid].regStats(); - } -} - template void LSQ::setActiveThreads(std::list *at_ptr) diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 8537e9dd7..90d1a3d53 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -410,6 +410,19 @@ class LSQUnit { /** Total number of loads forwaded from LSQ stores. */ Stats::Scalar<> lsqForwLoads; + /** Total number of loads ignored due to invalid addresses. */ + Stats::Scalar<> invAddrLoads; + + /** Total number of squashed loads. */ + Stats::Scalar<> lsqSquashedLoads; + + /** Total number of responses from the memory system that are + * ignored due to the instruction already being squashed. */ + Stats::Scalar<> lsqIgnoredResponses; + + /** Tota number of memory ordering violations. */ + Stats::Scalar<> lsqMemOrderViolation; + /** Total number of squashed stores. */ Stats::Scalar<> lsqSquashedStores; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 2922b81bd..98bea74fb 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -416,7 +416,7 @@ LSQUnit::executeLoad(DynInstPtr &inst) // realizes there is activity. // Mark it as executed unless it is an uncached load that // needs to hit the head of commit. - if (!(inst->req->flags & UNCACHEABLE) || inst->isAtCommit()) { + if (!(inst->req->getFlags() & UNCACHEABLE) || inst->isAtCommit()) { inst->setExecuted(); } iewStage->instToCommit(inst); @@ -832,6 +832,7 @@ LSQUnit::completeStore(int store_idx) // A bit conservative because a store completion may not free up entries, // but hopefully avoids two store completions in one cycle from making // the CPU tick twice. + cpu->wakeCPU(); cpu->activityThisCycle(); if (store_idx == storeHead) { diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index a4546e669..25e1db21c 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -54,7 +54,7 @@ template void O3ThreadContext::dumpFuncProfile() { - // Currently not supported + thread->dumpFuncProfile(); } #endif @@ -239,12 +239,16 @@ O3ThreadContext::readLastSuspend() template void O3ThreadContext::profileClear() -{} +{ + thread->profileClear(); +} template void O3ThreadContext::profileSample() -{} +{ + thread->profileSample(); +} #endif template diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index 0247deb52..5fe7bb94d 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -117,7 +117,7 @@ struct O3ThreadState : public ThreadState { void dumpFuncProfile() { std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); - profile->dump(xcProxy, *os); + profile->dump(tc, *os); } #endif }; diff --git a/src/cpu/ozone/checker_builder.cc b/src/cpu/ozone/checker_builder.cc index 99ba3e308..b4c4686b7 100644 --- a/src/cpu/ozone/checker_builder.cc +++ b/src/cpu/ozone/checker_builder.cc @@ -65,7 +65,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker) Param max_insts_all_threads; Param max_loads_any_thread; Param max_loads_all_threads; - Param stats_reset_inst; Param progress_interval; #if FULL_SYSTEM @@ -98,8 +97,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker) "terminate when any thread reaches this load count"), INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), - INIT_PARAM(stats_reset_inst, - "blah"), INIT_PARAM_DFLT(progress_interval, "CPU Progress Interval", 0), #if FULL_SYSTEM @@ -134,7 +131,6 @@ CREATE_SIM_OBJECT(OzoneChecker) params->max_insts_all_threads = 0; params->max_loads_any_thread = 0; params->max_loads_all_threads = 0; - params->stats_reset_inst = 0; params->exitOnError = exitOnError; params->updateOnError = updateOnError; params->warnOnlyOnLoadError = warnOnlyOnLoadError; @@ -149,7 +145,6 @@ CREATE_SIM_OBJECT(OzoneChecker) temp = max_insts_all_threads; temp = max_loads_any_thread; temp = max_loads_all_threads; - temp = stats_reset_inst; Tick temp2 = progress_interval; temp2++; params->progress_interval = 0; diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index ece68282f..8c5be9424 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -33,6 +33,7 @@ #include +#include "arch/regfile.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "config/full_system.hh" @@ -257,8 +258,8 @@ class OzoneCPU : public BaseCPU void setFuncExeInst(Counter new_val) { thread->funcExeInst = new_val; } #endif - void changeRegFileContext(TheISA::RegFile::ContextParam param, - TheISA::RegFile::ContextVal val) + void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) { panic("Not supported on Alpha!"); } }; diff --git a/src/cpu/ozone/cpu_builder.cc b/src/cpu/ozone/cpu_builder.cc index e3e4ec433..730158258 100644 --- a/src/cpu/ozone/cpu_builder.cc +++ b/src/cpu/ozone/cpu_builder.cc @@ -77,7 +77,6 @@ Param max_insts_any_thread; Param max_insts_all_threads; Param max_loads_any_thread; Param max_loads_all_threads; -Param stats_reset_inst; Param progress_interval; //SimObjectParam icache; @@ -210,9 +209,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivOzoneCPU) "Terminate when all threads have reached this load" "count", 0), - INIT_PARAM_DFLT(stats_reset_inst, - "blah", - 0), INIT_PARAM_DFLT(progress_interval, "Progress interval", 0), // INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL), @@ -360,7 +356,6 @@ CREATE_SIM_OBJECT(DerivOzoneCPU) params->max_insts_all_threads = max_insts_all_threads; params->max_loads_any_thread = max_loads_any_thread; params->max_loads_all_threads = max_loads_all_threads; - params->stats_reset_inst = stats_reset_inst; params->progress_interval = progress_interval; // diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 5c8b5001d..bf547bf94 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -35,6 +35,7 @@ #include "arch/isa_traits.hh" // For MachInst #include "base/trace.hh" #include "cpu/base.hh" +#include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "cpu/exetrace.hh" #include "cpu/ozone/cpu.hh" @@ -52,6 +53,7 @@ #include "base/callback.hh" #include "cpu/profile.hh" #include "kern/kernel_stats.hh" +#include "mem/physical.hh" #include "sim/faults.hh" #include "sim/sim_events.hh" #include "sim/sim_exit.hh" @@ -102,7 +104,7 @@ OzoneCPU::OzoneCPU(Params *p) _status = Idle; if (p->checker) { - +#if USE_CHECKER BaseCPU *temp_checker = p->checker; checker = dynamic_cast *>(temp_checker); checker->setMemory(mem); @@ -240,7 +242,7 @@ template void OzoneCPU::switchOut() { - BaseCPU::switchOut(_sampler); + BaseCPU::switchOut(); switchCount = 0; // Front end needs state from back end, so switch out the back end first. backEnd->switchOut(); @@ -468,10 +470,10 @@ OzoneCPU::serialize(std::ostream &os) // Use SimpleThread's ability to checkpoint to make it easier to // write out the registers. Also make this static so it doesn't // get instantiated multiple times (causes a panic in statistics). - static CPUExecContext temp; + static SimpleThread temp; nameOut(os, csprintf("%s.xc.0", name())); - temp.copyXC(thread.getXCProxy()); + temp.copyTC(thread.getTC()); temp.serialize(os); } @@ -487,11 +489,11 @@ OzoneCPU::unserialize(Checkpoint *cp, const std::string §ion) // Use SimpleThread's ability to checkpoint to make it easier to // read in the registers. Also make this static so it doesn't // get instantiated multiple times (causes a panic in statistics). - static CPUExecContext temp; + static SimpleThread temp; - temp.copyXC(thread.getXCProxy()); + temp.copyTC(thread.getTC()); temp.unserialize(cp, csprintf("%s.xc.0", section)); - thread.getXCProxy()->copyArchRegs(temp.getProxy()); + thread.getTC()->copyArchRegs(temp.getTC()); } template @@ -746,11 +748,13 @@ OzoneCPU::processInterrupts() if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) { thread.setMiscReg(IPR_ISR, summary); thread.setMiscReg(IPR_INTID, ipl); +#if USE_CHECKER // @todo: Make this more transparent if (checker) { checker->threadBase()->setMiscReg(IPR_ISR, summary); checker->threadBase()->setMiscReg(IPR_INTID, ipl); } +#endif Fault fault = new InterruptFault; fault->invoke(thread.getTC()); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", @@ -872,7 +876,7 @@ OzoneCPU::OzoneTC::takeOverFrom(ThreadContext *old_context) copyArchRegs(old_context); setCpuId(old_context->readCpuId()); - thread->inst = old_context->getInst(); + thread->setInst(old_context->getInst()); #if !FULL_SYSTEM setFuncExeInst(old_context->readFuncExeInst()); #else diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index ba0d70417..db1460eba 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -215,14 +215,14 @@ OzoneDynInst::clearMemDependents() } template -MiscReg +TheISA::MiscReg OzoneDynInst::readMiscReg(int misc_reg) { return this->thread->readMiscReg(misc_reg); } template -MiscReg +TheISA::MiscReg OzoneDynInst::readMiscRegWithEffect(int misc_reg, Fault &fault) { return this->thread->readMiscRegWithEffect(misc_reg, fault); diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index f87a2bc57..c39b9e08b 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -1197,7 +1197,7 @@ LWBackEnd::commitInst(int inst_num) // (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; // thread->profilePC = usermode ? 1 : inst->readPC(); thread->profilePC = inst->readPC(); - ProfileNode *node = thread->profile->consume(thread->getXCProxy(), + ProfileNode *node = thread->profile->consume(thread->getTC(), inst->staticInst); if (node) diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 31ffa9d67..4c96ad149 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -121,7 +121,7 @@ OzoneLWLSQ::completeDataAccess(PacketPtr pkt) } if (inst->isStore()) { - completeStore(state->idx); + completeStore(inst); } } @@ -178,6 +178,10 @@ OzoneLWLSQ::regStats() lsqMemOrderViolation .name(name() + ".memOrderViolation") .desc("Number of memory ordering violations"); +} + +template +void OzoneLWLSQ::setCPU(OzoneCPU *cpu_ptr) { cpu = cpu_ptr; @@ -390,7 +394,7 @@ OzoneLWLSQ::executeLoad(DynInstPtr &inst) // Actually probably want the oldest faulting load if (load_fault != NoFault) { DPRINTF(OzoneLSQ, "Load [sn:%lli] has a fault\n", inst->seqNum); - if (!(inst->req->flags & UNCACHEABLE && !inst->isAtCommit())) { + if (!(inst->req->getFlags() & UNCACHEABLE && !inst->isAtCommit())) { inst->setExecuted(); } // Maybe just set it as can commit here, although that might cause diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index adaa8e71b..c86f3552e 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -68,7 +68,7 @@ struct OzoneThreadState : public ThreadState { #if FULL_SYSTEM OzoneThreadState(CPUType *_cpu, int _thread_num) : ThreadState(-1, _thread_num), - cpu(_cpu), intrflag(0), inSyscall(0), trapPending(0) + intrflag(0), cpu(_cpu), inSyscall(0), trapPending(0) { if (cpu->params->profile) { profile = new FunctionProfile(cpu->params->system->kernelSymtab); @@ -151,7 +151,7 @@ struct OzoneThreadState : public ThreadState { void dumpFuncProfile() { std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); - profile->dump(xcProxy, *os); + profile->dump(tc, *os); } #endif }; diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 5479f8478..14e033b7f 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -195,20 +195,6 @@ struct ThreadState { #endif -#if FULL_SYSTEM - void profileClear() - { - if (profile) - profile->clear(); - } - - void profileSample() - { - if (profile) - profile->sample(profileNode, profilePC); - } -#endif - /** Current instruction the thread is committing. Only set and * used for DTB faults currently. */ diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 05ccbca6a..0b887cceb 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -26,8 +26,6 @@ class BaseCPU(SimObject): "terminate when all threads have reached this load count") max_loads_any_thread = Param.Counter(0, "terminate when any thread reaches this load count") - stats_reset_inst = Param.Counter(0, - "reset stats once this many instructions are committed") progress_interval = Param.Tick(0, "interval to print out the progress message") defer_registration = Param.Bool(False, diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index aae2f6021..b66c78b2c 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -149,9 +149,9 @@ namespace AlphaPseudo } void - loadsymbol(ExecContext *xc) + loadsymbol(ThreadContext *tc) { - const string &filename = xc->getCpuPtr()->system->params()->symbolfile; + const string &filename = tc->getCpuPtr()->system->params()->symbolfile; if (filename.empty()) { return; } @@ -187,7 +187,7 @@ namespace AlphaPseudo if (!to_number(address, addr)) continue; - if (!xc->getSystemPtr()->kernelSymtab->insert(addr, symbol)) + if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol)) continue;