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