diff options
Diffstat (limited to 'src')
232 files changed, 7176 insertions, 2455 deletions
diff --git a/src/Doxyfile b/src/Doxyfile index 38116f6b0..ed4245dd2 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -30,7 +30,7 @@ PROJECT_NUMBER = # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = docs/doxygen +OUTPUT_DIRECTORY = doxygen # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this @@ -570,7 +570,7 @@ HTML_HEADER = # each generated HTML page. If it is left blank doxygen will generate a # standard footer. -HTML_FOOTER = docs/footer.html +HTML_FOOTER = doxygen/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to diff --git a/src/SConscript b/src/SConscript index 9825cafe7..812089a00 100644 --- a/src/SConscript +++ b/src/SConscript @@ -98,6 +98,7 @@ base_sources = Split(''' mem/packet.cc mem/physical.cc mem/port.cc + mem/tport.cc mem/cache/base_cache.cc mem/cache/cache.cc @@ -298,7 +299,7 @@ alpha_eio_sources = Split(''' encumbered/eio/eio.cc ''') -if env['TARGET_ISA'] == 'ALPHA_ISA': +if env['TARGET_ISA'] == 'alpha': syscall_emulation_sources += alpha_eio_sources memtest_sources = Split(''' diff --git a/src/arch/SConscript b/src/arch/SConscript index bc517341a..59cea6211 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -48,12 +48,12 @@ sources = [] # List of headers to generate isa_switch_hdrs = Split(''' arguments.hh - constants.hh faults.hh isa_traits.hh process.hh regfile.hh stacktrace.hh + syscallreturn.hh tlb.hh types.hh utility.hh @@ -140,8 +140,15 @@ def isa_desc_emitter(target, source, env): # Pieces are in place, so create the builder. python = sys.executable # use same Python binary used to run scons -isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS', - emitter = isa_desc_emitter) + +# Also include the CheckerCPU as one of the models if it is being +# enabled via command line. +if env['USE_CHECKER']: + isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS CheckerCPU', + emitter = isa_desc_emitter) +else: + isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS', + emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index ae3b668ea..796ed07de 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -29,9 +29,10 @@ * Nathan Binkert */ -#include "arch/alpha/tlb.hh" +#include "arch/alpha/faults.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/osfpal.hh" +#include "arch/alpha/tlb.hh" #include "base/kgdb.h" #include "base/remote_gdb.hh" #include "base/stats/events.hh" diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 11a568174..3ef4d5521 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -32,7 +32,7 @@ #ifndef __ALPHA_FAULTS_HH__ #define __ALPHA_FAULTS_HH__ -#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" #include "sim/faults.hh" // The design of the "name" and "vect" functions is in sim/faults.hh diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index 7cf68e0db..8d50e1612 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index 08a0a2343..a5dda7fc6 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -668,7 +668,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + completeAccTemplate.subst(completeacc_iop)) }}; - def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 663b144ab..72e38ae3e 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -35,81 +35,252 @@ namespace LittleEndianGuest {} #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" -#include "arch/alpha/regfile.hh" #include "config/full_system.hh" #include "sim/host.hh" class StaticInstPtr; -#if !FULL_SYSTEM -class SyscallReturn { - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - - private: - uint64_t retval; - bool success; -}; +namespace AlphaISA +{ + + using namespace LittleEndianGuest; + + // 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); + + const Addr PageShift = 13; + const Addr PageBytes = ULL(1) << PageShift; + const Addr PageMask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; -#endif #if FULL_SYSTEM -#include "arch/alpha/isa_fullsys_traits.hh" -#endif + //////////////////////////////////////////////////////////////////////// + // + // Translation stuff + // -namespace AlphaISA -{ + const Addr PteShift = 3; + const Addr NPtePageShift = PageShift - PteShift; + const Addr NPtePage = ULL(1) << NPtePageShift; + const Addr PteMask = NPtePage - 1; -using namespace LittleEndianGuest; + // User Virtual + const Addr USegBase = ULL(0x0); + const Addr USegEnd = ULL(0x000003ffffffffff); -// redirected register map, really only used for the full system case. -extern const int reg_redir[NumIntRegs]; + // Kernel Direct Mapped + const Addr K0SegBase = ULL(0xfffffc0000000000); + const Addr K0SegEnd = ULL(0xfffffdffffffffff); - StaticInstPtr decodeInst(ExtMachInst); + // 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 - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) +#if FULL_SYSTEM + //////////////////////////////////////////////////////////////////////// + // + // Internal Processor Reigsters + // + enum md_ipr_names { - // 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->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg)-1); - regs->setIntReg(ReturnValueReg, -return_value.value()); - } - } + 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; + const int NumFloatArchRegs = 32; + // @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; + + // semantically meaningful register indices + const int ZeroReg = 31; // architecturally meaningful + // the rest of these depend on the ABI + const int StackPointerReg = 30; + const int GlobalPointerReg = 29; + const int ProcedureValueReg = 27; + const int ReturnAddressReg = 26; + const int ReturnValueReg = 0; + const int FramePointerReg = 15; + const int ArgumentReg0 = 16; + const int ArgumentReg1 = 17; + const int ArgumentReg2 = 18; + const int ArgumentReg3 = 19; + const int ArgumentReg4 = 20; + const int ArgumentReg5 = 21; + const int SyscallNumReg = ReturnValueReg; + 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; + + // return a no-op instruction... used for instruction fetch faults + // Alpha UNOP (ldq_u r31,0(r0)) + const ExtMachInst NoopMachInst = 0x2ffe0000; + + // redirected register map, really only used for the full system case. + extern const int reg_redir[NumIntRegs]; + }; #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc index bc0d48e0d..e6908a572 100644 --- a/src/arch/alpha/linux/linux.cc +++ b/src/arch/alpha/linux/linux.cc @@ -30,6 +30,8 @@ #include "arch/alpha/linux/linux.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable AlphaLinux::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index 9fe63c390..ef4e18cb5 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -191,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -209,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -227,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh new file mode 100644 index 000000000..3108c0a3e --- /dev/null +++ b/src/arch/alpha/pagetable.hh @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_PAGETABLE_H__ +#define __ARCH_ALPHA_PAGETABLE_H__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/utility.hh" +#include "config/full_system.hh" + +namespace AlphaISA { + +#if FULL_SYSTEM + struct VAddr + { + static const int ImplBits = 43; + static const Addr ImplMask = (ULL(1) << ImplBits) - 1; + static const Addr UnImplMask = ~ImplMask; + + VAddr(Addr a) : addr(a) {} + Addr addr; + operator Addr() const { return addr; } + const VAddr &operator=(Addr a) { addr = a; return *this; } + + Addr vpn() const { return (addr & ImplMask) >> PageShift; } + Addr page() const { return addr & PageMask; } + Addr offset() const { return addr & PageOffset; } + + Addr level3() const + { return AlphaISA::PteAddr(addr >> PageShift); } + Addr level2() const + { return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); } + Addr level1() const + { return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); } + }; + + struct PageTableEntry + { + PageTableEntry(uint64_t e) : entry(e) {} + uint64_t entry; + operator uint64_t() const { return entry; } + const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; } + const PageTableEntry &operator=(const PageTableEntry &e) + { entry = e.entry; return *this; } + + Addr _pfn() const { return (entry >> 32) & 0xffffffff; } + Addr _sw() const { return (entry >> 16) & 0xffff; } + int _rsv0() const { return (entry >> 14) & 0x3; } + bool _uwe() const { return (entry >> 13) & 0x1; } + bool _kwe() const { return (entry >> 12) & 0x1; } + int _rsv1() const { return (entry >> 10) & 0x3; } + bool _ure() const { return (entry >> 9) & 0x1; } + bool _kre() const { return (entry >> 8) & 0x1; } + bool _nomb() const { return (entry >> 7) & 0x1; } + int _gh() const { return (entry >> 5) & 0x3; } + bool _asm() const { return (entry >> 4) & 0x1; } + bool _foe() const { return (entry >> 3) & 0x1; } + bool _fow() const { return (entry >> 2) & 0x1; } + bool _for() const { return (entry >> 1) & 0x1; } + bool valid() const { return (entry >> 0) & 0x1; } + + Addr paddr() const { return _pfn() << PageShift; } + }; + + // ITB/DTB page table entry + struct PTE + { + Addr tag; // virtual page number tag + Addr ppn; // physical page number + uint8_t xre; // read permissions - VMEM_PERM_* mask + uint8_t xwe; // write permissions - VMEM_PERM_* mask + uint8_t asn; // address space number + bool asma; // address space match + bool fonr; // fault on read + bool fonw; // fault on write + bool valid; // valid page table entry + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; +#endif +}; +#endif // __ARCH_ALPHA_PAGETABLE_H__ + diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 970292cd8..32fb97229 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -29,7 +29,7 @@ * Ali Saidi */ -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "arch/alpha/process.hh" #include "base/loader/object_file.hh" #include "base/misc.hh" diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 9ecad6f42..43b48a0ab 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -32,14 +32,34 @@ #define __ARCH_ALPHA_REGFILE_HH__ #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "sim/faults.hh" +#include <string> + +//XXX These should be implemented by someone who knows the alpha stuff better + class Checkpoint; class ThreadContext; namespace AlphaISA { + + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + class IntRegFile { protected: @@ -268,14 +288,7 @@ namespace AlphaISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - enum ContextParam - { - CONTEXT_PALMODE - }; - - typedef bool ContextVal; - - void changeContext(ContextParam param, ContextVal val) + void changeContext(RegContextParam param, RegContextVal val) { //This would be an alternative place to call/implement //the swapPALShadow function diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh new file mode 100644 index 000000000..803c3b7da --- /dev/null +++ b/src/arch/alpha/syscallreturn.hh @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ +#define __ARCH_ALPHA_SYSCALLRETURN_HH__ + +class SyscallReturn { + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint64_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint64_t)v; + } + + ~SyscallReturn() {} + + SyscallReturn& operator=(const SyscallReturn& s) { + retval = s.retval; + success = s.success; + return *this; + } + + bool successful() { return success; } + uint64_t value() { return retval; } + + + private: + uint64_t retval; + bool success; +}; + +namespace AlphaISA +{ + 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->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + regs->setIntReg(SyscallSuccessReg, (IntReg)-1); + regs->setIntReg(ReturnValueReg, -return_value.value()); + } + } +} + +#endif diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index dce7365aa..a7e615531 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -221,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<std::string> kernel; Param<std::string> console; @@ -239,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -257,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index c6684274b..bab44c434 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -33,7 +33,9 @@ #include <string> #include <vector> +#include "arch/alpha/pagetable.hh" #include "arch/alpha/tlb.hh" +#include "arch/alpha/faults.hh" #include "base/inifile.hh" #include "base/str.hh" #include "base/trace.hh" diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 07d01fa5c..955460649 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -36,9 +36,11 @@ #include "arch/alpha/ev5.hh" #include "arch/alpha/isa_traits.hh" -#include "arch/alpha/faults.hh" +#include "arch/alpha/utility.hh" +#include "arch/alpha/vtophys.hh" #include "base/statistics.hh" #include "mem/request.hh" +#include "sim/faults.hh" #include "sim/sim_object.hh" class ThreadContext; diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc index 6c0edc1ee..3ef1e4d3c 100644 --- a/src/arch/alpha/tru64/system.cc +++ b/src/arch/alpha/tru64/system.cc @@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index 5859052e9..ae42552d8 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -32,7 +32,7 @@ #ifndef __ARCH_ALPHA_TYPES_HH__ #define __ARCH_ALPHA_TYPES_HH__ -#include "sim/host.hh" +#include <inttypes.h> namespace AlphaISA { @@ -56,6 +56,13 @@ namespace AlphaISA MiscReg ctrlreg; } AnyReg; + enum RegContextParam + { + CONTEXT_PALMODE + }; + + typedef bool RegContextVal; + enum annotes { ANNOTE_NONE = 0, // An impossible number for instruction annotations diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index ec136091c..d3ccc0444 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -34,7 +34,7 @@ #include "config/full_system.hh" #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "arch/alpha/regfile.hh" #include "base/misc.hh" diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index 472c694ff..32b999c37 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -33,22 +33,24 @@ #define __ARCH_ALPHA_VTOPHYS_H__ #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" +#include "arch/alpha/utility.hh" class ThreadContext; class FunctionalPort; namespace AlphaISA { -PageTableEntry -kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); + PageTableEntry + kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); -Addr vtophys(Addr vaddr); -Addr vtophys(ThreadContext *tc, Addr vaddr); + Addr vtophys(Addr vaddr); + Addr vtophys(ThreadContext *tc, Addr vaddr); -void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len); -void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len); -void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); -void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); + void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len); + void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len); + void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); + void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); }; #endif // __ARCH_ALPHA_VTOPHYS_H__ diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index cfeb045eb..2a8ab1df5 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -25,13 +25,15 @@ * (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 + * Authors: Gabe Black + * Korey Sewell */ #include "arch/mips/faults.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "base/trace.hh" + #if !FULL_SYSTEM #include "sim/process.hh" #include "mem/page_table.hh" @@ -110,35 +112,6 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; -#if FULL_SYSTEM - -void MipsFault::invoke(ThreadContext * tc) -{ - FaultBase::invoke(tc); - countStat()++; - - // exception restart address - if (setRestartAddress() || !tc->inPalMode()) - tc->setMiscReg(MipsISA::IPR_EXC_ADDR, tc->readPC()); - - if (skipFaultingInstruction()) { - // traps... skip faulting instruction. - tc->setMiscReg(MipsISA::IPR_EXC_ADDR, - tc->readMiscReg(MipsISA::IPR_EXC_ADDR) + 4); - } - - tc->setPC(tc->readMiscReg(MipsISA::IPR_PAL_BASE) + vect()); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); -} - -void ArithmeticFault::invoke(ThreadContext * tc) -{ - FaultBase::invoke(tc); - panic("Arithmetic traps are unimplemented!"); -} - -#else //!FULL_SYSTEM - void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); @@ -159,6 +132,5 @@ void PageTableFault::invoke(ThreadContext *tc) } } -#endif } // namespace MipsISA diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 95c61cfbc..9d2c5df32 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -25,7 +25,8 @@ * (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 + * Authors: Gabe Black + * Korey Sewell */ #ifndef __MIPS_FAULTS_HH__ diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa index f07b06e03..7c042f16f 100644 --- a/src/arch/mips/isa/base.isa +++ b/src/arch/mips/isa/base.isa @@ -79,21 +79,27 @@ output decoder {{ ccprintf(ss, "%-10s ", mnemonic); - if(_numDestRegs > 0){ - printReg(ss, _destRegIdx[0]); + // Need to find standard way to not print + // this info. Maybe add bool variable to + // class? + if (mnemonic != "syscall") { + if(_numDestRegs > 0){ + printReg(ss, _destRegIdx[0]); + } + + if(_numSrcRegs > 0) { + ss << ", "; + printReg(ss, _srcRegIdx[0]); + } + + if(_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } } - if(_numSrcRegs > 0) { - ss << ", "; - printReg(ss, _srcRegIdx[0]); - } - - if(_numSrcRegs > 1) { - ss << ", "; - printReg(ss, _srcRegIdx[1]); - } - - + // Should we define a separate inst. class + // just for two insts? if(mnemonic == "sll" || mnemonic == "sra"){ ccprintf(ss,", %d",SA); } diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 9ac982e34..d65e3eb94 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -133,7 +133,8 @@ decode OPCODE_HI default Unknown::unknown() { format BasicOp { 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); - 0x4: syscall({{ xc->syscall(R2); }}, IsNonSpeculative); + 0x4: syscall({{ xc->syscall(R2); }}, + IsSerializeAfter, IsNonSpeculative); 0x7: sync({{ ; }}, IsMemBarrier); } @@ -1089,7 +1090,7 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: StoreCond::sc({{ Mem.uw = Rt.uw;}}, {{ uint64_t tmp = write_result; Rt.uw = (tmp == 0 || tmp == 1) ? tmp : Rt.uw; - }}, mem_flags=LOCKED); + }}, mem_flags=LOCKED, inst_flags = IsStoreConditional); format StoreMemory { 0x1: swc1({{ Mem.uw = Ft.uw; }}); diff --git a/src/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa index 29dafd541..29a445b2c 100644 --- a/src/arch/mips/isa/formats/basic.isa +++ b/src/arch/mips/isa/formats/basic.isa @@ -26,7 +26,8 @@ // (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 +// Authors: Steve Reinhardt +// Korey Sewell // Declarations for execute() methods. def template BasicExecDeclare {{ @@ -85,7 +86,7 @@ def template BasicDecodeWithMnemonic {{ return new %(class_name)s("%(mnemonic)s", machInst); }}; -// The most basic instruction format... used only for a few misc. insts +// The most basic instruction format... def format BasicOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index 5230ce9cc..8c89fbfa2 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -36,7 +36,6 @@ output header {{ #include <iostream> - using namespace std; /** * Base class for instructions whose disassembly is not purely a @@ -235,10 +234,11 @@ def format Branch(code,*opt_flags) {{ else: inst_flags += (x, ) + #Take into account uncond. branch instruction if 'cond == 1' in code: - inst_flags += ('IsCondControl', ) + inst_flags += ('IsUnCondControl', ) else: - inst_flags += ('IsUncondControl', ) + inst_flags += ('IsCondControl', ) #Condition code code = 'bool cond;\n' + code diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa index 56a4ec204..654dd8921 100644 --- a/src/arch/mips/isa/formats/int.isa +++ b/src/arch/mips/isa/formats/int.isa @@ -34,7 +34,6 @@ // output header {{ #include <iostream> - using namespace std; /** * Base class for integer operations. */ diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index f03f7becd..d6b0c2938 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -26,7 +26,7 @@ // (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: Gabe Black +// Authors: Steve Reinhardt // Korey Sewell //////////////////////////////////////////////////////////////////// @@ -162,7 +162,7 @@ def template InitiateAccDeclare {{ def template CompleteAccDeclare {{ - Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; + Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; @@ -288,7 +288,7 @@ def template LoadInitiateAcc {{ def template LoadCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -297,7 +297,7 @@ def template LoadCompleteAcc {{ %(fp_enable_check)s; %(op_decl)s; - memcpy(&Mem, data, sizeof(Mem)); + Mem = pkt->get<typeof(Mem)>(); if (fault == NoFault) { %(memacc_code)s; @@ -390,7 +390,6 @@ def template StoreInitiateAcc {{ { Addr EA; Fault fault = NoFault; - uint64_t write_result = 0; %(fp_enable_check)s; %(op_decl)s; @@ -403,7 +402,7 @@ def template StoreInitiateAcc {{ if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, &write_result); + memAccessFlags, NULL); if (traceData) { traceData->setData(Mem); } } @@ -413,17 +412,38 @@ def template StoreInitiateAcc {{ def template StoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondCompleteAcc {{ + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { Fault fault = NoFault; - uint64_t write_result = 0; %(fp_enable_check)s; %(op_dest_decl)s; - memcpy(&write_result, data, sizeof(write_result)); + uint64_t write_result = pkt->req->getScResult(); if (fault == NoFault) { %(postacc_code)s; @@ -489,7 +509,7 @@ def template MiscInitiateAcc {{ def template MiscCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -580,5 +600,5 @@ def format StoreCond(memacc_code, postacc_code, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - postacc_code, exec_template_base = 'Store') + postacc_code, exec_template_base = 'StoreCond') }}; diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 0cc375af3..73164bc0d 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -65,7 +65,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, if (exec_template_base == 'Load'): initiateacc_cblk = CodeBlock(ea_code + memacc_code) completeacc_cblk = CodeBlock(memacc_code + postacc_code) - elif (exec_template_base == 'Store'): + elif (exec_template_base.startswith('Store')): initiateacc_cblk = CodeBlock(ea_code + memacc_code) completeacc_cblk = CodeBlock(postacc_code) else: @@ -83,7 +83,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, initiateacc_iop.memacc_code = memacc_cblk.code completeacc_iop.memacc_code = memacc_cblk.code completeacc_iop.postacc_code = postacc_cblk.code - elif (exec_template_base == 'Store'): + elif (exec_template_base.startswith('Store')): initiateacc_iop.ea_code = ea_cblk.code initiateacc_iop.memacc_code = memacc_cblk.code completeacc_iop.postacc_code = postacc_cblk.code @@ -104,6 +104,13 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, memacc_iop.constructor += s # select templates + + # define aliases... most StoreCond templates are the same as the + # corresponding Store templates (only CompleteAcc is different). + StoreCondMemAccExecute = StoreMemAccExecute + StoreCondExecute = StoreExecute + StoreCondInitiateAcc = StoreInitiateAcc + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') fullExecTemplate = eval(exec_template_base + 'Execute') initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') @@ -118,7 +125,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + initiateAccTemplate.subst(initiateacc_iop) + completeAccTemplate.subst(completeacc_iop)) }}; - output header {{ std::string inst2string(MachInst machInst); }}; @@ -127,7 +133,7 @@ output decoder {{ std::string inst2string(MachInst machInst) { - string str = ""; + std::string str = ""; uint32_t mask = 0x80000000; for(int i=0; i < 32; i++) { diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc index 85acc4e8c..3a8cb46a5 100644 --- a/src/arch/mips/isa_traits.cc +++ b/src/arch/mips/isa_traits.cc @@ -30,15 +30,13 @@ */ #include "arch/mips/isa_traits.hh" -//#include "config/full_system.hh" -#include "cpu/static_inst.hh" +#include "arch/mips/regfile/regfile.hh" #include "sim/serialize.hh" #include "base/bitfield.hh" using namespace MipsISA; using namespace std; - void MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) { @@ -46,6 +44,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) } void +MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Misc. Regs Not Implemented Yet\n"); +} + +void MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc) { panic("Copy Misc. Regs Not Implemented Yet\n"); @@ -67,9 +71,9 @@ void RegFile::serialize(std::ostream &os) { intRegFile.serialize(os); - //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //SERIALIZE_ARRAY(floatRegFile, NumFloatRegs); + //SERIALZE_ARRAY(miscRegFile); //SERIALIZE_SCALAR(miscRegs.fpcr); - //SERIALIZE_SCALAR(miscRegs.uniq); //SERIALIZE_SCALAR(miscRegs.lock_flag); //SERIALIZE_SCALAR(miscRegs.lock_addr); SERIALIZE_SCALAR(pc); @@ -82,9 +86,9 @@ void RegFile::unserialize(Checkpoint *cp, const std::string §ion) { intRegFile.unserialize(cp, section); - //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //UNSERIALIZE_ARRAY(floatRegFile); + //UNSERIALZE_ARRAY(miscRegFile); //UNSERIALIZE_SCALAR(miscRegs.fpcr); - //UNSERIALIZE_SCALAR(miscRegs.uniq); //UNSERIALIZE_SCALAR(miscRegs.lock_flag); //UNSERIALIZE_SCALAR(miscRegs.lock_addr); UNSERIALIZE_SCALAR(pc); diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index ff994bef9..fd484e315 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -32,149 +32,87 @@ #ifndef __ARCH_MIPS_ISA_TRAITS_HH__ #define __ARCH_MIPS_ISA_TRAITS_HH__ -#include "arch/mips/constants.hh" #include "arch/mips/types.hh" -#include "arch/mips/regfile/regfile.hh" -#include "arch/mips/faults.hh" -#include "arch/mips/utility.hh" -#include "base/misc.hh" -#include "config/full_system.hh" -#include "sim/byteswap.hh" #include "sim/host.hh" -#include "sim/faults.hh" - -#include <vector> - -class FastCPU; -class FullCPU; -class Checkpoint; -class ThreadContext; namespace LittleEndianGuest {}; #define TARGET_MIPS -class StaticInst; class StaticInstPtr; -class SyscallReturn { - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint32_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint32_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - - private: - uint64_t retval; - bool success; -}; - namespace MipsISA { using namespace LittleEndianGuest; - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) - { - if (return_value.successful()) { - // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg1, return_value.value()); - } else { - // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg) -1); - regs->setIntReg(ReturnValueReg1, -return_value.value()); - } - } - StaticInstPtr decodeInst(ExtMachInst); - static inline ExtMachInst - makeExtMI(MachInst inst, const uint64_t &pc) { -#if FULL_SYSTEM - ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); - else - return ext_inst; -#else - return ExtMachInst(inst); -#endif - } - - /** - * Function to insure ISA semantics about 0 registers. - * @param tc The thread context. - */ - template <class TC> - void zeroRegisters(TC *tc); - - const Addr MaxAddr = (Addr)-1; - - void copyRegs(ThreadContext *src, ThreadContext *dest); - - // 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 - - 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; - } + const Addr PageShift = 13; + const Addr PageBytes = ULL(1) << PageShift; + const Addr PageMask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; + + // return a no-op instruction... used for instruction fetch faults + const ExtMachInst NoopMachInst = 0x00000000; + + // Constants Related to the number of registers + const int NumIntArchRegs = 32; + const int NumIntSpecialRegs = 2; + const int NumFloatArchRegs = 32; + const int NumFloatSpecialRegs = 5; + const int NumControlRegs = 265; + const int NumInternalProcRegs = 0; + + const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs + const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// + const int NumMiscRegs = NumControlRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + + NumMiscRegs + 0/*NumInternalProcRegs*/; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + + // Static instruction parameters + const int MaxInstSrcRegs = 3; + const int MaxInstDestRegs = 2; + + // semantically meaningful register indices + const int ZeroReg = 0; + const int AssemblerReg = 1; + const int ReturnValueReg = 2; + const int ReturnValueReg1 = 2; + const int ReturnValueReg2 = 3; + const int ArgumentReg0 = 4; + const int ArgumentReg1 = 5; + const int ArgumentReg2 = 6; + const int ArgumentReg3 = 7; + const int KernelReg0 = 26; + const int KernelReg1 = 27; + const int GlobalPointerReg = 28; + const int StackPointerReg = 29; + const int FramePointerReg = 30; + const int ReturnAddressReg = 31; + + const int SyscallNumReg = ReturnValueReg1; + const int SyscallPseudoReturnReg = ReturnValueReg1; + const int SyscallSuccessReg = ArgumentReg3; + + const int LogVMPageSize = 13; // 8K bytes + const int VMPageSize = (1 << LogVMPageSize); + + const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned + + const int MachineBytes = 4; + const int WordBytes = 4; + const int HalfwordBytes = 2; + const int ByteBytes = 1; + + // These help enumerate all the registers for dependence tracking. + const int FP_Base_DepTag = 34; + const int Ctrl_Base_DepTag = 257; + + const int ANNOTE_NONE = 0; + const uint32_t ITOUCH_ANNOTE = 0xffffffff; }; diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc index 26e3dd479..90404af53 100644 --- a/src/arch/mips/linux/linux.cc +++ b/src/arch/mips/linux/linux.cc @@ -30,6 +30,8 @@ #include "arch/mips/linux/linux.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable MipsLinux::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index b0ef20399..400591599 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -50,6 +50,7 @@ class MipsLiveProcess : public LiveProcess std::vector<std::string> &envp); void startup(); + }; diff --git a/src/arch/mips/regfile.hh b/src/arch/mips/regfile.hh new file mode 100644 index 000000000..4b2f1ac35 --- /dev/null +++ b/src/arch/mips/regfile.hh @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ARCH_MIPS_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_HH__ + +#include "arch/mips/regfile/regfile.hh" + +#endif diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh index 61efbb416..ce5f1fdde 100644 --- a/src/arch/mips/regfile/float_regfile.hh +++ b/src/arch/mips/regfile/float_regfile.hh @@ -26,24 +26,61 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__ -#define __ARCH_MIPS_FLOAT_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" +#include "arch/mips/isa_traits.hh" #include "base/misc.hh" #include "base/bitfield.hh" -#include "config/full_system.hh" -#include "sim/byteswap.hh" #include "sim/faults.hh" -#include "sim/host.hh" + +#include <string> class Checkpoint; -class ExecContext; -class Regfile; namespace MipsISA { + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + const uint32_t MIPS32_QNAN = 0x7fbfffff; + const uint64_t MIPS64_QNAN = ULL(0x7fbfffffffffffff); + + enum FPControlRegNums { + FIR = NumFloatArchRegs, + FCCR, + FEXR, + FENR, + FCSR + }; + + enum FCSRBits { + Inexact = 1, + Underflow, + Overflow, + DivideByZero, + Invalid, + Unimplemented + }; + + enum FCSRFields { + Flag_Field = 1, + Enable_Field = 6, + Cause_Field = 11 + }; + + const int SingleWidth = 32; + const int SingleBytes = SingleWidth / 4; + + const int DoubleWidth = 64; + const int DoubleBytes = DoubleWidth / 4; + + const int QuadWidth = 128; + const int QuadBytes = QuadWidth / 4; + class FloatRegFile { protected: @@ -102,7 +139,6 @@ namespace MipsISA Fault setReg(int floatReg, const FloatRegVal &val, int width) { - using namespace std; switch(width) { case SingleWidth: @@ -131,7 +167,6 @@ namespace MipsISA Fault setRegBits(int floatReg, const FloatRegBits &val, int width) { - using namespace std; switch(width) { diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh index 5add1b7be..a45a17a85 100644 --- a/src/arch/mips/regfile/int_regfile.hh +++ b/src/arch/mips/regfile/int_regfile.hh @@ -28,20 +28,29 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_INT_REGFILE_HH__ -#define __ARCH_MIPS_INT_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_INT_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_INT_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" +#include "arch/mips/isa_traits.hh" #include "base/misc.hh" #include "sim/faults.hh" class Checkpoint; class ThreadContext; -class Regfile; namespace MipsISA { + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + enum MiscIntRegNums { + HI = NumIntArchRegs, + LO + }; + class IntRegFile { protected: diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 87961f97e..a4527a203 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -28,29 +28,191 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_MISC_REGFILE_HH__ -#define __ARCH_MIPS_MISC_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "sim/faults.hh" -class Checkpoint; class ThreadContext; -class Regfile; namespace MipsISA { + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + + //Coprocessor 0 Register Names + enum MiscRegTags { + //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 + //(Register Number-Register Select) Summary of Register + //------------------------------------------------------ + Index = 0, //Bank 0: 0 - 3 + MVPControl, + MVPConf0, + MVPConf1, + + Random = 8, //Bank 1: 8 - 15 + VPEControl, + VPEConf0, + VPEConf1, + YQMask, + VPESchedule, + VPEScheFBack, + VPEOpt, + + EntryLo0 = 16, //Bank 2: 16 - 23 + TCStatus, + TCBind, + TCRestart, + TCHalt, + TCContext, + TCSchedule, + TCScheFBack, + + EntryLo1 = 24, // Bank 3: 24 + + Context = 32, // Bank 4: 32 - 33 + ContextConfig, + + //PageMask = 40, //Bank 5: 40 - 41 + PageGrain = 41, + + Wired = 48, //Bank 6: 48 - 55 + SRSConf0, + SRSConf1, + SRSConf2, + SRSConf3, + SRSConf4, + + HWRena = 56, //Bank 7: 56 + + BadVAddr = 63, //Bank 8: 63 + + Count = 64, //Bank 9: 64 + + EntryHi = 72, //Bank 10:72 - 79 + + Compare = 80, //Bank 10:80 - 87 + + Status = 88, //Bank 12:88 - 96 + IntCtl = 89, + SRSCtl = 90, + SRSMap = 91, + + Cause = 97, //97-104 + + EPC = 105, //105-112 + + PRId = 113, //113-120, + EBase = 114, + + Config = 121, //Bank 16: 121-128 + Config1 = 122, + Config2 = 123, + Config3 = 124, + Config6 = 127, + Config7 = 128, + + + LLAddr = 129, //Bank 17: 129-136 + + WatchLo0 = 137, //Bank 18: 137-144 + WatchLo1 = 138, + WatchLo2 = 139, + WatchLo3 = 140, + WatchLo4 = 141, + WatchLo5 = 142, + WatchLo6 = 143, + WatchLo7 = 144, + + WatchHi0 = 145,//Bank 19: 145-152 + WatchHi1 = 146, + WatchHi2 = 147, + WatchHi3 = 148, + WatchHi4 = 149, + WatchHi5 = 150, + WatchHi6 = 151, + WatchHi7 = 152, + + XCContext64 = 153, //Bank 20: 153-160 + + //Bank 21: 161-168 + + //Bank 22: 169-176 + + Debug = 177, //Bank 23: 177-184 + TraceControl1 = 178, + TraceControl2 = 179, + UserTraceData = 180, + TraceBPC = 181, + + DEPC = 185,//Bank 24: 185-192 + + PerfCnt0 = 193,//Bank 25: 193 - 200 + PerfCnt1 = 194, + PerfCnt2 = 195, + PerfCnt3 = 196, + PerfCnt4 = 197, + PerfCnt5 = 198, + PerfCnt6 = 199, + PerfCnt7 = 200, + + ErrCtl = 201, //Bank 26: 201 - 208 + + CacheErr0 = 209, //Bank 27: 209 - 216 + CacheErr1 = 210, + CacheErr2 = 211, + CacheErr3 = 212, + + TagLo0 = 217,//Bank 28: 217 - 224 + DataLo1 = 218, + TagLo2 = 219, + DataLo3 = 220, + TagLo4 = 221, + DataLo5 = 222, + TagLo6 = 223, + DataLo7 = 234, + + TagHi0 = 233,//Bank 29: 233 - 240 + DataHi1 = 234, + TagHi2 = 235, + DataHi3 = 236, + TagHi4 = 237, + DataHi5 = 238, + TagHi6 = 239, + DataHi7 = 240, + + + ErrorEPC = 249,//Bank 30: 241 - 248 + + DESAVE = 257//Bank 31: 249-256 + }; + class MiscRegFile { protected: uint64_t fpcr; // floating point condition codes + // FPCR is not used in MIPS. Condition + // codes are kept as part of the FloatRegFile + bool lock_flag; // lock flag for LL/SC + // use LL reg. in the future + Addr lock_addr; // lock address for LL/SC + // use LLAddr reg. in the future MiscReg miscRegFile[NumMiscRegs]; public: + void clear() + { + fpcr = 0; + lock_flag = 0; + lock_addr = 0; + } + void copyMiscRegs(ThreadContext *tc); MiscReg readReg(int misc_reg) diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index a68120299..3a18c681b 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -28,11 +28,10 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_REGFILE_HH__ -#define __ARCH_MIPS_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "arch/mips/regfile/int_regfile.hh" #include "arch/mips/regfile/float_regfile.hh" #include "arch/mips/regfile/misc_regfile.hh" @@ -171,10 +170,7 @@ namespace MipsISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - typedef int ContextParam; - typedef int ContextVal; - - void changeContext(ContextParam param, ContextVal val) + void changeContext(RegContextParam param, RegContextVal val) { } }; diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh new file mode 100644 index 000000000..ef1093caf --- /dev/null +++ b/src/arch/mips/syscallreturn.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Korey Sewell + */ + +#ifndef __ARCH_MIPS_SYSCALLRETURN_HH__ +#define __ARCH_MIPS_SYSCALLRETURN_HH__ + +class SyscallReturn { + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint32_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint32_t)v; + } + + ~SyscallReturn() {} + + SyscallReturn& operator=(const SyscallReturn& s) { + retval = s.retval; + success = s.success; + return *this; + } + + bool successful() { return success; } + uint64_t value() { return retval; } + + + private: + uint64_t retval; + bool success; +}; + +namespace MipsISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + { + if (return_value.successful()) { + // no error + regs->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg1, return_value.value()); + } else { + // got an error, return details + regs->setIntReg(SyscallSuccessReg, (IntReg) -1); + regs->setIntReg(ReturnValueReg1, -return_value.value()); + } + } +} + +#endif diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index 6330044d9..d4fa296fd 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -58,6 +58,9 @@ namespace MipsISA MiscReg ctrlreg; } AnyReg; + typedef int RegContextParam; + typedef int RegContextVal; + //used in FP convert & round function enum ConvertType{ SINGLE_TO_DOUBLE, diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index e7455fdbf..9ac4bb6d8 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -28,15 +28,12 @@ * Authors: Korey Sewell */ -#include "arch/mips/isa_traits.hh" +#include "arch/mips/regfile.hh" #include "arch/mips/utility.hh" -#include "config/full_system.hh" -#include "cpu/static_inst.hh" -#include "sim/serialize.hh" +#include "base/misc.hh" #include "base/bitfield.hh" using namespace MipsISA; -using namespace std; uint64_t MipsISA::fpConvert(ConvertType cvt_type, double fp_val) diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index c5c69ddcd..ae2fe1aea 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -33,10 +33,14 @@ #define __ARCH_MIPS_UTILITY_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "base/misc.hh" +#include "config/full_system.hh" +//XXX This is needed for size_t. We should use something other than size_t +//#include "kern/linux/linux.hh" #include "sim/host.hh" +class ThreadContext; + namespace MipsISA { //Floating Point Utility Functions @@ -51,6 +55,48 @@ namespace MipsISA { bool isNan(void *val_ptr, int size); bool isQnan(void *val_ptr, int size); bool isSnan(void *val_ptr, int size); + + /** + * Function to insure ISA semantics about 0 registers. + * @param tc The thread context. + */ + template <class TC> + void zeroRegisters(TC *tc); + + void copyRegs(ThreadContext *src, ThreadContext *dest); + + // 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; + } + + static inline ExtMachInst + makeExtMI(MachInst inst, const uint64_t &pc) { +#if FULL_SYSTEM + ExtMachInst ext_inst = inst; + if (pc && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + else + return ext_inst; +#else + return ExtMachInst(inst); +#endif + } }; diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index e7a8278db..66f2b57e0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -45,22 +45,25 @@ Import('env') # Base sources used by all configurations. base_sources = Split(''' faults.cc - isa_traits.cc + floatregfile.cc + intregfile.cc + miscregfile.cc + regfile.cc ''') # Full-system sources full_system_sources = Split(''' - vtophys.cc ua2005.cc + vtophys.cc ''') # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' linux/linux.cc linux/process.cc - solaris/solaris.cc - solaris/process.cc process.cc + solaris/process.cc + solaris/solaris.cc ''') sources = base_sources diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc new file mode 100644 index 000000000..3cacbb278 --- /dev/null +++ b/src/arch/sparc/floatregfile.cc @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/floatregfile.hh" +#include "base/trace.hh" +#include "sim/byteswap.hh" +#include "sim/serialize.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +string SparcISA::getFloatRegName(RegIndex index) +{ + static std::string floatRegName[NumFloatRegs] = + {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", + "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", + "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63"}; + return floatRegName[index]; +} + +void FloatRegFile::clear() +{ + bzero(regSpace, sizeof(regSpace)); +} + +FloatReg FloatRegFile::readReg(int floatReg, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + float32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); + return htog(result32); + case DoubleWidth: + float64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); + return htog(result64); + case QuadWidth: + float128_t result128; + memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } +} + +FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + uint32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); + return htog(result32); + case DoubleWidth: + uint64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); + return htog(result64); + case QuadWidth: + uint64_t result128; + memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } +} + +Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + + uint32_t result32; + uint64_t result64; + DPRINTF(Sparc, "Setting floating point register %d\n", floatReg); + switch(width) + { + case SingleWidth: + result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + break; + case DoubleWidth: + result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + break; + case QuadWidth: + panic("Quad width FP not implemented."); + break; + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; +} + +Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + uint32_t result32; + uint64_t result64; + switch(width) + { + case SingleWidth: + result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + break; + case DoubleWidth: + result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + break; + case QuadWidth: + panic("Quad width FP not implemented."); + break; + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; +} + +void FloatRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY((unsigned char *)regSpace, + SingleWidth / 8 * NumFloatRegs); +} + +void FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY((unsigned char *)regSpace, + SingleWidth / 8 * NumFloatRegs); +} + diff --git a/src/arch/sparc/floatregfile.hh b/src/arch/sparc/floatregfile.hh new file mode 100644 index 000000000..9d760c9ff --- /dev/null +++ b/src/arch/sparc/floatregfile.hh @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_FLOATREGFILE_HH__ +#define __ARCH_SPARC_FLOATREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + std::string getFloatRegName(RegIndex); + + typedef float float32_t; + typedef double float64_t; + //FIXME long double refers to a 10 byte float, rather than a + //16 byte float as required. This data type may have to be emulated. + typedef double float128_t; + + class FloatRegFile + { + public: + static const int SingleWidth = 32; + static const int DoubleWidth = 64; + static const int QuadWidth = 128; + + protected: + + //Since the floating point registers overlap each other, + //A generic storage space is used. The float to be returned is + //pulled from the appropriate section of this region. + char regSpace[(SingleWidth / 8) * NumFloatRegs]; + + public: + + void clear(); + + FloatReg readReg(int floatReg, int width); + + FloatRegBits readRegBits(int floatReg, int width); + + Fault setReg(int floatReg, const FloatReg &val, int width); + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width); + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; +} + +#endif diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc new file mode 100644 index 000000000..0cc0a886a --- /dev/null +++ b/src/arch/sparc/intregfile.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/intregfile.hh" +#include "base/trace.hh" +#include "sim/serialize.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +string SparcISA::getIntRegName(RegIndex index) +{ + static std::string intRegName[NumIntRegs] = + {"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7"}; + return intRegName[index]; +} + +int IntRegFile::flattenIndex(int reg) +{ + int flatIndex = offset[reg >> FrameOffsetBits] + | (reg & FrameOffsetMask); + DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); + return flatIndex; +} + +void IntRegFile::clear() +{ + int x; + for (x = 0; x < MaxGL; x++) + memset(regGlobals[x], 0, sizeof(regGlobals[x])); + for(int x = 0; x < 2 * NWindows; x++) + bzero(regSegments[x], sizeof(regSegments[x])); +} + +IntRegFile::IntRegFile() +{ + offset[Globals] = 0; + regView[Globals] = regGlobals[0]; + setCWP(0); + clear(); +} + +IntReg IntRegFile::readReg(int intReg) +{ + IntReg val = + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); + return val; +} + +Fault IntRegFile::setReg(int intReg, const IntReg &val) +{ + if(intReg) + DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + return NoFault; +} + +//This doesn't effect the actual CWP register. +//It's purpose is to adjust the view of the register file +//to what it would be if CWP = cwp. +void IntRegFile::setCWP(int cwp) +{ + int index = ((NWindows - cwp) % NWindows) * 2; + offset[Outputs] = FrameOffset + (index * RegsPerFrame); + offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); + offset[Inputs] = FrameOffset + + (((index+2) % (NWindows * 2)) * RegsPerFrame); + regView[Outputs] = regSegments[index]; + regView[Locals] = regSegments[index+1]; + regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; + + DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); +} + +void IntRegFile::setGlobals(int gl) +{ + DPRINTF(Sparc, "Now using %d globals", gl); + + regView[Globals] = regGlobals[gl]; + offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; +} + +void IntRegFile::serialize(std::ostream &os) +{ + unsigned int x; + for(x = 0; x < MaxGL; x++) + SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); + for(x = 0; x < 2 * NWindows; x++) + SERIALIZE_ARRAY(regSegments[x], RegsPerFrame); +} + +void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + unsigned int x; + for(x = 0; x < MaxGL; x++) + UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); + for(unsigned int x = 0; x < 2 * NWindows; x++) + UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame); +} diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh new file mode 100644 index 000000000..d305c753b --- /dev/null +++ b/src/arch/sparc/intregfile.hh @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_INTREGFILE_HH__ +#define __ARCH_SPARC_INTREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + class RegFile; + + //This function translates integer register file indices into names + std::string getIntRegName(RegIndex); + + class IntRegFile + { + private: + friend class RegFile; + protected: + static const int FrameOffsetBits = 3; + static const int FrameNumBits = 2; + + static const int RegsPerFrame = 1 << FrameOffsetBits; + static const int FrameNumMask = + (FrameNumBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameNumBits) - 1; + static const int FrameOffsetMask = + (FrameOffsetBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameOffsetBits) - 1; + + IntReg regGlobals[MaxGL][RegsPerFrame]; + IntReg regSegments[2 * NWindows][RegsPerFrame]; + + enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; + + IntReg * regView[NumFrames]; + + static const int RegGlobalOffset = 0; + static const int FrameOffset = MaxGL * RegsPerFrame; + int offset[NumFrames]; + + public: + + int flattenIndex(int reg); + + void clear(); + + IntRegFile(); + + IntReg readReg(int intReg); + + Fault setReg(int intReg, const IntReg &val); + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + protected: + //This doesn't effect the actual CWP register. + //It's purpose is to adjust the view of the register file + //to what it would be if CWP = cwp. + void setCWP(int cwp); + + void setGlobals(int gl); + }; +} + +#endif diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 02f7cf61a..b518265aa 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -86,6 +86,11 @@ output header {{ const SymbolTable *symtab) const; void printReg(std::ostream &os, int reg) const; + void printSrcReg(std::ostream &os, int reg) const; + void printDestReg(std::ostream &os, int reg) const; + + void printRegArray(std::ostream &os, + const RegIndex indexArray[], int num) const; }; bool passesCondition(uint32_t codes, uint32_t condition); @@ -150,6 +155,33 @@ output decoder {{ ccprintf(os, "\t%s ", mnemonic); } + void SparcStaticInst::printRegArray(std::ostream &os, + const RegIndex indexArray[], int num) const + { + if(num <= 0) + return; + printReg(os, indexArray[0]); + for(int x = 1; x < num; x++) + { + os << ", "; + printReg(os, indexArray[x]); + } + } + + void + SparcStaticInst::printSrcReg(std::ostream &os, int reg) const + { + if(_numSrcRegs > reg) + printReg(os, _srcRegIdx[reg]); + } + + void + SparcStaticInst::printDestReg(std::ostream &os, int reg) const + { + if(_numDestRegs > reg) + printReg(os, _destRegIdx[reg]); + } + void SparcStaticInst::printReg(std::ostream &os, int reg) const { diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index fa8832920..0c2729833 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -39,30 +39,30 @@ decode OP default Unknown::unknown() { //Throw an illegal instruction acception 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); - 0x1: decode BPCC + format BranchN { - format Branch19 + 0x1: decode BPCC { - 0x0: bpcci({{ + 0x0: bpcci(19, {{ if(passesCondition(Ccr<3:0>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x2: bpccx({{ + 0x2: bpccx(19, {{ if(passesCondition(Ccr<7:4>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); } + 0x2: bicc(22, {{ + if(passesCondition(Ccr<3:0>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); } - 0x2: Branch22::bicc({{ - if(passesCondition(Ccr<3:0>, COND2)) - NNPC = xc->readPC() + disp; - else - handle_annul - }}); 0x3: decode RCOND2 { format BranchSplit @@ -110,22 +110,22 @@ decode OP default Unknown::unknown() 0x5: Trap::fbpfcc({{fault = new FpDisabled;}}); 0x6: Trap::fbfcc({{fault = new FpDisabled;}}); } - 0x1: Branch30::call({{ + 0x1: BranchN::call(30, {{ R15 = xc->readPC(); NNPC = R15 + disp; }}); 0x2: decode OP3 { format IntOp { 0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}}); - 0x01: and({{Rd = Rs1.udw & Rs2_or_imm13;}}); - 0x02: or({{Rd = Rs1.udw | Rs2_or_imm13;}}); - 0x03: xor({{Rd = Rs1.udw ^ Rs2_or_imm13;}}); + 0x01: and({{Rd = Rs1.sdw & Rs2_or_imm13;}}); + 0x02: or({{Rd = Rs1.sdw | Rs2_or_imm13;}}); + 0x03: xor({{Rd = Rs1.sdw ^ Rs2_or_imm13;}}); 0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}}); - 0x05: andn({{Rd = Rs1.udw & ~Rs2_or_imm13;}}); - 0x06: orn({{Rd = Rs1.udw | ~Rs2_or_imm13;}}); - 0x07: xnor({{Rd = ~(Rs1.udw ^ Rs2_or_imm13);}}); + 0x05: andn({{Rd = Rs1.sdw & ~Rs2_or_imm13;}}); + 0x06: orn({{Rd = Rs1.sdw | ~Rs2_or_imm13;}}); + 0x07: xnor({{Rd = ~(Rs1.sdw ^ Rs2_or_imm13);}}); 0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + Ccr<0:0>;}}); - 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}}); + 0x09: mulx({{Rd = Rs1.sdw * Rs2_or_imm13;}}); 0x0A: umul({{ Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>; Y = Rd<63:32>; @@ -134,7 +134,7 @@ decode OP default Unknown::unknown() Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>; Y = Rd.sdw; }}); - 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + Ccr<0:0>}}); + 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}}); 0x0D: udivx({{ if(Rs2_or_imm13 == 0) fault = new DivisionByZero; else Rd.udw = Rs1.udw / Rs2_or_imm13; @@ -208,7 +208,7 @@ decode OP default Unknown::unknown() 0x1C: subccc({{ int64_t resTemp, val2 = Rs2_or_imm13; int64_t carryin = Ccr<0:0>; - Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}}, + Rd = resTemp = Rs1 + ~val2 + 1 - carryin;}}, {{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}}, {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}}, @@ -272,8 +272,9 @@ decode OP default Unknown::unknown() ); 0x22: taddcctv({{ int64_t resTemp, val2 = Rs2_or_imm13; - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); + Rd = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || + (Rs1<31:> == val2<31:> && val2<31:> != Rd<31:>); if(overflow) fault = new TagOverflow;}}, {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, {{overflow}}, @@ -322,15 +323,21 @@ decode OP default Unknown::unknown() 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}}); } // XXX might want a format rdipr thing here - 0x28: rdasr({{ + 0x28: decode RS1 { + 0xF: decode I { + 0x0: Nop::stbar({{/*stuff*/}}); + 0x1: Nop::membar({{/*stuff*/}}); + } + default: rdasr({{ Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault); - }}); - 0x29: rdhpr({{ + }}); + } + 0x29: HPriv::rdhpr({{ // XXX Need to protect with format that traps non-priv/priv // access Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault); }}); - 0x2A: rdpr({{ + 0x2A: Priv::rdpr({{ // XXX Need to protect with format that traps non-priv // access Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault); @@ -397,18 +404,233 @@ decode OP default Unknown::unknown() 0x0: BasicOperate::saved({{/*Boogy Boogy*/}}); 0x1: BasicOperate::restored({{/*Boogy Boogy*/}}); } - 0x32: wrpr({{ + 0x32: Priv::wrpr({{ // XXX Need to protect with format that traps non-priv // access - xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); + fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); }}); - 0x33: wrhpr({{ + 0x33: HPriv::wrhpr({{ // XXX Need to protect with format that traps non-priv/priv // access - xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); + fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); }}); - 0x34: Trap::fpop1({{fault = new FpDisabled;}}); + 0x34: decode OPF{ + format BasicOperate{ + 0x01: fmovs({{ + Frd.sf = Frs2.sf; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x02: fmovd({{ + Frd.df = Frs2.df; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x03: Trap::fmovq({{fault = new FpDisabled;}}); + 0x05: fnegs({{ + //XXX might want to explicitly flip the sign bit + //So cases with Nan and +/-0 don't do weird things + Frd.sf = -Frs2.sf; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x06: fnegd({{ + //XXX might want to explicitly flip the sign bit + //So cases with Nan and +/-0 don't do weird things + Frd.df = -Frs2.df; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x07: Trap::fnegq({{fault = new FpDisabled;}}); + 0x09: fabss({{ + //XXX this instruction should be tested individually + //Clear the sign bit + Frd.sf = (float)(~(1 << 31) & ((uint32_t)Frs2.sf)); + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x0A: fabsd({{ + //XXX this instruction should be tested individually + //Clear the sign bit + Frd.df = (float)(~((uint64_t)1 << 63) & ((uint64_t)Frs2.df)); + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x0B: Trap::fabsq({{fault = new FpDisabled;}}); + 0x29: fsqrts({{Frd.sf = sqrt(Frs2.sf);}}); + 0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}}); + 0x2B: Trap::fsqrtq({{fault = new FpDisabled;}}); + 0x41: fadds({{Frd.sf = Frs1.sf + Frs2.sf;}}); + 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}}); + 0x43: Trap::faddq({{fault = new FpDisabled;}}); + 0x45: fsubs({{Frd.sf = Frs1.sf - Frs2.sf;}}); + 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}}); + 0x47: Trap::fsubq({{fault = new FpDisabled;}}); + 0x49: fmuls({{Frd.sf = Frs1.sf * Frs2.sf;}}); + 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}}); + 0x4B: Trap::fmulq({{fault = new FpDisabled;}}); + 0x4D: fdivs({{Frd.sf = Frs1.sf / Frs2.sf;}}); + 0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}}); + 0x4F: Trap::fdivq({{fault = new FpDisabled;}}); + 0x69: fsmuld({{Frd.df = Frs1.sf * Frs2.sf;}}); + 0x6E: Trap::fdmulq({{fault = new FpDisabled;}}); + 0x81: fstox({{ + Frd.df = (double)static_cast<int64_t>(Frs2.sf); + }}); + 0x82: fdtox({{ + Frd.df = (double)static_cast<int64_t>(Frs2.df); + }}); + 0x83: Trap::fqtox({{fault = new FpDisabled;}}); + 0x84: fxtos({{ + Frd.sf = static_cast<float>((int64_t)Frs2.df); + }}); + 0x88: fxtod({{ + Frd.df = static_cast<double>((int64_t)Frs2.df); + }}); + 0x8C: Trap::fxtoq({{fault = new FpDisabled;}}); + 0xC4: fitos({{ + Frd.sf = static_cast<float>((int32_t)Frs2.sf); + }}); + 0xC6: fdtos({{Frd.sf = Frs2.df;}}); + 0xC7: Trap::fqtos({{fault = new FpDisabled;}}); + 0xC8: fitod({{ + Frd.df = static_cast<double>((int32_t)Frs2.sf); + }}); + 0xC9: fstod({{Frd.df = Frs2.sf;}}); + 0xCB: Trap::fqtod({{fault = new FpDisabled;}}); + 0xCC: Trap::fitoq({{fault = new FpDisabled;}}); + 0xCD: Trap::fstoq({{fault = new FpDisabled;}}); + 0xCE: Trap::fdtoq({{fault = new FpDisabled;}}); + 0xD1: fstoi({{ + Frd.sf = (float)static_cast<int32_t>(Frs2.sf); + }}); + 0xD2: fdtoi({{ + Frd.sf = (float)static_cast<int32_t>(Frs2.df); + }}); + 0xD3: Trap::fqtoi({{fault = new FpDisabled;}}); + default: Trap::fpop1({{fault = new FpDisabled;}}); + } + } 0x35: Trap::fpop2({{fault = new FpDisabled;}}); + //This used to be just impdep1, but now it's a whole bunch + //of instructions + 0x36: decode OPF{ + 0x00: Trap::edge8({{fault = new IllegalInstruction;}}); + 0x01: Trap::edge8n({{fault = new IllegalInstruction;}}); + 0x02: Trap::edge8l({{fault = new IllegalInstruction;}}); + 0x03: Trap::edge8ln({{fault = new IllegalInstruction;}}); + 0x04: Trap::edge16({{fault = new IllegalInstruction;}}); + 0x05: Trap::edge16n({{fault = new IllegalInstruction;}}); + 0x06: Trap::edge16l({{fault = new IllegalInstruction;}}); + 0x07: Trap::edge16ln({{fault = new IllegalInstruction;}}); + 0x08: Trap::edge32({{fault = new IllegalInstruction;}}); + 0x09: Trap::edge32n({{fault = new IllegalInstruction;}}); + 0x0A: Trap::edge32l({{fault = new IllegalInstruction;}}); + 0x0B: Trap::edge32ln({{fault = new IllegalInstruction;}}); + 0x10: Trap::array8({{fault = new IllegalInstruction;}}); + 0x12: Trap::array16({{fault = new IllegalInstruction;}}); + 0x14: Trap::array32({{fault = new IllegalInstruction;}}); + 0x18: BasicOperate::alignaddress({{ + uint64_t sum = Rs1 + Rs2; + Frd = sum & ~7; + Gsr = (Gsr & ~7) | (sum & 7); + }}); + 0x19: Trap::bmask({{fault = new IllegalInstruction;}}); + 0x1A: BasicOperate::alignaddresslittle({{ + uint64_t sum = Rs1 + Rs2; + Frd = sum & ~7; + Gsr = (Gsr & ~7) | ((~sum + 1) & 7); + }}); + 0x20: Trap::fcmple16({{fault = new IllegalInstruction;}}); + 0x22: Trap::fcmpne16({{fault = new IllegalInstruction;}}); + 0x24: Trap::fcmple32({{fault = new IllegalInstruction;}}); + 0x26: Trap::fcmpne32({{fault = new IllegalInstruction;}}); + 0x28: Trap::fcmpgt16({{fault = new IllegalInstruction;}}); + 0x2A: Trap::fcmpeq16({{fault = new IllegalInstruction;}}); + 0x2C: Trap::fcmpgt32({{fault = new IllegalInstruction;}}); + 0x2E: Trap::fcmpeq32({{fault = new IllegalInstruction;}}); + 0x31: Trap::fmul8x16({{fault = new IllegalInstruction;}}); + 0x33: Trap::fmul8x16au({{fault = new IllegalInstruction;}}); + 0x35: Trap::fmul8x16al({{fault = new IllegalInstruction;}}); + 0x36: Trap::fmul8sux16({{fault = new IllegalInstruction;}}); + 0x37: Trap::fmul8ulx16({{fault = new IllegalInstruction;}}); + 0x38: Trap::fmuld8sux16({{fault = new IllegalInstruction;}}); + 0x39: Trap::fmuld8ulx16({{fault = new IllegalInstruction;}}); + 0x3A: Trap::fpack32({{fault = new IllegalInstruction;}}); + 0x3B: Trap::fpack16({{fault = new IllegalInstruction;}}); + 0x3D: Trap::fpackfix({{fault = new IllegalInstruction;}}); + 0x3E: Trap::pdist({{fault = new IllegalInstruction;}}); + 0x48: BasicOperate::faligndata({{ + uint64_t msbX = (uint64_t)Frs1; + uint64_t lsbX = (uint64_t)Frs2; + uint64_t msbShift = Gsr<2:0> * 8; + uint64_t lsbShift = (8 - Gsr<2:0>) * 8; + uint64_t msbMask = ((uint64_t)(-1)) << msbShift; + uint64_t lsbMask = ((uint64_t)(-1)) << lsbShift; + Frd = ((msbX << msbShift) & msbMask) | + ((lsbX << lsbShift) & lsbMask); + }}); + 0x4B: Trap::fpmerge({{fault = new IllegalInstruction;}}); + 0x4C: Trap::bshuffle({{fault = new IllegalInstruction;}}); + 0x4D: Trap::fexpand({{fault = new IllegalInstruction;}}); + 0x50: Trap::fpadd16({{fault = new IllegalInstruction;}}); + 0x51: Trap::fpadd16s({{fault = new IllegalInstruction;}}); + 0x52: Trap::fpadd32({{fault = new IllegalInstruction;}}); + 0x53: Trap::fpadd32s({{fault = new IllegalInstruction;}}); + 0x54: Trap::fpsub16({{fault = new IllegalInstruction;}}); + 0x55: Trap::fpsub16s({{fault = new IllegalInstruction;}}); + 0x56: Trap::fpsub32({{fault = new IllegalInstruction;}}); + 0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}}); + 0x60: BasicOperate::fzero({{Frd.df = 0;}}); + 0x61: BasicOperate::fzeros({{Frd.sf = 0;}}); + 0x62: Trap::fnor({{fault = new IllegalInstruction;}}); + 0x63: Trap::fnors({{fault = new IllegalInstruction;}}); + 0x64: Trap::fandnot2({{fault = new IllegalInstruction;}}); + 0x65: Trap::fandnot2s({{fault = new IllegalInstruction;}}); + 0x66: BasicOperate::fnot2({{ + Frd.df = (double)(~((uint64_t)Frs2.df)); + }}); + 0x67: BasicOperate::fnot2s({{ + Frd.sf = (float)(~((uint32_t)Frs2.sf)); + }}); + 0x68: Trap::fandnot1({{fault = new IllegalInstruction;}}); + 0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}}); + 0x6A: BasicOperate::fnot1({{ + Frd.df = (double)(~((uint64_t)Frs1.df)); + }}); + 0x6B: BasicOperate::fnot1s({{ + Frd.sf = (float)(~((uint32_t)Frs1.sf)); + }}); + 0x6C: Trap::fxor({{fault = new IllegalInstruction;}}); + 0x6D: Trap::fxors({{fault = new IllegalInstruction;}}); + 0x6E: Trap::fnand({{fault = new IllegalInstruction;}}); + 0x6F: Trap::fnands({{fault = new IllegalInstruction;}}); + 0x70: Trap::fand({{fault = new IllegalInstruction;}}); + 0x71: Trap::fands({{fault = new IllegalInstruction;}}); + 0x72: Trap::fxnor({{fault = new IllegalInstruction;}}); + 0x73: Trap::fxnors({{fault = new IllegalInstruction;}}); + 0x74: BasicOperate::fsrc1({{Frd.df = Frs1.df;}}); + 0x75: BasicOperate::fsrc1s({{Frd.sf = Frs1.sf;}}); + 0x76: Trap::fornot2({{fault = new IllegalInstruction;}}); + 0x77: Trap::fornot2s({{fault = new IllegalInstruction;}}); + 0x78: BasicOperate::fsrc2({{Frd.df = Frs2.df;}}); + 0x79: BasicOperate::fsrc2s({{Frd.sf = Frs2.sf;}}); + 0x7A: Trap::fornot1({{fault = new IllegalInstruction;}}); + 0x7B: Trap::fornot1s({{fault = new IllegalInstruction;}}); + 0x7C: Trap::for({{fault = new IllegalInstruction;}}); + 0x7D: Trap::fors({{fault = new IllegalInstruction;}}); + 0x7E: Trap::fone({{fault = new IllegalInstruction;}}); + 0x7F: Trap::fones({{fault = new IllegalInstruction;}}); + 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); + 0x81: Trap::siam({{fault = new IllegalInstruction;}}); + } + 0x37: Trap::impdep2({{fault = new IllegalInstruction;}}); 0x38: Branch::jmpl({{ Addr target = Rs1 + Rs2_or_imm13; if(target & 0x3) @@ -549,7 +771,7 @@ decode OP default Unknown::unknown() NNPC = Tnpc + 4; Tl = Tl - 1; }}); - 0x1: BasicOperate::retry({{ + 0x1: Priv::retry({{ if(Tl == 0) return new IllegalInstruction; Cwp = Tstate<4:0>; @@ -630,27 +852,28 @@ decode OP default Unknown::unknown() Mem = temp; }}, {{32}}); format Trap { - 0x20: ldf({{fault = new FpDisabled;}}); + 0x20: Load::ldf({{Frd.sf = ((float)Mem);}}, {{32}}); 0x21: decode X { 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}}); 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}}); } 0x22: ldqf({{fault = new FpDisabled;}}); - 0x23: lddf({{fault = new FpDisabled;}}); - 0x24: stf({{fault = new FpDisabled;}}); + 0x23: Load::lddf({{Frd.df = ((double)Mem);}}, {{64}}); + 0x24: Store::stf({{Mem = ((int32_t)Frd.sf);}}, {{32}}); 0x25: decode X { 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}}); 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}}); } 0x26: stqf({{fault = new FpDisabled;}}); - 0x27: stdf({{fault = new FpDisabled;}}); + 0x27: Store::stdf({{Mem = ((int64_t)Frd.df);}}, {{64}}); 0x2D: Nop::prefetch({{ }}); - 0x30: ldfa({{return new FpDisabled;}}); + 0x30: Load::ldfa({{Frd.sf = ((float)Mem);}}, {{32}}); 0x32: ldqfa({{fault = new FpDisabled;}}); - 0x33: lddfa({{fault = new FpDisabled;}}); - 0x34: stfa({{fault = new FpDisabled;}}); - 0x35: stqfa({{fault = new FpDisabled;}}); - 0x36: stdfa({{fault = new FpDisabled;}}); + 0x33: Load::lddfa({{Frd.df = ((double)Mem);}}, {{64}}); + 0x34: Store::stfa({{Mem = ((int32_t)Frd.sf);}}, {{32}}); + 0x36: stqfa({{fault = new FpDisabled;}}); + //XXX need to work in the ASI thing + 0x37: Store::stdfa({{Mem = ((uint64_t)Frd.df);}}, {{64}}); 0x3C: Cas::casa({{ uint64_t val = Mem.uw; if(Rs2.uw == val) diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index 60432cb6b..0a47a7ffe 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -63,7 +63,6 @@ def template BasicExecute {{ { Fault fault = NoFault; - %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; @@ -81,11 +80,6 @@ def template BasicDecode {{ return new %(class_name)s(machInst); }}; -// Basic decode template, passing mnemonic in as string arg to constructor. -def template BasicDecodeWithMnemonic {{ - return new %(class_name)s("%(mnemonic)s", machInst); -}}; - // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ iop = InstObjParams(name, Name, 'SparcStaticInst', diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 7d46ce739..8a3f05173 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -69,47 +69,18 @@ output header {{ }; /** - * Base class for branches with 19 bit displacements. + * Base class for branches with n bit displacements. */ - class Branch19 : public BranchDisp + template<int bits> + class BranchNBits : public BranchDisp { protected: // Constructor - Branch19(const char *mnem, MachInst _machInst, + BranchNBits(const char *mnem, MachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { - disp = sign_ext(DISP19 << 2, 21); - } - }; - - /** - * Base class for branches with 22 bit displacements. - */ - class Branch22 : public BranchDisp - { - protected: - // Constructor - Branch22(const char *mnem, MachInst _machInst, - OpClass __opClass) : - BranchDisp(mnem, _machInst, __opClass) - { - disp = sign_ext(DISP22 << 2, 24); - } - }; - - /** - * Base class for branches with 30 bit displacements. - */ - class Branch30 : public BranchDisp - { - protected: - // Constructor - Branch30(const char *mnem, MachInst _machInst, - OpClass __opClass) : - BranchDisp(mnem, _machInst, __opClass) - { - disp = sign_ext(DISP30 << 2, 32); + disp = sign_ext(_machInst << 2, bits + 2); } }; @@ -149,29 +120,23 @@ output header {{ }}; output decoder {{ + + template class BranchNBits<19>; + + template class BranchNBits<22>; + + template class BranchNBits<30>; + std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream response; printMnemonic(response, mnemonic); - - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numDestRegs && _numSrcRegs) response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - - if (_numDestRegs > 0) - { - if(_numSrcRegs > 0) - response << ", "; - printReg(response, _destRegIdx[0]); - } + printDestReg(response, 0); return response.str(); } @@ -182,27 +147,13 @@ output decoder {{ std::stringstream response; printMnemonic(response, mnemonic); - - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - + printRegArray(response, _srcRegIdx, _numSrcRegs); if(_numSrcRegs > 0) response << ", "; - ccprintf(response, "0x%x", imm); - if (_numDestRegs > 0) - { response << ", "; - printReg(response, _destRegIdx[0]); - } + printDestReg(response, 0); return response.str(); } @@ -292,32 +243,10 @@ def format Branch(code, *opt_flags) {{ }}; // Primary format for branch instructions: -def format Branch19(code, *opt_flags) {{ - code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - exec_output = BranchExecute.subst(iop) - decode_block = BasicDecode.subst(iop) -}}; - -// Primary format for branch instructions: -def format Branch22(code, *opt_flags) {{ - code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - exec_output = BranchExecute.subst(iop) - decode_block = BasicDecode.subst(iop) -}}; - -// Primary format for branch instructions: -def format Branch30(code, *opt_flags) {{ +def format BranchN(bits, code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags) + iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa index 1894ce541..27616216e 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -132,7 +132,7 @@ output header {{ OpClass __opClass) : IntOpImm(mnem, _machInst, __opClass) { - imm = (IMM22 << 10) & 0xFFFFFC00; + imm = (IMM22 & 0x3FFFFF) << 10; } std::string generateDisassembly(Addr pc, @@ -157,12 +157,9 @@ output decoder {{ if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0) { printMnemonic(os, "mov"); - if(_numSrcRegs > 0) - printReg(os, _srcRegIdx[1]); + printSrcReg(os, 1); ccprintf(os, ", "); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - + printDestReg(os, 0); return true; } return false; @@ -173,32 +170,24 @@ output decoder {{ { if(!strcmp(mnemonic, "or")) { - if(_srcRegIdx[0] == 0) + if(_numSrcRegs > 0 && _srcRegIdx[0] == 0) { if(imm == 0) - { printMnemonic(os, "clr"); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - return true; - } else { printMnemonic(os, "mov"); - ccprintf(os, ", 0x%x, ", imm); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - return true; + ccprintf(os, " 0x%x, ", imm); } + printDestReg(os, 0); + return true; } else if(imm == 0) { printMnemonic(os, "mov"); - if(_numSrcRegs > 0) - printReg(os, _srcRegIdx[0]); + printSrcReg(os, 0); ccprintf(os, ", "); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); + printDestReg(os, 0); return true; } } @@ -210,25 +199,13 @@ output decoder {{ { std::stringstream response; - if(!printPseudoOps(response, pc, symtab)) - { - printMnemonic(response, mnemonic); - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - if (_numDestRegs > 0) - { - if(_numSrcRegs > 0) - response << ", "; - printReg(response, _destRegIdx[0]); - } - } + if(printPseudoOps(response, pc, symtab)) + return response.str(); + printMnemonic(response, mnemonic); + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numDestRegs && _numSrcRegs) + response << ", "; + printDestReg(response, 0); return response.str(); } @@ -237,27 +214,16 @@ output decoder {{ { std::stringstream response; - if(!printPseudoOps(response, pc, symtab)) - { - printMnemonic(response, mnemonic); - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs - 1; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - if(_numSrcRegs > 0) - response << ", "; - ccprintf(response, "0x%x", imm); - if (_numDestRegs > 0) - { - response << ", "; - printReg(response, _destRegIdx[0]); - } - } + if(printPseudoOps(response, pc, symtab)) + return response.str(); + printMnemonic(response, mnemonic); + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numSrcRegs > 0) + response << ", "; + ccprintf(response, "0x%x", imm); + if(_numDestRegs > 0) + response << ", "; + printDestReg(response, 0); return response.str(); } @@ -267,10 +233,8 @@ output decoder {{ std::stringstream response; printMnemonic(response, mnemonic); - if(_numSrcRegs > 0) - response << ", "; ccprintf(response, "%%hi(0x%x), ", imm); - printReg(response, _destRegIdx[0]); + printDestReg(response, 0); return response.str(); } }}; @@ -316,38 +280,29 @@ let {{ return (header_output, decoder_output, exec_output, decode_block) calcCcCode = ''' - uint8_t tmp_ccriccc; - uint8_t tmp_ccriccv; - uint8_t tmp_ccriccz; - uint8_t tmp_ccriccn; - uint8_t tmp_ccrxccc; - uint8_t tmp_ccrxccv; - uint8_t tmp_ccrxccz; - uint8_t tmp_ccrxccn; - - tmp_ccriccn = (Rd >> 31) & 1; - tmp_ccriccz = ((Rd & 0xFFFFFFFF) == 0); - tmp_ccrxccn = (Rd >> 63) & 1; - tmp_ccrxccz = (Rd == 0); - tmp_ccriccv = %(ivValue)s & 1; - tmp_ccriccc = %(icValue)s & 1; - tmp_ccrxccv = %(xvValue)s & 1; - tmp_ccrxccc = %(xcValue)s & 1; - - Ccr = tmp_ccriccc | tmp_ccriccv << 1 | - tmp_ccriccz << 2 | tmp_ccriccn << 3| - tmp_ccrxccc << 4 | tmp_ccrxccv << 5| - tmp_ccrxccz << 6| tmp_ccrxccn << 7; - - - DPRINTF(Sparc, "in = %%d\\n", (uint16_t)tmp_ccriccn); - DPRINTF(Sparc, "iz = %%d\\n", (uint16_t)tmp_ccriccz); - DPRINTF(Sparc, "xn = %%d\\n", (uint16_t)tmp_ccrxccn); - DPRINTF(Sparc, "xz = %%d\\n", (uint16_t)tmp_ccrxccz); - DPRINTF(Sparc, "iv = %%d\\n", (uint16_t)tmp_ccriccv); - DPRINTF(Sparc, "ic = %%d\\n", (uint16_t)tmp_ccriccc); - DPRINTF(Sparc, "xv = %%d\\n", (uint16_t)tmp_ccrxccv); - DPRINTF(Sparc, "xc = %%d\\n", (uint16_t)tmp_ccrxccc); + uint16_t _ic, _iv, _iz, _in, _xc, _xv, _xz, _xn; + + _in = (Rd >> 31) & 1; + _iz = ((Rd & 0xFFFFFFFF) == 0); + _xn = (Rd >> 63) & 1; + _xz = (Rd == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + _xv = %(xvValue)s & 1; + _xc = %(xcValue)s & 1; + + Ccr = _ic << 0 | _iv << 1 | _iz << 2 | _in << 3 | + _xc << 4 | _xv << 5 | _xz << 6 | _xn << 7; + + + DPRINTF(Sparc, "in = %%d\\n", _in); + DPRINTF(Sparc, "iz = %%d\\n", _iz); + DPRINTF(Sparc, "xn = %%d\\n", _xn); + DPRINTF(Sparc, "xz = %%d\\n", _xz); + DPRINTF(Sparc, "iv = %%d\\n", _iv); + DPRINTF(Sparc, "ic = %%d\\n", _ic); + DPRINTF(Sparc, "xv = %%d\\n", _xv); + DPRINTF(Sparc, "xc = %%d\\n", _xc); ''' }}; diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 7df59d736..d7ee01519 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -72,7 +72,11 @@ output decoder {{ std::string Priv::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return "Privileged Instruction"; + std::stringstream response; + + printMnemonic(response, mnemonic); + + return response.str(); } }}; @@ -87,9 +91,10 @@ def template PrivExecute {{ if(%(check)s) return new PrivilegedAction; + Fault fault = NoFault; %(code)s; %(op_wb)s; - return NoFault; + return fault; } }}; @@ -116,10 +121,17 @@ let {{ // Primary format for integer operate instructions: def format Priv(code, *opt_flags) {{ - checkCode = "((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>)" + checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) || + ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)''' (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags) + checkCode, name, Name, opt_flags + ('IprAccessOp',)) }}; +def format HPriv(code, *opt_flags) {{ + checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags + ('IprAccessOp',)) +}}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index 40afb3722..3783051c4 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -36,7 +36,6 @@ output header {{ #include <sstream> #include <iostream> -#include <iomanip> #include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" @@ -50,7 +49,6 @@ output decoder {{ #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() -#include <math.h> #if defined(linux) #include <fenv.h> #endif @@ -59,14 +57,10 @@ using namespace SparcISA; }}; output exec {{ -#include <math.h> #if defined(linux) #include <fenv.h> #endif -#ifdef FULL_SYSTEM -//#include "sim/pseudo_inst.hh" -#endif #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 9e5c783e8..605816083 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -51,12 +51,12 @@ def operands {{ 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), - #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), - #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), - #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 4), - 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 4), + 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10), + 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), + 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), + 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20), + 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), + 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), 'R0': ('IntReg', 'udw', '0', None, 6), @@ -65,24 +65,25 @@ def operands {{ 'R16': ('IntReg', 'udw', '16', None, 9), # Control registers - 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12), - 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17), - 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26), + 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), + 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), + 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), - 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28), - 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 28), - 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 28), - 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1), - 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27), + 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43), + 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44), + 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45), + 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38), - 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 12), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53), + 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54), - 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47) + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55), + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56) }}; diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 346f7b730..7f830eb28 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -25,13 +25,13 @@ * (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 - * Gabe Black + * Authors: Gabe Black */ #ifndef __ARCH_SPARC_ISA_TRAITS_HH__ #define __ARCH_SPARC_ISA_TRAITS_HH__ +#include "arch/sparc/types.hh" #include "base/misc.hh" #include "config/full_system.hh" #include "sim/host.hh" @@ -46,70 +46,45 @@ class StaticInstPtr; namespace BigEndianGuest {} -#if !FULL_SYSTEM -class SyscallReturn -{ - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } - - ~SyscallReturn() {} - - SyscallReturn& operator=(const SyscallReturn& s) - { - retval = s.retval; - success = s.success; - return *this; - } - - bool successful() { return success; } - uint64_t value() { return retval; } - - private: - uint64_t retval; - bool success; -}; - -#endif - #if FULL_SYSTEM #include "arch/sparc/isa_fullsys_traits.hh" #endif namespace SparcISA { + class RegFile; + + //This makes sure the big endian versions of certain functions are used. + using namespace BigEndianGuest; + + //TODO this needs to be a SPARC Noop + // Alpha UNOP (ldq_u r31,0(r0)) + const MachInst NoopMachInst = 0x2ffe0000; + + const int NumIntRegs = 32; + const int NumFloatRegs = 64; + const int NumMiscRegs = 40; // 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 = 32, - Ctrl_Base_DepTag = 96, + // 32..95 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = NumIntRegs, + Ctrl_Base_DepTag = NumIntRegs + NumFloatRegs, //XXX These are here solely to get compilation and won't work Fpcr_DepTag = 0, Uniq_DepTag = 0 }; - //This makes sure the big endian versions of certain functions are used. - using namespace BigEndianGuest; - typedef uint32_t MachInst; - typedef uint64_t ExtMachInst; + // MAXTL - maximum trap level + const int MaxPTL = 2; + const int MaxTL = 6; + const int MaxGL = 3; + const int MaxPGL = 2; - const int NumIntRegs = 32; - const int NumFloatRegs = 64; - const int NumMiscRegs = 32; + // NWINDOWS - number of register windows, can be 3 to 32 + const int NWindows = 32; // semantically meaningful register indices const int ZeroReg = 0; // architecturally meaningful @@ -131,14 +106,6 @@ namespace SparcISA const int MaxInstSrcRegs = 8; const int MaxInstDestRegs = 9; - typedef uint64_t IntReg; - - // control register file contents - typedef uint64_t MiscReg; - - typedef double FloatReg; - typedef uint64_t FloatRegBits; - //8K. This value is implmentation specific; and should probably //be somewhere else. const int LogVMPageSize = 13; @@ -165,29 +132,4 @@ namespace SparcISA extern const MachInst NoopMachInst; } -#include "arch/sparc/regfile.hh" - -namespace SparcISA -{ - -#if !FULL_SYSTEM - static inline void setSyscallReturn(SyscallReturn return_value, - RegFile *regs) - { - // check for error condition. SPARC syscall convention is to - // indicate success/failure in reg the carry bit of the ccr - // and put the return value itself in the standard return value reg (). - if (return_value.successful()) { - // no error, clear XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF); - regs->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, set XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10); - regs->setIntReg(ReturnValueReg, return_value.value()); - } - } -#endif -}; - #endif // __ARCH_SPARC_ISA_TRAITS_HH__ diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc index ae6ffbc2a..1211d5f65 100644 --- a/src/arch/sparc/linux/linux.cc +++ b/src/arch/sparc/linux/linux.cc @@ -29,6 +29,7 @@ */ #include "arch/sparc/linux/linux.hh" +#include <fcntl.h> // open(2) flags translation table OpenFlagTransTable SparcLinux::openFlagTable[] = { diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index e27255e67..8c2de8ca3 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -199,7 +199,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 99 */ SyscallDesc("accept", unimplementedFunc), /* 100 */ SyscallDesc("getpriority", unimplementedFunc), /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), @@ -295,7 +295,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), /* 197 */ SyscallDesc("getppid", getppidFunc), - /* 198 */ SyscallDesc("sigaction", unimplementedFunc), + /* 198 */ SyscallDesc("sigaction", ignoreFunc), /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index f4819ba84..4af8f0f75 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -32,6 +32,7 @@ #define __SPARC_LINUX_PROCESS_HH__ #include "arch/sparc/linux/linux.hh" +#include "arch/sparc/syscallreturn.hh" #include "arch/sparc/process.hh" #include "sim/process.hh" diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc new file mode 100644 index 000000000..8041e45c0 --- /dev/null +++ b/src/arch/sparc/miscregfile.cc @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/miscregfile.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +//These functions map register indices to names +string SparcISA::getMiscRegName(RegIndex index) +{ + static::string miscRegName[NumMiscRegs] = + {"y", "ccr", "asi", "tick", "pc", "fprs", "pcr", "pic", + "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", + "stick", "stick_cmpr", + "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", + "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", + "wstate", "gl", + "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", + "hstick_cmpr", + "fsr"}; + return miscRegName[index]; +} + +#if FULL_SYSTEM + +//XXX These need an implementation someplace +/** Fullsystem only register version of ReadRegWithEffect() */ +MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); +/** Fullsystem only register version of SetRegWithEffect() */ +Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc); +#endif + +void MiscRegFile::reset() +{ + pstateFields.pef = 0; //No FPU + //pstateFields.pef = 1; //FPU +#if FULL_SYSTEM + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + tl = MaxTL; + gl = MaxGL; + + tickFields.counter = 0; //The TICK register is unreadable bya + tickFields.npt = 1; //The TICK register is unreadable by by !priv + + softint = 0; // Clear all the soft interrupt bits + tick_cmprFields.int_dis = 1; // disable timer compare interrupts + tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + stickFields.npt = 1; //The TICK register is unreadable by by !priv + stick_cmprFields.int_dis = 1; // disable timer compare interrupts + stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + + + tt[tl] = power_on_reset; + pstate = 0; // fields 0 but pef + pstateFields.pef = 1; + + hpstate = 0; + hpstateFields.red = 1; + hpstateFields.hpriv = 1; + hpstateFields.tlz = 0; // this is a guess + hintp = 0; // no interrupts pending + hstick_cmprFields.int_dis = 1; // disable timer compare interrupts + hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing +#else +/* //This sets up the initial state of the processor for usermode processes + pstateFields.priv = 0; //Process runs in user mode + pstateFields.ie = 1; //Interrupts are enabled + fsrFields.rd = 0; //Round to nearest + fsrFields.tem = 0; //Floating point traps not enabled + fsrFields.ns = 0; //Non standard mode off + fsrFields.qne = 0; //Floating point queue is empty + fsrFields.aexc = 0; //No accrued exceptions + fsrFields.cexc = 0; //No current exceptions + + //Register window management registers + otherwin = 0; //No windows contain info from other programs + canrestore = 0; //There are no windows to pop + cansave = MaxTL - 2; //All windows are available to save into + cleanwin = MaxTL;*/ +#endif +} + +MiscReg MiscRegFile::readReg(int miscReg) +{ + switch (miscReg) { + case MISCREG_Y: + return y; + case MISCREG_CCR: + return ccr; + case MISCREG_ASI: + return asi; + case MISCREG_FPRS: + return fprs; + case MISCREG_TICK: + return tick; + case MISCREG_PCR: + case MISCREG_PIC: + panic("ASR number %d not implemented\n", miscReg - AsrStart); + case MISCREG_GSR: + return gsr; + case MISCREG_SOFTINT: + return softint; + case MISCREG_TICK_CMPR: + return tick_cmpr; + case MISCREG_STICK: + return stick; + case MISCREG_STICK_CMPR: + return stick_cmpr; + + /** Privilged Registers */ + case MISCREG_TPC: + return tpc[tl-1]; + case MISCREG_TNPC: + return tnpc[tl-1]; + case MISCREG_TSTATE: + return tstate[tl-1]; + case MISCREG_TT: + return tt[tl-1]; + case MISCREG_PRIVTICK: + panic("Priviliged access to tick registers not implemented\n"); + case MISCREG_TBA: + return tba; + case MISCREG_PSTATE: + return pstate; + case MISCREG_TL: + return tl; + case MISCREG_PIL: + return pil; + case MISCREG_CWP: + return cwp; + case MISCREG_CANSAVE: + return cansave; + case MISCREG_CANRESTORE: + return canrestore; + case MISCREG_CLEANWIN: + return cleanwin; + case MISCREG_OTHERWIN: + return otherwin; + case MISCREG_WSTATE: + return wstate; + case MISCREG_GL: + return gl; + + /** Hyper privileged registers */ + case MISCREG_HPSTATE: + return hpstate; + case MISCREG_HTSTATE: + return htstate[tl-1]; + case MISCREG_HINTP: + panic("HINTP not implemented\n"); + case MISCREG_HTBA: + return htba; + case MISCREG_HVER: + return NWindows | MaxTL << 8 | MaxGL << 16; + case MISCREG_STRAND_STS_REG: + return strandStatusReg; + case MISCREG_HSTICK_CMPR: + return hstick_cmpr; + + /** Floating Point Status Register */ + case MISCREG_FSR: + return fsr; + default: + panic("Miscellaneous register %d not implemented\n", miscReg); + } +} + +MiscReg MiscRegFile::readRegWithEffect(int miscReg, + Fault &fault, ThreadContext * tc) +{ + fault = NoFault; + switch (miscReg) { + case MISCREG_Y: + case MISCREG_CCR: + case MISCREG_ASI: + return readReg(miscReg); + + case MISCREG_TICK: + case MISCREG_PRIVTICK: + // Check for reading privilege + if (tickFields.npt && !isNonPriv()) { + fault = new PrivilegedAction; + return 0; + } + return tc->getCpuPtr()->curCycle() - tickFields.counter | + tickFields.npt << 63; + case MISCREG_PC: + return tc->readPC(); + case MISCREG_FPRS: + fault = new UnimpFault("FPU not implemented\n"); + return 0; + case MISCREG_PCR: + fault = new UnimpFault("Performance Instrumentation not impl\n"); + return 0; + case MISCREG_PIC: + fault = new UnimpFault("Performance Instrumentation not impl\n"); + return 0; + case MISCREG_GSR: + return readReg(miscReg); + + /** Privilged Registers */ + case MISCREG_TPC: + case MISCREG_TNPC: + case MISCREG_TSTATE: + case MISCREG_TT: + if (tl == 0) { + fault = new IllegalInstruction; + return 0; + } // NOTE THE FALL THROUGH! + case MISCREG_PSTATE: + case MISCREG_TL: + return readReg(miscReg); + + case MISCREG_TBA: + return readReg(miscReg) & ULL(~0x7FFF); + + case MISCREG_PIL: + + case MISCREG_CWP: + case MISCREG_CANSAVE: + case MISCREG_CANRESTORE: + case MISCREG_CLEANWIN: + case MISCREG_OTHERWIN: + case MISCREG_WSTATE: + case MISCREG_GL: + return readReg(miscReg); + + /** Floating Point Status Register */ + case MISCREG_FSR: + panic("Floating Point not implemented\n"); + default: +#if FULL_SYSTEM + return readFSRegWithEffect(miscReg, fault, tc); +#else + fault = new IllegalInstruction; + return 0; +#endif + } +} + +Fault MiscRegFile::setReg(int miscReg, const MiscReg &val) +{ + switch (miscReg) { + case MISCREG_Y: + y = val; + return NoFault; + case MISCREG_CCR: + ccr = val; + return NoFault; + case MISCREG_ASI: + asi = val; + return NoFault; + case MISCREG_FPRS: + fprs = val; + return NoFault; + case MISCREG_TICK: + tick = val; + return NoFault; + case MISCREG_PCR: + case MISCREG_PIC: + panic("ASR number %d not implemented\n", miscReg - AsrStart); + case MISCREG_GSR: + gsr = val; + case MISCREG_SOFTINT: + softint = val; + return NoFault; + case MISCREG_TICK_CMPR: + tick_cmpr = val; + return NoFault; + case MISCREG_STICK: + stick = val; + return NoFault; + case MISCREG_STICK_CMPR: + stick_cmpr = val; + return NoFault; + + /** Privilged Registers */ + case MISCREG_TPC: + tpc[tl-1] = val; + return NoFault; + case MISCREG_TNPC: + tnpc[tl-1] = val; + return NoFault; + case MISCREG_TSTATE: + tstate[tl-1] = val; + return NoFault; + case MISCREG_TT: + tt[tl-1] = val; + return NoFault; + case MISCREG_PRIVTICK: + panic("Priviliged access to tick regesiters not implemented\n"); + case MISCREG_TBA: + tba = val; + return NoFault; + case MISCREG_PSTATE: + pstate = val; + return NoFault; + case MISCREG_TL: + tl = val; + return NoFault; + case MISCREG_PIL: + pil = val; + return NoFault; + case MISCREG_CWP: + cwp = val; + return NoFault; + case MISCREG_CANSAVE: + cansave = val; + return NoFault; + case MISCREG_CANRESTORE: + canrestore = val; + return NoFault; + case MISCREG_CLEANWIN: + cleanwin = val; + return NoFault; + case MISCREG_OTHERWIN: + otherwin = val; + return NoFault; + case MISCREG_WSTATE: + wstate = val; + return NoFault; + case MISCREG_GL: + gl = val; + return NoFault; + + /** Hyper privileged registers */ + case MISCREG_HPSTATE: + hpstate = val; + return NoFault; + case MISCREG_HTSTATE: + htstate[tl-1] = val; + return NoFault; + case MISCREG_HINTP: + panic("HINTP not implemented\n"); + case MISCREG_HTBA: + htba = val; + return NoFault; + case MISCREG_STRAND_STS_REG: + strandStatusReg = val; + return NoFault; + case MISCREG_HSTICK_CMPR: + hstick_cmpr = val; + return NoFault; + + /** Floating Point Status Register */ + case MISCREG_FSR: + fsr = val; + return NoFault; + default: + panic("Miscellaneous register %d not implemented\n", miscReg); + } +} + +Fault MiscRegFile::setRegWithEffect(int miscReg, + const MiscReg &val, ThreadContext * tc) +{ + const uint64_t Bit64 = (1ULL << 63); + switch (miscReg) { + case MISCREG_Y: + case MISCREG_CCR: + case MISCREG_ASI: + setReg(miscReg, val); + return NoFault; + case MISCREG_PRIVTICK: + case MISCREG_TICK: + if (isNonPriv()) + return new PrivilegedOpcode; + if (isPriv()) + return new PrivilegedAction; + tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; + tickFields.npt = val & Bit64 ? 1 : 0; + return NoFault; + case MISCREG_PC: + return new IllegalInstruction; + case MISCREG_FPRS: + return new UnimpFault("FPU not implemented\n"); + case MISCREG_PCR: + return new UnimpFault("Performance Instrumentation not impl\n"); + case MISCREG_PIC: + return new UnimpFault("Performance Instrumentation not impl\n"); + case MISCREG_GSR: + return setReg(miscReg, val); + + /** Privilged Registers */ + case MISCREG_TPC: + case MISCREG_TNPC: + case MISCREG_TSTATE: + case MISCREG_TT: + if (tl == 0) + return new IllegalInstruction; + setReg(miscReg, val); + return NoFault; + + case MISCREG_TBA: + // clear lower 7 bits on writes. + setReg(miscReg, val & ULL(~0x7FFF)); + return NoFault; + + case MISCREG_PSTATE: + setReg(miscReg, val); + return NoFault; + + case MISCREG_TL: + if (isHyperPriv() && val > MaxTL) + setReg(miscReg, MaxTL); + else if (isPriv() && !isHyperPriv() && val > MaxPTL) + setReg(miscReg, MaxPTL); + else + setReg(miscReg, val); + return NoFault; + + case MISCREG_CWP: + tc->changeRegFileContext(CONTEXT_CWP, val); + case MISCREG_CANSAVE: + case MISCREG_CANRESTORE: + case MISCREG_CLEANWIN: + case MISCREG_OTHERWIN: + case MISCREG_WSTATE: + setReg(miscReg, val); + return NoFault; + + case MISCREG_GL: + int newval; + if (isHyperPriv() && val > MaxGL) + newval = MaxGL; + else if (isPriv() && !isHyperPriv() && val > MaxPGL) + newval = MaxPGL; + else + newval = val; + tc->changeRegFileContext(CONTEXT_GLOBALS, newval); + setReg(miscReg, newval); + return NoFault; + + /** Floating Point Status Register */ + case MISCREG_FSR: + panic("Floating Point not implemented\n"); + default: +#if FULL_SYSTEM + setFSRegWithEffect(miscReg, val, tc); +#else + return new IllegalInstruction; +#endif + } +} + +void MiscRegFile::serialize(std::ostream & os) +{ + SERIALIZE_SCALAR(pstate); + SERIALIZE_SCALAR(tba); + SERIALIZE_SCALAR(y); + SERIALIZE_SCALAR(pil); + SERIALIZE_SCALAR(gl); + SERIALIZE_SCALAR(cwp); + SERIALIZE_ARRAY(tt, MaxTL); + SERIALIZE_SCALAR(ccr); + SERIALIZE_SCALAR(asi); + SERIALIZE_SCALAR(tl); + SERIALIZE_ARRAY(tpc, MaxTL); + SERIALIZE_ARRAY(tnpc, MaxTL); + SERIALIZE_ARRAY(tstate, MaxTL); + SERIALIZE_SCALAR(tick); + SERIALIZE_SCALAR(cansave); + SERIALIZE_SCALAR(canrestore); + SERIALIZE_SCALAR(otherwin); + SERIALIZE_SCALAR(cleanwin); + SERIALIZE_SCALAR(wstate); + SERIALIZE_SCALAR(fsr); + SERIALIZE_SCALAR(fprs); + SERIALIZE_SCALAR(hpstate); + SERIALIZE_ARRAY(htstate, MaxTL); + SERIALIZE_SCALAR(htba); + SERIALIZE_SCALAR(hstick_cmpr); +} + +void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) +{ + UNSERIALIZE_SCALAR(pstate); + UNSERIALIZE_SCALAR(tba); + UNSERIALIZE_SCALAR(y); + UNSERIALIZE_SCALAR(pil); + UNSERIALIZE_SCALAR(gl); + UNSERIALIZE_SCALAR(cwp); + UNSERIALIZE_ARRAY(tt, MaxTL); + UNSERIALIZE_SCALAR(ccr); + UNSERIALIZE_SCALAR(asi); + UNSERIALIZE_SCALAR(tl); + UNSERIALIZE_ARRAY(tpc, MaxTL); + UNSERIALIZE_ARRAY(tnpc, MaxTL); + UNSERIALIZE_ARRAY(tstate, MaxTL); + UNSERIALIZE_SCALAR(tick); + UNSERIALIZE_SCALAR(cansave); + UNSERIALIZE_SCALAR(canrestore); + UNSERIALIZE_SCALAR(otherwin); + UNSERIALIZE_SCALAR(cleanwin); + UNSERIALIZE_SCALAR(wstate); + UNSERIALIZE_SCALAR(fsr); + UNSERIALIZE_SCALAR(fprs); + UNSERIALIZE_SCALAR(hpstate); + UNSERIALIZE_ARRAY(htstate, MaxTL); + UNSERIALIZE_SCALAR(htba); + UNSERIALIZE_SCALAR(hstick_cmpr); +} + diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh new file mode 100644 index 000000000..be143311f --- /dev/null +++ b/src/arch/sparc/miscregfile.hh @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_MISCREGFILE_HH__ +#define __ARCH_SPARC_MISCREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + + //These functions map register indices to names + std::string getMiscRegName(RegIndex); + + const int AsrStart = 0; + const int PrStart = 32; + const int HprStart = 64; + const int MiscStart = 96; + + enum MiscRegIndex + { + /** Ancillary State Registers */ + MISCREG_Y = AsrStart + 0, + MISCREG_CCR = AsrStart + 2, + MISCREG_ASI = AsrStart + 3, + MISCREG_TICK = AsrStart + 4, + MISCREG_PC = AsrStart + 5, + MISCREG_FPRS = AsrStart + 6, + MISCREG_PCR = AsrStart + 16, + MISCREG_PIC = AsrStart + 17, + MISCREG_GSR = AsrStart + 19, + MISCREG_SOFTINT_SET = AsrStart + 20, + MISCREG_SOFTINT_CLR = AsrStart + 21, + MISCREG_SOFTINT = AsrStart + 22, + MISCREG_TICK_CMPR = AsrStart + 23, + MISCREG_STICK = AsrStart + 24, + MISCREG_STICK_CMPR = AsrStart + 25, + + /** Privilged Registers */ + MISCREG_TPC = PrStart + 0, + MISCREG_TNPC = PrStart + 1, + MISCREG_TSTATE = PrStart + 2, + MISCREG_TT = PrStart + 3, + MISCREG_PRIVTICK = PrStart + 4, + MISCREG_TBA = PrStart + 5, + MISCREG_PSTATE = PrStart + 6, + MISCREG_TL = PrStart + 7, + MISCREG_PIL = PrStart + 8, + MISCREG_CWP = PrStart + 9, + MISCREG_CANSAVE = PrStart + 10, + MISCREG_CANRESTORE = PrStart + 11, + MISCREG_CLEANWIN = PrStart + 12, + MISCREG_OTHERWIN = PrStart + 13, + MISCREG_WSTATE = PrStart + 14, + MISCREG_GL = PrStart + 16, + + /** Hyper privileged registers */ + MISCREG_HPSTATE = HprStart + 0, + MISCREG_HTSTATE = HprStart + 1, + MISCREG_HINTP = HprStart + 3, + MISCREG_HTBA = HprStart + 5, + MISCREG_HVER = HprStart + 6, + MISCREG_STRAND_STS_REG = HprStart + 16, + MISCREG_HSTICK_CMPR = HprStart + 31, + + /** Floating Point Status Register */ + MISCREG_FSR = MiscStart + 0 + + }; + + // The control registers, broken out into fields + class MiscRegFile + { + private: + + /* ASR Registers */ + union { + uint64_t y; // Y (used in obsolete multiplication) + struct { + uint64_t value:32; // The actual value stored in y + uint64_t :32; // reserved bits + } yFields; + }; + union { + uint8_t ccr; // Condition Code Register + struct { + union { + uint8_t icc:4; // 32-bit condition codes + struct { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } iccFields; + }; + union { + uint8_t xcc:4; // 64-bit condition codes + struct { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } xccFields; + }; + } ccrFields; + }; + uint8_t asi; // Address Space Identifier + union { + uint64_t tick; // Hardware clock-tick counter + struct { + int64_t counter:63; // Clock-tick count + uint64_t npt:1; // Non-priveleged trap + } tickFields; + }; + union { + uint8_t fprs; // Floating-Point Register State + struct { + uint8_t dl:1; // Dirty lower + uint8_t du:1; // Dirty upper + uint8_t fef:1; // FPRS enable floating-Point + } fprsFields; + }; + union { + uint64_t gsr; //General Status Register + struct { + uint64_t mask:32; + uint64_t :4; + uint64_t im:1; + uint64_t irnd:2; + uint64_t :17; + uint64_t scale:5; + uint64_t align:3; + } gsrFields; + }; + union { + uint64_t softint; + struct { + uint64_t tm:1; + uint64_t int_level:14; + uint64_t sm:1; + } softintFields; + }; + union { + uint64_t tick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } tick_cmprFields; + }; + union { + uint64_t stick; // Hardware clock-tick counter + struct { + int64_t :63; // Not used, storage in SparcSystem + uint64_t npt:1; // Non-priveleged trap + } stickFields; + }; + union { + uint64_t stick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } stick_cmprFields; + }; + + + /* Privileged Registers */ + uint64_t tpc[MaxTL]; // Trap Program Counter (value from + // previous trap level) + uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from + // previous trap level) + union { + uint64_t tstate[MaxTL]; // Trap State + struct { + //Values are from previous trap level + uint64_t cwp:5; // Current Window Pointer + uint64_t :3; // Reserved bits + uint64_t pstate:13; // Process State + uint64_t :3; // Reserved bits + uint64_t asi:8; // Address Space Identifier + uint64_t ccr:8; // Condition Code Register + uint64_t gl:8; // Global level + } tstateFields[MaxTL]; + }; + uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured + // on the previous level) + uint64_t tba; // Trap Base Address + + union { + uint16_t pstate; // Process State Register + struct { + uint16_t :1; // reserved + uint16_t ie:1; // Interrupt enable + uint16_t priv:1; // Privelege mode + uint16_t am:1; // Address mask + uint16_t pef:1; // PSTATE enable floating-point + uint16_t :1; // reserved2 + uint16_t mm:2; // Memory Model + uint16_t tle:1; // Trap little-endian + uint16_t cle:1; // Current little-endian + } pstateFields; + }; + uint8_t tl; // Trap Level + uint8_t pil; // Process Interrupt Register + uint8_t cwp; // Current Window Pointer + uint8_t cansave; // Savable windows + uint8_t canrestore; // Restorable windows + uint8_t cleanwin; // Clean windows + uint8_t otherwin; // Other windows + union { + uint8_t wstate; // Window State + struct { + uint8_t normal:3; // Bits TT<4:2> are set to on a normal + // register window trap + uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" + // register window trap + } wstateFields; + }; + uint8_t gl; // Global level register + + + /** Hyperprivileged Registers */ + union { + uint64_t hpstate; // Hyperprivileged State Register + struct { + uint8_t tlz: 1; + uint8_t :1; + uint8_t hpriv:1; + uint8_t :2; + uint8_t red:1; + uint8_t :4; + uint8_t ibe:1; + uint8_t id:1; + } hpstateFields; + }; + + uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register + uint64_t hintp; + uint64_t htba; // Hyperprivileged Trap Base Address register + union { + uint64_t hstick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } hstick_cmprFields; + }; + + uint64_t strandStatusReg; // Per strand status register + + + /** Floating point misc registers. */ + union { + uint64_t fsr; // Floating-Point State Register + struct { + union { + uint64_t cexc:5; // Current excpetion + struct { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } cexcFields; + }; + union { + uint64_t aexc:5; // Accrued exception + struct { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } aexcFields; + }; + uint64_t fcc0:2; // Floating-Point condtion codes + uint64_t :1; // Reserved bits + uint64_t qne:1; // Deferred trap queue not empty + // with no queue, it should read 0 + uint64_t ftt:3; // Floating-Point trap type + uint64_t ver:3; // Version (of the FPU) + uint64_t :2; // Reserved bits + uint64_t ns:1; // Nonstandard floating point + union { + uint64_t tem:5; // Trap Enable Mask + struct { + uint64_t nxm:1; // Inexact + uint64_t dzm:1; // Divide by zero + uint64_t ufm:1; // Underflow + uint64_t ofm:1; // Overflow + uint64_t nvm:1; // Invalid operand + } temFields; + }; + uint64_t :2; // Reserved bits + uint64_t rd:2; // Rounding direction + uint64_t fcc1:2; // Floating-Point condition codes + uint64_t fcc2:2; // Floating-Point condition codes + uint64_t fcc3:2; // Floating-Point condition codes + uint64_t :26; // Reserved bits + } fsrFields; + }; + + // These need to check the int_dis field and if 0 then + // set appropriate bit in softint and checkinterrutps on the cpu +#if FULL_SYSTEM + /** Process a tick compare event and generate an interrupt on the cpu if + * appropriate. */ + void processTickCompare(ThreadContext *tc); + void processSTickCompare(ThreadContext *tc); + void processHSTickCompare(ThreadContext *tc); + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processTickCompare> TickCompareEvent; + TickCompareEvent *tickCompare; + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processSTickCompare> STickCompareEvent; + STickCompareEvent *sTickCompare; + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processHSTickCompare> HSTickCompareEvent; + HSTickCompareEvent *hSTickCompare; + + /** Fullsystem only register version of ReadRegWithEffect() */ + MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); + /** Fullsystem only register version of SetRegWithEffect() */ + Fault setFSRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc); +#endif + public: + + void reset(); + + MiscRegFile() + { + reset(); + } + + /** read a value out of an either an SE or FS IPR. No checking is done + * about SE vs. FS as this is mostly used to copy the regfile. Thus more + * register are copied that are necessary for FS. However this prevents + * a bunch of ifdefs and is rarely called so is not performance + * criticial. */ + MiscReg readReg(int miscReg); + + /** Read a value from an IPR. Only the SE iprs are here and the rest + * are are readFSRegWithEffect (which is called by readRegWithEffect()). + * Checking is done for permission based on state bits in the miscreg + * file. */ + MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); + + /** write a value into an either an SE or FS IPR. No checking is done + * about SE vs. FS as this is mostly used to copy the regfile. Thus more + * register are copied that are necessary for FS. However this prevents + * a bunch of ifdefs and is rarely called so is not performance + * criticial.*/ + Fault setReg(int miscReg, const MiscReg &val); + + /** Write a value into an IPR. Only the SE iprs are here and the rest + * are are setFSRegWithEffect (which is called by setRegWithEffect()). + * Checking is done for permission based on state bits in the miscreg + * file. */ + Fault setRegWithEffect(int miscReg, + const MiscReg &val, ThreadContext * tc); + + void serialize(std::ostream & os); + + void unserialize(Checkpoint * cp, const std::string & section); + + void copyMiscRegs(ThreadContext * tc); + + protected: + + bool isHyperPriv() { return hpstateFields.hpriv; } + bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } + bool isNonPriv() { return !isPriv(); } + }; +} + +#endif diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 75f01e038..70c7e719f 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -32,6 +32,7 @@ #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "base/loader/object_file.hh" +#include "base/loader/elf_object.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" @@ -129,7 +130,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) SPARC_AT_UID = 11, SPARC_AT_EUID = 12, SPARC_AT_GID = 13, - SPARC_AT_EGID = 14 + SPARC_AT_EGID = 14, + SPARC_AT_SECURE = 23 }; enum hardwareCaps @@ -153,31 +155,42 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) M5_HWCAP_SPARC_V9 | M5_HWCAP_SPARC_ULTRA3; - //Setup the auxilliary vectors. These will already have - //endian conversion. - auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_GID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_UID, 100)); - //This would work, but the entry point is a protected member - //auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry)); - auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); - //This is the address of the elf "interpreter", which I don't - //think we currently set up. It should be set to 0 (I think) - //auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); - //This is the number of headers which were in the original elf - //file. This information isn't avaibale by this point. - //auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3)); - //This is the size of a program header entry. This isn't easy - //to compute here. - //auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah)); - //This is should be set to load_addr (whatever that is) + - //e_phoff. I think it's a pointer to the program headers. - //auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah)); - //This should be easy to get right, but I won't set it for now - //auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah)); - auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); - auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + + //Setup the auxilliary vectors. These will already have endian conversion. + //Auxilliary vectors are loaded only for elf formatted executables. + ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); + if(elfObject) + { + //Bits which describe the system hardware capabilities + auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + //The system page size + auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + //Defined to be 100 in the kernel source. + //Frequency at which times() increments + auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100)); + // For statically linked executables, this is the virtual address of the + // program header tables if they appear in the executable image + auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount())); + //This is the address of the elf "interpreter", It should be set + //to 0 for regular executables. It should be something else + //(not sure what) for dynamic libraries. + auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); + //This is hardwired to 0 in the elf loading code in the kernel + auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(buildAuxVect(SPARC_AT_UID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_GID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100)); + //Whether to enable "secure mode" in the executable + auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0)); + } //Figure out how big the initial stack needs to be diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc new file mode 100644 index 000000000..747426781 --- /dev/null +++ b/src/arch/sparc/regfile.cc @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/regfile.hh" +#include "cpu/thread_context.hh" + +class Checkpoint; + +using namespace SparcISA; +using namespace std; + +//RegFile class methods +Addr RegFile::readPC() +{ + return pc; +} + +void RegFile::setPC(Addr val) +{ + pc = val; +} + +Addr RegFile::readNextPC() +{ + return npc; +} + +void RegFile::setNextPC(Addr val) +{ + npc = val; +} + +Addr RegFile::readNextNPC() +{ + return nnpc; +} + +void RegFile::setNextNPC(Addr val) +{ + nnpc = val; +} + +void RegFile::clear() +{ + intRegFile.clear(); + floatRegFile.clear(); +} + +MiscReg RegFile::readMiscReg(int miscReg) +{ + return miscRegFile.readReg(miscReg); +} + +MiscReg RegFile::readMiscRegWithEffect(int miscReg, + Fault &fault, ThreadContext *tc) +{ + return miscRegFile.readRegWithEffect(miscReg, fault, tc); +} + +Fault RegFile::setMiscReg(int miscReg, const MiscReg &val) +{ + return miscRegFile.setReg(miscReg, val); +} + +Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc) +{ + return miscRegFile.setRegWithEffect(miscReg, val, tc); +} + +FloatReg RegFile::readFloatReg(int floatReg, int width) +{ + return floatRegFile.readReg(floatReg, width); +} + +FloatReg RegFile::readFloatReg(int floatReg) +{ + //Use the "natural" width of a single float + return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); +} + +FloatRegBits RegFile::readFloatRegBits(int floatReg, int width) +{ + return floatRegFile.readRegBits(floatReg, width); +} + +FloatRegBits RegFile::readFloatRegBits(int floatReg) +{ + //Use the "natural" width of a single float + return floatRegFile.readRegBits(floatReg, + FloatRegFile::SingleWidth); +} + +Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) +{ + return floatRegFile.setReg(floatReg, val, width); +} + +Fault RegFile::setFloatReg(int floatReg, const FloatReg &val) +{ + //Use the "natural" width of a single float + return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); +} + +Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) +{ + return floatRegFile.setRegBits(floatReg, val, width); +} + +Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) +{ + //Use the "natural" width of a single float + return floatRegFile.setRegBits(floatReg, val, + FloatRegFile::SingleWidth); +} + +IntReg RegFile::readIntReg(int intReg) +{ + return intRegFile.readReg(intReg); +} + +Fault RegFile::setIntReg(int intReg, const IntReg &val) +{ + return intRegFile.setReg(intReg, val); +} + +void RegFile::serialize(std::ostream &os) +{ + intRegFile.serialize(os); + floatRegFile.serialize(os); + miscRegFile.serialize(os); + SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); +} + +void RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + intRegFile.unserialize(cp, section); + floatRegFile.unserialize(cp, section); + miscRegFile.unserialize(cp, section); + UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); +} + +void RegFile::changeContext(RegContextParam param, RegContextVal val) +{ + switch(param) + { + case CONTEXT_CWP: + intRegFile.setCWP(val); + break; + case CONTEXT_GLOBALS: + intRegFile.setGlobals(val); + break; + default: + panic("Tried to set illegal context parameter in the SPARC regfile.\n"); + } +} + +int SparcISA::InterruptLevel(uint64_t softint) +{ + if (softint & 0x10000 || softint & 0x1) + return 14; + + int level = 14; + while (level >= 0 && !(1 << (level + 1) & softint)) + level--; + if (1 << (level + 1) & softint) + return level; + return 0; +} + +void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + + uint8_t tl = src->readMiscReg(MISCREG_TL); + + // Read all the trap level dependent registers and save them off + for(int i = 1; i <= MaxTL; i++) + { + src->setMiscReg(MISCREG_TL, i); + dest->setMiscReg(MISCREG_TL, i); + + dest->setMiscReg(MISCREG_TT, src->readMiscReg(MISCREG_TT)); + dest->setMiscReg(MISCREG_TPC, src->readMiscReg(MISCREG_TPC)); + dest->setMiscReg(MISCREG_TNPC, src->readMiscReg(MISCREG_TNPC)); + dest->setMiscReg(MISCREG_TSTATE, src->readMiscReg(MISCREG_TSTATE)); + } + + // Save off the traplevel + dest->setMiscReg(MISCREG_TL, tl); + src->setMiscReg(MISCREG_TL, tl); + + + // ASRs + dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); + dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); + dest->setMiscReg(MISCREG_ASI, src->readMiscReg(MISCREG_ASI)); + dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); + dest->setMiscReg(MISCREG_FPRS, src->readMiscReg(MISCREG_FPRS)); + dest->setMiscReg(MISCREG_SOFTINT, src->readMiscReg(MISCREG_SOFTINT)); + dest->setMiscReg(MISCREG_TICK_CMPR, src->readMiscReg(MISCREG_TICK_CMPR)); + dest->setMiscReg(MISCREG_STICK, src->readMiscReg(MISCREG_STICK)); + dest->setMiscReg(MISCREG_STICK_CMPR, src->readMiscReg(MISCREG_STICK_CMPR)); + + // Priv Registers + dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); + dest->setMiscReg(MISCREG_TBA, src->readMiscReg(MISCREG_TBA)); + dest->setMiscReg(MISCREG_PSTATE, src->readMiscReg(MISCREG_PSTATE)); + dest->setMiscReg(MISCREG_PIL, src->readMiscReg(MISCREG_PIL)); + dest->setMiscReg(MISCREG_CWP, src->readMiscReg(MISCREG_CWP)); + dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE)); + dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE)); + dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN)); + dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN)); + dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE)); + dest->setMiscReg(MISCREG_GL, src->readMiscReg(MISCREG_GL)); + + // Hyperprivilged registers + dest->setMiscReg(MISCREG_HPSTATE, src->readMiscReg(MISCREG_HPSTATE)); + dest->setMiscReg(MISCREG_HINTP, src->readMiscReg(MISCREG_HINTP)); + dest->setMiscReg(MISCREG_HTBA, src->readMiscReg(MISCREG_HTBA)); + dest->setMiscReg(MISCREG_STRAND_STS_REG, + src->readMiscReg(MISCREG_STRAND_STS_REG)); + dest->setMiscReg(MISCREG_HSTICK_CMPR, + src->readMiscReg(MISCREG_HSTICK_CMPR)); + + // FSR + dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR)); +} + +void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest) +{ + // First loop through the integer registers. + for (int i = 0; i < TheISA::NumIntRegs; ++i) { + dest->setIntReg(i, src->readIntReg(i)); + } + + // Then loop through the floating point registers. + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + dest->setFloatRegBits(i, src->readFloatRegBits(i)); + } + + // Copy misc. registers + copyMiscRegs(src, dest); + + // Lastly copy PC/NPC + dest->setPC(src->readPC()); + dest->setNextPC(src->readNextPC()); + dest->setNextNPC(src->readNextNPC()); +} diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index cbeb3c7b9..500fbbba4 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -32,833 +32,84 @@ #ifndef __ARCH_SPARC_REGFILE_HH__ #define __ARCH_SPARC_REGFILE_HH__ -#include "arch/sparc/exceptions.hh" #include "arch/sparc/faults.hh" -#include "base/trace.hh" -#include "sim/byteswap.hh" -#include "cpu/cpuevent.hh" +#include "arch/sparc/floatregfile.hh" +#include "arch/sparc/intregfile.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/miscregfile.hh" +#include "arch/sparc/types.hh" #include "sim/host.hh" +#include <string> + class Checkpoint; namespace SparcISA { - - typedef uint8_t RegIndex; - - // MAXTL - maximum trap level - const int MaxPTL = 2; - const int MaxTL = 6; - const int MaxGL = 3; - const int MaxPGL = 2; - - // NWINDOWS - number of register windows, can be 3 to 32 - const int NWindows = 32; - - - const int AsrStart = 0; - const int PrStart = 32; - const int HprStart = 64; - const int MiscStart = 96; - - const uint64_t Bit64 = (1ULL << 63); - - class IntRegFile + class RegFile { protected: - static const int FrameOffsetBits = 3; - static const int FrameNumBits = 2; - - static const int RegsPerFrame = 1 << FrameOffsetBits; - static const int FrameNumMask = - (FrameNumBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameNumBits) - 1; - static const int FrameOffsetMask = - (FrameOffsetBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameOffsetBits) - 1; - - IntReg regGlobals[MaxGL][RegsPerFrame]; - IntReg regSegments[2 * NWindows][RegsPerFrame]; - - enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; - - IntReg * regView[NumFrames]; - - static const int RegGlobalOffset = 0; - static const int FrameOffset = MaxGL * RegsPerFrame; - int offset[NumFrames]; + Addr pc; // Program Counter + Addr npc; // Next Program Counter + Addr nnpc; public: + Addr readPC(); + void setPC(Addr val); - int flattenIndex(int reg) - { - int flatIndex = offset[reg >> FrameOffsetBits] - | (reg & FrameOffsetMask); - DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); - return flatIndex; - } - - void clear() - { - int x; - for (x = 0; x < MaxGL; x++) - memset(regGlobals[x], 0, sizeof(regGlobals[x])); - for(int x = 0; x < 2 * NWindows; x++) - bzero(regSegments[x], sizeof(regSegments[x])); - } - - IntRegFile() - { - offset[Globals] = 0; - regView[Globals] = regGlobals[0]; - setCWP(0); - clear(); - } - - IntReg readReg(int intReg) - { - IntReg val = - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; - DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); - return val; - } - - Fault setReg(int intReg, const IntReg &val) - { - if(intReg) - DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; - return NoFault; - } - - //This doesn't effect the actual CWP register. - //It's purpose is to adjust the view of the register file - //to what it would be if CWP = cwp. - void setCWP(int cwp) - { - int index = ((NWindows - cwp) % NWindows) * 2; - offset[Outputs] = FrameOffset + (index * RegsPerFrame); - offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); - offset[Inputs] = FrameOffset + - (((index+2) % (NWindows * 2)) * RegsPerFrame); - regView[Outputs] = regSegments[index]; - regView[Locals] = regSegments[index+1]; - regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; - - DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); - } - - void setGlobals(int gl) - { - - DPRINTF(Sparc, "Now using %d globals", gl); - - regView[Globals] = regGlobals[gl]; - offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; - } - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - typedef float float32_t; - typedef double float64_t; - //FIXME long double refers to a 10 byte float, rather than a - //16 byte float as required. This data type may have to be emulated. - typedef double float128_t; + Addr readNextPC(); + void setNextPC(Addr val); - class FloatRegFile - { - public: - static const int SingleWidth = 32; - static const int DoubleWidth = 64; - static const int QuadWidth = 128; + Addr readNextNPC(); + void setNextNPC(Addr val); protected: - - //Since the floating point registers overlap each other, - //A generic storage space is used. The float to be returned is - //pulled from the appropriate section of this region. - char regSpace[SingleWidth / 8 * NumFloatRegs]; + IntRegFile intRegFile; // integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file public: - void clear() - { - bzero(regSpace, sizeof(regSpace)); - } - - FloatReg readReg(int floatReg, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - switch(width) - { - case SingleWidth: - float32_t result32; - memcpy(&result32, regSpace + 4 * floatReg, width); - return htog(result32); - case DoubleWidth: - float64_t result64; - memcpy(&result64, regSpace + 4 * floatReg, width); - return htog(result64); - case QuadWidth: - float128_t result128; - memcpy(&result128, regSpace + 4 * floatReg, width); - return htog(result128); - default: - panic("Attempted to read a %d bit floating point register!", width); - } - } - - FloatRegBits readRegBits(int floatReg, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - switch(width) - { - case SingleWidth: - uint32_t result32; - memcpy(&result32, regSpace + 4 * floatReg, width); - return htog(result32); - case DoubleWidth: - uint64_t result64; - memcpy(&result64, regSpace + 4 * floatReg, width); - return htog(result64); - case QuadWidth: - uint64_t result128; - memcpy(&result128, regSpace + 4 * floatReg, width); - return htog(result128); - default: - panic("Attempted to read a %d bit floating point register!", width); - } - } - - Fault setReg(int floatReg, const FloatReg &val, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - - uint32_t result32; - uint64_t result64; - switch(width) - { - case SingleWidth: - result32 = gtoh((uint32_t)val); - memcpy(regSpace + 4 * floatReg, &result32, width); - break; - case DoubleWidth: - result64 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result64, width); - break; - case QuadWidth: - panic("Quad width FP not implemented."); - break; - default: - panic("Attempted to read a %d bit floating point register!", width); - } - return NoFault; - } - - Fault setRegBits(int floatReg, const FloatRegBits &val, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - uint32_t result32; - uint64_t result64; - switch(width) - { - case SingleWidth: - result32 = gtoh((uint32_t)val); - memcpy(regSpace + 4 * floatReg, &result32, width); - break; - case DoubleWidth: - result64 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result64, width); - break; - case QuadWidth: - panic("Quad width FP not implemented."); - break; - default: - panic("Attempted to read a %d bit floating point register!", width); - } - return NoFault; - } + void clear(); - void serialize(std::ostream &os); + int FlattenIntIndex(int reg); - void unserialize(Checkpoint *cp, const std::string §ion); - }; + MiscReg readMiscReg(int miscReg); - enum MiscRegIndex - { - /** Ancillary State Registers */ - MISCREG_Y = AsrStart + 0, - MISCREG_CCR = AsrStart + 2, - MISCREG_ASI = AsrStart + 3, - MISCREG_TICK = AsrStart + 4, - MISCREG_PC = AsrStart + 5, - MISCREG_FPRS = AsrStart + 6, - MISCREG_PCR = AsrStart + 16, - MISCREG_PIC = AsrStart + 17, - MISCREG_GSR = AsrStart + 19, - MISCREG_SOFTINT_SET = AsrStart + 20, - MISCREG_SOFTINT_CLR = AsrStart + 21, - MISCREG_SOFTINT = AsrStart + 22, - MISCREG_TICK_CMPR = AsrStart + 23, - MISCREG_STICK = AsrStart + 24, - MISCREG_STICK_CMPR = AsrStart + 25, - - /** Privilged Registers */ - MISCREG_TPC = PrStart + 0, - MISCREG_TNPC = PrStart + 1, - MISCREG_TSTATE = PrStart + 2, - MISCREG_TT = PrStart + 3, - MISCREG_PRIVTICK = PrStart + 4, - MISCREG_TBA = PrStart + 5, - MISCREG_PSTATE = PrStart + 6, - MISCREG_TL = PrStart + 7, - MISCREG_PIL = PrStart + 8, - MISCREG_CWP = PrStart + 9, - MISCREG_CANSAVE = PrStart + 10, - MISCREG_CANRESTORE = PrStart + 11, - MISCREG_CLEANWIN = PrStart + 12, - MISCREG_OTHERWIN = PrStart + 13, - MISCREG_WSTATE = PrStart + 14, - MISCREG_GL = PrStart + 16, - - /** Hyper privileged registers */ - MISCREG_HPSTATE = HprStart + 0, - MISCREG_HTSTATE = HprStart + 1, - MISCREG_HINTP = HprStart + 3, - MISCREG_HTBA = HprStart + 5, - MISCREG_HVER = HprStart + 6, - MISCREG_STRAND_STS_REG = HprStart + 16, - MISCREG_HSTICK_CMPR = HprStart + 31, - - /** Floating Point Status Register */ - MISCREG_FSR = MiscStart + 0 + MiscReg readMiscRegWithEffect(int miscReg, + Fault &fault, ThreadContext *tc); - }; + Fault setMiscReg(int miscReg, const MiscReg &val); - // The control registers, broken out into fields - class MiscRegFile - { - private: - - /* ASR Registers */ - union { - uint64_t y; // Y (used in obsolete multiplication) - struct { - uint64_t value:32; // The actual value stored in y - uint64_t :32; // reserved bits - } yFields; - }; - union { - uint8_t ccr; // Condition Code Register - struct { - union { - uint8_t icc:4; // 32-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } iccFields; - }; - union { - uint8_t xcc:4; // 64-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } xccFields; - }; - } ccrFields; - }; - uint8_t asi; // Address Space Identifier - union { - uint64_t tick; // Hardware clock-tick counter - struct { - int64_t counter:63; // Clock-tick count - uint64_t npt:1; // Non-priveleged trap - } tickFields; - }; - union { - uint8_t fprs; // Floating-Point Register State - struct { - uint8_t dl:1; // Dirty lower - uint8_t du:1; // Dirty upper - uint8_t fef:1; // FPRS enable floating-Point - } fprsFields; - }; - union { - uint64_t softint; - struct { - uint64_t tm:1; - uint64_t int_level:14; - uint64_t sm:1; - } softintFields; - }; - union { - uint64_t tick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } tick_cmprFields; - }; - union { - uint64_t stick; // Hardware clock-tick counter - struct { - int64_t :63; // Not used, storage in SparcSystem - uint64_t npt:1; // Non-priveleged trap - } stickFields; - }; - union { - uint64_t stick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } stick_cmprFields; - }; - - - /* Privileged Registers */ - uint64_t tpc[MaxTL]; // Trap Program Counter (value from - // previous trap level) - uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from - // previous trap level) - union { - uint64_t tstate[MaxTL]; // Trap State - struct { - //Values are from previous trap level - uint64_t cwp:5; // Current Window Pointer - uint64_t :3; // Reserved bits - uint64_t pstate:13; // Process State - uint64_t :3; // Reserved bits - uint64_t asi:8; // Address Space Identifier - uint64_t ccr:8; // Condition Code Register - uint64_t gl:8; // Global level - } tstateFields[MaxTL]; - }; - uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured - // on the previous level) - uint64_t tba; // Trap Base Address - - union { - uint16_t pstate; // Process State Register - struct { - uint16_t :1; // reserved - uint16_t ie:1; // Interrupt enable - uint16_t priv:1; // Privelege mode - uint16_t am:1; // Address mask - uint16_t pef:1; // PSTATE enable floating-point - uint16_t :1; // reserved2 - uint16_t mm:2; // Memory Model - uint16_t tle:1; // Trap little-endian - uint16_t cle:1; // Current little-endian - } pstateFields; - }; - uint8_t tl; // Trap Level - uint8_t pil; // Process Interrupt Register - uint8_t cwp; // Current Window Pointer - uint8_t cansave; // Savable windows - uint8_t canrestore; // Restorable windows - uint8_t cleanwin; // Clean windows - uint8_t otherwin; // Other windows - union { - uint8_t wstate; // Window State - struct { - uint8_t normal:3; // Bits TT<4:2> are set to on a normal - // register window trap - uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" - // register window trap - } wstateFields; - }; - uint8_t gl; // Global level register - - - /** Hyperprivileged Registers */ - union { - uint64_t hpstate; // Hyperprivileged State Register - struct { - uint8_t tlz: 1; - uint8_t :1; - uint8_t hpriv:1; - uint8_t :2; - uint8_t red:1; - uint8_t :4; - uint8_t ibe:1; - uint8_t id:1; - } hpstateFields; - }; - - uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register - uint64_t hintp; - uint64_t htba; // Hyperprivileged Trap Base Address register - union { - uint64_t hstick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } hstick_cmprFields; - }; - - uint64_t strandStatusReg; // Per strand status register - - - /** Floating point misc registers. */ - union { - uint64_t fsr; // Floating-Point State Register - struct { - union { - uint64_t cexc:5; // Current excpetion - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } cexcFields; - }; - union { - uint64_t aexc:5; // Accrued exception - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } aexcFields; - }; - uint64_t fcc0:2; // Floating-Point condtion codes - uint64_t :1; // Reserved bits - uint64_t qne:1; // Deferred trap queue not empty - // with no queue, it should read 0 - uint64_t ftt:3; // Floating-Point trap type - uint64_t ver:3; // Version (of the FPU) - uint64_t :2; // Reserved bits - uint64_t ns:1; // Nonstandard floating point - union { - uint64_t tem:5; // Trap Enable Mask - struct { - uint64_t nxm:1; // Inexact - uint64_t dzm:1; // Divide by zero - uint64_t ufm:1; // Underflow - uint64_t ofm:1; // Overflow - uint64_t nvm:1; // Invalid operand - } temFields; - }; - uint64_t :2; // Reserved bits - uint64_t rd:2; // Rounding direction - uint64_t fcc1:2; // Floating-Point condition codes - uint64_t fcc2:2; // Floating-Point condition codes - uint64_t fcc3:2; // Floating-Point condition codes - uint64_t :26; // Reserved bits - } fsrFields; - }; - - // These need to check the int_dis field and if 0 then - // set appropriate bit in softint and checkinterrutps on the cpu -#if FULL_SYSTEM - /** Process a tick compare event and generate an interrupt on the cpu if - * appropriate. */ - void processTickCompare(ThreadContext *tc); - void processSTickCompare(ThreadContext *tc); - void processHSTickCompare(ThreadContext *tc); - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processTickCompare> TickCompareEvent; - TickCompareEvent *tickCompare; - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processSTickCompare> STickCompareEvent; - STickCompareEvent *sTickCompare; - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processHSTickCompare> HSTickCompareEvent; - HSTickCompareEvent *hSTickCompare; - - /** Fullsystem only register version of ReadRegWithEffect() */ - MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - /** Fullsystem only register version of SetRegWithEffect() */ - Fault setFSRegWithEffect(int miscReg, const MiscReg &val, + Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); -#endif - public: - void reset() - { - pstateFields.pef = 0; //No FPU - //pstateFields.pef = 1; //FPU -#if FULL_SYSTEM - //For SPARC, when a system is first started, there is a power - //on reset Trap which sets the processor into the following state. - //Bits that aren't set aren't defined on startup. - tl = MaxTL; - gl = MaxGL; - - tickFields.counter = 0; //The TICK register is unreadable bya - tickFields.npt = 1; //The TICK register is unreadable by by !priv - - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts - tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - stickFields.npt = 1; //The TICK register is unreadable by by !priv - stick_cmprFields.int_dis = 1; // disable timer compare interrupts - stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - - - tt[tl] = power_on_reset; - pstate = 0; // fields 0 but pef - pstateFields.pef = 1; - - hpstate = 0; - hpstateFields.red = 1; - hpstateFields.hpriv = 1; - hpstateFields.tlz = 0; // this is a guess - - hintp = 0; // no interrupts pending - hstick_cmprFields.int_dis = 1; // disable timer compare interrupts - hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - -#else -/* //This sets up the initial state of the processor for usermode processes - pstateFields.priv = 0; //Process runs in user mode - pstateFields.ie = 1; //Interrupts are enabled - fsrFields.rd = 0; //Round to nearest - fsrFields.tem = 0; //Floating point traps not enabled - fsrFields.ns = 0; //Non standard mode off - fsrFields.qne = 0; //Floating point queue is empty - fsrFields.aexc = 0; //No accrued exceptions - fsrFields.cexc = 0; //No current exceptions - - //Register window management registers - otherwin = 0; //No windows contain info from other programs - canrestore = 0; //There are no windows to pop - cansave = MaxTL - 2; //All windows are available to save into - cleanwin = MaxTL;*/ -#endif - } - - MiscRegFile() - { - reset(); - } - - /** read a value out of an either an SE or FS IPR. No checking is done - * about SE vs. FS as this is mostly used to copy the regfile. Thus more - * register are copied that are necessary for FS. However this prevents - * a bunch of ifdefs and is rarely called so is not performance - * criticial. */ - MiscReg readReg(int miscReg); - - /** Read a value from an IPR. Only the SE iprs are here and the rest - * are are readFSRegWithEffect (which is called by readRegWithEffect()). - * Checking is done for permission based on state bits in the miscreg - * file. */ - MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - - /** write a value into an either an SE or FS IPR. No checking is done - * about SE vs. FS as this is mostly used to copy the regfile. Thus more - * register are copied that are necessary for FS. However this prevents - * a bunch of ifdefs and is rarely called so is not performance - * criticial.*/ - Fault setReg(int miscReg, const MiscReg &val); - - /** Write a value into an IPR. Only the SE iprs are here and the rest - * are are setFSRegWithEffect (which is called by setRegWithEffect()). - * Checking is done for permission based on state bits in the miscreg - * file. */ - Fault setRegWithEffect(int miscReg, - const MiscReg &val, ThreadContext * tc); - - void serialize(std::ostream & os); - - void unserialize(Checkpoint * cp, const std::string & section); - - void copyMiscRegs(ThreadContext * tc); - - bool isHyperPriv() { return hpstateFields.hpriv; } - bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } - bool isNonPriv() { return !isPriv(); } - }; + FloatReg readFloatReg(int floatReg, int width); - typedef union - { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; + FloatReg readFloatReg(int floatReg); - class RegFile - { - protected: - Addr pc; // Program Counter - Addr npc; // Next Program Counter - Addr nnpc; - - public: - Addr readPC() - { - return pc; - } - - void setPC(Addr val) - { - pc = val; - } - - Addr readNextPC() - { - return npc; - } - - void setNextPC(Addr val) - { - npc = val; - } - - Addr readNextNPC() - { - return nnpc; - } - - void setNextNPC(Addr val) - { - nnpc = val; - } - - protected: - IntRegFile intRegFile; // integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file + FloatRegBits readFloatRegBits(int floatReg, int width); - public: + FloatRegBits readFloatRegBits(int floatReg); - void clear() - { - intRegFile.clear(); - floatRegFile.clear(); - } + Fault setFloatReg(int floatReg, const FloatReg &val, int width); - int FlattenIntIndex(int reg) - { - return intRegFile.flattenIndex(reg); - } + Fault setFloatReg(int floatReg, const FloatReg &val); - MiscReg readMiscReg(int miscReg) - { - return miscRegFile.readReg(miscReg); - } + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width); - MiscReg readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc) - { - return miscRegFile.readRegWithEffect(miscReg, fault, tc); - } + Fault setFloatRegBits(int floatReg, const FloatRegBits &val); - Fault setMiscReg(int miscReg, const MiscReg &val) - { - return miscRegFile.setReg(miscReg, val); - } + IntReg readIntReg(int intReg); - Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc) - { - return miscRegFile.setRegWithEffect(miscReg, val, tc); - } - - FloatReg readFloatReg(int floatReg, int width) - { - return floatRegFile.readReg(floatReg, width); - } - - FloatReg readFloatReg(int floatReg) - { - //Use the "natural" width of a single float - return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); - } - - FloatRegBits readFloatRegBits(int floatReg, int width) - { - return floatRegFile.readRegBits(floatReg, width); - } - - FloatRegBits readFloatRegBits(int floatReg) - { - //Use the "natural" width of a single float - return floatRegFile.readRegBits(floatReg, - FloatRegFile::SingleWidth); - } - - Fault setFloatReg(int floatReg, const FloatReg &val, int width) - { - return floatRegFile.setReg(floatReg, val, width); - } - - Fault setFloatReg(int floatReg, const FloatReg &val) - { - //Use the "natural" width of a single float - return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); - } - - Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) - { - return floatRegFile.setRegBits(floatReg, val, width); - } - - Fault setFloatRegBits(int floatReg, const FloatRegBits &val) - { - //Use the "natural" width of a single float - return floatRegFile.setRegBits(floatReg, val, - FloatRegFile::SingleWidth); - } - - IntReg readIntReg(int intReg) - { - return intRegFile.readReg(intReg); - } - - Fault setIntReg(int intReg, const IntReg &val) - { - return intRegFile.setReg(intReg, val); - } + Fault setIntReg(int intReg, const IntReg &val); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); public: - enum ContextParam - { - CONTEXT_CWP, - CONTEXT_GLOBALS - }; - typedef int ContextVal; - - void changeContext(ContextParam param, ContextVal val) - { - switch(param) - { - case CONTEXT_CWP: - intRegFile.setCWP(val); - break; - case CONTEXT_GLOBALS: - intRegFile.setGlobals(val); - break; - default: - panic("Tried to set illegal context parameter in the SPARC regfile.\n"); - } - } + void changeContext(RegContextParam param, RegContextVal val); }; void copyRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc index c588925b0..c53caa72a 100644 --- a/src/arch/sparc/solaris/solaris.cc +++ b/src/arch/sparc/solaris/solaris.cc @@ -30,6 +30,8 @@ #include "arch/sparc/solaris/solaris.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable SparcSolaris::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh index d12aee211..54d3d17be 100644 --- a/src/arch/sparc/stacktrace.hh +++ b/src/arch/sparc/stacktrace.hh @@ -28,8 +28,8 @@ * Authors: Nathan Binkert */ -#ifndef __ARCH_ALPHA_STACKTRACE_HH__ -#define __ARCH_ALPHA_STACKTRACE_HH__ +#ifndef __ARCH_SPARC_STACKTRACE_HH__ +#define __ARCH_SPARC_STACKTRACE_HH__ #include "base/trace.hh" #include "cpu/static_inst.hh" @@ -118,4 +118,4 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) return true; } -#endif // __ARCH_ALPHA_STACKTRACE_HH__ +#endif // __ARCH_SPARC_STACKTRACE_HH__ diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh new file mode 100644 index 000000000..d850f4b65 --- /dev/null +++ b/src/arch/sparc/syscallreturn.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_SYSCALLRETURN_HH__ +#define __ARCH_SPARC_SYSCALLRETURN_HH__ + +#include <inttypes.h> + +#include "arch/sparc/regfile.hh" + +class SyscallReturn +{ + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint64_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint64_t)v; + } + + ~SyscallReturn() {} + + SyscallReturn& operator=(const SyscallReturn& s) + { + retval = s.retval; + success = s.success; + return *this; + } + + bool successful() { return success; } + uint64_t value() { return retval; } + + private: + uint64_t retval; + bool success; +}; + +namespace SparcISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, + RegFile *regs) + { + // check for error condition. SPARC syscall convention is to + // indicate success/failure in reg the carry bit of the ccr + // and put the return value itself in the standard return value reg (). + if (return_value.successful()) { + // no error, clear XCC.C + regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF); + regs->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, set XCC.C + regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10); + regs->setIntReg(ReturnValueReg, return_value.value()); + } + } +}; + +#endif diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index e197e7918..63cbbe057 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<std::string> kernel; Param<std::string> reset_bin; @@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), @@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->reset_bin = reset_bin; p->hypervisor_bin = hypervisor_bin; diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh new file mode 100644 index 000000000..88fb24153 --- /dev/null +++ b/src/arch/sparc/types.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_TYPES_HH__ +#define __ARCH_SPARC_TYPES_HH__ + +#include <inttypes.h> + +namespace SparcISA +{ + typedef uint32_t MachInst; + typedef uint64_t ExtMachInst; + + typedef uint64_t IntReg; + typedef uint64_t MiscReg; + typedef double FloatReg; + typedef uint64_t FloatRegBits; + typedef union + { + IntReg intReg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + enum RegContextParam + { + CONTEXT_CWP, + CONTEXT_GLOBALS + }; + + typedef int RegContextVal; + + typedef uint8_t RegIndex; +} + +#endif diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index b89d48663..6493ddfd5 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -37,7 +37,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, int64_t time; SparcSystem *sys; switch (miscReg) { - /** Full system only ASRs */ + /* Full system only ASRs */ case MISCREG_SOFTINT: if (isNonPriv()) return new PrivilegedOpcode; @@ -94,7 +94,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, sTickCompare.schedule(time * Clock::Int::ns); return NoFault; - /** Fullsystem only Priv registers. */ + /* Fullsystem only Priv registers. */ case MISCREG_PIL: if (FULL_SYSTEM) { setReg(miscReg, val); @@ -104,7 +104,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, } else panic("PIL not implemented for syscall emulation\n"); - /** Hyper privileged registers */ + /* Hyper privileged registers */ case MISCREG_HPSTATE: case MISCREG_HINTP: setReg(miscReg, val); @@ -147,7 +147,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc) { switch (miscReg) { - /** Privileged registers. */ + /* Privileged registers. */ case MISCREG_SOFTINT: if (isNonPriv()) { fault = new PrivilegedOpcode; @@ -177,7 +177,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc) return readReg(miscReg); - /** Hyper privileged registers */ + /* Hyper privileged registers */ case MISCREG_HPSTATE: case MISCREG_HINTP: return readReg(miscReg); diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh index e9d5355ca..e8238464b 100644 --- a/src/base/chunk_generator.hh +++ b/src/base/chunk_generator.hh @@ -72,7 +72,7 @@ class ChunkGenerator public: /** * Constructor. - * @param startAddr The starting address of the region. + * @param _startAddr The starting address of the region. * @param totalSize The total size of the region. * @param _chunkSize The size/alignment of chunks into which * the region should be decomposed. diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 00d218b76..2ca0d4f4a 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -153,8 +153,38 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) } // while sections } + ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys); + + //The number of headers in the file + result->_programHeaderCount = ehdr.e_phnum; + //Record the size of each entry + result->_programHeaderSize = ehdr.e_phentsize; + if(result->_programHeaderCount) //If there is a program header table + { + //Figure out the virtual address of the header table in the + //final memory image. We use the program headers themselves + //to translate from a file offset to the address in the image. + GElf_Phdr phdr; + uint64_t e_phoff = ehdr.e_phoff; + result->_programHeaderTable = 0; + for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) + { + gelf_getphdr(elf, hdrnum, &phdr); + //Check if we've found the segment with the headers in it + if(phdr.p_offset <= e_phoff && + phdr.p_offset + phdr.p_filesz > e_phoff) + { + result->_programHeaderTable = phdr.p_vaddr + e_phoff; + break; + } + } + } + else + result->_programHeaderTable = 0; + + elf_end(elf); - return new ElfObject(fname, fd, len, data, arch, opSys); + return result; } } diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh index 46dbfe37b..9755426b4 100644 --- a/src/base/loader/elf_object.hh +++ b/src/base/loader/elf_object.hh @@ -37,6 +37,12 @@ class ElfObject : public ObjectFile { protected: + //These values are provided to a linux process by the kernel, so we + //need to keep them around. + Addr _programHeaderTable; + uint16_t _programHeaderSize; + uint16_t _programHeaderCount; + /// Helper functions for loadGlobalSymbols() and loadLocalSymbols(). bool loadSomeSymbols(SymbolTable *symtab, int binding); @@ -52,6 +58,9 @@ class ElfObject : public ObjectFile static ObjectFile *tryFile(const std::string &fname, int fd, size_t len, uint8_t *data); + Addr programHeaderTable() {return _programHeaderTable;} + uint16_t programHeaderSize() {return _programHeaderSize;} + uint16_t programHeaderCount() {return _programHeaderCount;} }; #endif // __ELF_OBJECT_HH__ diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 55ff0c86f..184c0a996 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -104,11 +104,11 @@ class SymbolTable /// Find the nearest symbol equal to or less than the supplied /// address (e.g., the label for the enclosing function). - /// @param address The address to look up. - /// @param symbol Return reference for symbol string. - /// @param sym_address Return reference for symbol address. - /// @param next_sym_address Address of following symbol (for - /// determining valid range of symbol). + /// @param addr The address to look up. + /// @param symbol Return reference for symbol string. + /// @param symaddr Return reference for symbol address. + /// @param nextaddr Address of following symbol (for + /// determining valid range of symbol). /// @retval True if a symbol was found. bool findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr, @@ -126,7 +126,7 @@ class SymbolTable } /// Overload for findNearestSymbol() for callers who don't care - /// about next_sym_address. + /// about nextaddr. bool findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const { diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 90b53e53f..8c3ce7572 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -33,6 +33,7 @@ #include <map> +#include "arch/types.hh" #include "base/kgdb.h" #include "cpu/pc_event.hh" #include "base/pollevent.hh" diff --git a/src/cpu/SConscript b/src/cpu/SConscript index bc4ec7923..2bb9a2399 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -71,7 +71,8 @@ virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) c # Generate a temporary CPU list, including the CheckerCPU if # it's enabled. This isn't used for anything else other than StaticInst # headers. -temp_cpu_list = env['CPU_MODELS'] +temp_cpu_list = env['CPU_MODELS'][:] + if env['USE_CHECKER']: temp_cpu_list.append('CheckerCPU') @@ -113,6 +114,9 @@ CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU'] # ################################################################# +# Keep a list of CPU models that support SMT +env['SMT_CPU_MODELS'] = [] + sources = [] need_simple_base = False @@ -156,6 +160,8 @@ if 'O3CPU' in env['CPU_MODELS']: ''') if env['USE_CHECKER']: sources += Split('o3/checker_builder.cc') + else: + env['SMT_CPU_MODELS'].append('O3CPU') # Checker doesn't support SMT right now if 'OzoneCPU' in env['CPU_MODELS']: need_bp_unit = True diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 9cc61f74c..40611abe6 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -215,6 +215,9 @@ class BaseDynInst : public FastAlloc, public RefCounted */ Addr nextPC; + /** Next non-speculative NPC. Target PC for Mips or Sparc. */ + Addr nextNPC; + /** Predicted next PC. */ Addr predPC; @@ -275,6 +278,11 @@ class BaseDynInst : public FastAlloc, public RefCounted */ Addr readNextPC() { return nextPC; } + /** Returns the next NPC. This could be the speculative next NPC if it is + * called prior to the actual branch target being calculated. + */ + Addr readNextNPC() { return nextNPC; } + /** Set the predicted target of this current instruction. */ void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } @@ -282,11 +290,20 @@ class BaseDynInst : public FastAlloc, public RefCounted Addr readPredTarg() { return predPC; } /** Returns whether the instruction was predicted taken or not. */ - bool predTaken() { return predPC != (PC + sizeof(MachInst)); } + bool predTaken() +#if THE_ISA == ALPHA_ISA + { return predPC != (PC + sizeof(MachInst)); } +#else + { return predPC != (nextPC + sizeof(MachInst)); } +#endif /** Returns whether the instruction mispredicted. */ - bool mispredicted() { return predPC != nextPC; } - + bool mispredicted() +#if THE_ISA == ALPHA_ISA + { return predPC != nextPC; } +#else + { return predPC != nextNPC; } +#endif // // Instruction types. Forward checks to StaticInst object. // @@ -308,6 +325,7 @@ class BaseDynInst : public FastAlloc, public RefCounted bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); } bool isCondCtrl() const { return staticInst->isCondCtrl(); } bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } + bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); } bool isThreadSync() const { return staticInst->isThreadSync(); } bool isSerializing() const { return staticInst->isSerializing(); } bool isSerializeBefore() const @@ -545,6 +563,12 @@ class BaseDynInst : public FastAlloc, public RefCounted nextPC = val; } + /** Set the next NPC of this instruction (the target in Mips or Sparc).*/ + void setNextNPC(uint64_t val) + { + nextNPC = val; + } + /** Sets the ASID. */ void setASID(short addr_space_id) { asid = addr_space_id; } diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 91424faad..f2109e88d 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -36,15 +36,12 @@ #include "base/cprintf.hh" #include "base/trace.hh" -#include "arch/faults.hh" +#include "sim/faults.hh" #include "cpu/exetrace.hh" #include "mem/request.hh" #include "cpu/base_dyn_inst.hh" -using namespace std; -using namespace TheISA; - #define NOHASH #ifndef NOHASH @@ -65,7 +62,7 @@ my_hash_t thishash; #endif template <class Impl> -BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC, +BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, Addr pred_PC, InstSeqNum seq_num, ImplCPU *cpu) : staticInst(machInst), traceData(NULL), cpu(cpu) @@ -73,7 +70,8 @@ BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC, seqNum = seq_num; PC = inst_PC; - nextPC = PC + sizeof(MachInst); + nextPC = PC + sizeof(TheISA::MachInst); + nextNPC = nextPC + sizeof(TheISA::MachInst); predPC = pred_PC; initVars(); @@ -249,7 +247,7 @@ void BaseDynInst<Impl>::dump() { cprintf("T%d : %#08d `", threadNumber, PC); - cout << staticInst->disassemble(PC); + std::cout << staticInst->disassemble(PC); cprintf("'\n"); } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index a508c56ba..6d6ae1e0a 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -170,7 +170,7 @@ class CheckerCPU : public BaseCPU virtual Counter totalInstructions() const { - return numInst - startNumInst; + return 0; } // number of simulated loads diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index c035e92ac..8c0186dae 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -31,6 +31,7 @@ #ifndef __CPU_CHECKER_THREAD_CONTEXT_HH__ #define __CPU_CHECKER_THREAD_CONTEXT_HH__ +#include "arch/types.hh" #include "cpu/checker/cpu.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" @@ -295,8 +296,8 @@ class CheckerThreadContext : public ThreadContext Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif - void changeRegFileContext(RegFile::ContextParam param, - RegFile::ContextVal val) + void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) { actualTC->changeRegFileContext(param, val); checkerTC->changeRegFileContext(param, val); diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 7fdad5113..748f66d37 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -34,6 +34,7 @@ #include <fstream> #include <iomanip> +#include "arch/regfile.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -42,7 +43,7 @@ #include "sim/system.hh" using namespace std; - +using namespace TheISA; //////////////////////////////////////////////////////////////////////// // @@ -53,7 +54,43 @@ using namespace std; void Trace::InstRecord::dump(ostream &outs) { - if (flags[INTEL_FORMAT]) { + if (flags[PRINT_REG_DELTA]) + { + outs << "PC = 0x" << setbase(16) + << setfill('0') + << setw(16) << PC << endl; + outs << setbase(10) + << setfill(' ') + << setw(0); + /* + int numSources = staticInst->numSrcRegs(); + int numDests = staticInst->numDestRegs(); + outs << "Sources:"; + for(int x = 0; x < numSources; x++) + { + int sourceNum = staticInst->srcRegIdx(x); + if(sourceNum < FP_Base_DepTag) + outs << " " << getIntRegName(sourceNum); + else if(sourceNum < Ctrl_Base_DepTag) + outs << " " << getFloatRegName(sourceNum - FP_Base_DepTag); + else + outs << " " << getMiscRegName(sourceNum - Ctrl_Base_DepTag); + } + outs << endl; + outs << "Destinations:"; + for(int x = 0; x < numDests; x++) + { + int destNum = staticInst->destRegIdx(x); + if(destNum < FP_Base_DepTag) + outs << " " << getIntRegName(destNum); + else if(destNum < Ctrl_Base_DepTag) + outs << " " << getFloatRegName(destNum - FP_Base_DepTag); + else + outs << " " << getMiscRegName(destNum - Ctrl_Base_DepTag); + } + outs << endl;*/ + } + else if (flags[INTEL_FORMAT]) { #if FULL_SYSTEM bool is_trace_system = (cpu->system->name() == trace_system); #else @@ -196,6 +233,8 @@ Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", "print fetch sequence number", false); Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", "print correct-path sequence number", false); +Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta", + "print which registers changed to what", false); Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol", "Use symbols for the PC if available", true); Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format", @@ -222,6 +261,7 @@ Trace::InstRecord::setParams() flags[PRINT_INT_REGS] = exe_trace_print_iregs; flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; + flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta; flags[PC_SYMBOL] = exe_trace_pc_symbol; flags[INTEL_FORMAT] = exe_trace_intel_format; trace_system = exe_trace_system; diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 95f8b449c..8cc98b777 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -147,6 +147,7 @@ class InstRecord : public Record PRINT_INT_REGS, PRINT_FETCH_SEQ, PRINT_CP_SEQ, + PRINT_REG_DELTA, PC_SYMBOL, INTEL_FORMAT, NUM_BITS diff --git a/src/cpu/o3/2bit_local_pred.hh b/src/cpu/o3/2bit_local_pred.hh index 0a2a71d3e..954b86b4c 100644 --- a/src/cpu/o3/2bit_local_pred.hh +++ b/src/cpu/o3/2bit_local_pred.hh @@ -31,9 +31,8 @@ #ifndef __CPU_O3_2BIT_LOCAL_PRED_HH__ #define __CPU_O3_2BIT_LOCAL_PRED_HH__ -// For Addr type. -#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" +#include "sim/host.hh" #include <vector> diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index e65d41411..afbd4c533 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -52,21 +52,19 @@ if env['TARGET_ISA'] == 'alpha': alpha/cpu_builder.cc ''') elif env['TARGET_ISA'] == 'mips': - sys.exit('O3 CPU does not support MIPS') - #sources += Split(''' - # mips/dyn_inst.cc - # mips/cpu.cc - # mips/thread_context.cc - # mips/cpu_builder.cc - # ''') + sources += Split(''' + mips/dyn_inst.cc + mips/cpu.cc + mips/thread_context.cc + mips/cpu_builder.cc + ''') elif env['TARGET_ISA'] == 'sparc': - sys.exit('O3 CPU does not support MIPS') - #sources += Split(''' - # sparc/dyn_inst.cc - # sparc/cpu.cc - # sparc/thread_context.cc - # sparc/cpu_builder.cc - # ''') + sources += Split(''' + sparc/dyn_inst.cc + sparc/cpu.cc + sparc/thread_context.cc + sparc/cpu_builder.cc + ''') else: sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA']) diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index b961341d5..9d97f9701 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -31,7 +31,8 @@ #ifndef __CPU_O3_ALPHA_CPU_HH__ #define __CPU_O3_ALPHA_CPU_HH__ -#include "arch/isa_traits.hh" +#include "arch/regfile.hh" +#include "arch/types.hh" #include "cpu/thread_context.hh" #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 0473e60c2..b7362fad9 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -31,6 +31,7 @@ #include "config/use_checker.hh" #include "arch/alpha/faults.hh" +#include "arch/alpha/isa_traits.hh" #include "base/cprintf.hh" #include "base/statistics.hh" #include "base/timebuf.hh" @@ -53,8 +54,6 @@ #include "sim/system.hh" #endif -using namespace TheISA; - template <class Impl> AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) #if FULL_SYSTEM @@ -191,14 +190,14 @@ AlphaO3CPU<Impl>::regStats() template <class Impl> -MiscReg +TheISA::MiscReg AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> -MiscReg +TheISA::MiscReg AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid) { @@ -300,6 +299,7 @@ template <class Impl> void AlphaO3CPU<Impl>::processInterrupts() { + using namespace TheISA; // Check for interrupts here. For now can copy the code that // exists within isa_fullsys_traits.hh. Also assume that thread 0 // is the one that handles the interrupts. @@ -411,12 +411,12 @@ AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) // return value itself in the standard return value reg (v0). if (return_value.successful()) { // no error - this->setArchIntReg(SyscallSuccessReg, 0, tid); - this->setArchIntReg(ReturnValueReg, return_value.value(), tid); + this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid); + this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid); } else { // got an error, return details - this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid); - this->setArchIntReg(ReturnValueReg, -return_value.value(), tid); + this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid); + this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid); } } #endif diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh index ad52b0d2e..70a09940f 100644 --- a/src/cpu/o3/alpha/thread_context.hh +++ b/src/cpu/o3/alpha/thread_context.hh @@ -26,9 +26,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim - * Korey Sewell */ +#include "arch/alpha/types.hh" #include "cpu/o3/thread_context.hh" template <class Impl> @@ -65,8 +65,8 @@ class AlphaTC : public O3ThreadContext<Impl> panic("Alpha has no NextNPC!"); } - virtual void changeRegFileContext(TheISA::RegFile::ContextParam param, - TheISA::RegFile::ContextVal val) + virtual void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) { panic("Not supported on Alpha!"); } diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index 2c0a39565..3c4c8e478 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -31,8 +31,6 @@ #ifndef __CPU_O3_BPRED_UNIT_HH__ #define __CPU_O3_BPRED_UNIT_HH__ -// For Addr type. -#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "cpu/inst_seq.hh" @@ -41,6 +39,8 @@ #include "cpu/o3/ras.hh" #include "cpu/o3/tournament_pred.hh" +#include "sim/host.hh" + #include <list> /** diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index 0da02145b..e4e656632 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -28,15 +28,11 @@ * Authors: Kevin Lim */ -#include <list> -#include <vector> - +#include "arch/types.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "cpu/o3/bpred_unit.hh" -using namespace std; - template<class Impl> BPredUnit<Impl>::BPredUnit(Params *params) : BTB(params->BTBEntries, @@ -159,7 +155,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid) void *bp_history = NULL; if (inst->isUncondCtrl()) { - DPRINTF(Fetch, "BranchPred: [tid:%i] Unconditional control.\n", tid); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Unconditional control.\n", tid); pred_taken = true; // Tell the BP there was an unconditional branch. BPUncond(bp_history); @@ -201,15 +197,20 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid) ++BTBLookups; if (inst->isCall()) { - RAS[tid].push(PC + sizeof(MachInst)); +#if THE_ISA == ALPHA_ISA + Addr ras_pc = PC + sizeof(MachInst); // Next PC +#else + Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC +#endif + RAS[tid].push(ras_pc); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. predict_record.wasCall = true; - DPRINTF(Fetch, "BranchPred: [tid:%i] Instruction %#x was a call" + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call" ", adding %#x to the RAS.\n", - tid, inst->readPC(), PC + sizeof(MachInst)); + tid, inst->readPC(), ras_pc); } if (BTB.valid(PC, tid)) { @@ -242,7 +243,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid) predHist[tid].push_front(predict_record); - DPRINTF(Fetch, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size()); + DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size()); return pred_taken; } @@ -251,8 +252,8 @@ template <class Impl> void BPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid) { - DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until sequence" - "number %lli.\n", tid, done_sn); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until " + "[sn:%lli].\n", tid, done_sn); while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { diff --git a/src/cpu/o3/btb.cc b/src/cpu/o3/btb.cc index 01640f4d1..93d6ee768 100644 --- a/src/cpu/o3/btb.cc +++ b/src/cpu/o3/btb.cc @@ -32,8 +32,6 @@ #include "base/trace.hh" #include "cpu/o3/btb.hh" -using namespace TheISA; - DefaultBTB::DefaultBTB(unsigned _numEntries, unsigned _tagBits, unsigned _instShiftAmt) diff --git a/src/cpu/o3/btb.hh b/src/cpu/o3/btb.hh index dfa3b7b06..3c4899e89 100644 --- a/src/cpu/o3/btb.hh +++ b/src/cpu/o3/btb.hh @@ -31,9 +31,8 @@ #ifndef __CPU_O3_BTB_HH__ #define __CPU_O3_BTB_HH__ -// For Addr type. -#include "arch/isa_traits.hh" #include "base/misc.hh" +#include "sim/host.hh" class DefaultBTB { diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index bf1bd08e8..aa58fc20e 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -33,8 +33,7 @@ #include <vector> -#include "arch/faults.hh" -#include "arch/isa_traits.hh" +#include "sim/faults.hh" #include "cpu/inst_seq.hh" #include "sim/host.hh" @@ -88,6 +87,7 @@ struct DefaultIEWDefaultCommit { bool squash[Impl::MaxThreads]; bool branchMispredict[Impl::MaxThreads]; bool branchTaken[Impl::MaxThreads]; + bool condDelaySlotBranch[Impl::MaxThreads]; uint64_t mispredPC[Impl::MaxThreads]; uint64_t nextPC[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; @@ -113,6 +113,7 @@ struct TimeBufStruct { uint64_t branchAddr; InstSeqNum doneSeqNum; + InstSeqNum bdelayDoneSeqNum; // @todo: Might want to package this kind of branch stuff into a single // struct as it is used pretty frequently. @@ -165,6 +166,9 @@ struct TimeBufStruct { // retired or squashed sequence number. InstSeqNum doneSeqNum; + InstSeqNum bdelayDoneSeqNum; + bool squashDelaySlot; + //Just in case we want to do a commit/squash on a cycle //(necessary for multiple ROBs?) bool commitInsts; diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 956b6ec3e..7575783f7 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -32,7 +32,6 @@ #ifndef __CPU_O3_COMMIT_HH__ #define __CPU_O3_COMMIT_HH__ -#include "arch/faults.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/exetrace.hh" @@ -165,6 +164,9 @@ class DefaultCommit /** Sets the pointer to the IEW stage. */ void setIEWStage(IEW *iew_stage); + /** Skid buffer between rename and commit. */ + std::queue<DynInstPtr> skidBuffer; + /** The pointer to the IEW stage. Used solely to ensure that * various events (traps, interrupts, syscalls) do not occur until * all stores have written back. @@ -256,6 +258,9 @@ class DefaultCommit /** Gets instructions from rename and inserts them into the ROB. */ void getInsts(); + /** Insert all instructions from rename into skidBuffer */ + void skidInsert(); + /** Marks completed instructions using information sent from IEW. */ void markCompletedInsts(); @@ -286,13 +291,11 @@ class DefaultCommit /** Sets the next PC of a specific thread. */ void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; } -#if THE_ISA != ALPHA_ISA /** Reads the next NPC of a specific thread. */ - uint64_t readNextPC(unsigned tid) { return nextNPC[tid]; } + uint64_t readNextNPC(unsigned tid) { return nextNPC[tid]; } /** Sets the next NPC of a specific thread. */ - void setNextPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; } -#endif + void setNextNPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; } private: /** Time buffer interface. */ @@ -397,10 +400,8 @@ class DefaultCommit /** The next PC of each thread. */ Addr nextPC[Impl::MaxThreads]; -#if THE_ISA != ALPHA_ISA /** The next NPC of each thread. */ Addr nextNPC[Impl::MaxThreads]; -#endif /** The sequence number of the youngest valid instruction in the ROB. */ InstSeqNum youngestSeqNum[Impl::MaxThreads]; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 904af1071..f200f5f18 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim + * Korey Sewell */ #include "config/full_system.hh" @@ -44,8 +45,6 @@ #include "cpu/checker/cpu.hh" #endif -using namespace std; - template <class Impl> DefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit, unsigned _tid) @@ -86,7 +85,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params) { _status = Active; _nextStatus = Inactive; - string policy = params->smtCommitPolicy; + std::string policy = params->smtCommitPolicy; //Convert string to lowercase std::transform(policy.begin(), policy.end(), policy.begin(), @@ -120,7 +119,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params) changedROBNumEntries[i] = false; trapSquash[i] = false; tcSquash[i] = false; - PC[i] = nextPC[i] = 0; + PC[i] = nextPC[i] = nextNPC[i] = 0; } } @@ -235,7 +234,7 @@ DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr) template <class Impl> void -DefaultCommit<Impl>::setThreads(vector<Thread *> &threads) +DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads) { thread = threads; } @@ -296,7 +295,7 @@ DefaultCommit<Impl>::setIEWStage(IEW *iew_stage) template<class Impl> void -DefaultCommit<Impl>::setActiveThreads(list<unsigned> *at_ptr) +DefaultCommit<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(Commit, "Commit: Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -390,7 +389,7 @@ void DefaultCommit<Impl>::updateStatus() { // reset ROB changed variable - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; changedROBNumEntries[tid] = false; @@ -419,7 +418,7 @@ DefaultCommit<Impl>::setNextStatus() { int squashes = 0; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -442,7 +441,7 @@ template <class Impl> bool DefaultCommit<Impl>::changedROBEntries() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -569,7 +568,7 @@ DefaultCommit<Impl>::tick() if ((*activeThreads).size() <= 0) return; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); // Check if any of the threads are done squashing. Change the // status if they are done. @@ -687,7 +686,7 @@ DefaultCommit<Impl>::commit() // Check for any possible squashes, handle them first //////////////////////////////////// - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -723,14 +722,48 @@ DefaultCommit<Impl>::commit() // then use one older sequence number. InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid]; - if (fromIEW->includeSquashInst[tid] == true) - squashed_inst--; +#if THE_ISA != ALPHA_ISA + InstSeqNum bdelay_done_seq_num; + bool squash_bdelay_slot; + + if (fromIEW->branchMispredict[tid]) { + if (fromIEW->branchTaken[tid] && + fromIEW->condDelaySlotBranch[tid]) { + DPRINTF(Commit, "[tid:%i]: Cond. delay slot branch" + "mispredicted as taken. Squashing after previous " + "inst, [sn:%i]\n", + tid, squashed_inst); + bdelay_done_seq_num = squashed_inst; + squash_bdelay_slot = true; + } else { + DPRINTF(Commit, "[tid:%i]: Branch Mispredict. Squashing " + "after delay slot [sn:%i]\n", tid, squashed_inst+1); + bdelay_done_seq_num = squashed_inst + 1; + squash_bdelay_slot = false; + } + } else { + bdelay_done_seq_num = squashed_inst; + } +#endif + if (fromIEW->includeSquashInst[tid] == true) { + squashed_inst--; +#if THE_ISA != ALPHA_ISA + bdelay_done_seq_num--; +#endif + } // All younger instructions will be squashed. Set the sequence // number as the youngest instruction in the ROB. youngestSeqNum[tid] = squashed_inst; +#if THE_ISA == ALPHA_ISA rob->squash(squashed_inst, tid); + toIEW->commitInfo[tid].squashDelaySlot = true; +#else + rob->squash(bdelay_done_seq_num, tid); + toIEW->commitInfo[tid].squashDelaySlot = squash_bdelay_slot; + toIEW->commitInfo[tid].bdelayDoneSeqNum = bdelay_done_seq_num; +#endif changedROBNumEntries[tid] = true; toIEW->commitInfo[tid].doneSeqNum = squashed_inst; @@ -766,6 +799,10 @@ DefaultCommit<Impl>::commit() // Try to commit any instructions. commitInsts(); + } else { +#if THE_ISA != ALPHA_ISA + skidInsert(); +#endif } //Check for any activity @@ -840,6 +877,7 @@ DefaultCommit<Impl>::commitInsts() } else { PC[tid] = head_inst->readPC(); nextPC[tid] = head_inst->readNextPC(); + nextNPC[tid] = head_inst->readNextNPC(); // Increment the total number of non-speculative instructions // executed. @@ -868,7 +906,13 @@ DefaultCommit<Impl>::commitInsts() } PC[tid] = nextPC[tid]; +#if THE_ISA == ALPHA_ISA nextPC[tid] = nextPC[tid] + sizeof(TheISA::MachInst); +#else + nextPC[tid] = nextNPC[tid]; + nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst); +#endif + #if FULL_SYSTEM int count = 0; Addr oldpc; @@ -996,6 +1040,12 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Check if the instruction caused a fault. If so, trap. Fault inst_fault = head_inst->getFault(); + // DTB will sometimes need the machine instruction for when + // faults happen. So we will set it here, prior to the DTB + // possibly needing it for its fault. + thread[tid]->setInst( + static_cast<TheISA::MachInst>(head_inst->staticInst->machInst)); + if (inst_fault != NoFault) { head_inst->setCompleted(); DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", @@ -1018,12 +1068,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // execution doesn't generate extra squashes. thread[tid]->inSyscall = true; - // DTB will sometimes need the machine instruction for when - // faults happen. So we will set it here, prior to the DTB - // possibly needing it for its fault. - thread[tid]->setInst( - static_cast<TheISA::MachInst>(head_inst->staticInst->machInst)); - // Execute the trap. Although it's slightly unrealistic in // terms of timing (as it doesn't wait for the full timing of // the trap event to complete before updating state), it's @@ -1069,12 +1113,39 @@ template <class Impl> void DefaultCommit<Impl>::getInsts() { + DPRINTF(Commit, "Getting instructions from Rename stage.\n"); + +#if THE_ISA == ALPHA_ISA + // Read any renamed instructions and place them into the ROB. + int insts_to_process = std::min((int)renameWidth, fromRename->size); +#else // Read any renamed instructions and place them into the ROB. - int insts_to_process = min((int)renameWidth, fromRename->size); + int insts_to_process = std::min((int)renameWidth, + (int)(fromRename->size + skidBuffer.size())); + int rename_idx = 0; - for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) - { - DynInstPtr inst = fromRename->insts[inst_num]; + DPRINTF(Commit, "%i insts available to process. Rename Insts:%i " + "SkidBuffer Insts:%i\n", insts_to_process, fromRename->size, + skidBuffer.size()); +#endif + + + for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) { + DynInstPtr inst; + +#if THE_ISA == ALPHA_ISA + inst = fromRename->insts[inst_num]; +#else + // Get insts from skidBuffer or from Rename + if (skidBuffer.size() > 0) { + DPRINTF(Commit, "Grabbing skidbuffer inst.\n"); + inst = skidBuffer.front(); + skidBuffer.pop(); + } else { + DPRINTF(Commit, "Grabbing rename inst.\n"); + inst = fromRename->insts[rename_idx++]; + } +#endif int tid = inst->threadNumber; if (!inst->isSquashed() && @@ -1095,6 +1166,53 @@ DefaultCommit<Impl>::getInsts() inst->readPC(), inst->seqNum, tid); } } + +#if THE_ISA != ALPHA_ISA + if (rename_idx < fromRename->size) { + DPRINTF(Commit,"Placing Rename Insts into skidBuffer.\n"); + + for (; + rename_idx < fromRename->size; + rename_idx++) { + DynInstPtr inst = fromRename->insts[rename_idx]; + int tid = inst->threadNumber; + + if (!inst->isSquashed()) { + DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", + "skidBuffer.\n", inst->readPC(), inst->seqNum, tid); + skidBuffer.push(inst); + } else { + DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + "squashed, skipping.\n", + inst->readPC(), inst->seqNum, tid); + } + } + } +#endif + +} + +template <class Impl> +void +DefaultCommit<Impl>::skidInsert() +{ + DPRINTF(Commit, "Attempting to any instructions from rename into " + "skidBuffer.\n"); + + for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) { + DynInstPtr inst = fromRename->insts[inst_num]; + int tid = inst->threadNumber; + + if (!inst->isSquashed()) { + DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", + "skidBuffer.\n", inst->readPC(), inst->seqNum, tid); + skidBuffer.push(inst); + } else { + DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + "squashed, skipping.\n", + inst->readPC(), inst->seqNum, tid); + } + } } template <class Impl> @@ -1124,7 +1242,7 @@ template <class Impl> bool DefaultCommit<Impl>::robDoneSquashing() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -1221,8 +1339,8 @@ template<class Impl> int DefaultCommit<Impl>::roundRobin() { - list<unsigned>::iterator pri_iter = priority_list.begin(); - list<unsigned>::iterator end = priority_list.end(); + std::list<unsigned>::iterator pri_iter = priority_list.begin(); + std::list<unsigned>::iterator end = priority_list.end(); while (pri_iter != end) { unsigned tid = *pri_iter; @@ -1252,7 +1370,7 @@ DefaultCommit<Impl>::oldestReady() unsigned oldest = 0; bool first = true; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 7d2727401..af032132e 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -441,7 +441,7 @@ FullO3CPU<Impl>::tick() if (!tickEvent.scheduled()) { if (_status == SwitchedOut || - getState() == SimObject::DrainedTiming) { + getState() == SimObject::Drained) { // increment stat lastRunningCycle = curTick; } else if (!activityRec.active()) { @@ -577,39 +577,19 @@ void FullO3CPU<Impl>::suspendContext(int tid) { DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); - unscheduleTickEvent(); + deactivateThread(tid); + if (activeThreads.size() == 0) + unscheduleTickEvent(); _status = Idle; -/* - //Remove From Active List, if Active - list<unsigned>::iterator isActive = find( - activeThreads.begin(), activeThreads.end(), tid); - - if (isActive != activeThreads.end()) { - DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", - tid); - activeThreads.erase(isActive); - } -*/ } template <class Impl> void FullO3CPU<Impl>::haltContext(int tid) { - DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid); -/* - //Remove From Active List, if Active - list<unsigned>::iterator isActive = find( - activeThreads.begin(), activeThreads.end(), tid); - - if (isActive != activeThreads.end()) { - DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", - tid); - activeThreads.erase(isActive); - - removeThread(tid); - } -*/ + //For now, this is the same as deallocate + DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); + deallocateContext(tid, 1); } template <class Impl> @@ -687,11 +667,12 @@ FullO3CPU<Impl>::removeThread(unsigned tid) } // Squash Throughout Pipeline - fetch.squash(0,tid); + InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; + fetch.squash(0, squash_seq_num, true, tid); decode.squash(tid); - rename.squash(tid); + rename.squash(squash_seq_num, tid); iew.squash(tid); - commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid); + commit.rob->squash(squash_seq_num, tid); assert(iew.ldstQueue.getCount(tid) == 0); @@ -765,7 +746,8 @@ template <class Impl> void FullO3CPU<Impl>::serialize(std::ostream &os) { - SERIALIZE_ENUM(_status); + SimObject::State so_state = SimObject::getState(); + SERIALIZE_ENUM(so_state); BaseCPU::serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); @@ -786,7 +768,8 @@ template <class Impl> void FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ENUM(_status); + SimObject::State so_state; + UNSERIALIZE_ENUM(so_state); BaseCPU::unserialize(cp, section); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); @@ -803,7 +786,7 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) } template <class Impl> -bool +unsigned int FullO3CPU<Impl>::drain(Event *drain_event) { drainCount = 0; @@ -815,7 +798,7 @@ FullO3CPU<Impl>::drain(Event *drain_event) // Wake the CPU and record activity so everything can drain out if // the CPU was not able to immediately drain. - if (getState() != SimObject::DrainedTiming) { + if (getState() != SimObject::Drained) { // A bit of a hack...set the drainEvent after all the drain() // calls have been made, that way if all of the stages drain // immediately, the signalDrained() function knows not to call @@ -825,9 +808,9 @@ FullO3CPU<Impl>::drain(Event *drain_event) wakeCPU(); activityRec.activity(); - return false; + return 1; } else { - return true; + return 0; } } @@ -835,19 +818,21 @@ template <class Impl> void FullO3CPU<Impl>::resume() { + assert(system->getMemoryMode() == System::Timing); fetch.resume(); decode.resume(); rename.resume(); iew.resume(); commit.resume(); + changeState(SimObject::Running); + if (_status == SwitchedOut || _status == Idle) return; if (!tickEvent.scheduled()) tickEvent.schedule(curTick); _status = Running; - changeState(SimObject::Timing); } template <class Impl> @@ -858,7 +843,7 @@ FullO3CPU<Impl>::signalDrained() if (tickEvent.scheduled()) tickEvent.squash(); - changeState(SimObject::DrainedTiming); + changeState(SimObject::Drained); if (drainEvent) { drainEvent->process(); @@ -1063,7 +1048,8 @@ template <class Impl> void FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid) { - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); + int idx = reg_idx + TheISA::FP_Base_DepTag; + PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); regFile.setFloatReg(phys_reg, val); } @@ -1072,7 +1058,8 @@ template <class Impl> void FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid) { - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); + int idx = reg_idx + TheISA::FP_Base_DepTag; + PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); regFile.setFloatReg(phys_reg, val, 64); } @@ -1081,7 +1068,8 @@ template <class Impl> void FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid) { - PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx); + int idx = reg_idx + TheISA::FP_Base_DepTag; + PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx); regFile.setFloatRegBits(phys_reg, val); } @@ -1114,7 +1102,6 @@ FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid) commit.setNextPC(val, tid); } -#if THE_ISA != ALPHA_ISA template <class Impl> uint64_t FullO3CPU<Impl>::readNextNPC(unsigned tid) @@ -1124,11 +1111,10 @@ FullO3CPU<Impl>::readNextNPC(unsigned tid) template <class Impl> void -FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid) +FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid) { commit.setNextNPC(val, tid); } -#endif template <class Impl> typename FullO3CPU<Impl>::ListIt @@ -1178,7 +1164,9 @@ FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) template <class Impl> void -FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) +FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid, + bool squash_delay_slot, + const InstSeqNum &delay_slot_seq_num) { DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" " list.\n", tid); @@ -1209,6 +1197,12 @@ FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid) while (inst_it != end_it) { assert(!instList.empty()); +#if THE_ISA != ALPHA_ISA + if(!squash_delay_slot && + delay_slot_seq_num >= (*inst_it)->seqNum) { + break; + } +#endif squashInstIt(inst_it, tid); inst_it--; diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 2fbd013ac..7e18571f1 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -38,7 +38,7 @@ #include <set> #include <vector> -#include "arch/isa_traits.hh" +#include "arch/types.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "config/full_system.hh" @@ -330,7 +330,7 @@ class FullO3CPU : public BaseO3CPU /** Starts draining the CPU's pipeline of all instructions in * order to stop all memory accesses. */ - virtual bool drain(Event *drain_event); + virtual unsigned int drain(Event *drain_event); /** Resumes execution after a drain. */ virtual void resume(); @@ -449,8 +449,10 @@ class FullO3CPU : public BaseO3CPU */ void removeFrontInst(DynInstPtr &inst); - /** Remove all instructions that are not currently in the ROB. */ - void removeInstsNotInROB(unsigned tid); + /** Remove all instructions that are not currently in the ROB. + * There's also an option to not squash delay slot instructions.*/ + void removeInstsNotInROB(unsigned tid, bool squash_delay_slot, + const InstSeqNum &delay_slot_seq_num); /** Remove all instructions younger than the given sequence number. */ void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid); diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh index 7f5ecbc26..4a845e670 100644 --- a/src/cpu/o3/decode.hh +++ b/src/cpu/o3/decode.hh @@ -276,6 +276,19 @@ class DefaultDecode /** Maximum size of the skid buffer. */ unsigned skidBufferMax; + /** SeqNum of Squashing Branch Delay Instruction (used for MIPS)*/ + Addr bdelayDoneSeqNum[Impl::MaxThreads]; + + /** Instruction used for squashing branch (used for MIPS)*/ + DynInstPtr squashInst[Impl::MaxThreads]; + + /** Tells when their is a pending delay slot inst. to send + * to rename. If there is, then wait squash after the next + * instruction (used for MIPS). + */ + bool squashAfterDelaySlot[Impl::MaxThreads]; + + /** Stat for total number of idle cycles. */ Stats::Scalar<> decodeIdleCycles; /** Stat for total number of blocked cycles. */ diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 8b851c032..160845378 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -30,8 +30,6 @@ #include "cpu/o3/decode.hh" -using namespace std; - template<class Impl> DefaultDecode<Impl>::DefaultDecode(Params *params) : renameToDecodeDelay(params->renameToDecodeDelay), @@ -50,6 +48,8 @@ DefaultDecode<Impl>::DefaultDecode(Params *params) stalls[i].rename = false; stalls[i].iew = false; stalls[i].commit = false; + + squashAfterDelaySlot[i] = false; } // @todo: Make into a parameter @@ -158,7 +158,7 @@ DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) template<class Impl> void -DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr) +DefaultDecode<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(Decode, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -278,13 +278,25 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) // Send back mispredict information. toFetch->decodeInfo[tid].branchMispredict = true; - toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; toFetch->decodeInfo[tid].predIncorrect = true; + toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; toFetch->decodeInfo[tid].squash = true; toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); +#if THE_ISA == ALPHA_ISA toFetch->decodeInfo[tid].branchTaken = inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); + InstSeqNum squash_seq_num = inst->seqNum; +#else + toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() != + (inst->readNextPC() + sizeof(TheISA::MachInst)); + + toFetch->decodeInfo[tid].bdelayDoneSeqNum = bdelayDoneSeqNum[tid]; + squashAfterDelaySlot[tid] = false; + + InstSeqNum squash_seq_num = bdelayDoneSeqNum[tid]; +#endif + // Might have to tell fetch to unblock. if (decodeStatus[tid] == Blocked || decodeStatus[tid] == Unblocking) { @@ -296,7 +308,7 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) for (int i=0; i<fromFetch->size; i++) { if (fromFetch->insts[i]->threadNumber == tid && - fromFetch->insts[i]->seqNum > inst->seqNum) { + fromFetch->insts[i]->seqNum > squash_seq_num) { fromFetch->insts[i]->setSquashed(); } } @@ -304,15 +316,35 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) // Clear the instruction list and skid buffer in case they have any // insts in them. while (!insts[tid].empty()) { + +#if THE_ISA != ALPHA_ISA + if (insts[tid].front()->seqNum <= squash_seq_num) { + DPRINTF(Decode, "[tid:%i]: Cannot remove incoming decode " + "instructions before delay slot [sn:%i]. %i insts" + "left in decode.\n", tid, squash_seq_num, + insts[tid].size()); + break; + } +#endif insts[tid].pop(); } while (!skidBuffer[tid].empty()) { + +#if THE_ISA != ALPHA_ISA + if (skidBuffer[tid].front()->seqNum <= squash_seq_num) { + DPRINTF(Decode, "[tid:%i]: Cannot remove skidBuffer " + "instructions before delay slot [sn:%i]. %i insts" + "left in decode.\n", tid, squash_seq_num, + insts[tid].size()); + break; + } +#endif skidBuffer[tid].pop(); } // Squash instructions up until this one - cpu->removeInstsUntil(inst->seqNum, tid); + cpu->removeInstsUntil(squash_seq_num, tid); } template<class Impl> @@ -392,7 +424,7 @@ template<class Impl> bool DefaultDecode<Impl>::skidsEmpty() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { if (!skidBuffer[*threads++].empty()) @@ -408,7 +440,7 @@ DefaultDecode<Impl>::updateStatus() { bool any_unblocking = false; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); threads = (*activeThreads).begin(); @@ -565,7 +597,7 @@ DefaultDecode<Impl>::tick() toRenameIndex = 0; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); sortInsts(); @@ -611,7 +643,7 @@ DefaultDecode<Impl>::decode(bool &status_change, unsigned tid) // will allow, as long as it is not currently blocked. if (decodeStatus[tid] == Running || decodeStatus[tid] == Idle) { - DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run " + DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " "stage.\n",tid); decodeInsts(tid); @@ -710,6 +742,9 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid) // Ensure that if it was predicted as a branch, it really is a // branch. if (inst->predTaken() && !inst->isControl()) { + DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC, + inst->nextPC + 4); + panic("Instruction predicted as a branch!"); ++decodeControlMispred; @@ -730,12 +765,43 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid) // Might want to set some sort of boolean and just do // a check at the end +#if THE_ISA == ALPHA_ISA squash(inst, inst->threadNumber); inst->setPredTarg(inst->branchTarget()); - break; +#else + // If mispredicted as taken, then ignore delay slot + // instruction... else keep delay slot and squash + // after it is sent to rename + if (inst->predTaken() && inst->isCondDelaySlot()) { + DPRINTF(Decode, "[tid:%i]: Conditional delay slot inst." + "[sn:%i] PC %#x mispredicted as taken.\n", tid, + inst->seqNum, inst->PC); + bdelayDoneSeqNum[tid] = inst->seqNum; + squash(inst, inst->threadNumber); + inst->setPredTarg(inst->branchTarget()); + break; + } else { + DPRINTF(Decode, "[tid:%i]: Misprediction detected at " + "[sn:%i] PC %#x, will squash after delay slot " + "inst. is sent to Rename\n", + tid, inst->seqNum, inst->PC); + bdelayDoneSeqNum[tid] = inst->seqNum + 1; + squashAfterDelaySlot[tid] = true; + squashInst[tid] = inst; + continue; + } +#endif } } + + if (squashAfterDelaySlot[tid]) { + assert(!inst->isSquashed()); + squash(squashInst[tid], squashInst[tid]->threadNumber); + squashInst[tid]->setPredTarg(squashInst[tid]->branchTarget()); + assert(!inst->isSquashed()); + break; + } } // If we didn't process all instructions, then we will need to block diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index a2cdf2dba..279513493 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -34,12 +34,19 @@ #include "arch/isa_specific.hh" #if THE_ISA == ALPHA_ISA -template <class Impl> -class AlphaDynInst; - -struct AlphaSimpleImpl; - -typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst; + template <class Impl> class AlphaDynInst; + struct AlphaSimpleImpl; + typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst; +#elif THE_ISA == MIPS_ISA + template <class Impl> class MipsDynInst; + struct MipsSimpleImpl; + typedef MipsDynInst<MipsSimpleImpl> O3DynInst; +#elif THE_ISA == SPARC_ISA + template <class Impl> class SparcDynInst; + struct SparcSimpleImpl; + typedef SparcDynInst<SparcSimpleImpl> O3DynInst; +#else + #error "O3DynInst not defined for this ISA" #endif #endif // __CPU_O3_DYN_INST_HH__ diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 85654cebc..1a2ca32a4 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -106,6 +106,7 @@ class DefaultFetch virtual void recvRetry(); }; + public: /** Overall fetch status. Used to determine if the CPU can * deschedule itsef due to a lack of activity. @@ -218,9 +219,10 @@ class DefaultFetch * @param next_PC Next PC variable passed in by reference. It is * expected to be set to the current PC; it will be updated with what * the next PC will be. + * @param next_NPC Used for ISAs which use delay slots. * @return Whether or not a branch was predicted as taken. */ - bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC); + bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC); /** * Fetches the cache line that contains fetch_PC. Returns any @@ -255,7 +257,8 @@ class DefaultFetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const Addr &new_PC, unsigned tid); + void squash(const Addr &new_PC, const InstSeqNum &seq_num, + bool squash_delay_slot, unsigned tid); /** Ticks the fetch stage, processing all inputs signals and fetching * as many instructions as possible. @@ -340,14 +343,12 @@ class DefaultFetch /** Per-thread next PC. */ Addr nextPC[Impl::MaxThreads]; -#if THE_ISA != ALPHA_ISA /** Per-thread next Next PC. * This is not a real register but is used for * architectures that use a branch-delay slot. * (such as MIPS or Sparc) */ Addr nextNPC[Impl::MaxThreads]; -#endif /** Memory request used to access cache. */ RequestPtr memReq[Impl::MaxThreads]; @@ -360,6 +361,19 @@ class DefaultFetch /** Tracks how many instructions has been fetched this cycle. */ int numInst; + /** Tracks delay slot information for threads in ISAs which use + * delay slots; + */ + struct DelaySlotInfo { + InstSeqNum delaySlotSeqNum; + InstSeqNum branchSeqNum; + int numInsts; + Addr targetAddr; + bool targetReady; + }; + + DelaySlotInfo delaySlotInfo[Impl::MaxThreads]; + /** Source of possible stalls. */ struct Stalls { bool decode; @@ -404,6 +418,12 @@ class DefaultFetch /** The cache line being fetched. */ uint8_t *cacheData[Impl::MaxThreads]; + /** The PC of the cacheline that has been loaded. */ + Addr cacheDataPC[Impl::MaxThreads]; + + /** Whether or not the cache data is valid. */ + bool cacheDataValid[Impl::MaxThreads]; + /** Size of instructions. */ int instSize; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 39a13f9f8..990db88ac 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -51,9 +51,6 @@ #include <algorithm> -using namespace std; -using namespace TheISA; - template<class Impl> Tick DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt) @@ -118,7 +115,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params) // Set fetch stage's status to inactive. _status = Inactive; - string policy = params->smtFetchPolicy; + std::string policy = params->smtFetchPolicy; // Convert string to lowercase std::transform(policy.begin(), policy.end(), policy.begin(), @@ -162,15 +159,22 @@ DefaultFetch<Impl>::DefaultFetch(Params *params) // Create space to store a cache line. cacheData[tid] = new uint8_t[cacheBlkSize]; + cacheDataPC[tid] = 0; + cacheDataValid[tid] = false; + + delaySlotInfo[tid].branchSeqNum = -1; + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetAddr = 0; + delaySlotInfo[tid].targetReady = false; - stalls[tid].decode = 0; - stalls[tid].rename = 0; - stalls[tid].iew = 0; - stalls[tid].commit = 0; + stalls[tid].decode = false; + stalls[tid].rename = false; + stalls[tid].iew = false; + stalls[tid].commit = false; } // Get the size of an instruction. - instSize = sizeof(MachInst); + instSize = sizeof(TheISA::MachInst); } template <class Impl> @@ -286,6 +290,9 @@ DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr) } #endif + // Schedule fetch to get the correct PC from the CPU + // scheduleFetchStartupEvent(1); + // Fetch needs to start fetching instructions at the very beginning, // so it must start up in active state. switchToActive(); @@ -307,7 +314,7 @@ DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer) template<class Impl> void -DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr) +DefaultFetch<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(Fetch, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -358,6 +365,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) } memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize); + cacheDataValid[tid] = true; if (!drainPending) { // Wake up the CPU (if it went to sleep and was waiting on @@ -423,6 +431,10 @@ DefaultFetch<Impl>::takeOverFrom() nextPC[i] = cpu->readNextPC(i); #if THE_ISA != ALPHA_ISA nextNPC[i] = cpu->readNextNPC(i); + delaySlotInfo[i].branchSeqNum = -1; + delaySlotInfo[i].numInsts = 0; + delaySlotInfo[i].targetAddr = 0; + delaySlotInfo[i].targetReady = false; #endif fetchStatus[i] = Running; } @@ -471,7 +483,8 @@ DefaultFetch<Impl>::switchToInactive() template <class Impl> bool -DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC) +DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, + Addr &next_NPC) { // Do branch prediction check here. // A bit of a misnomer...next_PC is actually the current PC until @@ -479,12 +492,54 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC) bool predict_taken; if (!inst->isControl()) { +#if THE_ISA == ALPHA_ISA next_PC = next_PC + instSize; inst->setPredTarg(next_PC); +#else + Addr cur_PC = next_PC; + next_PC = cur_PC + instSize; //next_NPC; + next_NPC = cur_PC + (2 * instSize);//next_NPC + instSize; + inst->setPredTarg(next_NPC); +#endif return false; } - predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber); + int tid = inst->threadNumber; +#if THE_ISA == ALPHA_ISA + predict_taken = branchPred.predict(inst, next_PC, tid); +#else + Addr pred_PC = next_PC; + predict_taken = branchPred.predict(inst, pred_PC, tid); + + if (predict_taken) { + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be true.\n", tid); + } else { + DPRINTF(Fetch, "[tid:%i]: Branch predicted to be false.\n", tid); + } + + if (predict_taken) { + next_PC = next_NPC; + next_NPC = pred_PC; + + // Update delay slot info + ++delaySlotInfo[tid].numInsts; + delaySlotInfo[tid].targetAddr = pred_PC; + DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) to process.\n", tid, + delaySlotInfo[tid].numInsts); + } else { // !predict_taken + if (inst->isCondDelaySlot()) { + next_PC = pred_PC; + // The delay slot is skipped here if there is on + // prediction + } else { + next_PC = next_NPC; + // No need to declare a delay slot here since + // there is no for the pred. target to jump + } + + next_NPC = next_NPC + instSize; + } +#endif ++fetchedBranches; @@ -519,6 +574,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Align the fetch PC so it's at the start of a cache block. fetch_PC = icacheBlockAlignPC(fetch_PC); + // If we've already got the block, no need to try to fetch it again. + if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) { + return true; + } + // Setup the memReq to do a read of the first instruction's address. // Set the appropriate read size and flags as well. // Build request here. @@ -550,7 +610,10 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Build packet here. PacketPtr data_pkt = new Packet(mem_req, Packet::ReadReq, Packet::Broadcast); - data_pkt->dataDynamic(new uint8_t[cacheBlkSize]); + data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]); + + cacheDataPC[tid] = fetch_PC; + cacheDataValid[tid] = false; DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); @@ -595,6 +658,7 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid) PC[tid] = new_PC; nextPC[tid] = new_PC + instSize; + nextNPC[tid] = new_PC + (2 * instSize); // Clear the icache miss if it's outstanding. if (fetchStatus[tid] == IcacheWaitResponse) { @@ -628,6 +692,14 @@ DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, doSquash(new_PC, tid); +#if THE_ISA != ALPHA_ISA + if (seq_num <= delaySlotInfo[tid].branchSeqNum) { + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetAddr = 0; + delaySlotInfo[tid].targetReady = false; + } +#endif + // Tell the CPU to remove any instructions that are in flight between // fetch and decode. cpu->removeInstsUntil(seq_num, tid); @@ -664,7 +736,7 @@ typename DefaultFetch<Impl>::FetchStatus DefaultFetch<Impl>::updateFetchStatus() { //Check Running - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { @@ -701,21 +773,33 @@ DefaultFetch<Impl>::updateFetchStatus() template <class Impl> void -DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid) +DefaultFetch<Impl>::squash(const Addr &new_PC, const InstSeqNum &seq_num, + bool squash_delay_slot, unsigned tid) { DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); doSquash(new_PC, tid); +#if THE_ISA == ALPHA_ISA + // Tell the CPU to remove any instructions that are not in the ROB. + cpu->removeInstsNotInROB(tid, true, 0); +#else + if (seq_num <= delaySlotInfo[tid].branchSeqNum) { + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetAddr = 0; + delaySlotInfo[tid].targetReady = false; + } + // Tell the CPU to remove any instructions that are not in the ROB. - cpu->removeInstsNotInROB(tid); + cpu->removeInstsNotInROB(tid, squash_delay_slot, seq_num); +#endif } template <class Impl> void DefaultFetch<Impl>::tick() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); bool status_change = false; wroteToTimeBuffer = false; @@ -817,8 +901,16 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " "from commit.\n",tid); +#if THE_ISA == ALPHA_ISA + InstSeqNum doneSeqNum = fromCommit->commitInfo[tid].doneSeqNum; +#else + InstSeqNum doneSeqNum = fromCommit->commitInfo[tid].bdelayDoneSeqNum; +#endif // In any case, squash. - squash(fromCommit->commitInfo[tid].nextPC,tid); + squash(fromCommit->commitInfo[tid].nextPC, + doneSeqNum, + fromCommit->commitInfo[tid].squashDelaySlot, + tid); // Also check if there's a mispredict that happened. if (fromCommit->commitInfo[tid].branchMispredict) { @@ -865,9 +957,15 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) } if (fetchStatus[tid] != Squashing) { + +#if THE_ISA == ALPHA_ISA + InstSeqNum doneSeqNum = fromDecode->decodeInfo[tid].doneSeqNum; +#else + InstSeqNum doneSeqNum = fromDecode->decodeInfo[tid].bdelayDoneSeqNum; +#endif // Squash unless we're already squashing squashFromDecode(fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].doneSeqNum, + doneSeqNum, tid); return true; @@ -973,6 +1071,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) } Addr next_PC = fetch_PC; + Addr next_NPC = next_PC + instSize; InstSeqNum inst_seq; MachInst inst; ExtMachInst ext_inst; @@ -991,10 +1090,13 @@ DefaultFetch<Impl>::fetch(bool &status_change) // ended this fetch block. bool predicted_branch = false; + // Need to keep track of whether or not a delay slot + // instruction has been fetched + for (; offset < cacheBlkSize && numInst < fetchWidth && - !predicted_branch; + (!predicted_branch || delaySlotInfo[tid].numInsts > 0); ++numInst) { // Get a sequence number. @@ -1004,7 +1106,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) assert(offset <= cacheBlkSize - instSize); // Get the instruction from the array of the cache line. - inst = gtoh(*reinterpret_cast<MachInst *> + inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (&cacheData[tid][offset])); ext_inst = TheISA::makeExtMI(inst, fetch_PC); @@ -1031,7 +1133,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) instruction->staticInst, instruction->readPC(),tid); - predicted_branch = lookupAndUpdateNextPC(instruction, next_PC); + predicted_branch = lookupAndUpdateNextPC(instruction, next_PC, + next_NPC); // Add instruction to the CPU's list of instructions. instruction->setInstListIt(cpu->addInst(instruction)); @@ -1057,7 +1160,41 @@ DefaultFetch<Impl>::fetch(bool &status_change) break; } - offset+= instSize; + offset += instSize; + +#if THE_ISA != ALPHA_ISA + if (predicted_branch) { + delaySlotInfo[tid].branchSeqNum = inst_seq; + + DPRINTF(Fetch, "[tid:%i]: Delay slot branch set to [sn:%i]\n", + tid, inst_seq); + continue; + } else if (delaySlotInfo[tid].numInsts > 0) { + --delaySlotInfo[tid].numInsts; + + // It's OK to set PC to target of branch + if (delaySlotInfo[tid].numInsts == 0) { + delaySlotInfo[tid].targetReady = true; + + // Break the looping condition + predicted_branch = true; + } + + DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) left to" + " process.\n", tid, delaySlotInfo[tid].numInsts); + } +#endif + } + + if (offset >= cacheBlkSize) { + DPRINTF(Fetch, "[tid:%i]: Done fetching, reached the end of cache " + "block.\n", tid); + } else if (numInst >= fetchWidth) { + DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth " + "for this cycle.\n", tid); + } else if (predicted_branch && delaySlotInfo[tid].numInsts <= 0) { + DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch " + "instruction encountered.\n", tid); } } @@ -1068,18 +1205,26 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Now that fetching is completed, update the PC to signify what the next // cycle will be. if (fault == NoFault) { - DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC); - #if THE_ISA == ALPHA_ISA + DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC); PC[tid] = next_PC; nextPC[tid] = next_PC + instSize; #else - PC[tid] = next_PC; - nextPC[tid] = next_PC + instSize; - nextPC[tid] = next_PC + instSize; + if (delaySlotInfo[tid].targetReady && + delaySlotInfo[tid].numInsts == 0) { + // Set PC to target + PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC + nextPC[tid] = next_PC + instSize; //next_NPC + nextNPC[tid] = next_PC + (2 * instSize); + + delaySlotInfo[tid].targetReady = false; + } else { + PC[tid] = next_PC; + nextPC[tid] = next_NPC; + nextNPC[tid] = next_NPC + instSize; + } - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); + DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, PC[tid]); #endif } else { // We shouldn't be in an icache miss and also have a fault (an ITB @@ -1123,9 +1268,9 @@ DefaultFetch<Impl>::fetch(bool &status_change) fetchStatus[tid] = TrapPending; status_change = true; - warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]); + warn("cycle %lli: fault (%s) detected @ PC %08p", curTick, fault->name(), PC[tid]); #else // !FULL_SYSTEM - warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]); + warn("cycle %lli: fault (%s) detected @ PC %08p", curTick, fault->name(), PC[tid]); #endif // FULL_SYSTEM } } @@ -1202,8 +1347,8 @@ template<class Impl> int DefaultFetch<Impl>::roundRobin() { - list<unsigned>::iterator pri_iter = priorityList.begin(); - list<unsigned>::iterator end = priorityList.end(); + std::list<unsigned>::iterator pri_iter = priorityList.begin(); + std::list<unsigned>::iterator end = priorityList.end(); int high_pri; @@ -1232,9 +1377,9 @@ template<class Impl> int DefaultFetch<Impl>::iqCount() { - priority_queue<unsigned> PQ; + std::priority_queue<unsigned> PQ; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -1262,10 +1407,10 @@ template<class Impl> int DefaultFetch<Impl>::lsqCount() { - priority_queue<unsigned> PQ; + std::priority_queue<unsigned> PQ; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -1293,7 +1438,7 @@ template<class Impl> int DefaultFetch<Impl>::branchCount() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); panic("Branch Count Fetch policy unimplemented\n"); return *threads; } diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index fb9afde54..76fa008ee 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -31,11 +31,12 @@ #ifndef __CPU_O3_IEW_HH__ #define __CPU_O3_IEW_HH__ +#include "config/full_system.hh" + #include <queue> #include "base/statistics.hh" #include "base/timebuf.hh" -#include "config/full_system.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/scoreboard.hh" #include "cpu/o3/lsq.hh" @@ -215,7 +216,7 @@ class DefaultIEW if (++wbOutstanding == wbMax) ableToIssue = false; DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding); -#if DEBUG +#ifdef DEBUG wbList.insert(sn); #endif } @@ -225,13 +226,13 @@ class DefaultIEW if (wbOutstanding-- == wbMax) ableToIssue = true; DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding); -#if DEBUG +#ifdef DEBUG assert(wbList.find(sn) != wbList.end()); wbList.erase(sn); #endif } -#if DEBUG +#ifdef DEBUG std::set<InstSeqNum> wbList; void dumpWb() @@ -404,6 +405,9 @@ class DefaultIEW /** Records if there is a fetch redirect on this cycle for each thread. */ bool fetchRedirect[Impl::MaxThreads]; + /** Keeps track of the last valid branch delay slot instss for threads */ + InstSeqNum bdelayDoneSeqNum[Impl::MaxThreads]; + /** Used to track if all instructions have been dispatched this cycle. * If they have not, then blocking must have occurred, and the instructions * would already be added to the skid buffer. diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 684ae2295..cdc36c6c3 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -38,8 +38,6 @@ #include "cpu/o3/fu_pool.hh" #include "cpu/o3/iew.hh" -using namespace std; - template<class Impl> DefaultIEW<Impl>::DefaultIEW(Params *params) : issueToExecQueue(params->backComSize, params->forwardComSize), @@ -73,6 +71,7 @@ DefaultIEW<Impl>::DefaultIEW(Params *params) dispatchStatus[i] = Running; stalls[i].commit = false; fetchRedirect[i] = false; + bdelayDoneSeqNum[i] = 0; } wbMax = wbWidth * params->wbDepth; @@ -335,7 +334,7 @@ DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) template<class Impl> void -DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr) +DefaultIEW<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(IEW, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -428,13 +427,31 @@ DefaultIEW<Impl>::squash(unsigned tid) instQueue.squash(tid); // Tell the LDSTQ to start squashing. +#if THE_ISA == ALPHA_ISA ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); - +#else + ldstQueue.squash(fromCommit->commitInfo[tid].bdelayDoneSeqNum, tid); +#endif updatedQueues = true; // Clear the skid buffer in case it has any data in it. - while (!skidBuffer[tid].empty()) { + DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", + tid, fromCommit->commitInfo[tid].bdelayDoneSeqNum); + while (!skidBuffer[tid].empty()) { +#if THE_ISA != ALPHA_ISA + if (skidBuffer[tid].front()->seqNum <= + fromCommit->commitInfo[tid].bdelayDoneSeqNum) { + DPRINTF(IEW, "[tid:%i]: Cannot remove skidbuffer instructions " + "that occur before delay slot [sn:%i].\n", + fromCommit->commitInfo[tid].bdelayDoneSeqNum, + tid); + break; + } else { + DPRINTF(IEW, "[tid:%i]: Removing instruction [sn:%i] from " + "skidBuffer.\n", tid, skidBuffer[tid].front()->seqNum); + } +#endif if (skidBuffer[tid].front()->isLoad() || skidBuffer[tid].front()->isStore() ) { toRename->iewInfo[tid].dispatchedToLSQ++; @@ -445,6 +462,8 @@ DefaultIEW<Impl>::squash(unsigned tid) skidBuffer[tid].pop(); } + bdelayDoneSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum; + emptyRenameInsts(tid); } @@ -458,10 +477,26 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->mispredPC[tid] = inst->readPC(); - toCommit->nextPC[tid] = inst->readNextPC(); toCommit->branchMispredict[tid] = true; + +#if THE_ISA == ALPHA_ISA toCommit->branchTaken[tid] = inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); + toCommit->nextPC[tid] = inst->readNextPC(); +#else + bool branch_taken = inst->readNextNPC() != + (inst->readNextPC() + sizeof(TheISA::MachInst)); + + toCommit->branchTaken[tid] = branch_taken; + + toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot(); + + if (inst->isCondDelaySlot() && branch_taken) { + toCommit->nextPC[tid] = inst->readNextPC(); + } else { + toCommit->nextPC[tid] = inst->readNextNPC(); + } +#endif toCommit->includeSquashInst[tid] = false; @@ -626,7 +661,7 @@ DefaultIEW<Impl>::skidCount() { int max=0; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned thread_count = skidBuffer[*threads++].size(); @@ -641,7 +676,7 @@ template<class Impl> bool DefaultIEW<Impl>::skidsEmpty() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { if (!skidBuffer[*threads++].empty()) @@ -657,7 +692,7 @@ DefaultIEW<Impl>::updateStatus() { bool any_unblocking = false; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); threads = (*activeThreads).begin(); @@ -825,9 +860,11 @@ DefaultIEW<Impl>::sortInsts() { int insts_from_rename = fromRename->size; #ifdef DEBUG +#if THE_ISA == ALPHA_ISA for (int i = 0; i < numThreads; i++) assert(insts[i].empty()); #endif +#endif for (int i = 0; i < insts_from_rename; ++i) { insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); } @@ -837,7 +874,23 @@ template <class Impl> void DefaultIEW<Impl>::emptyRenameInsts(unsigned tid) { + DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions until " + "[sn:%i].\n", tid, bdelayDoneSeqNum[tid]); + while (!insts[tid].empty()) { + +#if THE_ISA != ALPHA_ISA + if (insts[tid].front()->seqNum <= bdelayDoneSeqNum[tid]) { + DPRINTF(IEW, "[tid:%i]: Done removing, cannot remove instruction" + " that occurs at or before delay slot [sn:%i].\n", + tid, bdelayDoneSeqNum[tid]); + break; + } else { + DPRINTF(IEW, "[tid:%i]: Removing incoming rename instruction " + "[sn:%i].\n", tid, insts[tid].front()->seqNum); + } +#endif + if (insts[tid].front()->isLoad() || insts[tid].front()->isStore() ) { toRename->iewInfo[tid].dispatchedToLSQ++; @@ -1120,7 +1173,7 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid) } if (!insts_to_dispatch.empty()) { - DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n"); + DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); block(tid); toRename->iewUnblock[tid] = false; } @@ -1140,13 +1193,13 @@ DefaultIEW<Impl>::printAvailableInsts() { int inst = 0; - cout << "Available Instructions: "; + std::cout << "Available Instructions: "; while (fromIssue->insts[inst]) { - if (inst%3==0) cout << "\n\t"; + if (inst%3==0) std::cout << "\n\t"; - cout << "PC: " << fromIssue->insts[inst]->readPC() + std::cout << "PC: " << fromIssue->insts[inst]->readPC() << " TN: " << fromIssue->insts[inst]->threadNumber << " SN: " << fromIssue->insts[inst]->seqNum << " | "; @@ -1154,7 +1207,7 @@ DefaultIEW<Impl>::printAvailableInsts() } - cout << "\n"; + std::cout << "\n"; } template <class Impl> @@ -1164,7 +1217,7 @@ DefaultIEW<Impl>::executeInsts() wbNumInst = 0; wbCycle = 0; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -1263,9 +1316,13 @@ DefaultIEW<Impl>::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); +#if THE_ISA == ALPHA_ISA DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", inst->nextPC); - +#else + DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n", + inst->nextNPC); +#endif // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); @@ -1384,7 +1441,7 @@ DefaultIEW<Impl>::tick() // Free function units marked as being freed this cycle. fuPool->processFreeUnits(); - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); // Check stall and squash signals, dispatch any instructions. while (threads != (*activeThreads).end()) { diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index 4c69ca384..d745faf7b 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -26,7 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim - * Korey Sewell */ #ifndef __CPU_O3_INST_QUEUE_HH__ diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 36e0842be..e7991662b 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -37,8 +37,6 @@ #include "cpu/o3/fu_pool.hh" #include "cpu/o3/inst_queue.hh" -using namespace std; - template <class Impl> InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst, int fu_idx, @@ -100,7 +98,7 @@ InstructionQueue<Impl>::InstructionQueue(Params *params) resetState(); - string policy = params->smtIQPolicy; + std::string policy = params->smtIQPolicy; //Convert string to lowercase std::transform(policy.begin(), policy.end(), policy.begin(), @@ -279,7 +277,7 @@ InstructionQueue<Impl>::regStats() ; for (int i=0; i<Num_OpClasses; ++i) { - stringstream subname; + std::stringstream subname; subname << opClassStrings[i] << "_delay"; issueDelayDist.subname(i, subname.str()); } @@ -359,7 +357,7 @@ InstructionQueue<Impl>::resetState() template <class Impl> void -InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr) +InstructionQueue<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(IQ, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -421,8 +419,8 @@ InstructionQueue<Impl>::resetEntries() if (iqPolicy != Dynamic || numThreads > 1) { int active_threads = (*activeThreads).size(); - list<unsigned>::iterator threads = (*activeThreads).begin(); - list<unsigned>::iterator list_end = (*activeThreads).end(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator list_end = (*activeThreads).end(); while (threads != list_end) { if (iqPolicy == Partitioned) { @@ -993,7 +991,11 @@ InstructionQueue<Impl>::squash(unsigned tid) // Read instruction sequence number of last instruction out of the // time buffer. +#if THE_ISA == ALPHA_ISA squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum; +#else + squashedSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum; +#endif // Call doSquash if there are insts in the IQ if (count[tid] > 0) { diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index f8a9dd8cc..4937589e3 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -35,6 +35,11 @@ #include "cpu/o3/alpha/impl.hh" #include "cpu/o3/alpha/params.hh" #include "cpu/o3/alpha/dyn_inst.hh" +#elif THE_ISA == MIPS_ISA + #include "cpu/o3/mips/cpu.hh" + #include "cpu/o3/mips/impl.hh" + #include "cpu/o3/mips/params.hh" + #include "cpu/o3/mips/dyn_inst.hh" #else - #error "O3CPU doesnt support this ISA" + #error "ISA-specific header files O3CPU not defined ISA" #endif diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index d5890950f..190734dc2 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -70,7 +70,7 @@ class LSQ { * to work. For now it just returns the port from one of the * threads. */ - Port *getDcachePort() { return thread[0].getDcachePort(); } + Port *getDcachePort() { return &dcachePort; } /** Sets the pointer to the list of active threads. */ void setActiveThreads(std::list<unsigned> *at_ptr); @@ -258,6 +258,15 @@ class LSQ { bool willWB(unsigned tid) { return thread[tid].willWB(); } + /** Returns if the cache is currently blocked. */ + bool cacheBlocked() + { return retryTid != -1; } + + /** Sets the retry thread id, indicating that one of the LSQUnits + * tried to access the cache but the cache was blocked. */ + void setRetryTid(int tid) + { retryTid = tid; } + /** Debugging function to print out all instructions. */ void dumpInsts(); /** Debugging function to print out instructions from a specific thread. */ @@ -274,7 +283,49 @@ class LSQ { template <class T> Fault write(RequestPtr req, T &data, int store_idx); - private: + /** DcachePort class for this LSQ. Handles doing the + * communication with the cache/memory. + */ + class DcachePort : public Port + { + protected: + /** Pointer to LSQ. */ + LSQ *lsq; + + public: + /** Default constructor. */ + DcachePort(LSQ *_lsq) + : lsq(_lsq) + { } + + protected: + /** Atomic version of receive. Panics. */ + virtual Tick recvAtomic(PacketPtr pkt); + + /** Functional version of receive. Panics. */ + virtual void recvFunctional(PacketPtr pkt); + + /** Receives status change. Other than range changing, panics. */ + virtual void recvStatusChange(Status status); + + /** Returns the address ranges of this device. */ + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + + /** Timing version of receive. Handles writing back and + * completing the load or store that has returned from + * memory. */ + virtual bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of the previous send. */ + virtual void recvRetry(); + }; + + /** D-cache port. */ + DcachePort dcachePort; + + protected: /** The LSQ policy for SMT mode. */ LSQPolicy lsqPolicy; @@ -303,6 +354,10 @@ class LSQ { /** Number of Threads. */ unsigned numThreads; + + /** The thread id of the LSQ Unit that is currently waiting for a + * retry. */ + int retryTid; }; template <class Impl> diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 89fd1a71d..db2c253e1 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -29,23 +29,66 @@ */ #include <algorithm> +#include <list> #include <string> #include "cpu/o3/lsq.hh" -using namespace std; +template <class Impl> +Tick +LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) +{ + panic("O3CPU model does not work with atomic mode!"); + return curTick; +} + +template <class Impl> +void +LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) +{ + panic("O3CPU doesn't expect recvFunctional callback!"); +} + +template <class Impl> +void +LSQ<Impl>::DcachePort::recvStatusChange(Status status) +{ + if (status == RangeChange) + return; + + panic("O3CPU doesn't expect recvStatusChange callback!"); +} + +template <class Impl> +bool +LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) +{ + lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); + return true; +} + +template <class Impl> +void +LSQ<Impl>::DcachePort::recvRetry() +{ + lsq->thread[lsq->retryTid].recvRetry(); + // Speculatively clear the retry Tid. This will get set again if + // the LSQUnit was unable to complete its access. + lsq->retryTid = -1; +} template <class Impl> LSQ<Impl>::LSQ(Params *params) - : LQEntries(params->LQEntries), SQEntries(params->SQEntries), - numThreads(params->numberOfThreads) + : dcachePort(this), LQEntries(params->LQEntries), + SQEntries(params->SQEntries), numThreads(params->numberOfThreads), + retryTid(-1) { DPRINTF(LSQ, "Creating LSQ object.\n"); //**********************************************/ //************ Handle SMT Parameters ***********/ //**********************************************/ - string policy = params->smtLSQPolicy; + std::string policy = params->smtLSQPolicy; //Convert string to lowercase std::transform(policy.begin(), policy.end(), policy.begin(), @@ -94,7 +137,8 @@ LSQ<Impl>::LSQ(Params *params) //Initialize LSQs for (int tid=0; tid < numThreads; tid++) { - thread[tid].init(params, maxLQEntries, maxSQEntries, tid); + thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); + thread[tid].setDcachePort(&dcachePort); } } @@ -118,7 +162,7 @@ LSQ<Impl>::regStats() template<class Impl> void -LSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr) +LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { activeThreads = at_ptr; assert(activeThreads != 0); @@ -130,6 +174,8 @@ LSQ<Impl>::setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; + dcachePort.setName(name()); + for (int tid=0; tid < numThreads; tid++) { thread[tid].setCPU(cpu_ptr); } @@ -182,8 +228,8 @@ LSQ<Impl>::resetEntries() if (lsqPolicy != Dynamic || numThreads > 1) { int active_threads = (*activeThreads).size(); - list<unsigned>::iterator threads = (*activeThreads).begin(); - list<unsigned>::iterator list_end = (*activeThreads).end(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator list_end = (*activeThreads).end(); int maxEntries; @@ -221,7 +267,7 @@ template<class Impl> void LSQ<Impl>::tick() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -270,7 +316,7 @@ template<class Impl> void LSQ<Impl>::writebackStores() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -289,7 +335,7 @@ bool LSQ<Impl>::violation() { /* Answers: Does Anybody Have a Violation?*/ - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -306,7 +352,7 @@ LSQ<Impl>::getCount() { unsigned total = 0; - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -322,7 +368,7 @@ LSQ<Impl>::numLoads() { unsigned total = 0; - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -338,7 +384,7 @@ LSQ<Impl>::numStores() { unsigned total = 0; - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -354,7 +400,7 @@ LSQ<Impl>::numLoadsReady() { unsigned total = 0; - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -370,7 +416,7 @@ LSQ<Impl>::numFreeEntries() { unsigned total = 0; - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -394,7 +440,7 @@ template<class Impl> bool LSQ<Impl>::isFull() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -421,7 +467,7 @@ template<class Impl> bool LSQ<Impl>::lqFull() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -448,7 +494,7 @@ template<class Impl> bool LSQ<Impl>::sqFull() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -475,7 +521,7 @@ template<class Impl> bool LSQ<Impl>::isStalled() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -500,7 +546,7 @@ template<class Impl> bool LSQ<Impl>::hasStoresToWB() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); if ((*activeThreads).empty()) return false; @@ -518,7 +564,7 @@ template<class Impl> bool LSQ<Impl>::willWB() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; @@ -533,7 +579,7 @@ template<class Impl> void LSQ<Impl>::dumpInsts() { - list<unsigned>::iterator active_threads = (*activeThreads).begin(); + std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 4d7a8350b..512b5a63c 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -64,6 +64,7 @@ class LSQUnit { typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::CPUPol::IEW IEW; + typedef typename Impl::CPUPol::LSQ LSQ; typedef typename Impl::CPUPol::IssueStruct IssueStruct; public: @@ -71,17 +72,12 @@ class LSQUnit { LSQUnit(); /** Initializes the LSQ unit with the specified number of entries. */ - void init(Params *params, unsigned maxLQEntries, + void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, unsigned id); /** Returns the name of the LSQ unit. */ std::string name() const; - /** Returns the dcache port. - * @todo: Remove this once the port moves up to the LSQ level. - */ - Port *getDcachePort() { return dcachePort; } - /** Registers statistics. */ void regStats(); @@ -92,6 +88,10 @@ class LSQUnit { void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; } + /** Sets the pointer to the dcache port. */ + void setDcachePort(Port *dcache_port) + { dcachePort = dcache_port; } + /** Switches out LSQ unit. */ void switchOut(); @@ -211,6 +211,9 @@ class LSQUnit { !storeQueue[storeWBIdx].completed && !isStoreBlocked; } + /** Handles doing the retry. */ + void recvRetry(); + private: /** Writes back the instruction, sending it to IEW. */ void writeback(DynInstPtr &inst, PacketPtr pkt); @@ -221,9 +224,6 @@ class LSQUnit { /** Completes the store at the specified index. */ void completeStore(int store_idx); - /** Handles doing the retry. */ - void recvRetry(); - /** Increments the given store index (circular queue). */ inline void incrStIdx(int &store_idx); /** Decrements the given store index (circular queue). */ @@ -244,54 +244,11 @@ class LSQUnit { /** Pointer to the IEW stage. */ IEW *iewStage; - /** Pointer to memory object. */ - MemObject *mem; + /** Pointer to the LSQ. */ + LSQ *lsq; - /** DcachePort class for this LSQ Unit. Handles doing the - * communication with the cache/memory. - * @todo: Needs to be moved to the LSQ level and have some sort - * of arbitration. - */ - class DcachePort : public Port - { - protected: - /** Pointer to CPU. */ - O3CPU *cpu; - /** Pointer to LSQ. */ - LSQUnit *lsq; - - public: - /** Default constructor. */ - DcachePort(O3CPU *_cpu, LSQUnit *_lsq) - : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq) - { } - - protected: - /** Atomic version of receive. Panics. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive. Panics. */ - virtual void recvFunctional(PacketPtr pkt); - - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } - - /** Timing version of receive. Handles writing back and - * completing the load or store that has returned from - * memory. */ - virtual bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of the previous send. */ - virtual void recvRetry(); - }; - - /** Pointer to the D-cache. */ - DcachePort *dcachePort; + /** Pointer to the dcache port. Used only for sending. */ + Port *dcachePort; /** Derived class to hold any sender state the LSQ needs. */ class LSQSenderState : public Packet::SenderState @@ -644,6 +601,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) // Tell IQ/mem dep unit that this instruction will need to be // rescheduled eventually iewStage->rescheduleMemInst(load_inst); + iewStage->decrWb(load_inst->seqNum); ++lsqRescheduledLoads; // Do not generate a writeback event as this instruction is not @@ -658,7 +616,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) } // If there's no forwarding case, then go access memory - DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n", + DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", load_inst->seqNum, load_inst->readPC()); assert(!load_inst->memData); @@ -666,9 +624,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) ++usedPorts; - DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n", - load_inst->readPC()); - PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); data_pkt->dataStatic(load_inst->memData); @@ -678,8 +633,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) state->inst = load_inst; data_pkt->senderState = state; - // if we have a cache, do cache access too - if (!dcachePort->sendTiming(data_pkt)) { + // if we the cache is not blocked, do cache access + if (!lsq->cacheBlocked()) { + if (!dcachePort->sendTiming(data_pkt)) { + // If the access didn't succeed, tell the LSQ by setting + // the retry thread id. + lsq->setRetryTid(lsqID); + } + } + + // If the cache was blocked, or has become blocked due to the access, + // handle it. + if (lsq->cacheBlocked()) { ++lsqCacheBlocked; // There's an older load that's already going to squash. if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 8e951534f..4f5dbbf1c 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -31,6 +31,7 @@ #include "config/use_checker.hh" +#include "cpu/o3/lsq.hh" #include "cpu/o3/lsq_unit.hh" #include "base/str.hh" #include "mem/packet.hh" @@ -96,46 +97,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt) } template <class Impl> -Tick -LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt) -{ - panic("O3CPU model does not work with atomic mode!"); - return curTick; -} - -template <class Impl> -void -LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt) -{ - panic("O3CPU doesn't expect recvFunctional callback!"); -} - -template <class Impl> -void -LSQUnit<Impl>::DcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) - return; - - panic("O3CPU doesn't expect recvStatusChange callback!"); -} - -template <class Impl> -bool -LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt) -{ - lsq->completeDataAccess(pkt); - return true; -} - -template <class Impl> -void -LSQUnit<Impl>::DcachePort::recvRetry() -{ - lsq->recvRetry(); -} - -template <class Impl> LSQUnit<Impl>::LSQUnit() : loads(0), stores(0), storesToWB(0), stalled(false), isStoreBlocked(false), isLoadBlocked(false), @@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit() template<class Impl> void -LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, +LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, unsigned id) { DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); switchedOut = false; + lsq = lsq_ptr; + lsqID = id; // Add 1 for the sentinel entry (they are circular queues). @@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, usedPorts = 0; cachePorts = params->cachePorts; - mem = params->mem; - memDepViolator = NULL; blockedLoadSeqNum = 0; @@ -180,7 +141,6 @@ void LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; - dcachePort = new DcachePort(cpu, this); #if USE_CHECKER if (cpu->checker) { @@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores() storeQueue[storeWBIdx].canWB && usedPorts < cachePorts) { - if (isStoreBlocked) { + if (isStoreBlocked || lsq->cacheBlocked()) { DPRINTF(LSQUnit, "Unable to write back any more stores, cache" " is blocked!\n"); break; @@ -830,6 +790,7 @@ LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) // Squashed instructions do not need to complete their access. if (inst->isSquashed()) { + iewStage->decrWb(inst->seqNum); assert(!inst->isStore()); ++lsqIgnoredResponses; return; @@ -911,6 +872,7 @@ LSQUnit<Impl>::recvRetry() } else { // Still blocked! ++lsqCacheBlocked; + lsq->setRetryTid(lsqID); } } else if (isLoadBlocked) { DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " diff --git a/src/cpu/o3/mips/cpu.cc b/src/cpu/o3/mips/cpu.cc new file mode 100755 index 000000000..420f460b2 --- /dev/null +++ b/src/cpu/o3/mips/cpu.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include "cpu/o3/mips/impl.hh" +#include "cpu/o3/mips/cpu_impl.hh" +#include "cpu/o3/mips/dyn_inst.hh" + +// Force instantiation of MipsO3CPU for all the implemntations that are +// needed. Consider merging this and mips_dyn_inst.cc, and maybe all +// classes that depend on a certain impl, into one file (mips_impl.cc?). +template class MipsO3CPU<MipsSimpleImpl>; diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh new file mode 100755 index 000000000..bf04b9f69 --- /dev/null +++ b/src/cpu/o3/mips/cpu.hh @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_O3_MIPS_CPU_HH__ +#define __CPU_O3_MIPS_CPU_HH__ + +#include "arch/mips/regfile.hh" +#include "arch/mips/syscallreturn.hh" +#include "cpu/thread_context.hh" +#include "cpu/o3/cpu.hh" +#include "sim/byteswap.hh" +#include "sim/faults.hh" + +class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; + +class TranslatingPort; + +/** + * MipsO3CPU class. Derives from the FullO3CPU class, and + * implements all ISA and implementation specific functions of the + * CPU. This is the CPU class that is used for the SimObjects, and is + * what is given to the DynInsts. Most of its state exists in the + * FullO3CPU; the state is has is mainly for ISA specific + * functionality. + */ +template <class Impl> +class MipsO3CPU : public FullO3CPU<Impl> +{ + public: + typedef O3ThreadState<Impl> ImplState; + typedef O3ThreadState<Impl> Thread; + typedef typename Impl::Params Params; + + /** Constructs an MipsO3CPU with the given parameters. */ + MipsO3CPU(Params *params); + + /** Registers statistics. */ + void regStats(); + + /** Translates instruction requestion in syscall emulation mode. */ + Fault translateInstReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data read request in syscall emulation mode. */ + Fault translateDataReadReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data write request in syscall emulation mode. */ + Fault translateDataWriteReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + + /** Reads a misc. register, including any side effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegWithEffect(int misc_reg, + Fault &fault, unsigned tid); + + /** Sets a miscellaneous register. */ + Fault setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + + /** Sets a misc. register, including any side effects the write + * might have as defined by the architecture. + */ + Fault setMiscRegWithEffect(int misc_reg, + const TheISA::MiscReg &val, unsigned tid); + + /** Initiates a squash of all in-flight instructions for a given + * thread. The source of the squash is an external update of + * state through the TC. + */ + void squashFromTC(unsigned tid); + + /** Traps to handle given fault. */ + void trap(Fault fault, unsigned tid); + + /** Executes a syscall. + * @todo: Determine if this needs to be virtual. + */ + void syscall(int64_t callnum, int tid); + /** Gets a syscall argument. */ + TheISA::IntReg getSyscallArg(int i, int tid); + + /** Used to shift args for indirect syscall. */ + void setSyscallArg(int i, TheISA::IntReg val, int tid); + + /** Sets the return value of a syscall. */ + void setSyscallReturn(SyscallReturn return_value, int tid); + + /** CPU read function, forwards read to LSQ. */ + template <class T> + Fault read(RequestPtr &req, T &data, int load_idx) + { + return this->iew.ldstQueue.read(req, data, load_idx); + } + + /** CPU write function, forwards write to LSQ. */ + template <class T> + Fault write(RequestPtr &req, T &data, int store_idx) + { + return this->iew.ldstQueue.write(req, data, store_idx); + } + + Addr lockAddr; + + /** Temporary fix for the lock flag, works in the UP case. */ + bool lockFlag; +}; + +#endif // __CPU_O3_MIPS_CPU_HH__ diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc new file mode 100644 index 000000000..f1c3b33a5 --- /dev/null +++ b/src/cpu/o3/mips/cpu_builder.cc @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include <string> + +#include "cpu/base.hh" +#include "cpu/o3/mips/cpu.hh" +#include "cpu/o3/mips/impl.hh" +#include "cpu/o3/mips/params.hh" +#include "cpu/o3/fu_pool.hh" +#include "sim/builder.hh" + +class DerivO3CPU : public MipsO3CPU<MipsSimpleImpl> +{ + public: + DerivO3CPU(MipsSimpleParams *p) + : MipsO3CPU<MipsSimpleImpl>(p) + { } +}; + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) + +Param<int> clock; +Param<int> numThreads; +Param<int> activity; + +SimObjectVectorParam<Process *> workload; + +SimObjectParam<MemObject *> mem; + +SimObjectParam<BaseCPU *> checker; + +Param<Counter> max_insts_any_thread; +Param<Counter> max_insts_all_threads; +Param<Counter> max_loads_any_thread; +Param<Counter> max_loads_all_threads; + +Param<unsigned> cachePorts; + +Param<unsigned> decodeToFetchDelay; +Param<unsigned> renameToFetchDelay; +Param<unsigned> iewToFetchDelay; +Param<unsigned> commitToFetchDelay; +Param<unsigned> fetchWidth; + +Param<unsigned> renameToDecodeDelay; +Param<unsigned> iewToDecodeDelay; +Param<unsigned> commitToDecodeDelay; +Param<unsigned> fetchToDecodeDelay; +Param<unsigned> decodeWidth; + +Param<unsigned> iewToRenameDelay; +Param<unsigned> commitToRenameDelay; +Param<unsigned> decodeToRenameDelay; +Param<unsigned> renameWidth; + +Param<unsigned> commitToIEWDelay; +Param<unsigned> renameToIEWDelay; +Param<unsigned> issueToExecuteDelay; +Param<unsigned> dispatchWidth; +Param<unsigned> issueWidth; +Param<unsigned> wbWidth; +Param<unsigned> wbDepth; +SimObjectParam<FUPool *> fuPool; + +Param<unsigned> iewToCommitDelay; +Param<unsigned> renameToROBDelay; +Param<unsigned> commitWidth; +Param<unsigned> squashWidth; +Param<Tick> trapLatency; + +Param<unsigned> backComSize; +Param<unsigned> forwardComSize; + +Param<std::string> predType; +Param<unsigned> localPredictorSize; +Param<unsigned> localCtrBits; +Param<unsigned> localHistoryTableSize; +Param<unsigned> localHistoryBits; +Param<unsigned> globalPredictorSize; +Param<unsigned> globalCtrBits; +Param<unsigned> globalHistoryBits; +Param<unsigned> choicePredictorSize; +Param<unsigned> choiceCtrBits; + +Param<unsigned> BTBEntries; +Param<unsigned> BTBTagSize; + +Param<unsigned> RASSize; + +Param<unsigned> LQEntries; +Param<unsigned> SQEntries; +Param<unsigned> LFSTSize; +Param<unsigned> SSITSize; + +Param<unsigned> numPhysIntRegs; +Param<unsigned> numPhysFloatRegs; +Param<unsigned> numIQEntries; +Param<unsigned> numROBEntries; + +Param<unsigned> smtNumFetchingThreads; +Param<std::string> smtFetchPolicy; +Param<std::string> smtLSQPolicy; +Param<unsigned> smtLSQThreshold; +Param<std::string> smtIQPolicy; +Param<unsigned> smtIQThreshold; +Param<std::string> smtROBPolicy; +Param<unsigned> smtROBThreshold; +Param<std::string> smtCommitPolicy; + +Param<unsigned> instShiftAmt; + +Param<bool> defer_registration; + +Param<bool> function_trace; +Param<Tick> function_trace_start; + +END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU) + +BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU) + + INIT_PARAM(clock, "clock speed"), + INIT_PARAM(numThreads, "number of HW thread contexts"), + INIT_PARAM_DFLT(activity, "Initial activity count", 0), + + INIT_PARAM(workload, "Processes to run"), + + INIT_PARAM(mem, "Memory"), + + INIT_PARAM_DFLT(checker, "Checker CPU", NULL), + + INIT_PARAM_DFLT(max_insts_any_thread, + "Terminate when any thread reaches this inst count", + 0), + INIT_PARAM_DFLT(max_insts_all_threads, + "Terminate when all threads have reached" + "this inst count", + 0), + INIT_PARAM_DFLT(max_loads_any_thread, + "Terminate when any thread reaches this load count", + 0), + INIT_PARAM_DFLT(max_loads_all_threads, + "Terminate when all threads have reached this load" + "count", + 0), + + INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200), + + INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"), + INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"), + INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch" + "delay"), + INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"), + INIT_PARAM(fetchWidth, "Fetch width"), + INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"), + INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode" + "delay"), + INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"), + INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"), + INIT_PARAM(decodeWidth, "Decode width"), + + INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename" + "delay"), + INIT_PARAM(commitToRenameDelay, "Commit to rename delay"), + INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"), + INIT_PARAM(renameWidth, "Rename width"), + + INIT_PARAM(commitToIEWDelay, "Commit to " + "Issue/Execute/Writeback delay"), + INIT_PARAM(renameToIEWDelay, "Rename to " + "Issue/Execute/Writeback delay"), + INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal" + "to the IEW stage)"), + INIT_PARAM(dispatchWidth, "Dispatch width"), + INIT_PARAM(issueWidth, "Issue width"), + INIT_PARAM(wbWidth, "Writeback width"), + INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"), + INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL), + + INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit " + "delay"), + INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"), + INIT_PARAM(commitWidth, "Commit width"), + INIT_PARAM(squashWidth, "Squash width"), + INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6), + + INIT_PARAM(backComSize, "Time buffer size for backwards communication"), + INIT_PARAM(forwardComSize, "Time buffer size for forward communication"), + + INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"), + INIT_PARAM(localPredictorSize, "Size of local predictor"), + INIT_PARAM(localCtrBits, "Bits per counter"), + INIT_PARAM(localHistoryTableSize, "Size of local history table"), + INIT_PARAM(localHistoryBits, "Bits for the local history"), + INIT_PARAM(globalPredictorSize, "Size of global predictor"), + INIT_PARAM(globalCtrBits, "Bits per counter"), + INIT_PARAM(globalHistoryBits, "Bits of history"), + INIT_PARAM(choicePredictorSize, "Size of choice predictor"), + INIT_PARAM(choiceCtrBits, "Bits of choice counters"), + + INIT_PARAM(BTBEntries, "Number of BTB entries"), + INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"), + + INIT_PARAM(RASSize, "RAS size"), + + INIT_PARAM(LQEntries, "Number of load queue entries"), + INIT_PARAM(SQEntries, "Number of store queue entries"), + INIT_PARAM(LFSTSize, "Last fetched store table size"), + INIT_PARAM(SSITSize, "Store set ID table size"), + + INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"), + INIT_PARAM(numPhysFloatRegs, "Number of physical floating point " + "registers"), + INIT_PARAM(numIQEntries, "Number of instruction queue entries"), + INIT_PARAM(numROBEntries, "Number of reorder buffer entries"), + + INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1), + INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"), + INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"), + INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100), + INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"), + INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100), + INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"), + INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100), + INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"), + + INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"), + INIT_PARAM(defer_registration, "defer system registration (for sampling)"), + + INIT_PARAM(function_trace, "Enable function trace"), + INIT_PARAM(function_trace_start, "Cycle to start function trace") + +END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU) + +CREATE_SIM_OBJECT(DerivO3CPU) +{ + DerivO3CPU *cpu; + + // In non-full-system mode, we infer the number of threads from + // the workload if it's not explicitly specified. + int actual_num_threads = + (numThreads.isValid() && numThreads >= workload.size()) ? + numThreads : workload.size(); + + if (workload.size() == 0) { + fatal("Must specify at least one workload!"); + } + + MipsSimpleParams *params = new MipsSimpleParams; + + params->clock = clock; + + params->name = getInstanceName(); + params->numberOfThreads = actual_num_threads; + params->activity = activity; + + params->workload = workload; + + params->mem = mem; + + params->checker = checker; + + params->max_insts_any_thread = max_insts_any_thread; + 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; + + // + // Caches + // + params->cachePorts = cachePorts; + + params->decodeToFetchDelay = decodeToFetchDelay; + params->renameToFetchDelay = renameToFetchDelay; + params->iewToFetchDelay = iewToFetchDelay; + params->commitToFetchDelay = commitToFetchDelay; + params->fetchWidth = fetchWidth; + + params->renameToDecodeDelay = renameToDecodeDelay; + params->iewToDecodeDelay = iewToDecodeDelay; + params->commitToDecodeDelay = commitToDecodeDelay; + params->fetchToDecodeDelay = fetchToDecodeDelay; + params->decodeWidth = decodeWidth; + + params->iewToRenameDelay = iewToRenameDelay; + params->commitToRenameDelay = commitToRenameDelay; + params->decodeToRenameDelay = decodeToRenameDelay; + params->renameWidth = renameWidth; + + params->commitToIEWDelay = commitToIEWDelay; + params->renameToIEWDelay = renameToIEWDelay; + params->issueToExecuteDelay = issueToExecuteDelay; + params->dispatchWidth = dispatchWidth; + params->issueWidth = issueWidth; + params->wbWidth = wbWidth; + params->wbDepth = wbDepth; + params->fuPool = fuPool; + + params->iewToCommitDelay = iewToCommitDelay; + params->renameToROBDelay = renameToROBDelay; + params->commitWidth = commitWidth; + params->squashWidth = squashWidth; + params->trapLatency = trapLatency; + + params->backComSize = backComSize; + params->forwardComSize = forwardComSize; + + params->predType = predType; + params->localPredictorSize = localPredictorSize; + params->localCtrBits = localCtrBits; + params->localHistoryTableSize = localHistoryTableSize; + params->localHistoryBits = localHistoryBits; + params->globalPredictorSize = globalPredictorSize; + params->globalCtrBits = globalCtrBits; + params->globalHistoryBits = globalHistoryBits; + params->choicePredictorSize = choicePredictorSize; + params->choiceCtrBits = choiceCtrBits; + + params->BTBEntries = BTBEntries; + params->BTBTagSize = BTBTagSize; + + params->RASSize = RASSize; + + params->LQEntries = LQEntries; + params->SQEntries = SQEntries; + + params->SSITSize = SSITSize; + params->LFSTSize = LFSTSize; + + params->numPhysIntRegs = numPhysIntRegs; + params->numPhysFloatRegs = numPhysFloatRegs; + params->numIQEntries = numIQEntries; + params->numROBEntries = numROBEntries; + + params->smtNumFetchingThreads = smtNumFetchingThreads; + + // Default smtFetchPolicy to "RoundRobin", if necessary. + std::string round_robin_policy = "RoundRobin"; + std::string single_thread = "SingleThread"; + + if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) + params->smtFetchPolicy = round_robin_policy; + else + params->smtFetchPolicy = smtFetchPolicy; + + params->smtIQPolicy = smtIQPolicy; + params->smtLSQPolicy = smtLSQPolicy; + params->smtLSQThreshold = smtLSQThreshold; + params->smtROBPolicy = smtROBPolicy; + params->smtROBThreshold = smtROBThreshold; + params->smtCommitPolicy = smtCommitPolicy; + + params->instShiftAmt = 2; + + params->deferRegistration = defer_registration; + + params->functionTrace = function_trace; + params->functionTraceStart = function_trace_start; + + cpu = new DerivO3CPU(params); + + return cpu; +} + +REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU) + diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh new file mode 100644 index 000000000..e08741626 --- /dev/null +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include "config/use_checker.hh" + +#include "arch/mips/faults.hh" +#include "base/cprintf.hh" +#include "base/statistics.hh" +#include "base/timebuf.hh" +#include "cpu/checker/thread_context.hh" +#include "sim/sim_events.hh" +#include "sim/stats.hh" + +#include "cpu/o3/mips/cpu.hh" +#include "cpu/o3/mips/params.hh" +#include "cpu/o3/mips/thread_context.hh" +#include "cpu/o3/comm.hh" +#include "cpu/o3/thread_state.hh" + +template <class Impl> +MipsO3CPU<Impl>::MipsO3CPU(Params *params) + : FullO3CPU<Impl>(params) +{ + DPRINTF(O3CPU, "Creating MipsO3CPU object.\n"); + + // Setup any thread state. + this->thread.resize(this->numThreads); + + for (int i = 0; i < this->numThreads; ++i) { + if (i < params->workload.size()) { + DPRINTF(O3CPU, "Workload[%i] process is %#x", + i, this->thread[i]); + this->thread[i] = new Thread(this, i, params->workload[i], + i, params->mem); + + this->thread[i]->setStatus(ThreadContext::Suspended); + + + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + TranslatingPort *trans_port; + trans_port = new TranslatingPort(csprintf("%s-%d-funcport", + name(), i), + params->workload[i]->pTable, + false); + mem_port = params->mem->getPort("functional"); + mem_port->setPeer(trans_port); + trans_port->setPeer(mem_port); + this->thread[i]->setMemPort(trans_port); + + //usedTids[i] = true; + //threadMap[i] = i; + } else { + //Allocate Empty thread so M5 can use later + //when scheduling threads to CPU + Process* dummy_proc = NULL; + + this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem); + //usedTids[i] = false; + } + + ThreadContext *tc; + + // Setup the TC that will serve as the interface to the threads/CPU. + MipsTC<Impl> *mips_tc = + new MipsTC<Impl>; + + tc = mips_tc; + + // If we're using a checker, then the TC should be the + // CheckerThreadContext. +#if USE_CHECKER + if (params->checker) { + tc = new CheckerThreadContext<MipsTC<Impl> >( + mips_tc, this->checker); + } +#endif + + mips_tc->cpu = this; + mips_tc->thread = this->thread[i]; + + // Give the thread the TC. + this->thread[i]->tc = tc; + + // Add the TC to the CPU's list of TC's. + this->threadContexts.push_back(tc); + } + + for (int i=0; i < this->numThreads; i++) { + this->thread[i]->setFuncExeInst(0); + } + + // Sets CPU pointers. These must be set at this level because the CPU + // pointers are defined to be the highest level of CPU class. + this->fetch.setCPU(this); + this->decode.setCPU(this); + this->rename.setCPU(this); + this->iew.setCPU(this); + this->commit.setCPU(this); + + this->rob.setCPU(this); + this->regFile.setCPU(this); + + lockAddr = 0; + lockFlag = false; +} + +template <class Impl> +void +MipsO3CPU<Impl>::regStats() +{ + // Register stats for everything that has stats. + this->fullCPURegStats(); + this->fetch.regStats(); + this->decode.regStats(); + this->rename.regStats(); + this->iew.regStats(); + this->commit.regStats(); +} + + +template <class Impl> +MiscReg +MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscReg(misc_reg, tid); +} + +template <class Impl> +MiscReg +MipsO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault, + unsigned tid) +{ + return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid); +} + +template <class Impl> +Fault +MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +{ + return this->regFile.setMiscReg(misc_reg, val, tid); +} + +template <class Impl> +Fault +MipsO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, + unsigned tid) +{ + return this->regFile.setMiscRegWithEffect(misc_reg, val, tid); +} + +template <class Impl> +void +MipsO3CPU<Impl>::squashFromTC(unsigned tid) +{ + this->thread[tid]->inSyscall = true; + this->commit.generateTCEvent(tid); +} + +template <class Impl> +void +MipsO3CPU<Impl>::trap(Fault fault, unsigned tid) +{ + // Pass the thread's TC into the invoke method. + fault->invoke(this->threadContexts[tid]); +} + +#if !FULL_SYSTEM + +template <class Impl> +void +MipsO3CPU<Impl>::syscall(int64_t callnum, int tid) +{ + DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); + + DPRINTF(Activity,"Activity: syscall() called.\n"); + + // Temporarily increase this by one to account for the syscall + // instruction. + ++(this->thread[tid]->funcExeInst); + + // Execute the actual syscall. + this->thread[tid]->syscall(callnum); + + // Decrease funcExeInst by one as the normal commit will handle + // incrementing it. + --(this->thread[tid]->funcExeInst); + + DPRINTF(O3CPU, "[tid:%i] Register 2 is %i ", tid, this->readIntReg(2)); +} + +template <class Impl> +TheISA::IntReg +MipsO3CPU<Impl>::getSyscallArg(int i, int tid) +{ + return this->readArchIntReg(MipsISA::ArgumentReg0 + i, tid); +} + +template <class Impl> +void +MipsO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid) +{ + this->setArchIntReg(MipsISA::ArgumentReg0 + i, val, tid); +} + +template <class Impl> +void +MipsO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) +{ + // check for error condition. + if (return_value.successful()) { + // no error + this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid); + this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid); + } else { + // got an error, return details + this->setArchIntReg(TheISA::SyscallSuccessReg, + (TheISA::IntReg) -1, tid); + this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid); + } +} +#endif diff --git a/src/cpu/o3/mips/dyn_inst.cc b/src/cpu/o3/mips/dyn_inst.cc new file mode 100755 index 000000000..216aa7d2c --- /dev/null +++ b/src/cpu/o3/mips/dyn_inst.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include "cpu/o3/mips/dyn_inst_impl.hh" +#include "cpu/o3/mips/impl.hh" + +// Force instantiation of MipsDynInst for all the implementations that +// are needed. +template class MipsDynInst<MipsSimpleImpl>; diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh new file mode 100755 index 000000000..06bdfcec4 --- /dev/null +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_O3_MIPS_DYN_INST_HH__ +#define __CPU_O3_MIPS_DYN_INST_HH__ + +#include "arch/isa_traits.hh" +#include "cpu/base_dyn_inst.hh" +#include "cpu/inst_seq.hh" +#include "cpu/o3/mips/cpu.hh" +#include "cpu/o3/mips/impl.hh" + +class Packet; + +/** + * Mostly implementation & ISA specific MipsDynInst. As with most + * other classes in the new CPU model, it is templated on the Impl to + * allow for passing in of all types, such as the CPU type and the ISA + * type. The MipsDynInst serves as the primary interface to the CPU + * for instructions that are executing. + */ +template <class Impl> +class MipsDynInst : public BaseDynInst<Impl> +{ + public: + /** Typedef for the CPU. */ + typedef typename Impl::O3CPU O3CPU; + + /** Binary machine instruction type. */ + typedef TheISA::MachInst MachInst; + /** Extended machine instruction type. */ + typedef TheISA::ExtMachInst ExtMachInst; + /** Logical register index type. */ + typedef TheISA::RegIndex RegIndex; + /** Integer register index type. */ + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + /** Misc register index type. */ + typedef TheISA::MiscReg MiscReg; + + enum { + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs + }; + + public: + /** BaseDynInst constructor given a binary instruction. */ + MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num, + O3CPU *cpu); + + /** BaseDynInst constructor given a static inst pointer. */ + MipsDynInst(StaticInstPtr &_staticInst); + + /** Executes the instruction.*/ + Fault execute(); + + /** Initiates the access. Only valid for memory operations. */ + Fault initiateAcc(); + + /** Completes the access. Only valid for memory operations. */ + Fault completeAcc(Packet *pkt); + + private: + /** Initializes variables. */ + void initVars(); + + public: + /** Reads a miscellaneous register. */ + MiscReg readMiscReg(int misc_reg) + { + return this->cpu->readMiscReg(misc_reg, this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + return this->cpu->readMiscRegWithEffect(misc_reg, fault, + this->threadNumber); + } + + /** Sets a misc. register. */ + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + return this->cpu->setMiscRegWithEffect(misc_reg, val, + this->threadNumber); + } + + /** Calls a syscall. */ + void syscall(int64_t callnum); + + private: + /** Physical register index of the destination registers of this + * instruction. + */ + PhysRegIndex _destRegIdx[MaxInstDestRegs]; + + /** Physical register index of the source registers of this + * instruction. + */ + PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; + + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; + + public: + + // The register accessor methods provide the index of the + // instruction's operand (e.g., 0 or 1), not the architectural + // register index, to simplify the implementation of register + // renaming. We find the architectural register index by indexing + // into the instruction's own operand index table. Note that a + // raw pointer to the StaticInst is provided instead of a + // ref-counted StaticInstPtr to redice overhead. This is fine as + // long as these methods don't copy the pointer into any long-term + // storage (which is pretty hard to imagine they would have reason + // to do). + + uint64_t readIntReg(const StaticInst *si, int idx) + { + return this->cpu->readIntReg(_srcRegIdx[idx]); + } + + FloatReg readFloatReg(const StaticInst *si, int idx, int width) + { + return this->cpu->readFloatReg(_srcRegIdx[idx], width); + } + + FloatReg readFloatReg(const StaticInst *si, int idx) + { + return this->cpu->readFloatReg(_srcRegIdx[idx]); + } + + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + } + + FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx]); + } + + /** @todo: Make results into arrays so they can handle multiple dest + * registers. + */ + void setIntReg(const StaticInst *si, int idx, uint64_t val) + { + this->cpu->setIntReg(_destRegIdx[idx], val); + BaseDynInst<Impl>::setIntReg(si, idx, val); + } + + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) + { + this->cpu->setFloatReg(_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatReg(si, idx, val, width); + } + + void setFloatReg(const StaticInst *si, int idx, FloatReg val) + { + this->cpu->setFloatReg(_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatReg(si, idx, val); + } + + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + BaseDynInst<Impl>::setFloatRegBits(si, idx, val); + } + + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val); + BaseDynInst<Impl>::setFloatRegBits(si, idx, val); + } + + /** Returns the physical register index of the i'th destination + * register. + */ + PhysRegIndex renamedDestRegIdx(int idx) const + { + return _destRegIdx[idx]; + } + + /** Returns the physical register index of the i'th source register. */ + PhysRegIndex renamedSrcRegIdx(int idx) const + { + return _srcRegIdx[idx]; + } + + /** Returns the physical register index of the previous physical register + * that remapped to the same logical register index. + */ + PhysRegIndex prevDestRegIdx(int idx) const + { + return _prevDestRegIdx[idx]; + } + + /** Renames a destination register to a physical register. Also records + * the previous physical register that the logical register mapped to. + */ + void renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename) + { + _destRegIdx[idx] = renamed_dest; + _prevDestRegIdx[idx] = previous_rename; + } + + /** Renames a source logical register to the physical register which + * has/will produce that logical register's result. + * @todo: add in whether or not the source register is ready. + */ + void renameSrcReg(int idx, PhysRegIndex renamed_src) + { + _srcRegIdx[idx] = renamed_src; + } + + public: + /** Calculates EA part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault calcEA() + { + return this->staticInst->eaCompInst()->execute(this, this->traceData); + } + + /** Does the memory access part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault memAccess() + { + return this->staticInst->memAccInst()->execute(this, this->traceData); + } +}; + +#endif // __CPU_O3_MIPS_DYN_INST_HH__ + diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh new file mode 100755 index 000000000..57dec1ccf --- /dev/null +++ b/src/cpu/o3/mips/dyn_inst_impl.hh @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "cpu/o3/mips/dyn_inst.hh" + +template <class Impl> +MipsDynInst<Impl>::MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu) +{ + initVars(); +} + +template <class Impl> +MipsDynInst<Impl>::MipsDynInst(StaticInstPtr &_staticInst) + : BaseDynInst<Impl>(_staticInst) +{ + initVars(); +} + +template <class Impl> +void +MipsDynInst<Impl>::initVars() +{ + // Make sure to have the renamed register entries set to the same + // as the normal register entries. It will allow the IQ to work + // without any modifications. + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + _destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } +} + +template <class Impl> +Fault +MipsDynInst<Impl>::execute() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->execute(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template <class Impl> +Fault +MipsDynInst<Impl>::initiateAcc() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->initiateAcc(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template <class Impl> +Fault +MipsDynInst<Impl>::completeAcc(Packet *pkt) +{ + this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); + + return this->fault; +} + +template <class Impl> +void +MipsDynInst<Impl>::syscall(int64_t callnum) +{ + this->cpu->syscall(callnum, this->threadNumber); +} + diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh new file mode 100644 index 000000000..ac7181a19 --- /dev/null +++ b/src/cpu/o3/mips/impl.hh @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_O3_MIPS_IMPL_HH__ +#define __CPU_O3_MIPS_IMPL_HH__ + +#include "arch/mips/isa_traits.hh" + +#include "cpu/o3/mips/params.hh" +#include "cpu/o3/cpu_policy.hh" + + +// Forward declarations. +template <class Impl> +class MipsDynInst; + +template <class Impl> +class MipsO3CPU; + +/** Implementation specific struct that defines several key types to the + * CPU, the stages within the CPU, the time buffers, and the DynInst. + * The struct defines the ISA, the CPU policy, the specific DynInst, the + * specific O3CPU, and all of the structs from the time buffers to do + * communication. + * This is one of the key things that must be defined for each hardware + * specific CPU implementation. + */ +struct MipsSimpleImpl +{ + /** The type of MachInst. */ + typedef TheISA::MachInst MachInst; + + /** The CPU policy to be used, which defines all of the CPU stages. */ + typedef SimpleCPUPolicy<MipsSimpleImpl> CPUPol; + + /** The DynInst type to be used. */ + typedef MipsDynInst<MipsSimpleImpl> DynInst; + + /** The refcounted DynInst pointer to be used. In most cases this is + * what should be used, and not DynInst *. + */ + typedef RefCountingPtr<DynInst> DynInstPtr; + + /** The O3CPU type to be used. */ + typedef MipsO3CPU<MipsSimpleImpl> O3CPU; + + /** Same typedef, but for CPUType. BaseDynInst may not always use + * an O3 CPU, so it's clearer to call it CPUType instead in that + * case. + */ + typedef O3CPU CPUType; + + /** The Params to be passed to each stage. */ + typedef MipsSimpleParams Params; + + enum { + MaxWidth = 8, + MaxThreads = 4 + }; +}; + +/** The O3Impl to be used. */ +typedef MipsSimpleImpl O3CPUImpl; + +#endif // __CPU_O3_MIPS_IMPL_HH__ diff --git a/src/cpu/o3/mips/params.hh b/src/cpu/o3/mips/params.hh new file mode 100644 index 000000000..d1ac62e21 --- /dev/null +++ b/src/cpu/o3/mips/params.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_O3_MIPS_PARAMS_HH__ +#define __CPU_O3_MIPS_PARAMS_HH__ + +#include "cpu/o3/cpu.hh" +#include "cpu/o3/params.hh" + +//Forward declarations +//class MipsDTB; +//class MipsITB; +class MemObject; +class Process; +class System; + +/** + * This file defines the parameters that will be used for the MipsO3CPU. + * This must be defined externally so that the Impl can have a params class + * defined that it can pass to all of the individual stages. + */ + +class MipsSimpleParams : public O3Params +{ + public: + MipsSimpleParams() {} + +#if FULL_SYSTEM + //Full System Paramater Objects place here + MipsITB *itb; + MipsDTB *dtb; +#endif +}; + +#endif // __CPU_O3_MIPS_PARAMS_HH__ diff --git a/src/cpu/o3/mips/thread_context.cc b/src/cpu/o3/mips/thread_context.cc new file mode 100755 index 000000000..0061a2a63 --- /dev/null +++ b/src/cpu/o3/mips/thread_context.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include "cpu/o3/thread_context.hh" +#include "cpu/o3/thread_context_impl.hh" + +template class O3ThreadContext<MipsSimpleImpl>; + diff --git a/src/cpu/o3/mips/thread_context.hh b/src/cpu/o3/mips/thread_context.hh new file mode 100644 index 000000000..26b1e2e7f --- /dev/null +++ b/src/cpu/o3/mips/thread_context.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#include "arch/mips/types.hh" +#include "cpu/o3/thread_context.hh" + +template <class Impl> +class MipsTC : public O3ThreadContext<Impl> +{ + public: + virtual uint64_t readNextNPC() + { + return this->cpu->readNextNPC(this->thread->readTid()); + } + + virtual void setNextNPC(uint64_t val) + { + this->cpu->setNextNPC(val, this->thread->readTid()); + } + + virtual void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) + { panic("Not supported on Mips!"); } + + /** This function exits the thread context in the CPU and returns + * 1 if the CPU has no more active threads (meaning it's OK to exit); + * Used in syscall-emulation mode when a thread executes the 'exit' + * syscall. + */ + virtual int exit() + { + this->deallocate(); + + // If there are still threads executing in the system + if (this->cpu->numActiveThreads()) + return 0; // don't exit simulation + else + return 1; // exit simulation + } +}; diff --git a/src/cpu/o3/ras.hh b/src/cpu/o3/ras.hh index 5c8a93285..97846ed16 100644 --- a/src/cpu/o3/ras.hh +++ b/src/cpu/o3/ras.hh @@ -31,8 +31,7 @@ #ifndef __CPU_O3_RAS_HH__ #define __CPU_O3_RAS_HH__ -// For Addr type. -#include "arch/isa_traits.hh" +#include "sim/host.hh" #include <vector> /** Return address stack class, implements a simple RAS. */ diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index b6677b4b1..512cf0721 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -33,11 +33,11 @@ #define __CPU_O3_REGFILE_HH__ #include "arch/isa_traits.hh" -#include "arch/faults.hh" #include "arch/types.hh" #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/o3/comm.hh" +#include "sim/faults.hh" #if FULL_SYSTEM #include "kern/kernel_stats.hh" diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 034087feb..ba26a01dd 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -76,6 +76,7 @@ class DefaultRename // using a list instead of a queue. (Most other stages use a // queue) typedef std::list<DynInstPtr> InstQueue; + typedef typename std::list<DynInstPtr>::iterator ListIt; public: /** Overall rename status. Used to determine if the CPU can @@ -170,7 +171,7 @@ class DefaultRename void takeOverFrom(); /** Squashes all instructions in a thread. */ - void squash(unsigned tid); + void squash(const InstSeqNum &squash_seq_num, unsigned tid); /** Ticks rename, which processes all input signals and attempts to rename * as many instructions as possible. @@ -222,7 +223,7 @@ class DefaultRename bool unblock(unsigned tid); /** Executes actual squash, removing squashed instructions. */ - void doSquash(unsigned tid); + void doSquash(const InstSeqNum &squash_seq_num, unsigned tid); /** Removes a committed instruction's rename history. */ void removeFromHistory(InstSeqNum inst_seq_num, unsigned tid); diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 805a72808..892eb12cf 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim + * Korey Sewell */ #include <list> @@ -33,8 +34,6 @@ #include "config/full_system.hh" #include "cpu/o3/rename.hh" -using namespace std; - template <class Impl> DefaultRename<Impl>::DefaultRename(Params *params) : iewToRenameDelay(params->iewToRenameDelay), @@ -222,7 +221,7 @@ DefaultRename<Impl>::initStage() template<class Impl> void -DefaultRename<Impl>::setActiveThreads(list<unsigned> *at_ptr) +DefaultRename<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(Rename, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -271,7 +270,8 @@ DefaultRename<Impl>::switchOut() { // Clear any state, fix up the rename map. for (int i = 0; i < numThreads; i++) { - typename list<RenameHistory>::iterator hb_it = historyBuffer[i].begin(); + typename std::list<RenameHistory>::iterator hb_it = + historyBuffer[i].begin(); while (!historyBuffer[i].empty()) { assert(hb_it != historyBuffer[i].end()); @@ -318,7 +318,7 @@ DefaultRename<Impl>::takeOverFrom() template <class Impl> void -DefaultRename<Impl>::squash(unsigned tid) +DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid) { DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid); @@ -341,19 +341,55 @@ DefaultRename<Impl>::squash(unsigned tid) unsigned squashCount = 0; for (int i=0; i<fromDecode->size; i++) { - if (fromDecode->insts[i]->threadNumber == tid) { + if (fromDecode->insts[i]->threadNumber == tid && + fromDecode->insts[i]->seqNum > squash_seq_num) { fromDecode->insts[i]->setSquashed(); wroteToTimeBuffer = true; squashCount++; } + } + // Clear the instruction list and skid buffer in case they have any + // insts in them. Since we support multiple ISAs, we cant just: + // "insts[tid].clear();" or "skidBuffer[tid].clear()" since there is + // a possible delay slot inst for different architectures + // insts[tid].clear(); +#if THE_ISA == ALPHA_ISA insts[tid].clear(); +#else + DPRINTF(Rename, "[tid:%i] Squashing incoming decode instructions until " + "[sn:%i].\n",tid, squash_seq_num); + ListIt ilist_it = insts[tid].begin(); + while (ilist_it != insts[tid].end()) { + if ((*ilist_it)->seqNum > squash_seq_num) { + (*ilist_it)->setSquashed(); + DPRINTF(Rename, "Squashing incoming decode instruction, " + "[tid:%i] [sn:%i] PC %08p.\n", tid, (*ilist_it)->seqNum, (*ilist_it)->PC); + } + ilist_it++; + } +#endif // Clear the skid buffer in case it has any data in it. + // See comments above. + // skidBuffer[tid].clear(); +#if THE_ISA == ALPHA_ISA skidBuffer[tid].clear(); - - doSquash(tid); +#else + DPRINTF(Rename, "[tid:%i] Squashing incoming skidbuffer instructions " + "until [sn:%i].\n", tid, squash_seq_num); + ListIt slist_it = skidBuffer[tid].begin(); + while (slist_it != skidBuffer[tid].end()) { + if ((*slist_it)->seqNum > squash_seq_num) { + (*slist_it)->setSquashed(); + DPRINTF(Rename, "Squashing skidbuffer instruction, [tid:%i] [sn:%i]" + "PC %08p.\n", tid, (*slist_it)->seqNum, (*slist_it)->PC); + } + slist_it++; + } +#endif + doSquash(squash_seq_num, tid); } template <class Impl> @@ -370,7 +406,7 @@ DefaultRename<Impl>::tick() sortInsts(); - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); // Check stall and squash signals. while (threads != (*activeThreads).end()) { @@ -572,7 +608,7 @@ DefaultRename<Impl>::renameInsts(unsigned tid) if (inst->isSquashed()) { DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is " "squashed, skipping.\n", - tid, inst->seqNum, inst->threadNumber,inst->readPC()); + tid, inst->seqNum, inst->readPC()); ++renameSquashedInsts; @@ -707,9 +743,11 @@ DefaultRename<Impl>::sortInsts() { int insts_from_decode = fromDecode->size; #ifdef DEBUG +#if THE_ISA == ALPHA_ISA for (int i=0; i < numThreads; i++) assert(insts[i].empty()); #endif +#endif for (int i = 0; i < insts_from_decode; ++i) { DynInstPtr inst = fromDecode->insts[i]; insts[inst->threadNumber].push_back(inst); @@ -720,7 +758,7 @@ template<class Impl> bool DefaultRename<Impl>::skidsEmpty() { - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { if (!skidBuffer[*threads++].empty()) @@ -736,7 +774,7 @@ DefaultRename<Impl>::updateStatus() { bool any_unblocking = false; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); threads = (*activeThreads).begin(); @@ -824,11 +862,10 @@ DefaultRename<Impl>::unblock(unsigned tid) template <class Impl> void -DefaultRename<Impl>::doSquash(unsigned tid) +DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, unsigned tid) { - typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].begin(); - - InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum; + typename std::list<RenameHistory>::iterator hb_it = + historyBuffer[tid].begin(); // After a syscall squashes everything, the history buffer may be empty // but the ROB may still be squashing instructions. @@ -866,7 +903,8 @@ DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid) "history buffer %u (size=%i), until [sn:%lli].\n", tid, tid, historyBuffer[tid].size(), inst_seq_num); - typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].end(); + typename std::list<RenameHistory>::iterator hb_it = + historyBuffer[tid].end(); --hb_it; @@ -963,8 +1001,9 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid) historyBuffer[tid].push_front(hb_entry); - DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer, " - "[sn:%lli].\n",tid, + DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer " + "(size=%i), [sn:%lli].\n",tid, + historyBuffer[tid].size(), (*historyBuffer[tid].begin()).instSeqNum); // Tell the instruction to rename the appropriate destination @@ -1143,7 +1182,13 @@ DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid) DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from " "commit.\n", tid); - squash(tid); +#if THE_ISA == ALPHA_ISA + InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum; +#else + InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].bdelayDoneSeqNum; +#endif + + squash(squashed_seq_num, tid); return true; } @@ -1258,7 +1303,7 @@ template <class Impl> void DefaultRename<Impl>::dumpHistory() { - typename list<RenameHistory>::iterator buf_it; + typename std::list<RenameHistory>::iterator buf_it; for (int i = 0; i < numThreads; i++) { diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh index c4c90c99a..896c66f3e 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -40,8 +40,7 @@ #include <vector> #include "cpu/o3/free_list.hh" -//For RegIndex -#include "arch/isa_traits.hh" +#include "arch/types.hh" class SimpleRenameMap { diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh index 1b9f666b8..fab114a74 100644 --- a/src/cpu/o3/rob_impl.hh +++ b/src/cpu/o3/rob_impl.hh @@ -32,11 +32,11 @@ #include "config/full_system.hh" #include "cpu/o3/rob.hh" -using namespace std; +#include <list> template <class Impl> ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth, - string _smtROBPolicy, unsigned _smtROBThreshold, + std::string _smtROBPolicy, unsigned _smtROBThreshold, unsigned _numThreads) : numEntries(_numEntries), squashWidth(_squashWidth), @@ -49,7 +49,7 @@ ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth, threadEntries[tid] = 0; } - string policy = _smtROBPolicy; + std::string policy = _smtROBPolicy; //Convert string to lowercase std::transform(policy.begin(), policy.end(), policy.begin(), @@ -118,7 +118,7 @@ ROB<Impl>::setCPU(O3CPU *cpu_ptr) template <class Impl> void -ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr) +ROB<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) { DPRINTF(ROB, "Setting active threads list pointer.\n"); activeThreads = at_ptr; @@ -157,8 +157,8 @@ ROB<Impl>::resetEntries() if (robPolicy != Dynamic || numThreads > 1) { int active_threads = (*activeThreads).size(); - list<unsigned>::iterator threads = (*activeThreads).begin(); - list<unsigned>::iterator list_end = (*activeThreads).end(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator list_end = (*activeThreads).end(); while (threads != list_end) { if (robPolicy == Partitioned) { @@ -318,7 +318,7 @@ bool ROB<Impl>::canCommit() { //@todo: set ActiveThreads through ROB or CPU - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; @@ -432,7 +432,7 @@ ROB<Impl>::updateHead() bool first_valid = true; // @todo: set ActiveThreads through ROB or CPU - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned thread_num = *threads++; @@ -472,7 +472,7 @@ ROB<Impl>::updateTail() tail = instList[0].end(); bool first_valid = true; - list<unsigned>::iterator threads = (*activeThreads).begin(); + std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { unsigned tid = *threads++; diff --git a/src/cpu/o3/scoreboard.hh b/src/cpu/o3/scoreboard.hh index f8e4df3b7..eefff1d8b 100644 --- a/src/cpu/o3/scoreboard.hh +++ b/src/cpu/o3/scoreboard.hh @@ -35,7 +35,6 @@ #include <iostream> #include <utility> #include <vector> -#include "arch/alpha/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "cpu/o3/comm.hh" diff --git a/src/cpu/o3/store_set.hh b/src/cpu/o3/store_set.hh index f5a44a1ac..f9f7637d0 100644 --- a/src/cpu/o3/store_set.hh +++ b/src/cpu/o3/store_set.hh @@ -36,8 +36,8 @@ #include <utility> #include <vector> -#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" +#include "sim/host.hh" struct ltseqnum { bool operator()(const InstSeqNum &lhs, const InstSeqNum &rhs) const diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index df8d1a6d8..9ca02b9f3 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -26,12 +26,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim - * Korey Sewell */ #ifndef __CPU_O3_THREAD_CONTEXT_HH__ #define __CPU_O3_THREAD_CONTEXT_HH__ +#include "cpu/thread_context.hh" #include "cpu/o3/isa_specific.hh" class EndQuiesceEvent; diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index bf8cbf850..a4546e669 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -32,8 +32,6 @@ #include "cpu/o3/thread_context.hh" #include "cpu/quiesce_event.hh" -using namespace TheISA; - #if FULL_SYSTEM template <class Impl> VirtualPort * @@ -285,7 +283,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) } // Copy the misc regs. - copyMiscRegs(tc, this); + TheISA::copyMiscRegs(tc, this); // Then finally set the PC and the next PC. cpu->setPC(tc->readPC(), tid); @@ -308,7 +306,7 @@ O3ThreadContext<Impl>::readIntReg(int reg_idx) } template <class Impl> -FloatReg +TheISA::FloatReg O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) { switch(width) { @@ -323,14 +321,14 @@ O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) } template <class Impl> -FloatReg +TheISA::FloatReg O3ThreadContext<Impl>::readFloatReg(int reg_idx) { return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); } template <class Impl> -FloatRegBits +TheISA::FloatRegBits O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) { DPRINTF(Fault, "Reading floatint register through the TC!\n"); @@ -338,7 +336,7 @@ O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) } template <class Impl> -FloatRegBits +TheISA::FloatRegBits O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) { return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index 1c8105204..b6f2e14c0 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -31,8 +31,6 @@ #ifndef __CPU_O3_THREAD_STATE_HH__ #define __CPU_O3_THREAD_STATE_HH__ -#include "arch/faults.hh" -#include "arch/isa_traits.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" diff --git a/src/cpu/o3/tournament_pred.hh b/src/cpu/o3/tournament_pred.hh index 92402adc6..66b4aaae2 100644 --- a/src/cpu/o3/tournament_pred.hh +++ b/src/cpu/o3/tournament_pred.hh @@ -31,9 +31,8 @@ #ifndef __CPU_O3_TOURNAMENT_PRED_HH__ #define __CPU_O3_TOURNAMENT_PRED_HH__ -// For Addr type. -#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" +#include "sim/host.hh" #include <vector> /** diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index f58b81990..80f18434c 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -47,6 +47,7 @@ #include "arch/faults.hh" #include "arch/alpha/osfpal.hh" #include "arch/alpha/tlb.hh" +#include "arch/alpha/types.hh" #include "arch/vtophys.hh" #include "base/callback.hh" //#include "base/remote_gdb.hh" diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 67691d416..75ac464ec 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -32,6 +32,7 @@ #define __CPU_OZONE_DYN_INST_HH__ #include "arch/isa_traits.hh" +#include "arch/types.hh" #include "config/full_system.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index bad902c2a..ba0d70417 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -29,13 +29,10 @@ */ #include "arch/faults.hh" -#include "arch/isa_traits.hh" #include "config/full_system.hh" #include "cpu/ozone/dyn_inst.hh" #include "kern/kernel_stats.hh" -using namespace TheISA; - template <class Impl> OzoneDynInst<Impl>::OzoneDynInst(OzoneCPU *cpu) : BaseDynInst<Impl>(0, 0, 0, 0, cpu) diff --git a/src/cpu/ozone/ea_list.hh b/src/cpu/ozone/ea_list.hh index 64882632c..d9e9d701f 100644 --- a/src/cpu/ozone/ea_list.hh +++ b/src/cpu/ozone/ea_list.hh @@ -35,8 +35,8 @@ #include <list> #include <utility> -#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" +#include "sim/host.hh" /** * Simple class to hold onto a list of pairs, each pair having a memory diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 9da937320..c9c5a869b 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -32,6 +32,7 @@ #include "arch/faults.hh" #include "arch/isa_traits.hh" +#include "arch/utility.hh" #include "base/statistics.hh" #include "cpu/thread_context.hh" #include "cpu/exetrace.hh" diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index cbb73364e..701fc0ee9 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -29,12 +29,10 @@ */ #include "arch/faults.hh" -#include "arch/isa_traits.hh" +#include "arch/types.hh" #include "cpu/ozone/inorder_back_end.hh" #include "cpu/ozone/thread_state.hh" -using namespace TheISA; - template <class Impl> InorderBackEnd<Impl>::InorderBackEnd(Params *params) : squashPending(false), diff --git a/src/cpu/ozone/lsq_unit.hh b/src/cpu/ozone/lsq_unit.hh index 1b5340e55..38c1c09a2 100644 --- a/src/cpu/ozone/lsq_unit.hh +++ b/src/cpu/ozone/lsq_unit.hh @@ -36,7 +36,7 @@ #include <algorithm> #include "arch/faults.hh" -#include "arch/isa_traits.hh" +#include "arch/types.hh" #include "config/full_system.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/ozone/lsq_unit_impl.hh b/src/cpu/ozone/lsq_unit_impl.hh index f8cb18634..ee0804036 100644 --- a/src/cpu/ozone/lsq_unit_impl.hh +++ b/src/cpu/ozone/lsq_unit_impl.hh @@ -28,7 +28,7 @@ * Authors: Kevin Lim */ -#include "arch/isa_traits.hh" +#include "arch/faults.hh" #include "base/str.hh" #include "cpu/ozone/lsq_unit.hh" diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 2eb09d01a..9a21a9d01 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -37,7 +37,7 @@ #include <algorithm> #include "arch/faults.hh" -#include "arch/isa_traits.hh" +#include "arch/types.hh" #include "config/full_system.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 88e9c218f..7eef4b11f 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -30,7 +30,7 @@ #include "config/use_checker.hh" -#include "arch/isa_traits.hh" +#include "arch/faults.hh" #include "base/str.hh" #include "cpu/ozone/lw_lsq.hh" #include "cpu/checker/cpu.hh" diff --git a/src/cpu/ozone/null_predictor.hh b/src/cpu/ozone/null_predictor.hh index a98c89d69..0751338b7 100644 --- a/src/cpu/ozone/null_predictor.hh +++ b/src/cpu/ozone/null_predictor.hh @@ -31,8 +31,8 @@ #ifndef __CPU_OZONE_NULL_PREDICTOR_HH__ #define __CPU_OZONE_NULL_PREDICTOR_HH__ -#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" +#include "sim/host.hh" template <class Impl> class NullPredictor diff --git a/src/cpu/ozone/ozone_impl.hh b/src/cpu/ozone/ozone_impl.hh index 503675738..2271cd68a 100644 --- a/src/cpu/ozone/ozone_impl.hh +++ b/src/cpu/ozone/ozone_impl.hh @@ -31,7 +31,6 @@ #ifndef __CPU_OZONE_OZONE_IMPL_HH__ #define __CPU_OZONE_OZONE_IMPL_HH__ -#include "arch/alpha/isa_traits.hh" #include "cpu/o3/bpred_unit.hh" #include "cpu/ozone/front_end.hh" #include "cpu/ozone/inst_queue.hh" diff --git a/src/cpu/ozone/simple_impl.hh b/src/cpu/ozone/simple_impl.hh index 3199d8d8a..42002180b 100644 --- a/src/cpu/ozone/simple_impl.hh +++ b/src/cpu/ozone/simple_impl.hh @@ -31,7 +31,6 @@ #ifndef __CPU_OZONE_SIMPLE_IMPL_HH__ #define __CPU_OZONE_SIMPLE_IMPL_HH__ -#include "arch/isa_traits.hh" #include "cpu/o3/bpred_unit.hh" #include "cpu/ozone/cpu.hh" #include "cpu/ozone/front_end.hh" diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index ef4b1429d..8234cf938 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -32,7 +32,8 @@ #define __CPU_OZONE_THREAD_STATE_HH__ #include "arch/faults.hh" -#include "arch/isa_traits.hh" +#include "arch/types.hh" +#include "arch/regfile.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" #include "sim/process.hh" diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 12bfdeb9b..c396f5033 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -33,6 +33,7 @@ #include "cpu/simple/atomic.hh" #include "mem/packet_impl.hh" #include "sim/builder.hh" +#include "sim/system.hh" using namespace std; using namespace TheISA; @@ -158,18 +159,31 @@ AtomicSimpleCPU::~AtomicSimpleCPU() void AtomicSimpleCPU::serialize(ostream &os) { - SERIALIZE_ENUM(_status); - BaseSimpleCPU::serialize(os); + SimObject::State so_state = SimObject::getState(); + SERIALIZE_ENUM(so_state); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); + BaseSimpleCPU::serialize(os); } void AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { - UNSERIALIZE_ENUM(_status); - BaseSimpleCPU::unserialize(cp, section); + SimObject::State so_state; + UNSERIALIZE_ENUM(so_state); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); + BaseSimpleCPU::unserialize(cp, section); +} + +void +AtomicSimpleCPU::resume() +{ + assert(system->getMemoryMode() == System::Atomic); + changeState(SimObject::Running); + if (thread->status() == ThreadContext::Active) { + if (!tickEvent.scheduled()) + tickEvent.schedule(curTick); + } } void @@ -451,11 +465,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU) Param<Counter> max_loads_any_thread; Param<Counter> max_loads_all_threads; SimObjectParam<MemObject *> mem; + SimObjectParam<System *> system; #if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; - SimObjectParam<System *> system; Param<int> cpu_id; Param<Tick> profile; #else @@ -483,11 +497,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU) INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), INIT_PARAM(mem, "memory"), + INIT_PARAM(system, "system object"), #if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(profile, ""), #else @@ -520,11 +534,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU) params->width = width; params->simulate_stalls = simulate_stalls; params->mem = mem; + params->system = system; #if FULL_SYSTEM params->itb = itb; params->dtb = dtb; - params->system = system; params->cpu_id = cpu_id; params->profile = profile; #else diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 179b4a721..b602af558 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -126,6 +126,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); + virtual void resume(); void switchOut(); void takeOverFrom(BaseCPU *oldCPU); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index a50541189..801c96c88 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -26,10 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Steve Reinhardt - * Korey Sewell */ #include "arch/utility.hh" +#include "arch/faults.hh" #include "base/cprintf.hh" #include "base/inifile.hh" #include "base/loader/symtab.hh" @@ -55,10 +55,10 @@ #include "sim/sim_events.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" +#include "sim/system.hh" #if FULL_SYSTEM #include "base/remote_gdb.hh" -#include "sim/system.hh" #include "arch/tlb.hh" #include "arch/stacktrace.hh" #include "arch/vtophys.hh" @@ -178,8 +178,8 @@ void BaseSimpleCPU::serialize(ostream &os) { BaseCPU::serialize(os); - SERIALIZE_SCALAR(inst); - nameOut(os, csprintf("%s.xc", name())); +// SERIALIZE_SCALAR(inst); + nameOut(os, csprintf("%s.xc.0", name())); thread->serialize(os); } @@ -187,8 +187,8 @@ void BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { BaseCPU::unserialize(cp, section); - UNSERIALIZE_SCALAR(inst); - thread->unserialize(cp, csprintf("%s.xc", section)); +// UNSERIALIZE_SCALAR(inst); + thread->unserialize(cp, csprintf("%s.xc.0", section)); } void @@ -455,6 +455,7 @@ BaseSimpleCPU::advancePC(Fault fault) #else thread->setNextPC(thread->readNextNPC()); thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); + assert(thread->readNextPC() != thread->readNextNPC()); #endif } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index e55301c6b..5c1654f7e 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -33,6 +33,7 @@ #include "cpu/simple/timing.hh" #include "mem/packet_impl.hh" #include "sim/builder.hh" +#include "sim/system.hh" using namespace std; using namespace TheISA; @@ -84,14 +85,22 @@ TimingSimpleCPU::CpuPort::recvStatusChange(Status status) panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); } + +void +TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t) +{ + pkt = _pkt; + Event::schedule(t); +} + TimingSimpleCPU::TimingSimpleCPU(Params *p) - : BaseSimpleCPU(p), icachePort(this), dcachePort(this) + : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock) { _status = Idle; ifetch_pkt = dcache_pkt = NULL; drainEvent = NULL; fetchEvent = NULL; - state = SimObject::Timing; + changeState(SimObject::Running); } @@ -102,29 +111,31 @@ TimingSimpleCPU::~TimingSimpleCPU() void TimingSimpleCPU::serialize(ostream &os) { - SERIALIZE_ENUM(_status); + SimObject::State so_state = SimObject::getState(); + SERIALIZE_ENUM(so_state); BaseSimpleCPU::serialize(os); } void TimingSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { - UNSERIALIZE_ENUM(_status); + SimObject::State so_state; + UNSERIALIZE_ENUM(so_state); BaseSimpleCPU::unserialize(cp, section); } -bool +unsigned int TimingSimpleCPU::drain(Event *drain_event) { // TimingSimpleCPU is ready to drain if it's not waiting for // an access to complete. if (status() == Idle || status() == Running || status() == SwitchedOut) { - changeState(SimObject::DrainedTiming); - return true; + changeState(SimObject::Drained); + return 0; } else { changeState(SimObject::Draining); drainEvent = drain_event; - return false; + return 1; } } @@ -134,7 +145,9 @@ TimingSimpleCPU::resume() if (_status != SwitchedOut && _status != Idle) { // Delete the old event if it existed. if (fetchEvent) { - assert(!fetchEvent->scheduled()); + if (fetchEvent->scheduled()) + fetchEvent->deschedule(); + delete fetchEvent; } @@ -142,12 +155,9 @@ TimingSimpleCPU::resume() new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); fetchEvent->schedule(curTick); } -} -void -TimingSimpleCPU::setMemoryMode(State new_mode) -{ - assert(new_mode == SimObject::Timing); + assert(system->getMemoryMode() == System::Timing); + changeState(SimObject::Running); } void @@ -460,11 +470,26 @@ TimingSimpleCPU::completeIfetch(Packet *pkt) } } +void +TimingSimpleCPU::IcachePort::ITickEvent::process() +{ + cpu->completeIfetch(pkt); +} bool TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) { - cpu->completeIfetch(pkt); + // These next few lines could be replaced with something faster + // who knows what though + Tick time = pkt->req->getTime(); + while (time < curTick) + time += lat; + + if (time == curTick) + cpu->completeIfetch(pkt); + else + tickEvent.schedule(pkt, time); + return true; } @@ -514,18 +539,32 @@ void TimingSimpleCPU::completeDrain() { DPRINTF(Config, "Done draining\n"); - changeState(SimObject::DrainedTiming); + changeState(SimObject::Drained); drainEvent->process(); } bool TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt) { - cpu->completeDataAccess(pkt); + Tick time = pkt->req->getTime(); + while (time < curTick) + time += lat; + + if (time == curTick) + cpu->completeDataAccess(pkt); + else + tickEvent.schedule(pkt, time); + return true; } void +TimingSimpleCPU::DcachePort::DTickEvent::process() +{ + cpu->completeDataAccess(pkt); +} + +void TimingSimpleCPU::DcachePort::recvRetry() { // we shouldn't get a retry unless we have a packet that we're @@ -551,11 +590,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU) Param<Counter> max_loads_any_thread; Param<Counter> max_loads_all_threads; SimObjectParam<MemObject *> mem; + SimObjectParam<System *> system; #if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; - SimObjectParam<System *> system; Param<int> cpu_id; Param<Tick> profile; #else @@ -583,11 +622,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU) INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), INIT_PARAM(mem, "memory"), + INIT_PARAM(system, "system object"), #if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(profile, ""), #else @@ -618,11 +657,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU) params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; params->mem = mem; + params->system = system; #if FULL_SYSTEM params->itb = itb; params->dtb = dtb; - params->system = system; params->cpu_id = cpu_id; params->profile = profile; #else diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 0a3f91e6c..d03fa4bc0 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -74,11 +74,12 @@ class TimingSimpleCPU : public BaseSimpleCPU { protected: TimingSimpleCPU *cpu; + Tick lat; public: - CpuPort(const std::string &_name, TimingSimpleCPU *_cpu) - : Port(_name), cpu(_cpu) + CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat) + : Port(_name), cpu(_cpu), lat(_lat) { } protected: @@ -92,14 +93,26 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) { resp.clear(); snoop.clear(); } + + struct TickEvent : public Event + { + Packet *pkt; + TimingSimpleCPU *cpu; + + TickEvent(TimingSimpleCPU *_cpu) + :Event(&mainEventQueue), cpu(_cpu) {} + const char *description() { return "Timing CPU clock event"; } + void schedule(Packet *_pkt, Tick t); + }; + }; class IcachePort : public CpuPort { public: - IcachePort(TimingSimpleCPU *_cpu) - : CpuPort(_cpu->name() + "-iport", _cpu) + IcachePort(TimingSimpleCPU *_cpu, Tick _lat) + : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu) { } protected: @@ -107,14 +120,26 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual bool recvTiming(Packet *pkt); virtual void recvRetry(); + + struct ITickEvent : public TickEvent + { + + ITickEvent(TimingSimpleCPU *_cpu) + : TickEvent(_cpu) {} + void process(); + const char *description() { return "Timing CPU clock event"; } + }; + + ITickEvent tickEvent; + }; class DcachePort : public CpuPort { public: - DcachePort(TimingSimpleCPU *_cpu) - : CpuPort(_cpu->name() + "-dport", _cpu) + DcachePort(TimingSimpleCPU *_cpu, Tick _lat) + : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) { } protected: @@ -122,6 +147,17 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual bool recvTiming(Packet *pkt); virtual void recvRetry(); + + struct DTickEvent : public TickEvent + { + DTickEvent(TimingSimpleCPU *_cpu) + : TickEvent(_cpu) {} + void process(); + const char *description() { return "Timing CPU clock event"; } + }; + + DTickEvent tickEvent; + }; IcachePort icachePort; @@ -137,9 +173,8 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - virtual bool drain(Event *drain_event); + virtual unsigned int drain(Event *drain_event); virtual void resume(); - virtual void setMemoryMode(State new_mode); void switchOut(); void takeOverFrom(BaseCPU *oldCPU); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index af1db2ff2..5f86cf2b7 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -196,6 +196,7 @@ SimpleThread::copyState(ThreadContext *oldContext) #if !FULL_SYSTEM funcExeInst = oldContext->readFuncExeInst(); #endif + inst = oldContext->getInst(); } void diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index d36853db4..242cfd0e1 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -449,8 +449,8 @@ class SimpleThread : public ThreadState } #endif - void changeRegFileContext(RegFile::ContextParam param, - RegFile::ContextVal val) + void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) { regs.changeContext(param, val); } diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index ea1a65148..578d14191 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -34,14 +34,16 @@ #include <bitset> #include <string> +#include "arch/isa_traits.hh" +#include "sim/faults.hh" #include "base/bitfield.hh" #include "base/hashmap.hh" #include "base/misc.hh" #include "base/refcnt.hh" #include "cpu/op_class.hh" #include "cpu/o3/dyn_inst.hh" +#include "sim/faults.hh" #include "sim/host.hh" -#include "arch/isa_traits.hh" // forward declarations struct AlphaSimpleImpl; @@ -214,6 +216,7 @@ class StaticInstBase : public RefCounted bool isIndirectCtrl() const { return flags[IsIndirectControl]; } bool isCondCtrl() const { return flags[IsCondControl]; } bool isUncondCtrl() const { return flags[IsUncondControl]; } + bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; } bool isThreadSync() const { return flags[IsThreadSync]; } bool isSerializing() const { return flags[IsSerializing] || diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index e019e22bc..73046097d 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -31,6 +31,9 @@ #ifndef __CPU_THREAD_CONTEXT_HH__ #define __CPU_THREAD_CONTEXT_HH__ +#include "arch/types.hh" +#include "arch/regfile.hh" +#include "arch/syscallreturn.hh" #include "config/full_system.hh" #include "mem/request.hh" #include "sim/faults.hh" @@ -254,8 +257,8 @@ class ThreadContext virtual int exit() { return 1; }; #endif - virtual void changeRegFileContext(RegFile::ContextParam param, - RegFile::ContextVal val) = 0; + virtual void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) = 0; }; /** @@ -438,8 +441,8 @@ class ProxyThreadContext : public ThreadContext Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif - void changeRegFileContext(RegFile::ContextParam param, - RegFile::ContextVal val) + void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) { actualTC->changeRegFileContext(param, val); } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index b03a2e2bb..6e985054f 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -31,7 +31,7 @@ #ifndef __CPU_THREAD_STATE_HH__ #define __CPU_THREAD_STATE_HH__ -#include "arch/isa_traits.hh" +#include "arch/types.hh" #include "cpu/thread_context.hh" #if !FULL_SYSTEM diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index 5ffc02d34..e8d7f4817 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -756,6 +756,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) Param<uint32_t> pci_dev; Param<uint32_t> pci_func; Param<Tick> pio_latency; + Param<Tick> config_latency; SimObjectVectorParam<IdeDisk *> disks; END_DECLARE_SIM_OBJECT_PARAMS(IdeController) @@ -769,6 +770,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(config_latency, "Number of cycles for a config read or write"), INIT_PARAM(disks, "IDE disks attached to this controller") END_INIT_SIM_OBJECT_PARAMS(IdeController) @@ -784,6 +786,7 @@ CREATE_SIM_OBJECT(IdeController) params->deviceNum = pci_dev; params->functionNum = pci_func; params->pio_delay = pio_latency; + params->config_delay = config_latency; params->disks = disks; return new IdeController(params); } diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index dc78021f8..12564ddd0 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -318,7 +318,7 @@ IdeDisk::doDmaTransfer() panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n", dmaState, devState); - if (ctrl->dmaPending()) { + if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); return; } else @@ -398,8 +398,7 @@ IdeDisk::doDmaRead() curPrd.getByteCount(), TheISA::PageBytes); } - if (ctrl->dmaPending()) { - panic("shouldn't be reentant??"); + if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaReadCG->done()) { @@ -474,8 +473,7 @@ IdeDisk::doDmaWrite() dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(), curPrd.getByteCount(), TheISA::PageBytes); } - if (ctrl->dmaPending()) { - panic("shouldn't be reentant??"); + if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaWriteCG->done()) { diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index cb4850108..b51a93190 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -32,10 +32,11 @@ #include "base/trace.hh" #include "dev/io_device.hh" #include "sim/builder.hh" +#include "sim/system.hh" -PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname) - : Port(dev->name() + pname), device(dev), platform(p) +PioPort::PioPort(PioDevice *dev, System *s, std::string pname) + : SimpleTimingPort(dev->name() + pname), device(dev), sys(s) { } @@ -59,38 +60,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) } -void -PioPort::recvRetry() -{ - bool result = true; - while (result && transmitList.size()) { - result = Port::sendTiming(transmitList.front()); - if (result) - transmitList.pop_front(); - } -} - -void -PioPort::SendEvent::process() -{ - if (port->Port::sendTiming(packet)) - return; - - port->transmitList.push_back(packet); -} - -void -PioPort::resendNacked(Packet *pkt) { - pkt->reinitNacked(); - if (transmitList.size()) { - transmitList.push_front(pkt); - } else { - if (!Port::sendTiming(pkt)) - transmitList.push_front(pkt); - } -}; - - bool PioPort::recvTiming(Packet *pkt) { @@ -119,6 +88,19 @@ PioDevice::init() pioPort->sendStatusChange(Port::RangeChange); } + +unsigned int +PioDevice::drain(Event *de) +{ + unsigned int count; + count = pioPort->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} + void BasicPioDevice::addressRanges(AddrRangeList &range_list) { @@ -128,8 +110,9 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list) } -DmaPort::DmaPort(DmaDevice *dev, Platform *p) - : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) +DmaPort::DmaPort(DmaDevice *dev, System *s) + : Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0), + actionInProgress(0), drainEvent(NULL) { } bool @@ -159,6 +142,11 @@ DmaPort::recvTiming(Packet *pkt) } delete pkt->req; delete pkt; + + if (pendingCount == 0 && drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } } else { panic("Got packet without sender state... huh?\n"); } @@ -170,6 +158,29 @@ DmaDevice::DmaDevice(Params *p) : PioDevice(p), dmaPort(NULL) { } + +unsigned int +DmaDevice::drain(Event *de) +{ + unsigned int count; + count = pioPort->drain(de) + dmaPort->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} + +unsigned int +DmaPort::drain(Event *de) +{ + if (pendingCount == 0) + return 0; + drainEvent = de; + return 1; +} + + void DmaPort::recvRetry() { @@ -195,6 +206,8 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, { assert(event); + assert(device->getState() == SimObject::Running); + DmaReqState *reqState = new DmaReqState(event, this, size); for (ChunkGenerator gen(addr, size, peerBlockSize()); @@ -212,51 +225,54 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, pendingCount++; sendDma(pkt); } + } void DmaPort::sendDma(Packet *pkt, bool front) { - // some kind of selction between access methods - // more work is going to have to be done to make - // switching actually work - /* MemState state = device->platform->system->memState; - - if (state == Timing) { */ - DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n", - pkt, pkt->getAddr()); - if (transmitList.size() || !sendTiming(pkt)) { - if (front) - transmitList.push_front(pkt); - else - transmitList.push_back(pkt); - DPRINTF(DMA, "-- Failed: queued\n"); - } else { - DPRINTF(DMA, "-- Done\n"); - } - /* } else if (state == Atomic) { - sendAtomic(pkt); - if (pkt->senderState) { - DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); - assert(state); - state->completionEvent->schedule(curTick + (pkt->time - - pkt->req->getTime()) +1); - delete state; - } - pendingCount--; - assert(pendingCount >= 0); - delete pkt->req; - delete pkt; - - } else if (state == Functional) { - sendFunctional(pkt); - // Is this correct??? - completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime); - completionEvent == NULL; + // some kind of selction between access methods + // more work is going to have to be done to make + // switching actually work + + System::MemoryMode state = sys->getMemoryMode(); + if (state == System::Timing) { + DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n", + pkt, pkt->getAddr()); + if (transmitList.size() || !sendTiming(pkt)) { + if (front) + transmitList.push_front(pkt); + else + transmitList.push_back(pkt); + DPRINTF(DMA, "-- Failed: queued\n"); + } else { + DPRINTF(DMA, "-- Done\n"); + } + } else if (state == System::Atomic) { + Tick lat; + lat = sendAtomic(pkt); + assert(pkt->senderState); + DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); + assert(state); + + state->numBytes += pkt->req->getSize(); + if (state->totBytes == state->numBytes) { + state->completionEvent->schedule(curTick + lat); + delete state; + delete pkt->req; + } + pendingCount--; + assert(pendingCount >= 0); + delete pkt; + + if (pendingCount == 0 && drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } + } else panic("Unknown memory command state."); - */ } DmaDevice::~DmaDevice() diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 40edf6875..710b22b2c 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -37,6 +37,7 @@ #include "mem/packet_impl.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" +#include "mem/tport.hh" class Platform; class PioDevice; @@ -48,25 +49,17 @@ class System; * sensitive to an address range use. The port takes all the memory * access types and roles them into one read() and write() call that the device * must respond to. The device must also provide the addressRanges() function - * with which it returns the address ranges it is interested in. An extra - * sendTiming() function is implemented which takes an delay. In this way the - * device can immediatly call sendTiming(pkt, time) after processing a request - * and the request will be handled by the port even if the port bus the device - * connects to is blocked. - */ -class PioPort : public Port + * with which it returns the address ranges it is interested in. */ + +class PioPort : public SimpleTimingPort { protected: /** The device that this port serves. */ PioDevice *device; - /** The platform that device/port are in. This is used to select which mode + /** The system that device/port are in. This is used to select which mode * we are currently operating in. */ - Platform *platform; - - /** A list of outgoing timing response packets that haven't been serviced - * yet. */ - std::list<Packet*> transmitList; + System *sys; /** The current status of the peer(bus) that we are connected to. */ Status peerStatus; @@ -82,42 +75,9 @@ class PioPort : public Port virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); - void resendNacked(Packet *pkt); - - /** - * This class is used to implemented sendTiming() with a delay. When a delay - * is requested a new event is created. When the event time expires it - * attempts to send the packet. If it cannot, the packet is pushed onto the - * transmit list to be sent when recvRetry() is called. */ - class SendEvent : public Event - { - PioPort *port; - Packet *packet; - - SendEvent(PioPort *p, Packet *pkt, Tick t) - : Event(&mainEventQueue), port(p), packet(pkt) - { schedule(curTick + t); } - - virtual void process(); - - virtual const char *description() - { return "Future scheduled sendTiming event"; } - - friend class PioPort; - }; - - /** Schedule a sendTiming() event to be called in the future. */ - void sendTiming(Packet *pkt, Tick time) - { new PioPort::SendEvent(this, pkt, time); } - - /** This function is notification that the device should attempt to send a - * packet again. */ - virtual void recvRetry(); - public: - PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport"); + PioPort(PioDevice *dev, System *s, std::string pname = "-pioport"); - friend class PioPort::SendEvent; }; @@ -147,13 +107,20 @@ class DmaPort : public Port DmaDevice *device; std::list<Packet*> transmitList; - /** The platform that device/port are in. This is used to select which mode + /** The system that device/port are in. This is used to select which mode * we are currently operating in. */ - Platform *platform; + System *sys; /** Number of outstanding packets the dma port has. */ int pendingCount; + /** If a dmaAction is in progress. */ + int actionInProgress; + + /** If we need to drain, keep the drain event around until we're done + * here.*/ + Event *drainEvent; + virtual bool recvTiming(Packet *pkt); virtual Tick recvAtomic(Packet *pkt) { panic("dma port shouldn't be used for pio access."); } @@ -171,13 +138,14 @@ class DmaPort : public Port void sendDma(Packet *pkt, bool front = false); public: - DmaPort(DmaDevice *dev, Platform *p); + DmaPort(DmaDevice *dev, System *s); void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data = NULL); bool dmaPending() { return pendingCount > 0; } + unsigned int drain(Event *de); }; /** @@ -196,6 +164,8 @@ class PioDevice : public MemObject * transaction we should perform. */ Platform *platform; + System *sys; + /** The pioPort that handles the requests for us and provides us requests * that it sees. */ PioPort *pioPort; @@ -240,20 +210,22 @@ class PioDevice : public MemObject const Params *params() const { return _params; } PioDevice(Params *p) - : MemObject(p->name), platform(p->platform), pioPort(NULL), - _params(p) + : MemObject(p->name), platform(p->platform), sys(p->system), + pioPort(NULL), _params(p) {} virtual ~PioDevice(); virtual void init(); + virtual unsigned int drain(Event *de); + virtual Port *getPort(const std::string &if_name, int idx = -1) { if (if_name == "pio") { if (pioPort != NULL) panic("pio port already connected to."); - pioPort = new PioPort(this, params()->platform); + pioPort = new PioPort(this, sys); return pioPort; } else return NULL; @@ -287,7 +259,7 @@ class BasicPioDevice : public PioDevice {} /** return the address ranges that this device responds to. - * @params range_list range list to populate with ranges + * @param range_list range list to populate with ranges */ void addressRanges(AddrRangeList &range_list); @@ -310,17 +282,19 @@ class DmaDevice : public PioDevice bool dmaPending() { return dmaPort->dmaPending(); } + virtual unsigned int drain(Event *de); + virtual Port *getPort(const std::string &if_name, int idx = -1) { if (if_name == "pio") { if (pioPort != NULL) panic("pio port already connected to."); - pioPort = new PioPort(this, params()->platform); + pioPort = new PioPort(this, sys); return pioPort; } else if (if_name == "dma") { if (dmaPort != NULL) panic("dma port already connected to."); - dmaPort = new DmaPort(this, params()->platform); + dmaPort = new DmaPort(this, sys); return dmaPort; } else return NULL; diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh index a7a469e17..5166882f8 100644 --- a/src/dev/isa_fake.hh +++ b/src/dev/isa_fake.hh @@ -65,14 +65,14 @@ class IsaFake : public BasicPioDevice /** * This read always returns -1. - * @param req The memory request. + * @param pkt The memory request. * @param data Where to put the data. */ virtual Tick read(Packet *pkt); /** * All writes are simply ignored. - * @param req The memory request. + * @param pkt The memory request. * @param data the data to not write. */ virtual Tick write(Packet *pkt); diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 179a2c62d..704afcf7d 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -1377,7 +1377,7 @@ NSGigE::doRxDmaRead() assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); rxDmaState = dmaReading; - if (dmaPending()) + if (dmaPending() || getState() != Running) rxDmaState = dmaReadWaiting; else dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); @@ -1408,7 +1408,7 @@ NSGigE::doRxDmaWrite() assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); rxDmaState = dmaWriting; - if (dmaPending()) + if (dmaPending() || getState() != Running) rxDmaState = dmaWriteWaiting; else dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); @@ -1826,7 +1826,7 @@ NSGigE::doTxDmaRead() assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); txDmaState = dmaReading; - if (dmaPending()) + if (dmaPending() || getState() != Running) txDmaState = dmaReadWaiting; else dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); @@ -1857,7 +1857,7 @@ NSGigE::doTxDmaWrite() assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); txDmaState = dmaWriting; - if (dmaPending()) + if (dmaPending() || getState() != Running) txDmaState = dmaWriteWaiting; else dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); @@ -2406,6 +2406,20 @@ NSGigE::recvPacket(EthPacketPtr packet) return true; } + +void +NSGigE::resume() +{ + SimObject::resume(); + + // During drain we could have left the state machines in a waiting state and + // they wouldn't get out until some other event occured to kick them. + // This way they'll get out immediately + txKick(); + rxKick(); +} + + //===================================================================== // // @@ -2801,6 +2815,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<uint32_t> pci_dev; Param<uint32_t> pci_func; Param<Tick> pio_latency; + Param<Tick> config_latency; Param<Tick> clock; Param<bool> dma_desc_free; @@ -2834,6 +2849,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(config_latency, "Number of cycles for a config read or write"), INIT_PARAM(clock, "State machine cycle time"), INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), @@ -2871,6 +2887,7 @@ CREATE_SIM_OBJECT(NSGigE) params->deviceNum = pci_dev; params->functionNum = pci_func; params->pio_delay = pio_latency; + params->config_delay = config_latency; params->clock = clock; params->dma_desc_free = dma_desc_free; diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh index ea7243777..080c0b1f3 100644 --- a/src/dev/ns_gige.hh +++ b/src/dev/ns_gige.hh @@ -391,6 +391,8 @@ class NSGigE : public PciDev virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); + virtual void resume(); + public: void regStats(); diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 62a7324ad..e81e0d1ee 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -56,8 +56,8 @@ using namespace std; PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, int funcid, Platform *p) - : PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid), - functionId(funcid) + : PioPort(dev,p->system,"-pciconf"), device(dev), platform(p), + busId(busid), deviceId(devid), functionId(funcid) { configAddr = platform->calcConfigAddr(busId, deviceId, functionId); } @@ -132,6 +132,18 @@ PciDev::init() PioDevice::init(); } +unsigned int +PciDev::drain(Event *de) +{ + unsigned int count; + count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} + Tick PciDev::readConfig(Packet *pkt) { diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index 20ab9364a..847fb07d0 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -95,6 +95,8 @@ class PciDev : public DmaDevice virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); + Platform *platform; + int busId; int deviceId; int functionId; @@ -249,6 +251,9 @@ class PciDev : public DmaDevice */ virtual void unserialize(Checkpoint *cp, const std::string §ion); + + virtual unsigned int drain(Event *de); + virtual Port *getPort(const std::string &if_name, int idx = -1) { if (if_name == "config") { diff --git a/src/dev/platform.cc b/src/dev/platform.cc index 8546b7805..07288249c 100644 --- a/src/dev/platform.cc +++ b/src/dev/platform.cc @@ -29,6 +29,7 @@ * Nathan Binkert */ +#include "base/misc.hh" #include "dev/platform.hh" #include "sim/builder.hh" #include "sim/sim_exit.hh" diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index dddda1f1c..40bf29c87 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -921,7 +921,7 @@ Device::rxKick() break; case rxBeginCopy: - if (dmaPending()) + if (dmaPending() || getState() != Running) goto exit; rxDmaAddr = params()->platform->pciToDma( @@ -1109,7 +1109,7 @@ Device::txKick() break; case txBeginCopy: - if (dmaPending()) + if (dmaPending() || getState() != Running) goto exit; txDmaAddr = params()->platform->pciToDma( @@ -1287,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet) return true; } +void +Device::resume() +{ + SimObject::resume(); + + // During drain we could have left the state machines in a waiting state and + // they wouldn't get out until some other event occured to kick them. + // This way they'll get out immediately + txKick(); + rxKick(); +} + //===================================================================== // // @@ -1627,6 +1639,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) Param<uint32_t> pci_dev; Param<uint32_t> pci_func; Param<Tick> pio_latency; + Param<Tick> config_latency; Param<Tick> intr_delay; Param<Tick> clock; @@ -1669,6 +1682,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device) INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(config_latency, "Number of cycles for a config read or write"), INIT_PARAM(intr_delay, "Interrupt Delay"), INIT_PARAM(clock, "State machine cycle time"), @@ -1713,6 +1727,7 @@ CREATE_SIM_OBJECT(Device) params->deviceNum = pci_dev; params->functionNum = pci_func; params->pio_delay = pio_latency; + params->config_delay = config_latency; params->intr_delay = intr_delay; params->clock = clock; diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh index f6c229039..eece4ba6b 100644 --- a/src/dev/sinic.hh +++ b/src/dev/sinic.hh @@ -266,6 +266,7 @@ class Device : public Base public: virtual Tick read(Packet *pkt); virtual Tick write(Packet *pkt); + virtual void resume(); void prepareIO(int cpu, int index); void prepareRead(int cpu, int index); diff --git a/src/dev/tsunami.hh b/src/dev/tsunami.hh index 8bb66e914..6fbfac851 100644 --- a/src/dev/tsunami.hh +++ b/src/dev/tsunami.hh @@ -83,7 +83,8 @@ class Tsunami : public Platform /** * Constructor for the Tsunami Class. * @param name name of the object - * @param intrctrl pointer to the interrupt controller + * @param s system the object belongs to + * @param intctrl pointer to the interrupt controller */ Tsunami(const std::string &name, System *s, IntrControl *intctrl); diff --git a/src/dev/tsunami_io.hh b/src/dev/tsunami_io.hh index ee25bbdfd..9084a1be8 100644 --- a/src/dev/tsunami_io.hh +++ b/src/dev/tsunami_io.hh @@ -126,12 +126,14 @@ class TsunamiIO : public BasicPioDevice /** * Serialize this object to the given output stream. + * @param base The base name of the counter object. * @param os The stream to serialize to. */ void serialize(const std::string &base, std::ostream &os); /** * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. * @param cp The checkpoint use. * @param section The section name of this object */ @@ -221,12 +223,14 @@ class TsunamiIO : public BasicPioDevice /** * Serialize this object to the given output stream. - * @param os The stream to serialize to. + * @param base The base name of the counter object. + * @param os The stream to serialize to. */ void serialize(const std::string &base, std::ostream &os); /** * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. * @param cp The checkpoint use. * @param section The section name of this object */ @@ -254,12 +258,14 @@ class TsunamiIO : public BasicPioDevice /** * Serialize this object to the given output stream. + * @param base The base name of the counter object. * @param os The stream to serialize to. */ void serialize(const std::string &base, std::ostream &os); /** * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. * @param cp The checkpoint use. * @param section The section name of this object */ diff --git a/src/doxygen/footer.html b/src/doxygen/footer.html new file mode 100644 index 000000000..6ef5293de --- /dev/null +++ b/src/doxygen/footer.html @@ -0,0 +1,5 @@ +<hr size="1"><address style="align: right;"><small> +Generated on $datetime for $projectname by <a href="http://www.doxygen.org/index.html"> doxygen</a> $doxygenversion</small></address> + +</body> +</html> diff --git a/src/doxygen/stl.hh b/src/doxygen/stl.hh new file mode 100644 index 000000000..fd9f68140 --- /dev/null +++ b/src/doxygen/stl.hh @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Erik Hallnor + * Nathan Binkert + */ + +/** + * @file + * Dummy definitions of STL classes to pick up relationships in doxygen. + */ + +namespace std { + +/** STL vector class*/ +template <class T> class vector { + public: + /** Dummy Item */ + T item; +}; + +/** STL deque class */ +template <class T> class deque { + public: + /** Dummy Item */ + T item; +}; + +/** STL list class */ +template <class T> class list { + public: + /** Dummy Item */ + T item; +}; + +/** STL pair class */ +template <class X, class Y> class pair { + public: + /** Dummy Item */ + X item1; + /** Dummy Item */ + Y item2; +}; + +} diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 29ea2e12f..9c14e7ee2 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -31,7 +31,8 @@ */ /** - * @file Definition of a simple bus bridge without buffering. + * @file + * Definition of a simple bus bridge without buffering. */ #include <algorithm> diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index b3525d3e0..2ab9799c7 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -30,7 +30,8 @@ */ /** - * @file Decleration of a simple bus bridge object with no buffering + * @file + * Declaration of a simple bus bridge object with no buffering */ #ifndef __MEM_BRIDGE_HH__ @@ -49,7 +50,7 @@ class Bridge : public MemObject { protected: - /** Decleration of the buses port type, one will be instantiated for each + /** Declaration of the buses port type, one will be instantiated for each of the interfaces connecting to the bus. */ class BridgePort : public Port { diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 31271106b..b945f93b3 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -29,7 +29,8 @@ */ /** - * @file Definition of a bus object. + * @file + * Definition of a bus object. */ diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 3a2896886..cd25fab2c 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -30,7 +30,8 @@ */ /** - * @file Decleration of a bus object. + * @file + * Declaration of a bus object. */ #ifndef __MEM_BUS_HH__ @@ -97,7 +98,7 @@ class Bus : public MemObject void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id); - /** Decleration of the buses port type, one will be instantiated for each + /** Declaration of the buses port type, one will be instantiated for each of the interfaces connecting to the bus. */ class BusPort : public Port { diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 823465769..9fb790cee 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -490,7 +490,7 @@ class BaseCache : public MemObject /** * Send a response to the slave interface. - * @param req The request being responded to. + * @param pkt The request being responded to. * @param time The time the response is ready. */ void respond(Packet *pkt, Tick time) @@ -503,7 +503,7 @@ class BaseCache : public MemObject /** * Send a reponse to the slave interface and calculate miss latency. - * @param req The request to respond to. + * @param pkt The request to respond to. * @param time The time the response is ready. */ void respondToMiss(Packet *pkt, Tick time) @@ -519,7 +519,7 @@ class BaseCache : public MemObject /** * Suppliess the data if cache to cache transfers are enabled. - * @param req The bus transaction to fulfill. + * @param pkt The bus transaction to fulfill. */ void respondToSnoop(Packet *pkt) { diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index ec5b800a8..a26d91709 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -159,7 +159,7 @@ class Cache : public BaseCache /** * Performs the access specified by the request. - * @param req The request to perform. + * @param pkt The request to perform. * @return The result of the access. */ bool access(Packet * &pkt); @@ -172,26 +172,26 @@ class Cache : public BaseCache /** * Was the request was sent successfully? - * @param req The request. + * @param pkt The request. * @param success True if the request was sent successfully. */ virtual void sendResult(Packet * &pkt, bool success); /** * Handles a response (cache line fill/write ack) from the bus. - * @param req The request being responded to. + * @param pkt The request being responded to. */ void handleResponse(Packet * &pkt); /** * Start handling a copy transaction. - * @param req The copy request to perform. + * @param pkt The copy request to perform. */ void startCopy(Packet * &pkt); /** * Handle a delayed copy transaction. - * @param req The delayed copy request to continue. + * @param pkt The delayed copy request to continue. * @param addr The address being responded to. * @param blk The block of the current response. * @param mshr The mshr being handled. @@ -206,7 +206,7 @@ class Cache : public BaseCache /** * Snoops bus transactions to maintain coherence. - * @param req The current bus transaction. + * @param pkt The current bus transaction. */ void snoop(Packet * &pkt); @@ -221,9 +221,9 @@ class Cache : public BaseCache void invalidateBlk(Addr addr, int asid); /** - * Aquash all requests associated with specified thread. + * Squash all requests associated with specified thread. * intended for use by I-cache. - * @param req->getThreadNum()ber The thread to squash. + * @param threadNum The thread to squash. */ void squash(int threadNum) { @@ -246,7 +246,7 @@ class Cache : public BaseCache * time of completion. This function can either update the hierarchy state * or just perform the access wherever the data is found depending on the * state of the update flag. - * @param req The memory request to satisfy + * @param pkt The memory request to satisfy * @param update If true, update the hierarchy, otherwise just perform the * request. * @return The estimated completion time. @@ -257,7 +257,7 @@ class Cache : public BaseCache * Snoop for the provided request in the cache and return the estimated * time of completion. * @todo Can a snoop probe not change state? - * @param req The memory request to satisfy + * @param pkt The memory request to satisfy * @param update If true, update the hierarchy, otherwise just perform the * request. * @return The estimated completion time. diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index 67e65d25b..a75c9611d 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -38,6 +38,8 @@ #include "sim/root.hh" // for Tick #include "arch/isa_traits.hh" // for Addr +#include <iostream> + /** * Cache block status bit assignments */ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index db012920f..b215960c4 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -53,8 +53,6 @@ #include "sim/sim_events.hh" // for SimExitEvent -using namespace std; - template<class TagStore, class Buffering, class Coherence> bool Cache<TagStore,Buffering,Coherence>:: @@ -501,7 +499,7 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update) MSHR* mshr = missQueue->findMSHR(blk_addr, pkt->req->getAsid()); // There can be many matching outstanding writes. - vector<MSHR*> writes; + std::vector<MSHR*> writes; missQueue->findWrites(blk_addr, pkt->req->getAsid(), writes); if (!update) { diff --git a/src/mem/cache/coherence/coherence_protocol.hh b/src/mem/cache/coherence/coherence_protocol.hh index 21351ace4..b5d7d80aa 100644 --- a/src/mem/cache/coherence/coherence_protocol.hh +++ b/src/mem/cache/coherence/coherence_protocol.hh @@ -85,7 +85,7 @@ class CoherenceProtocol : public SimObject /** * Return the proper state given the current state and the bus response. - * @param req The bus response. + * @param pkt The bus response. * @param oldState The current block state. * @return The new state. */ @@ -95,7 +95,7 @@ class CoherenceProtocol : public SimObject /** * Handle snooped bus requests. * @param cache The cache that snooped the request. - * @param req The snooped bus request. + * @param pkt The snooped bus request. * @param blk The cache block corresponding to the request, if any. * @param mshr The MSHR corresponding to the request, if any. * @param new_state The new coherence state of the block. diff --git a/src/mem/cache/coherence/simple_coherence.hh b/src/mem/cache/coherence/simple_coherence.hh index ca9d18beb..71d8f36f4 100644 --- a/src/mem/cache/coherence/simple_coherence.hh +++ b/src/mem/cache/coherence/simple_coherence.hh @@ -96,7 +96,7 @@ class SimpleCoherence /** * Return the proper state given the current state and the bus response. - * @param req The bus response. + * @param pkt The bus response. * @param current The current block state. * @return The new state. */ @@ -107,7 +107,7 @@ class SimpleCoherence /** * Handle snooped bus requests. - * @param req The snooped bus request. + * @param pkt The snooped bus request. * @param blk The cache block corresponding to the request, if any. * @param mshr The MSHR corresponding to the request, if any. * @param new_state Return the new state for the block. diff --git a/src/mem/cache/coherence/uni_coherence.hh b/src/mem/cache/coherence/uni_coherence.hh index 764bf6276..27b6c7fb5 100644 --- a/src/mem/cache/coherence/uni_coherence.hh +++ b/src/mem/cache/coherence/uni_coherence.hh @@ -88,7 +88,7 @@ class UniCoherence /** * Just return readable and writeable. - * @param req The bus response. + * @param pkt The bus response. * @param current The current block state. * @return The new state. */ @@ -116,7 +116,7 @@ class UniCoherence /** * Handle snooped bus requests. - * @param req The snooped bus request. + * @param pkt The snooped bus request. * @param blk The cache block corresponding to the request, if any. * @param mshr The MSHR corresponding to the request, if any. * @param new_state The new coherence state of the block. diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc index 10d53b109..2f61e8a54 100644 --- a/src/mem/cache/miss/blocking_buffer.cc +++ b/src/mem/cache/miss/blocking_buffer.cc @@ -40,8 +40,6 @@ #include "sim/eventq.hh" // for Event declaration. #include "mem/request.hh" -using namespace TheISA; - /** * @todo Move writebacks into shared BaseBuffer class. */ diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index 39a06a377..a6261f62c 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -107,7 +107,7 @@ public: /** * Handle a cache miss properly. Requests the bus and marks the cache as * blocked. - * @param req The request that missed in the cache. + * @param pkt The request that missed in the cache. * @param blk_size The block size of the cache. * @param time The time the miss is detected. */ @@ -128,43 +128,43 @@ public: } /** - * Selects a outstanding request to service. - * @return The request to service, NULL if none found. + * Selects a outstanding pktuest to service. + * @return The pktuest to service, NULL if none found. */ Packet * getPacket(); /** * Set the command to the given bus command. - * @param req The request to update. + * @param pkt The request to update. * @param cmd The bus command to use. */ void setBusCmd(Packet * &pkt, Packet::Command cmd); /** * Restore the original command in case of a bus transmission error. - * @param req The request to reset. + * @param pkt The request to reset. */ void restoreOrigCmd(Packet * &pkt); /** - * Marks a request as in service (sent on the bus). This can have side + * Marks a pktuest as in service (sent on the bus). This can have side * effect since storage for no response commands is deallocated once they * are successfully sent. - * @param req The request that was sent on the bus. + * @param pkt The request that was sent on the bus. */ void markInService(Packet * &pkt); /** - * Frees the resources of the request and unblock the cache. - * @param req The request that has been satisfied. - * @param time The time when the request is satisfied. + * Frees the resources of the pktuest and unblock the cache. + * @param pkt The request that has been satisfied. + * @param time The time when the pktuest is satisfied. */ void handleResponse(Packet * &pkt, Tick time); /** - * Removes all outstanding requests for a given thread number. If a request + * Removes all outstanding pktuests for a given thread number. If a request * has been sent to the bus, this function removes all of its targets. - * @param req->getThreadNum()ber The thread number of the requests to squash. + * @param threadNum The thread number of the requests to squash. */ void squash(int threadNum); @@ -220,14 +220,14 @@ public: int size, uint8_t *data, bool compressed); /** - * Perform a writeback request. - * @param req The writeback request. + * Perform a writeback pktuest. + * @param pkt The writeback request. */ void doWriteback(Packet * &pkt); /** - * Returns true if there are outstanding requests. - * @return True if there are outstanding requests. + * Returns true if there are outstanding pktuests. + * @return True if there are outstanding pktuests. */ bool havePending() { @@ -237,7 +237,7 @@ public: /** * Add a target to the given MSHR. This assumes it is in the miss queue. * @param mshr The mshr to add a target to. - * @param req The target to add. + * @param pkt The target to add. */ void addTarget(MSHR *mshr, Packet * &pkt) { diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh index b88b7038c..c558df956 100644 --- a/src/mem/cache/miss/miss_queue.hh +++ b/src/mem/cache/miss/miss_queue.hh @@ -77,7 +77,7 @@ class MissQueue /** The block size of the parent cache. */ int blkSize; - /** Increasing order number assigned to each incoming request. */ + /** Increasing order number assigned to each incoming pktuest. */ uint64_t order; bool prefetchMiss; @@ -164,7 +164,7 @@ class MissQueue /** * Allocate a new MSHR to handle the provided miss. - * @param req The miss to buffer. + * @param pkt The miss to buffer. * @param size The number of bytes to fetch. * @param time The time the miss occurs. * @return A pointer to the new MSHR. @@ -173,7 +173,7 @@ class MissQueue /** * Allocate a new WriteBuffer to handle the provided write. - * @param req The write to handle. + * @param pkt The write to handle. * @param size The number of bytes to write. * @param time The time the write occurs. * @return A pointer to the new write buffer. @@ -212,9 +212,9 @@ class MissQueue void setPrefetcher(BasePrefetcher *_prefetcher); /** - * Handle a cache miss properly. Either allocate an MSHR for the request, + * Handle a cache miss properly. Either allocate an MSHR for the pktuest, * or forward it through the write buffer. - * @param req The request that missed in the cache. + * @param pkt The request that missed in the cache. * @param blk_size The block size of the cache. * @param time The time the miss is detected. */ @@ -232,43 +232,43 @@ class MissQueue Packet * &target); /** - * Selects a outstanding request to service. - * @return The request to service, NULL if none found. + * Selects a outstanding pktuest to service. + * @return The pktuest to service, NULL if none found. */ Packet * getPacket(); /** * Set the command to the given bus command. - * @param req The request to update. + * @param pkt The request to update. * @param cmd The bus command to use. */ void setBusCmd(Packet * &pkt, Packet::Command cmd); /** * Restore the original command in case of a bus transmission error. - * @param req The request to reset. + * @param pkt The request to reset. */ void restoreOrigCmd(Packet * &pkt); /** - * Marks a request as in service (sent on the bus). This can have side + * Marks a pktuest as in service (sent on the bus). This can have side * effect since storage for no response commands is deallocated once they * are successfully sent. - * @param req The request that was sent on the bus. + * @param pkt The request that was sent on the bus. */ void markInService(Packet * &pkt); /** - * Collect statistics and free resources of a satisfied request. - * @param req The request that has been satisfied. - * @param time The time when the request is satisfied. + * Collect statistics and free resources of a satisfied pktuest. + * @param pkt The request that has been satisfied. + * @param time The time when the pktuest is satisfied. */ void handleResponse(Packet * &pkt, Tick time); /** - * Removes all outstanding requests for a given thread number. If a request + * Removes all outstanding pktuests for a given thread number. If a request * has been sent to the bus, this function removes all of its targets. - * @param req->getThreadNum()ber The thread number of the requests to squash. + * @param threadNum The thread number of the requests to squash. */ void squash(int threadNum); @@ -313,21 +313,21 @@ class MissQueue int size, uint8_t *data, bool compressed); /** - * Perform the given writeback request. - * @param req The writeback request. + * Perform the given writeback pktuest. + * @param pkt The writeback request. */ void doWriteback(Packet * &pkt); /** - * Returns true if there are outstanding requests. - * @return True if there are outstanding requests. + * Returns true if there are outstanding pktuests. + * @return True if there are outstanding pktuests. */ bool havePending(); /** * Add a target to the given MSHR. This assumes it is in the miss queue. * @param mshr The mshr to add a target to. - * @param req The target to add. + * @param pkt The target to add. */ void addTarget(MSHR *mshr, Packet * &pkt) { diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 167aa26cd..ad2865973 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -44,7 +44,7 @@ class MSHR; /** * Miss Status and handling Register. This class keeps all the information - * needed to handle a cache miss including a list of target requests. + * needed to handle a cache miss including a list of target pktuests. */ class MSHR { public: @@ -63,15 +63,15 @@ class MSHR { Addr addr; /** Adress space id of the miss. */ short asid; - /** True if the request has been sent to the bus. */ + /** True if the pktuest has been sent to the bus. */ bool inService; /** Thread number of the miss. */ int threadNum; - /** The request that is forwarded to the next level of the hierarchy. */ + /** The pktuest that is forwarded to the next level of the hierarchy. */ Packet * pkt; /** The number of currently allocated targets. */ short ntargets; - /** The original requesting command. */ + /** The original pktuesting command. */ Packet::Command originalCmd; /** Order number of assigned by the miss queue. */ uint64_t order; @@ -88,24 +88,24 @@ class MSHR { Iterator allocIter; private: - /** List of all requests that match the address */ + /** List of all pktuests that match the address */ TargetList targets; public: /** * Allocate a miss to this MSHR. - * @param cmd The requesting command. + * @param cmd The pktuesting command. * @param addr The address of the miss. * @param asid The address space id of the miss. - * @param size The number of bytes to request. - * @param req The original miss. + * @param size The number of bytes to pktuest. + * @param pkt The original miss. */ void allocate(Packet::Command cmd, Addr addr, int asid, int size, Packet * &pkt); /** - * Allocate this MSHR as a buffer for the given request. - * @param target The memory request to buffer. + * Allocate this MSHR as a buffer for the given pktuest. + * @param target The memory pktuest to buffer. */ void allocateAsBuffer(Packet * &target); @@ -115,7 +115,7 @@ public: void deallocate(); /** - * Add a request to the list of targets. + * Add a pktuest to the list of targets. * @param target The target. */ void allocateTarget(Packet * &target); diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh index a67f1b9a6..02b6a026d 100644 --- a/src/mem/cache/miss/mshr_queue.hh +++ b/src/mem/cache/miss/mshr_queue.hh @@ -39,7 +39,7 @@ #include "mem/cache/miss/mshr.hh" /** - * A Class for maintaining a list of pending and allocated memory requests. + * A Class for maintaining a list of pending and allocated memory pktuests. */ class MSHRQueue { private: @@ -55,7 +55,7 @@ class MSHRQueue { // Parameters /** * The total number of MSHRs in this queue. This number is set as the - * number of MSHRs requested plus (numReserve - 1). This allows for + * number of MSHRs pktuested plus (numReserve - 1). This allows for * the same number of effective MSHRs while still maintaining the reserve. */ const int numMSHRs; @@ -103,16 +103,16 @@ class MSHRQueue { bool findMatches(Addr addr, int asid, std::vector<MSHR*>& matches) const; /** - * Find any pending requests that overlap the given request. - * @param req The request to find. + * Find any pending pktuests that overlap the given request. + * @param pkt The request to find. * @return A pointer to the earliest matching MSHR. */ MSHR* findPending(Packet * &pkt) const; /** - * Allocates a new MSHR for the request and size. This places the request + * Allocates a new MSHR for the pktuest and size. This places the request * as the first target in the MSHR. - * @param req The request to handle. + * @param pkt The request to handle. * @param size The number in bytes to fetch from memory. * @return The a pointer to the MSHR allocated. * @@ -121,12 +121,12 @@ class MSHRQueue { MSHR* allocate(Packet * &pkt, int size = 0); /** - * Allocate a read request for the given address, and places the given + * Allocate a read pktuest for the given address, and places the given * target on the target list. * @param addr The address to fetch. * @param asid The address space for the fetch. - * @param size The number of bytes to request. - * @param target The first target for the request. + * @param size The number of bytes to pktuest. + * @param target The first target for the pktuest. * @return Pointer to the new MSHR. */ MSHR* allocateFetch(Addr addr, int asid, int size, Packet * &target); @@ -135,7 +135,7 @@ class MSHRQueue { * Allocate a target list for the given address. * @param addr The address to fetch. * @param asid The address space for the fetch. - * @param size The number of bytes to request. + * @param size The number of bytes to pktuest. * @return Pointer to the new MSHR. */ MSHR* allocateTargetList(Addr addr, int asid, int size); @@ -151,7 +151,7 @@ class MSHRQueue { * Allocates a target to the given MSHR. Used to keep track of the number * of outstanding targets. * @param mshr The MSHR to allocate the target to. - * @param req The target request. + * @param pkt The target request. */ void allocateTarget(MSHR* mshr, Packet * &pkt) { @@ -181,22 +181,22 @@ class MSHRQueue { void markInService(MSHR* mshr); /** - * Mark an in service mshr as pending, used to resend a request. + * Mark an in service mshr as pending, used to resend a pktuest. * @param mshr The MSHR to resend. * @param cmd The command to resend. */ void markPending(MSHR* mshr, Packet::Command cmd); /** - * Squash outstanding requests with the given thread number. If a request + * Squash outstanding pktuests with the given thread number. If a request * is in service, just squashes the targets. - * @param req->getThreadNum()ber The thread to squash. + * @param threadNum The thread to squash. */ void squash(int threadNum); /** * Returns true if the pending list is not empty. - * @return True if there are outstanding requests. + * @return True if there are outstanding pktuests. */ bool havePending() const { @@ -213,8 +213,8 @@ class MSHRQueue { } /** - * Returns the request at the head of the pendingList. - * @return The next request to service. + * Returns the pktuest at the head of the pendingList. + * @return The next pktuest to service. */ Packet * getReq() const { diff --git a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh index db5c94820..e554b3cec 100644 --- a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh +++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh @@ -33,6 +33,7 @@ * Describes a tagged prefetcher based on template policies. */ +#include "arch/isa_traits.hh" #include "mem/cache/prefetch/tagged_prefetcher.hh" template <class TagStore, class Buffering> diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 566e36c27..444954917 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -193,7 +193,7 @@ public: /** * Find the block in the cache and update the replacement data. Returns * the access latency and the in cache flags as a side effect - * @param req The req whose block to find + * @param pkt The req whose block to find * @param lat The latency of the access. * @param inCache The FALRUBlk::inCache flags. * @return Pointer to the cache block. @@ -210,7 +210,7 @@ public: /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -328,7 +328,7 @@ public: * @param source The block aligned source address. * @param dest The block aligned destination adddress. * @param asid The address space ID. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks) { diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 6628f7e7a..514d16bdd 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -454,7 +454,7 @@ class IIC : public BaseTags /** * Find the block and update the replacement data. This call also returns * the access latency as a side effect. - * @param req The req whose block to find + * @param pkt The req whose block to find * @param lat The access latency. * @return A pointer to the block found, if any. */ @@ -470,7 +470,7 @@ class IIC : public BaseTags /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -502,14 +502,14 @@ class IIC : public BaseTags * @param source The block-aligned source address. * @param dest The block-aligned destination address. * @param asid The address space DI. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks); /** * If a block is currently marked copy on write, copy it before writing. - * @param req The write request. - * @param writebacks List for any generated writeback requests. + * @param pkt The write request. + * @param writebacks List for any generated writeback pktuests. */ void fixCopy(Packet * &pkt, PacketList &writebacks); diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 437244660..8f0f3ae27 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -170,7 +170,7 @@ public: /** * Finds the given address in the cache and update replacement data. * Returns the access latency as a side effect. - * @param req The request whose block to find. + * @param pkt The request whose block to find. * @param lat The access latency. * @return Pointer to the cache block if found. */ @@ -196,7 +196,7 @@ public: /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -307,7 +307,7 @@ public: * @param source The block-aligned source address. * @param dest The block-aligned destination address. * @param asid The address space DI. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks); diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh index 5e0340269..25180a02b 100644 --- a/src/mem/cache/tags/split.hh +++ b/src/mem/cache/tags/split.hh @@ -71,13 +71,13 @@ class Split : public BaseTags Addr blkMask; - /** Number of NIC requests that hit in the NIC partition */ + /** Number of NIC pktuests that hit in the NIC partition */ Stats::Scalar<> NR_NP_hits; - /** Number of NIC requests that hit in the CPU partition */ + /** Number of NIC pktuests that hit in the CPU partition */ Stats::Scalar<> NR_CP_hits; - /** Number of CPU requests that hit in the NIC partition */ + /** Number of CPU pktuests that hit in the NIC partition */ Stats::Scalar<> CR_NP_hits; - /** Number of CPU requests that hit in the CPU partition */ + /** Number of CPU pktuests that hit in the CPU partition */ Stats::Scalar<> CR_CP_hits; /** The number of nic replacements (i.e. misses) */ Stats::Scalar<> nic_repl; @@ -203,7 +203,7 @@ class Split : public BaseTags /** * Finds the given address in the cache and update replacement data. * Returns the access latency as a side effect. - * @param req The memory request whose block to find + * @param pkt The memory request whose block to find * @param lat The access latency. * @return Pointer to the cache block if found. */ @@ -219,7 +219,7 @@ class Split : public BaseTags /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -315,7 +315,7 @@ class Split : public BaseTags * @param source The block-aligned source address. * @param dest The block-aligned destination address. * @param asid The address space DI. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks); diff --git a/src/mem/cache/tags/split_blk.hh b/src/mem/cache/tags/split_blk.hh index f38516180..64d903579 100644 --- a/src/mem/cache/tags/split_blk.hh +++ b/src/mem/cache/tags/split_blk.hh @@ -47,7 +47,7 @@ class SplitBlk : public CacheBlk { bool isTouched; /** Has this block been used after being brought in? (for LIFO partition) */ bool isUsed; - /** is this blk a NIC block? (i.e. requested by the NIC) */ + /** is this blk a NIC block? (i.e. pktuested by the NIC) */ bool isNIC; /** timestamp of the arrival of this block into the cache */ Tick ts; diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh index dfcaa0b67..52956b192 100644 --- a/src/mem/cache/tags/split_lifo.hh +++ b/src/mem/cache/tags/split_lifo.hh @@ -203,7 +203,7 @@ public: /** * Finds the given address in the cache and update replacement data. * Returns the access latency as a side effect. - * @param req The req whose block to find + * @param pkt The req whose block to find * @param lat The access latency. * @return Pointer to the cache block if found. */ @@ -219,7 +219,7 @@ public: /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -330,7 +330,7 @@ public: * @param source The block-aligned source address. * @param dest The block-aligned destination address. * @param asid The address space DI. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks); diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh index 03886b1d8..6d370c5dd 100644 --- a/src/mem/cache/tags/split_lru.hh +++ b/src/mem/cache/tags/split_lru.hh @@ -186,7 +186,7 @@ public: /** * Finds the given address in the cache and update replacement data. * Returns the access latency as a side effect. - * @param req The req whose block to find. + * @param pkt The req whose block to find. * @param lat The access latency. * @return Pointer to the cache block if found. */ @@ -202,7 +202,7 @@ public: /** * Find a replacement block for the address provided. - * @param req The request to a find a replacement candidate for. + * @param pkt The request to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. * @param compress_blocks List of blocks to compress, for adaptive comp. * @return The block to place the replacement in. @@ -313,7 +313,7 @@ public: * @param source The block-aligned source address. * @param dest The block-aligned destination address. * @param asid The address space DI. - * @param writebacks List for any generated writeback requests. + * @param writebacks List for any generated writeback pktuests. */ void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks); diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index c81ea03d8..d12eeffe0 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -30,7 +30,7 @@ /** * @file - * Base Memory Object decleration. + * Base Memory Object declaration. */ #ifndef __MEM_MEM_OBJECT_HH__ diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 534db0077..83b4006e2 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -39,7 +39,7 @@ #define __MEM_PACKET_HH__ #include "mem/request.hh" -#include "arch/isa_traits.hh" +#include "sim/host.hh" #include "sim/root.hh" #include <list> diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index a34a0393a..2b460306f 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -64,7 +64,7 @@ PageTable::~PageTable() } Fault -PageTable::page_check(Addr addr, int size) const +PageTable::page_check(Addr addr, int64_t size) const { if (size < sizeof(uint64_t)) { if (!isPowerOf2(size)) { @@ -92,7 +92,7 @@ PageTable::page_check(Addr addr, int size) const void -PageTable::allocate(Addr vaddr, int size) +PageTable::allocate(Addr vaddr, int64_t size) { // starting address must be page aligned assert(pageOffset(vaddr) == 0); diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index 494c0ce9a..fce063280 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -38,6 +38,7 @@ #include <string> +#include "sim/faults.hh" #include "arch/isa_traits.hh" #include "base/hashmap.hh" #include "base/trace.hh" @@ -48,7 +49,7 @@ class System; /** - * Page Table Decleration. + * Page Table Declaration. */ class PageTable { @@ -76,9 +77,9 @@ class PageTable Addr pageAlign(Addr a) { return (a & ~offsetMask); } Addr pageOffset(Addr a) { return (a & offsetMask); } - Fault page_check(Addr addr, int size) const; + Fault page_check(Addr addr, int64_t size) const; - void allocate(Addr vaddr, int size); + void allocate(Addr vaddr, int64_t size); /** * Translate function diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 2d66602ab..291c70d8c 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ron Dreslinski + * Ali Saidi */ #include <sys/types.h> @@ -52,24 +53,6 @@ using namespace std; using namespace TheISA; -PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m) - : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m) -{ - - this->setFlags(AutoDelete); -} - -void -PhysicalMemory::MemResponseEvent::process() -{ - memoryPort->sendTiming(pkt); -} - -const char * -PhysicalMemory::MemResponseEvent::description() -{ - return "Physical Memory Timing Access respnse event"; -} PhysicalMemory::PhysicalMemory(const string &n, Tick latency) : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) @@ -124,27 +107,8 @@ PhysicalMemory::deviceBlockSize() return 0; } -bool -PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort) -{ - doFunctionalAccess(pkt); - - // turn packet around to go back to requester - pkt->makeTimingResponse(); - MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); - response->schedule(curTick + lat); - - return true; -} Tick -PhysicalMemory::doAtomicAccess(Packet *pkt) -{ - doFunctionalAccess(pkt); - return lat; -} - -void PhysicalMemory::doFunctionalAccess(Packet *pkt) { assert(pkt->getAddr() + pkt->getSize() < pmem_size); @@ -170,6 +134,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt) } pkt->result = Packet::Success; + return lat; } Port * @@ -195,7 +160,7 @@ PhysicalMemory::recvStatusChange(Port::Status status) PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, PhysicalMemory *_memory) - : Port(_name), memory(_memory) + : SimpleTimingPort(_name), memory(_memory) { } void @@ -228,13 +193,20 @@ PhysicalMemory::MemoryPort::deviceBlockSize() bool PhysicalMemory::MemoryPort::recvTiming(Packet *pkt) { - return memory->doTimingAccess(pkt, this); + assert(pkt->result != Packet::Nacked); + + Tick latency = memory->doFunctionalAccess(pkt); + + pkt->makeTimingResponse(); + sendTiming(pkt, latency); + + return true; } Tick PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) { - return memory->doAtomicAccess(pkt); + return memory->doFunctionalAccess(pkt); } void @@ -243,7 +215,16 @@ PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) memory->doFunctionalAccess(pkt); } - +unsigned int +PhysicalMemory::drain(Event *de) +{ + int count = port->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} void PhysicalMemory::serialize(ostream &os) diff --git a/src/mem/physical.hh b/src/mem/physical.hh index 50fa75ed3..b549c1f8b 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -37,7 +37,7 @@ #include "base/range.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" -#include "mem/port.hh" +#include "mem/tport.hh" #include "sim/eventq.hh" #include <map> #include <string> @@ -47,7 +47,7 @@ // class PhysicalMemory : public MemObject { - class MemoryPort : public Port + class MemoryPort : public SimpleTimingPort { PhysicalMemory *memory; @@ -74,16 +74,6 @@ class PhysicalMemory : public MemObject int numPorts; - struct MemResponseEvent : public Event - { - Packet *pkt; - MemoryPort *memoryPort; - - MemResponseEvent(Packet *pkt, MemoryPort *memoryPort); - void process(); - const char *description(); - }; - private: // prevent copying of a MainMemory object PhysicalMemory(const PhysicalMemory &specmem); @@ -110,13 +100,10 @@ class PhysicalMemory : public MemObject void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); virtual Port *getPort(const std::string &if_name, int idx = -1); void virtual init(); + unsigned int drain(Event *de); - // fast back-door memory access for vtophys(), remote gdb, etc. - // uint64_t phys_read_qword(Addr addr) const; private: - bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort); - Tick doAtomicAccess(Packet *pkt); - void doFunctionalAccess(Packet *pkt); + Tick doFunctionalAccess(Packet *pkt); void recvStatusChange(Port::Status status); diff --git a/src/mem/port.cc b/src/mem/port.cc index bec9d2274..17924b759 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -29,7 +29,8 @@ */ /** - * @file Port object definitions. + * @file + * Port object definitions. */ #include "base/chunk_generator.hh" diff --git a/src/mem/port.hh b/src/mem/port.hh index 17b1f4a00..42e369205 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -30,7 +30,7 @@ /** * @file - * Port Object Decleration. Ports are used to interface memory objects to + * Port Object Declaration. Ports are used to interface memory objects to * each other. They will always come in pairs, and we refer to the other * port object as the peer. These are used to make the design more * modular so that a specific interface between every type of objcet doesn't diff --git a/src/mem/port_impl.hh b/src/mem/port_impl.hh index e9a159293..b7980bdd2 100644 --- a/src/mem/port_impl.hh +++ b/src/mem/port_impl.hh @@ -28,8 +28,6 @@ * Authors: Ali Saidi */ -#include "arch/isa_specific.hh" -#include "arch/isa_traits.hh" #include "mem/port.hh" #include "sim/byteswap.hh" @@ -37,7 +35,7 @@ template <typename T> void FunctionalPort::writeHtoG(Addr addr, T d) { - d = TheISA::htog(d); + d = htog(d); writeBlob(addr, (uint8_t*)&d, sizeof(T)); } @@ -48,6 +46,6 @@ FunctionalPort::readGtoH(Addr addr) { T d; readBlob(addr, (uint8_t*)&d, sizeof(T)); - return TheISA::gtoh(d); + return gtoh(d); } diff --git a/src/mem/request.hh b/src/mem/request.hh index a1524f807..457310298 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -31,14 +31,16 @@ */ /** - * @file Decleration of a request, the overall memory request consisting of + * @file + * Declaration of a request, the overall memory request consisting of the parts of the request that are persistent throughout the transaction. */ #ifndef __MEM_REQUEST_HH__ #define __MEM_REQUEST_HH__ -#include "arch/isa_traits.hh" +#include "sim/host.hh" +#include "sim/root.hh" class Request; diff --git a/src/mem/tport.cc b/src/mem/tport.cc new file mode 100644 index 000000000..90cf68f02 --- /dev/null +++ b/src/mem/tport.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "mem/tport.hh" + +void +SimpleTimingPort::recvRetry() +{ + bool result = true; + while (result && transmitList.size()) { + result = Port::sendTiming(transmitList.front()); + if (result) + transmitList.pop_front(); + } + if (transmitList.size() == 0 && drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } +} + +void +SimpleTimingPort::SendEvent::process() +{ + port->outTiming--; + assert(port->outTiming >= 0); + if (port->Port::sendTiming(packet)) + if (port->transmitList.size() == 0 && port->drainEvent) { + port->drainEvent->process(); + port->drainEvent = NULL; + } + return; + + port->transmitList.push_back(packet); +} + +void +SimpleTimingPort::resendNacked(Packet *pkt) { + pkt->reinitNacked(); + if (transmitList.size()) { + transmitList.push_front(pkt); + } else { + if (!Port::sendTiming(pkt)) + transmitList.push_front(pkt); + } +}; + + +unsigned int +SimpleTimingPort::drain(Event *de) +{ + if (outTiming == 0 && transmitList.size() == 0) + return 0; + drainEvent = de; + return 1; +} diff --git a/src/mem/tport.hh b/src/mem/tport.hh new file mode 100644 index 000000000..5473e945e --- /dev/null +++ b/src/mem/tport.hh @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/** + * @file + * Implement a port which adds simple support of a sendTiming() function that + * takes a delay. In this way the * device can immediatly call + * sendTiming(pkt, time) after processing a request and the request will be + * handled by the port even if the port bus the device connects to is blocked. + */ + +/** recvTiming and drain should be implemented something like this when this + * class is used. + +bool +PioPort::recvTiming(Packet *pkt) +{ + if (pkt->result == Packet::Nacked) { + resendNacked(pkt); + } else { + Tick latency = device->recvAtomic(pkt); + // turn packet around to go back to requester + pkt->makeTimingResponse(); + sendTiming(pkt, latency); + } + return true; +} + +PioDevice::drain(Event *de) +{ + unsigned int count; + count = SimpleTimingPort->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} +*/ + +#ifndef __MEM_TPORT_HH__ +#define __MEM_TPORT_HH__ + +#include "mem/port.hh" +#include "sim/eventq.hh" +#include <list> +#include <string> + +class SimpleTimingPort : public Port +{ + protected: + /** A list of outgoing timing response packets that haven't been serviced + * yet. */ + std::list<Packet*> transmitList; + /** + * This class is used to implemented sendTiming() with a delay. When a delay + * is requested a new event is created. When the event time expires it + * attempts to send the packet. If it cannot, the packet is pushed onto the + * transmit list to be sent when recvRetry() is called. */ + class SendEvent : public Event + { + SimpleTimingPort *port; + Packet *packet; + + SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t) + : Event(&mainEventQueue), port(p), packet(pkt) + { setFlags(AutoDelete); schedule(curTick + t); } + + virtual void process(); + + virtual const char *description() + { return "Future scheduled sendTiming event"; } + + friend class SimpleTimingPort; + }; + + + /** Number of timing requests that are emulating the device timing before + * attempting to end up on the bus. + */ + int outTiming; + + /** If we need to drain, keep the drain event around until we're done + * here.*/ + Event *drainEvent; + + /** Schedule a sendTiming() event to be called in the future. */ + void sendTiming(Packet *pkt, Tick time) + { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); } + + /** This function is notification that the device should attempt to send a + * packet again. */ + virtual void recvRetry(); + + void resendNacked(Packet *pkt); + public: + + SimpleTimingPort(std::string pname) + : Port(pname), outTiming(0), drainEvent(NULL) + {} + + unsigned int drain(Event *de); + + friend class SimpleTimingPort::SendEvent; +}; + +#endif // __MEM_TPORT_HH__ diff --git a/src/mem/vport.cc b/src/mem/vport.cc index cd297bb8e..8030c5a15 100644 --- a/src/mem/vport.cc +++ b/src/mem/vport.cc @@ -29,7 +29,8 @@ */ /** - * @file Port object definitions. + * @file + * Port object definitions. */ #include "base/chunk_generator.hh" diff --git a/src/mem/vport.hh b/src/mem/vport.hh index 697c8e5f3..c83836258 100644 --- a/src/mem/vport.hh +++ b/src/mem/vport.hh @@ -30,7 +30,7 @@ /** * @file - * Virtual Port Object Decleration. These ports incorporate some translation + * Virtual Port Object Declaration. These ports incorporate some translation * into their access methods. Thus you can use one to read and write data * to/from virtual addresses. */ diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 3d0e3defa..950d605df 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -44,6 +44,11 @@ def panic(string): print >>sys.stderr, 'panic:', string sys.exit(1) +def makeList(objOrList): + if isinstance(objOrList, list): + return objOrList + return [objOrList] + # Prepend given directory to system module search path. We may not # need this anymore if we can structure our config library more like a # Python package. diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 8291e1e1b..df4b74cbd 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -547,8 +547,7 @@ class SimObject(object): count = 0 # ParamContexts don't serialize if isinstance(self, SimObject) and not isinstance(self, ParamContext): - if not self._ccObject.drain(drain_event): - count = 1 + count += self._ccObject.drain(drain_event) if recursive: for child in self._children.itervalues(): count += child.startDrain(drain_event, True) @@ -561,7 +560,7 @@ class SimObject(object): child.resume() def changeTiming(self, mode): - if isinstance(self, SimObject) and not isinstance(self, ParamContext): + if isinstance(self, System): self._ccObject.setMemoryMode(mode) for child in self._children.itervalues(): child.changeTiming(mode) @@ -666,7 +665,8 @@ class BaseProxy(object): result, done = self.find(obj) if not done: - raise AttributeError, "Can't resolve proxy '%s' from '%s'" % \ + raise AttributeError, \ + "Can't resolve proxy '%s' from '%s'" % \ (self.path(), base.path()) if isinstance(result, BaseProxy): diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 904b241ca..e296453db 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -119,6 +119,8 @@ add_option('-d', "--outdir", metavar="DIR", default=".", help="Set the output directory to DIR [Default: %default]") add_option('-i', "--interactive", action="store_true", default=False, help="Invoke the interactive interpreter after running the script") +add_option("--pdb", action="store_true", default=False, + help="Invoke the python debugger before running the script") add_option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':', help="Prepend PATH to the system path when invoking the script") add_option('-q', "--quiet", action="count", default=0, @@ -175,12 +177,14 @@ bool_option("print-fetch-seq", default=False, help="Print fetch sequence numbers in trace output") bool_option("print-cpseq", default=False, help="Print correct path sequence numbers in trace output") +#bool_option("print-reg-delta", default=False, +# help="Print which registers changed to what in trace output") options = attrdict() arguments = [] def usage(exitcode=None): - print parser.help + parser.print_help() if exitcode is not None: sys.exit(exitcode) @@ -244,9 +248,15 @@ def main(): print "M5 compiled %s" % cc_main.cvar.compileDate; print "M5 started %s" % datetime.now().ctime() print "M5 executing on %s" % socket.gethostname() + print "command line:", + for argv in sys.argv: + print argv, + print # check to make sure we can find the listed script if not arguments or not os.path.isfile(arguments[0]): + if arguments and not os.path.isfile(arguments[0]): + print "Script %s not found" % arguments[0] usage(2) # tell C++ about output directory @@ -282,12 +292,25 @@ def main(): objects.ExecutionTrace.print_iregs = options.print_iregs objects.ExecutionTrace.print_fetchseq = options.print_fetch_seq objects.ExecutionTrace.print_cpseq = options.print_cpseq + #objects.ExecutionTrace.print_reg_delta = options.print_reg_delta - scope = { '__file__' : sys.argv[0] } sys.argv = arguments sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path - exec("import readline", scope) - execfile(sys.argv[0], scope) + + scope = { '__file__' : sys.argv[0] } + + # we want readline if we're doing anything interactive + if options.interactive or options.pdb: + exec("import readline", scope) + + # if pdb was requested, execfile the thing under pdb, otherwise, + # just do the execfile normally + if options.pdb: + from pdb import Pdb + debugger = Pdb() + debugger.run('execfile("%s")' % sys.argv[0], scope) + else: + execfile(sys.argv[0], scope) # once the script is done if options.interactive: diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 2e78578df..5bf98be9c 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -6,10 +6,10 @@ class BaseCPU(SimObject): abstract = True mem = Param.MemObject("memory") + system = Param.System(Parent.any, "system object") if build_env['FULL_SYSTEM']: dtb = Param.AlphaDTB("Data TLB") itb = Param.AlphaITB("Instruction TLB") - system = Param.System(Parent.any, "system object") cpu_id = Param.Int(-1, "CPU identifier") else: workload = VectorParam.Process("processes to run") diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py index 222f750da..f72c8e73f 100644 --- a/src/python/m5/objects/Device.py +++ b/src/python/m5/objects/Device.py @@ -12,7 +12,7 @@ class BasicPioDevice(PioDevice): type = 'BasicPioDevice' abstract = True pio_addr = Param.Addr("Device Address") - pio_latency = Param.Tick(1, "Programmed IO latency in simticks") + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") class DmaDevice(PioDevice): type = 'DmaDevice' diff --git a/src/python/m5/objects/DiskImage.py b/src/python/m5/objects/DiskImage.py index 70d8b2e45..a98b35a4f 100644 --- a/src/python/m5/objects/DiskImage.py +++ b/src/python/m5/objects/DiskImage.py @@ -10,6 +10,6 @@ class RawDiskImage(DiskImage): class CowDiskImage(DiskImage): type = 'CowDiskImage' - child = Param.DiskImage("child image") + child = Param.DiskImage(RawDiskImage(read_only=True), + "child image") table_size = Param.Int(65536, "initial table size") - image_file = '' diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py index 418670592..fb641bf80 100644 --- a/src/python/m5/objects/Ethernet.py +++ b/src/python/m5/objects/Ethernet.py @@ -1,7 +1,7 @@ from m5 import build_env from m5.config import * from Device import DmaDevice -from Pci import PciDevice +from Pci import PciDevice, PciConfigData class EtherInt(SimObject): type = 'EtherInt' @@ -68,6 +68,8 @@ class EtherDevBase(PciDevice): clock = Param.Clock('0ns', "State machine processor frequency") + config_latency = Param.Latency('20ns', "Config read or write latency") + dma_read_delay = Param.Latency('0us', "fixed delay for dma reads") dma_read_factor = Param.Latency('0us', "multiplier for dma reads") dma_write_delay = Param.Latency('0us', "fixed delay for dma writes") @@ -84,6 +86,26 @@ class EtherDevBase(PciDevice): tx_thread = Param.Bool(False, "dedicated kernel threads for receive") rss = Param.Bool(False, "Receive Side Scaling") +class NSGigEPciData(PciConfigData): + VendorID = 0x100B + DeviceID = 0x0022 + Status = 0x0290 + SubClassCode = 0x00 + ClassCode = 0x02 + ProgIF = 0x00 + BAR0 = 0x00000001 + BAR1 = 0x00000000 + BAR2 = 0x00000000 + BAR3 = 0x00000000 + BAR4 = 0x00000000 + BAR5 = 0x00000000 + MaximumLatency = 0x34 + MinimumGrant = 0xb0 + InterruptLine = 0x1e + InterruptPin = 0x01 + BAR0Size = '256B' + BAR1Size = '4kB' + class NSGigE(EtherDevBase): type = 'NSGigE' @@ -91,11 +113,32 @@ class NSGigE(EtherDevBase): dma_desc_free = Param.Bool(False, "DMA of Descriptors is free") dma_no_allocate = Param.Bool(True, "Should we allocate cache on read") + configdata = NSGigEPciData() + class NSGigEInt(EtherInt): type = 'NSGigEInt' device = Param.NSGigE("Ethernet device of this interface") +class SinicPciData(PciConfigData): + VendorID = 0x1291 + DeviceID = 0x1293 + Status = 0x0290 + SubClassCode = 0x00 + ClassCode = 0x02 + ProgIF = 0x00 + BAR0 = 0x00000000 + BAR1 = 0x00000000 + BAR2 = 0x00000000 + BAR3 = 0x00000000 + BAR4 = 0x00000000 + BAR5 = 0x00000000 + MaximumLatency = 0x34 + MinimumGrant = 0xb0 + InterruptLine = 0x1e + InterruptPin = 0x01 + BAR0Size = '64kB' + class Sinic(EtherDevBase): type = 'Sinic' @@ -111,6 +154,8 @@ class Sinic(EtherDevBase): delay_copy = Param.Bool(False, "Delayed copy transmit") virtual_addr = Param.Bool(False, "Virtual addressing") + configdata = SinicPciData() + class SinicInt(EtherInt): type = 'SinicInt' device = Param.Sinic("Ethernet device of this interface") diff --git a/src/python/m5/objects/Ide.py b/src/python/m5/objects/Ide.py index 9ee578177..a8bd4ac5a 100644 --- a/src/python/m5/objects/Ide.py +++ b/src/python/m5/objects/Ide.py @@ -1,8 +1,31 @@ from m5.config import * -from Pci import PciDevice +from Pci import PciDevice, PciConfigData class IdeID(Enum): vals = ['master', 'slave'] +class IdeControllerPciData(PciConfigData): + VendorID = 0x8086 + DeviceID = 0x7111 + Command = 0x0 + Status = 0x280 + Revision = 0x0 + ClassCode = 0x01 + SubClassCode = 0x01 + ProgIF = 0x85 + BAR0 = 0x00000001 + BAR1 = 0x00000001 + BAR2 = 0x00000001 + BAR3 = 0x00000001 + BAR4 = 0x00000001 + BAR5 = 0x00000001 + InterruptLine = 0x1f + InterruptPin = 0x01 + BAR0Size = '8B' + BAR1Size = '4B' + BAR2Size = '8B' + BAR3Size = '4B' + BAR4Size = '16B' + class IdeDisk(SimObject): type = 'IdeDisk' delay = Param.Latency('1us', "Fixed disk delay in microseconds") @@ -12,3 +35,7 @@ class IdeDisk(SimObject): class IdeController(PciDevice): type = 'IdeController' disks = VectorParam.IdeDisk("IDE disks attached to this controller") + + config_latency = Param.Latency('20ns', "Config read or write latency") + + configdata =IdeControllerPciData() diff --git a/src/python/m5/objects/O3CPU.py b/src/python/m5/objects/O3CPU.py index d6bc454ad..41208929a 100644 --- a/src/python/m5/objects/O3CPU.py +++ b/src/python/m5/objects/O3CPU.py @@ -1,91 +1,101 @@ from m5 import build_env from m5.config import * from BaseCPU import BaseCPU +from Checker import O3Checker class DerivO3CPU(BaseCPU): type = 'DerivO3CPU' - activity = Param.Unsigned("Initial count") - numThreads = Param.Unsigned("number of HW thread contexts") - - checker = Param.BaseCPU(NULL, "checker") + activity = Param.Unsigned(0, "Initial count") + numThreads = Param.Unsigned(1, "number of HW thread contexts") + + if build_env['USE_CHECKER']: + if not build_env['FULL_SYSTEM']: + checker = Param.BaseCPU(O3Checker(workload=Parent.workload, + exitOnError=True, + warnOnlyOnLoadError=False), + "checker") + else: + checker = Param.BaseCPU(O3Checker(exitOnError=True, warnOnlyOnLoadError=False), "checker") + checker.itb = Parent.itb + checker.dtb = Parent.dtb cachePorts = Param.Unsigned("Cache Ports") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") - decodeToFetchDelay = Param.Unsigned("Decode to fetch delay") - renameToFetchDelay = Param.Unsigned("Rename to fetch delay") - iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch " - "delay") - commitToFetchDelay = Param.Unsigned("Commit to fetch delay") - fetchWidth = Param.Unsigned("Fetch width") + decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay") + renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay") + iewToFetchDelay = Param.Unsigned(1, "Issue/Execute/Writeback to fetch " + "delay") + commitToFetchDelay = Param.Unsigned(1, "Commit to fetch delay") + fetchWidth = Param.Unsigned(8, "Fetch width") - renameToDecodeDelay = Param.Unsigned("Rename to decode delay") - iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode " + renameToDecodeDelay = Param.Unsigned(1, "Rename to decode delay") + iewToDecodeDelay = Param.Unsigned(1, "Issue/Execute/Writeback to decode " "delay") - commitToDecodeDelay = Param.Unsigned("Commit to decode delay") - fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay") - decodeWidth = Param.Unsigned("Decode width") + commitToDecodeDelay = Param.Unsigned(1, "Commit to decode delay") + fetchToDecodeDelay = Param.Unsigned(1, "Fetch to decode delay") + decodeWidth = Param.Unsigned(8, "Decode width") - iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename " + iewToRenameDelay = Param.Unsigned(1, "Issue/Execute/Writeback to rename " "delay") - commitToRenameDelay = Param.Unsigned("Commit to rename delay") - decodeToRenameDelay = Param.Unsigned("Decode to rename delay") - renameWidth = Param.Unsigned("Rename width") + commitToRenameDelay = Param.Unsigned(1, "Commit to rename delay") + decodeToRenameDelay = Param.Unsigned(1, "Decode to rename delay") + renameWidth = Param.Unsigned(8, "Rename width") - commitToIEWDelay = Param.Unsigned("Commit to " + commitToIEWDelay = Param.Unsigned(1, "Commit to " "Issue/Execute/Writeback delay") - renameToIEWDelay = Param.Unsigned("Rename to " + renameToIEWDelay = Param.Unsigned(2, "Rename to " "Issue/Execute/Writeback delay") - issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal " + issueToExecuteDelay = Param.Unsigned(1, "Issue to execute delay (internal " "to the IEW stage)") - dispatchWidth = Param.Unsigned("Dispatch width") - issueWidth = Param.Unsigned("Issue width") - wbWidth = Param.Unsigned("Writeback width") - wbDepth = Param.Unsigned("Writeback depth") - fuPool = Param.FUPool(NULL, "Functional Unit pool") + dispatchWidth = Param.Unsigned(8, "Dispatch width") + issueWidth = Param.Unsigned(8, "Issue width") + wbWidth = Param.Unsigned(8, "Writeback width") + wbDepth = Param.Unsigned(1, "Writeback depth") + fuPool = Param.FUPool("Functional Unit pool") - iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit " + iewToCommitDelay = Param.Unsigned(1, "Issue/Execute/Writeback to commit " "delay") - renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay") - commitWidth = Param.Unsigned("Commit width") - squashWidth = Param.Unsigned("Squash width") - trapLatency = Param.Tick("Trap latency") - fetchTrapLatency = Param.Tick("Fetch trap latency") - - backComSize = Param.Unsigned("Time buffer size for backwards communication") - forwardComSize = Param.Unsigned("Time buffer size for forward communication") - - predType = Param.String("Branch predictor type ('local', 'tournament')") - localPredictorSize = Param.Unsigned("Size of local predictor") - localCtrBits = Param.Unsigned("Bits per counter") - localHistoryTableSize = Param.Unsigned("Size of local history table") - localHistoryBits = Param.Unsigned("Bits for the local history") - globalPredictorSize = Param.Unsigned("Size of global predictor") - globalCtrBits = Param.Unsigned("Bits per counter") - globalHistoryBits = Param.Unsigned("Bits of history") - choicePredictorSize = Param.Unsigned("Size of choice predictor") - choiceCtrBits = Param.Unsigned("Bits of choice counters") - - BTBEntries = Param.Unsigned("Number of BTB entries") - BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits") - - RASSize = Param.Unsigned("RAS size") - - LQEntries = Param.Unsigned("Number of load queue entries") - SQEntries = Param.Unsigned("Number of store queue entries") - LFSTSize = Param.Unsigned("Last fetched store table size") - SSITSize = Param.Unsigned("Store set ID table size") - - numRobs = Param.Unsigned("Number of Reorder Buffers"); - - numPhysIntRegs = Param.Unsigned("Number of physical integer registers") - numPhysFloatRegs = Param.Unsigned("Number of physical floating point " - "registers") - numIQEntries = Param.Unsigned("Number of instruction queue entries") - numROBEntries = Param.Unsigned("Number of reorder buffer entries") - - instShiftAmt = Param.Unsigned("Number of bits to shift instructions by") + renameToROBDelay = Param.Unsigned(1, "Rename to reorder buffer delay") + commitWidth = Param.Unsigned(8, "Commit width") + squashWidth = Param.Unsigned(8, "Squash width") + trapLatency = Param.Tick(13, "Trap latency") + fetchTrapLatency = Param.Tick(1, "Fetch trap latency") + + backComSize = Param.Unsigned(5, "Time buffer size for backwards communication") + forwardComSize = Param.Unsigned(5, "Time buffer size for forward communication") + + predType = Param.String("tournament", "Branch predictor type ('local', 'tournament')") + localPredictorSize = Param.Unsigned(2048, "Size of local predictor") + localCtrBits = Param.Unsigned(2, "Bits per counter") + localHistoryTableSize = Param.Unsigned(2048, "Size of local history table") + localHistoryBits = Param.Unsigned(11, "Bits for the local history") + globalPredictorSize = Param.Unsigned(8192, "Size of global predictor") + globalCtrBits = Param.Unsigned(2, "Bits per counter") + globalHistoryBits = Param.Unsigned(4096, "Bits of history") + choicePredictorSize = Param.Unsigned(8192, "Size of choice predictor") + choiceCtrBits = Param.Unsigned(2, "Bits of choice counters") + + BTBEntries = Param.Unsigned(4096, "Number of BTB entries") + BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits") + + RASSize = Param.Unsigned(16, "RAS size") + + LQEntries = Param.Unsigned(32, "Number of load queue entries") + SQEntries = Param.Unsigned(32, "Number of store queue entries") + LFSTSize = Param.Unsigned(1024, "Last fetched store table size") + SSITSize = Param.Unsigned(1024, "Store set ID table size") + + numRobs = Param.Unsigned(1, "Number of Reorder Buffers"); + + numPhysIntRegs = Param.Unsigned(256, "Number of physical integer registers") + numPhysFloatRegs = Param.Unsigned(256, "Number of physical floating point " + "registers") + numIQEntries = Param.Unsigned(64, "Number of instruction queue entries") + numROBEntries = Param.Unsigned(192, "Number of reorder buffer entries") + + instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py index 29014bb37..cc0d1cf4a 100644 --- a/src/python/m5/objects/Pci.py +++ b/src/python/m5/objects/Pci.py @@ -52,7 +52,7 @@ class PciDevice(DmaDevice): pci_bus = Param.Int("PCI bus") pci_dev = Param.Int("PCI device number") pci_func = Param.Int("PCI function code") - pio_latency = Param.Tick(1, "Programmed IO latency in simticks") + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") configdata = Param.PciConfigData(Parent.any, "PCI Config data") class PciFake(PciDevice): diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index 373475a7a..33dd22620 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -7,7 +7,7 @@ from Debug import Debug class Root(SimObject): type = 'Root' - clock = Param.RootClock('200MHz', "tick frequency") + clock = Param.RootClock('1THz', "tick frequency") max_tick = Param.Tick('0', "maximum simulation ticks (0 = infinite)") progress_interval = Param.Tick('0', "print a progress message every n ticks (0 = never)") diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py index 9a1e1d690..386f39277 100644 --- a/src/python/m5/objects/System.py +++ b/src/python/m5/objects/System.py @@ -1,9 +1,12 @@ from m5 import build_env from m5.config import * +class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing'] + class System(SimObject): type = 'System' physmem = Param.PhysicalMemory(Parent.any, "phsyical memory") + mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in") if build_env['FULL_SYSTEM']: boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, "boot processor frequency") diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py index 4613571d8..0b5ff9e7d 100644 --- a/src/python/m5/objects/Tsunami.py +++ b/src/python/m5/objects/Tsunami.py @@ -1,11 +1,10 @@ from m5.config import * from Device import BasicPioDevice from Platform import Platform - -class Tsunami(Platform): - type = 'Tsunami' -# pciconfig = Param.PciConfigAll("PCI configuration") - system = Param.System(Parent.any, "system") +from AlphaConsole import AlphaConsole +from Uart import Uart8250 +from Pci import PciConfigAll +from BadDevice import BadDevice class TsunamiCChip(BasicPioDevice): type = 'TsunamiCChip' @@ -25,3 +24,71 @@ class TsunamiIO(BasicPioDevice): class TsunamiPChip(BasicPioDevice): type = 'TsunamiPChip' tsunami = Param.Tsunami(Parent.any, "Tsunami") + +class Tsunami(Platform): + type = 'Tsunami' + system = Param.System(Parent.any, "system") + + cchip = TsunamiCChip(pio_addr=0x801a0000000) + pchip = TsunamiPChip(pio_addr=0x80180000000) + pciconfig = PciConfigAll() + fake_sm_chip = IsaFake(pio_addr=0x801fc000370) + + fake_uart1 = IsaFake(pio_addr=0x801fc0002f8) + fake_uart2 = IsaFake(pio_addr=0x801fc0003e8) + fake_uart3 = IsaFake(pio_addr=0x801fc0002e8) + fake_uart4 = IsaFake(pio_addr=0x801fc0003f0) + + fake_ppc = IsaFake(pio_addr=0x801fc0003bc) + + fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000) + + fake_pnp_addr = IsaFake(pio_addr=0x801fc000279) + fake_pnp_write = IsaFake(pio_addr=0x801fc000a79) + fake_pnp_read0 = IsaFake(pio_addr=0x801fc000203) + fake_pnp_read1 = IsaFake(pio_addr=0x801fc000243) + fake_pnp_read2 = IsaFake(pio_addr=0x801fc000283) + fake_pnp_read3 = IsaFake(pio_addr=0x801fc0002c3) + fake_pnp_read4 = IsaFake(pio_addr=0x801fc000303) + fake_pnp_read5 = IsaFake(pio_addr=0x801fc000343) + fake_pnp_read6 = IsaFake(pio_addr=0x801fc000383) + fake_pnp_read7 = IsaFake(pio_addr=0x801fc0003c3) + + fake_ata0 = IsaFake(pio_addr=0x801fc0001f0) + fake_ata1 = IsaFake(pio_addr=0x801fc000170) + + fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer') + io = TsunamiIO(pio_addr=0x801fc000000) + uart = Uart8250(pio_addr=0x801fc0003f8) + console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk) + + # Attach I/O devices to specified bus object. Can't do this + # earlier, since the bus object itself is typically defined at the + # System level. + def attachIO(self, bus): + self.cchip.pio = bus.port + self.pchip.pio = bus.port + self.pciconfig.pio = bus.default + self.fake_sm_chip.pio = bus.port + self.fake_uart1.pio = bus.port + self.fake_uart2.pio = bus.port + self.fake_uart3.pio = bus.port + self.fake_uart4.pio = bus.port + self.fake_ppc.pio = bus.port + self.fake_OROM.pio = bus.port + self.fake_pnp_addr.pio = bus.port + self.fake_pnp_write.pio = bus.port + self.fake_pnp_read0.pio = bus.port + self.fake_pnp_read1.pio = bus.port + self.fake_pnp_read2.pio = bus.port + self.fake_pnp_read3.pio = bus.port + self.fake_pnp_read4.pio = bus.port + self.fake_pnp_read5.pio = bus.port + self.fake_pnp_read6.pio = bus.port + self.fake_pnp_read7.pio = bus.port + self.fake_ata0.pio = bus.port + self.fake_ata1.pio = bus.port + self.fb.pio = bus.port + self.io.pio = bus.port + self.uart.pio = bus.port + self.console.pio = bus.port diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index f1f244150..7648b8fcd 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -25,7 +25,8 @@ * (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: Ali Saidi + * Authors: Gabe Black + * Ali Saidi * Nathan Binkert */ diff --git a/src/sim/main.cc b/src/sim/main.cc index d0725ab37..4ea8c4138 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -215,7 +215,7 @@ loadIniFile(PyObject *_resolveFunc) configStream = simout.find("config.out"); // The configuration database is now complete; start processing it. - inifile.load("config.ini"); + inifile.load(simout.resolve("config.ini")); // Initialize statistics database Stats::InitSimStats(); diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 5e5b7d95f..4a83b93e0 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -30,10 +30,8 @@ class ThreadContext; -//We need the "Tick" data type from here +//We need the "Tick" and "Addr" data types from here #include "sim/host.hh" -//We need the "Addr" data type from here -#include "arch/isa_traits.hh" namespace AlphaPseudo { diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index a0278dba0..d12b06b7a 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -72,7 +72,7 @@ SimObject::SimObject(Params *p) doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); - state = Atomic; + state = Running; } // @@ -88,7 +88,7 @@ SimObject::SimObject(const string &_name) doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); - state = Atomic; + state = Running; } void @@ -269,38 +269,23 @@ SimObject::recordEvent(const std::string &stat) Stats::recordEvent(stat); } -bool +unsigned int SimObject::drain(Event *drain_event) { - if (state != DrainedAtomic && state != Atomic) { - panic("Must implement your own drain function if it is to be used " - "in timing mode!"); - } - state = DrainedAtomic; - return true; + state = Drained; + return 0; } void SimObject::resume() { - if (state == DrainedAtomic) { - state = Atomic; - } else if (state == DrainedTiming) { - state = Timing; - } + state = Running; } void SimObject::setMemoryMode(State new_mode) { - assert(new_mode == Timing || new_mode == Atomic); - if (state == DrainedAtomic && new_mode == Timing) { - state = DrainedTiming; - } else if (state == DrainedTiming && new_mode == Atomic) { - state = DrainedAtomic; - } else { - state = new_mode; - } + panic("setMemoryMode() should only be called on systems"); } void diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 7ecc00958..38f2bdd23 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -60,16 +60,15 @@ class SimObject : public Serializable, protected StartupCallback }; enum State { - Atomic, - Timing, + Running, Draining, - DrainedAtomic, - DrainedTiming + Drained }; + private: + State state; protected: Params *_params; - State state; void changeState(State new_state) { state = new_state; } @@ -116,8 +115,10 @@ class SimObject : public Serializable, protected StartupCallback // Methods to drain objects in order to take checkpoints // Or switch from timing -> atomic memory model - // Drain returns false if the SimObject cannot drain immediately. - virtual bool drain(Event *drain_event); + // Drain returns 0 if the simobject can drain immediately or + // the number of times the drain_event's process function will be called + // before the object will be done draining. Normally this should be 1 + virtual unsigned int drain(Event *drain_event); virtual void resume(); virtual void setMemoryMode(State new_mode); virtual void switchOut(); diff --git a/src/sim/system.cc b/src/sim/system.cc index 89e7b8542..ad70b9b03 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -63,7 +63,7 @@ System::System(Params *p) #else page_ptr(0), #endif - _params(p) + memoryMode(p->mem_mode), _params(p) { // add self to global system list systemList.push_back(this); @@ -143,6 +143,14 @@ int rgdb_wait = -1; #endif // FULL_SYSTEM + +void +System::setMemoryMode(MemoryMode mode) +{ + assert(getState() == Drained); + memoryMode = mode; +} + int System::registerThreadContext(ThreadContext *tc, int id) { @@ -249,6 +257,9 @@ printSystems() System::printSystems(); } +const char *System::MemoryModeStrings[3] = {"invalid", "atomic", + "timing"}; + #if FULL_SYSTEM // In full system mode, only derived classes (e.g. AlphaLinuxSystem) @@ -261,12 +272,15 @@ DEFINE_SIM_OBJECT_CLASS_NAME("System", System) BEGIN_DECLARE_SIM_OBJECT_PARAMS(System) SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; END_DECLARE_SIM_OBJECT_PARAMS(System) BEGIN_INIT_SIM_OBJECT_PARAMS(System) - INIT_PARAM(physmem, "physical memory") + INIT_PARAM(physmem, "physical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings) END_INIT_SIM_OBJECT_PARAMS(System) @@ -275,6 +289,7 @@ CREATE_SIM_OBJECT(System) System::Params *p = new System::Params; p->name = getInstanceName(); p->physmem = physmem; + p->mem_mode = mem_mode; return new System(p); } diff --git a/src/sim/system.hh b/src/sim/system.hh index 059dc92dc..c138d2ee4 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -39,6 +39,7 @@ #include "base/loader/symtab.hh" #include "base/misc.hh" #include "base/statistics.hh" +#include "config/full_system.hh" #include "cpu/pc_event.hh" #include "mem/port.hh" #include "sim/sim_object.hh" @@ -61,6 +62,23 @@ class RemoteGDB; class System : public SimObject { public: + enum MemoryMode { + Invalid=0, + Atomic, + Timing + }; + + static const char *MemoryModeStrings[3]; + + + MemoryMode getMemoryMode() { assert(memoryMode); return memoryMode; } + + /** Change the memory mode of the system. This should only be called by the + * python!! + * @param mode Mode to change to (atomic/timing) + */ + void setMemoryMode(MemoryMode mode); + PhysicalMemory *physmem; PCEventQueue pcEventQueue; @@ -108,6 +126,8 @@ class System : public SimObject protected: + MemoryMode memoryMode; + #if FULL_SYSTEM /** * Fix up an address used to match PCs for hooking simulator @@ -153,6 +173,7 @@ class System : public SimObject { std::string name; PhysicalMemory *physmem; + MemoryMode mem_mode; #if FULL_SYSTEM Tick boot_cpu_frequency; |